Definición de números por oído: implementación en Arduino

En este artículo, continuaré encarnando mi inspiración en el trabajo de laboratorio No. 3 que ya está en la glándula. Estamos hablando de detectar un dígito por sonido en el modo de marcación por tonos en el Arduino usando el algoritmo Goertzel.

Para implementar esto, utilicé Arduino UNO, un micrófono electret ( adafruit ) y una pantalla de 8x8 con el controlador MAX7219.

Plan de acción


  • Discretice una cantidad suficiente de muestras (usando el programa del artículo anterior , estaba convencido de que 256 es suficiente).
  • Encuentre las amplitudes de la respuesta de frecuencia correspondiente a las frecuencias deseadas que codifican los caracteres.
  • Los dos valores máximos de la amplitud darán los índices de fila y columna del carácter deseado, por ejemplo, se ve la figura 3.
    imagen

Implementación


Antes de embarcarnos en una implementación, respondemos la pregunta: ¿Arduino UNO tendrá suficiente rendimiento para nosotros?

Frecuencia de reloj: 16MHz
Un ciclo de muestreo toma 13 ciclos de reloj
Valor de preescalador que proporciona la mayor precisión: 128

Resulta que 16 MHz / 13/128 ~ 9615 Hz, la frecuencia de muestreo deseada, lo que significa que puede trabajar con frecuencias de hasta 4.8 kHz.

Ajuste de ADC


Hay varios modos de operación ADC, los más interesantes se enumeran a continuación (una lista completa en la hoja de datos para la palabra clave ADCSRB)

  • lectura única: usando el método analogRead (), pero esta es una llamada de bloqueo que toma 100 µs, y es imposible proporcionar una frecuencia de muestreo constante
  • modo de ejecución libre: en este modo, el siguiente ciclo de muestreo comienza inmediatamente después del final del anterior y se proporciona la frecuencia de muestreo máxima
  • desbordamiento del temporizador: el muestreo comienza con el desbordamiento del temporizador, esto le permite ajustar la frecuencia de muestreo

Código de configuración ADC, por simplicidad utilicé el modo de ejecución libre.

ADMUX = 0; // Channel sel, right-adj, use AREF pin ADCSRA = _BV(ADEN) | // ADC enable _BV(ADSC) | // ADC start _BV(ADATE) | // Auto trigger _BV(ADIE) | // Interrupt enable _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0); // 128:1 / 13 = 9615 Hz ADCSRB = 0; // Free-run mode DIDR0 = _BV(0); // Turn off digital input for ADC pin TIMSK0 = 0; // Timer0 off 

Procesamiento de señal


Tan pronto como se tipea la matriz completa de muestras, apagamos la interrupción por el ADC y calculamos la amplitud del espectro utilizando el algoritmo de Goertzel. No competiré en la descripción del algoritmo con este recurso exhaustivo, pero daré mi implementación:

 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; } } 

Los senos y cosenos se calcularon previamente para muestras correspondientes a las frecuencias deseadas. La versión completa del código está aquí .

Conclusiones


Lo que es más importante, resultó y los recursos de Arduino UNO son suficientes para un procesamiento de sonido simple.


La lección principal que aprendí es que el ADC es algo sensible, después de reconocer y enviar con éxito el personaje a la consola, pasé una semana depurándolo para que funcione con la pantalla, porque conecté el suelo del micrófono y el max7219 y todas las muestras se convirtieron en ruido de inmediato.

¿Podría haber sido mejor? Sí, sería más correcto seleccionar la frecuencia de muestreo y el número de muestras para que las frecuencias deseadas coincidan con la red de muestreo, esto evitaría la propagación del espectro. Dichos parámetros ya son f = 8 kHz, N = 205, en cuyo caso necesita ejecutar ADC no en modo de ejecución libre, sino desbordamiento del temporizador, y la diferencia sería obvia.



El curso está llegando a su fin, pero todavía hay muchas ideas.
Gracias por su atencion

Source: https://habr.com/ru/post/es432498/


All Articles