Sintetizador Digital ESP32
2024Sintetizador sequenciador de passos polifônico no ESP32. Pipeline de síntese subtrativa: tabela de onda SAW2048 → filtro passa-baixas ressonante → envelope ADSR → soft clipping → DAC. Sequenciador de 8 passos baseado em tick com swing, randomização e dois multiplexadores CD4051 para 8 pots analógicos + 5 botões. Firmware C++ modular com camadas AudioEngine, Sequencer, Controls e UI.
O ESP32 Synthesizer é um sintetizador de áudio digital em hardware construído em um microcontrolador ESP32. Implementa uma cadeia completa de síntese subtrativa — oscilador de tabela de ondas, filtro passa-baixas ressonante, envelope ADSR e soft clipping — conduzida por um sequenciador de 8 passos baseado em ticks com timing de swing e randomização por passo. O instrumento é controlado por 8 potenciômetros analógicos lidos via multiplexadores CD4051, exibidos tanto em uma tela OLED quanto em um módulo LED/7-segmentos TM1638.
Sintetizadores comerciais na faixa de preço acessível oferecem programabilidade limitada e nenhuma personalização de hardware. Construir um sintetizador a partir de primitivas de microcontrolador requer resolver três restrições simultâneas: timing de áudio determinístico, entrada analógica sem ruído (8 pots em um barramento ADC compartilhado), e atualizações de display em tempo real que não roubem CPU do rendering de áudio.
Construir um sintetizador de hardware tocável que: (1) implemente síntese subtrativa com controle de filtro e envelope em tempo real; (2) execute um sequenciador de 8 passos capaz de swing com timing determinístico; (3) leia 8 pots analógicos + 5 botões via multiplexadores sem contenda no ADC; (4) exiba estado de parâmetros em tempo real em displays duplos; (5) use arquitetura de firmware modular para manutenibilidade.
- ◈Desenvolvedor embedded solo — design de hardware, arquitetura de firmware, algoritmo de síntese, UI
- 01Biblioteca Mozzi com tabela de ondas SAW2048 — o Mozzi fornece uma tabela de onda sawtooth de 2048 amostras 8-bit que o oscilador reproduz em qualquer frequência via interpolação de tabela. Isso evita computação de forma de onda em tempo real (que exigiria funções trigonométricas a 16.384kHz — inatingível no ESP32). A divisão control-rate/audio-rate do Mozzi (128Hz/16384Hz) aplica uma arquitetura limpa.
- 02Timing do sequenciador baseado em ticks — em vez de transições de passos baseadas em millis() (que derivam sob carga), o sequenciador conta ticks de controle Mozzi: ticksPerStep = (CONTROL_RATE × 60) / BPM. Cada tick é exatamente 1/128s. O swing é aplicado ajustando contagens de passos ímpares.
- 03Varredura round-robin do multiplexador CD4051 — um único multiplexador analógico de 8 canais CD4051 conecta 8 potenciômetros a um pino ADC do ESP32. O loop de controle lê um canal por tick (round-robin), ciclando por todos os 8 pots em 8 ticks. Isso elimina problemas de tempo de assentamento do ADC.
- 04Suavização IIR em todas as entradas analógicas — em vez de uma média móvel em buffer circular, cada pot usa um IIR de instrução única: novo = antigo + (bruto − antigo) >> 3. Equivalente a um IIR passa-baixas de 1 polo em fc ≈ 8Hz — suficiente para eliminar ruído sem introduzir lag perceptível.
- 05Soft clipping para evitar saturação digital — a etapa de saída final aplica soft clipping assimétrico: se (x > 30000) x = 30000 + (x − 30000) / 4. Isso suavemente reduz picos acima de ±30000 em vez de truncar bruscamente.
- 06Headers C++ modulares — o firmware original era um arquivo .ino monolítico. Refatorar em AudioEngine.h, Sequencer.h, Controls.h, Events.h, UI.h e Types.h permite testar a lógica de tick do sequenciador independentemente do Mozzi.
- →O timing baseado em ticks é a arquitetura correta para sequenciadores embedded — uma versão inicial baseada em millis() tinha deriva de timing que se acumulava ao longo de minutos. Mudar para ticks de controle Mozzi (que são acionados por interrupção de hardware) eliminou a deriva completamente.
- →O tempo de assentamento do multiplexador ADC é um problema real — a primeira revisão de hardware lia todos os 8 pots em rápida sucessão em um único tick de controle. O ADC não conseguia se estabilizar entre trocas de canal, produzindo crosstalk. Round-robin (um pot por tick) deu ao ADC 8 ticks completos (~62ms) para estabilizar.
- →A suavização IIR é a ferramenta certa para ruído analógico — uma média móvel de 4 amostras adicionava 4 ticks de lag (~31ms) a cada movimento de pot, fazendo o cutoff parecer lento durante a performance ao vivo. A abordagem IIR elimina a sensação de lag enquanto ainda filtra o ruído.
- →O firmware modular desbloqueia a testabilidade — o .ino monolítico original não podia ser testado unitariamente porque a interrupção de áudio do Mozzi rodaria durante a execução do teste. Extrair o Sequencer para um header C++ puro sem dependências Mozzi permitiu testes de timing em uma máquina host sem hardware.
Construído — instrumento de hardware tocável