002 — Frequency Generator
02/03/2026
Introdução
Esse projeto nasceu da minha necessidade de ter um gerador de frequências para um outro projeto que eu estava fazendo. Infelizmente, bons aparelhos comercialmente disponíveis são muito caros, então tive que adaptar com o que eu tinha disponível.
As opções então foram: fazer um circuito com osciladores que gerava uma frequência única ou utilizar um microcontrolador para gerar uma onda com frequências variadas, escolhidas pelo usuário. Optei pela segunda.
A maioria dos processadores consegue emular sinais analógicos a partir da modulação do comprimento de pulso (Pulse Width Modulation - PWM). Controlando a fase ativa e inativa de uma onda quadrada em uma frequência suficientemente alta, podemos criar a impressão de que estamos gerando um sinal analógico. Os Arduinos mais comuns possuem uma frequência fixa para os pulsos de PWM, de 490 ou 980 Hz, dependendo do pino utilizado. Por conta disso, um Arduino não nos serviria, já que queremos controlar essa frequência.
O Teensy, irmão mais robusto do Arduino, por outro lado, possui uma função chamada analogWriteFrequency, que permite o controle da frequência de PWM de pinos específicos atrelados a timers do microcontrolador. A primeira versão do gerador usava um Teensy 3.2, mas ele acabou queimando, e o substituto foi um Teensy 4.0, que tem o mesmo tamanho e a mesma disposição de pinos. Nele, o pino 4 pode ter sua frequência alterada. O código é simples: analogWriteFrequency define a frequência do PWM, e o analogWrite define sua fase ativa.
O desafio agora é criar uma interface intuitiva para a seleção das frequências. Botões ou teclados matriciais me pareciam desnecessários. Além disso, eu tinha comprado um encoder japonês que queria testar. A frequência seria exibida em um display OLED, e para evitar fritar meu precioso Teensy, o sinal gerado seria fisicamente isolado do microcontrolador através de um optoacoplador, outro componente que eu estava animado para testar!
Operação
A operação do dispositivo é simples e intuitiva: o usuário pode aumentar e diminuir o valor da frequência utilizando o encoder. O encoder pode ser empurrado para baixo para aumentar o incremento de frequência em potências de 10, facilitando a configuração de altas frequências. Ao definir a frequência desejada, o usuário deve pressionar a chave tátil, à direita do dispositivo, para ligar a saída, e pressioná-la de novo para desligar. O display mostra se a saída está ligada (ON) ou desligada (OFF), e a frequência pode ser ajustada com calma enquanto ela estiver desligada. O sinal gerado passará pelo optoacoplador, cujas saídas devem ser conectadas a algum dispositivo, como um alto falante, através de um simples circuito de amplificação usando um transistor.
O circuito
O circuito consiste dos seguintes componentes:
- Teensy 4.0
- Encoder
- Display OLED I2C
- Chave tátil
- Optoacoplador
- Resistores
- Borne banana
Aqui está um diagrama do circuito:

Circuito do gerador de frequências, feito no EasyEDA
O código
O coração do programa é bem curto. A cada volta do loop, o Teensy lê a posição do encoder e calcula a nova frequência a partir da última frequência definida, somando quantos “cliques” o encoder girou multiplicados pelo incremento atual:
freq = oldfreq + (Position - oldPosition)*pow(10, increment);
O incremento começa em 1 Hz e, a cada vez que o botão é pressionado, sobe uma potência de 10: 10, 100, 1000 e 10000 Hz. Depois disso, volta para 1. É parecido com ajustar um relógio de ponteiros: primeiro giramos o ponteiro das horas para chegar perto do horário certo, e só depois refinamos com o dos minutos. O incremento atual aparece no canto do display, para que o usuário sempre saiba quanto cada clique vale. A frequência mínima é de 20 Hz, mais ou menos o som mais grave que o ouvido humano consegue perceber.
Já o analogWrite(genPin, 128) define a fase ativa da onda. Como a escala vai de 0 a 255, o valor 128 deixa o sinal ligado metade do tempo e desligado na outra metade, formando uma onda quadrada simétrica.
Revisando o código para publicá-lo aqui, encontrei um problema curioso. Na primeira versão, a função analogWriteFrequency era chamada em toda volta do loop, mesmo quando a frequência não tinha mudado. O detalhe é que essa função reinicia o contador interno do timer do Teensy 3.2. Como cada volta do loop leva uma fração de segundo (boa parte desse tempo é gasta atualizando o display), a onda era interrompida e recomeçava várias vezes por segundo, como um músico que volta para o início da música toda vez que vira a página da partitura. A correção foi simples: só reconfigurar o timer quando a frequência realmente muda.
if(freq != lastfreq){
analogWriteFrequency(genPin, freq);
analogWrite(genPin, 128);
lastfreq = freq;
}
Versões
1- Protótipo em breadboard
Montei a primeira versão do projeto em uma breadboard (protoboard) para testar a interface do usuário, através do encoder, e a geração de frequências no pino 4 do Teensy.

Protótipo em breadboard
2- Versão final em perfboard
Finalizei o projeto montando os componentes em uma placa perfurada (perfboard) para deixar as conexões mais seguras. Aproveitei para adicionar um botão para acionar a geração de frequências, e um optoacoplador para evitar fritar meu Teensy, pois só tenho esse.

Versão final em perfboard

Teste com alto-falante
Conclusão
Iniciei esse projeto querendo usá-lo para estudar atenuação de sinais de altas frequências, mas ao estudar melhor o assunto, parece que as ondas quadradas geradas por meu aparelho não são boas para esse tipo de coisa. O ideal era uma onda senoidal. E atualmente tenho acesso a um gerador profissional em meu laboratório. De todo modo, esse projeto me ensinou bastante sobre interfaces de usuário e virou um brinquedo musical bem divertido. Quem sabe não uso o Teensy como o oscilador de um sintetizador algum dia…