Neste artigo,
continuarei a incorporar minha inspiração no trabalho de laboratório nº 3 já na glândula. Estamos falando sobre a detecção de um dígito pelo som no modo de discagem por tom no Arduino usando o algoritmo de Goertzel.
Para implementar isso, usei o Arduino UNO, um microfone de eletreto (
adafruit ) e uma tela 8x8 com o driver MAX7219.
Plano de ação
- Discretize um número suficiente de amostras (usando o programa do artigo anterior, eu estava convencido de que 256 é suficiente).
- Encontre as amplitudes da resposta de frequência correspondente às frequências desejadas que codificam os caracteres.
- Os dois valores máximos da amplitude fornecerão os índices de linha e coluna do caractere desejado, por exemplo, a figura 3 se parece.

Implementação
Antes de iniciar uma implementação, respondemos à pergunta - o Arduino UNO terá desempenho suficiente para nós?
Frequência de clock: 16MHz
Um ciclo de amostragem leva 13 ciclos de relógio
Valor do Prescaler que fornece a maior precisão: 128
Acontece 16 MHz / 13/128 ~ 9615 Hz - a frequência de amostragem desejada, o que significa que você pode trabalhar com frequências de até 4,8 kHz.
Ajuste ADC
Existem vários modos de operação ADC, os mais interessantes estão listados abaixo (uma lista completa na
folha de
dados da palavra-chave ADCSRB)
- leitura única - usando o método analogRead (), mas é uma chamada de bloqueio que leva 100 µs e, usando-o, é impossível fornecer uma taxa de amostragem constante
- modo de execução livre - nesse modo, o próximo ciclo de amostragem começa imediatamente após o final do anterior e a freqüência máxima de amostragem é fornecida
- overflow do temporizador - a amostragem começa com o overflow do temporizador, permitindo ajustar a frequência de amostragem
Código de configuração ADC, para simplificar, usei o modo de execução livre.
ADMUX = 0;
Processamento de sinal
Assim que o conjunto completo de amostras é digitado, desligamos a interrupção pelo ADC e calculamos a amplitude do espectro usando o algoritmo de Goertzel. Não competirei na descrição do algoritmo com este
recurso exaustivo, mas darei minha implementação:
void goertzel(uint8_t *samples, float *spectrum) { float v_0, v_1, v_2; float re, im, amp; for (uint8_t k = 0; k < IX_LEN; k++) { float cos = pgm_read_float(&(cos_t[k])); float sin = pgm_read_float(&(sin_t[k])); float a = 2. * cos; v_0 = v_1 = v_2 = 0; for (uint16_t i = 0; i < N; i++) { v_0 = v_1; v_1 = v_2; v_2 = (float)(samples[i]) + a * v_1 - v_0; } re = cos * v_2 - v_1; im = sin * v_2; amp = sqrt(re * re + im * im); spectrum[k] = amp; } }
Senos e cossenos foram previamente calculados para amostras correspondentes às frequências desejadas. A versão completa do código está
aqui .
Conclusões
Mais importante ainda, os recursos do Arduino UNO são suficientes para o processamento de som simples.
A principal lição que aprendi que o ADC é uma coisa sensível, depois de reconhecer e enviar o personagem para o console com sucesso, passei uma semana depurando-o para trabalhar com a tela, porque liguei o terra do microfone e o max7219 e todas as amostras se transformaram em ruído imediatamente.
Poderia ter sido melhor? Sim, seria mais correto selecionar a frequência de amostragem e o número de amostras para que as frequências desejadas coincidissem com a rede de amostragem, isso impediria a propagação do espectro. Esses parâmetros já são f = 8 kHz, N = 205; nesse caso, você precisa executar o ADC não no modo de execução livre, mas o estouro do timer e a diferença seriam óbvias.
O curso está chegando ao fim, mas ainda há muitas idéias.
Obrigado pela atenção.