Définition des nombres à l'oreille: implémentation sur Arduino

Dans cet article, je continuerai d'incarner mon inspiration dans les travaux de laboratoire n ° 3 déjà dans la glande. Nous parlons de détecter un chiffre par le son dans le mode de tonalité de numérotation sur l'Arduino en utilisant l'algorithme de Goertzel.

Pour implémenter cela, j'ai utilisé Arduino UNO, un microphone à électret ( adafruit ) et un écran 8x8 avec le pilote MAX7219.

Plan d'action


  • Discrétisez un nombre suffisant d'échantillons (en utilisant le programme de l' article précédent j'étais convaincu que 256 suffisait).
  • Trouvez les amplitudes de la réponse en fréquence correspondant aux fréquences souhaitées encodant les caractères.
  • Les deux valeurs d'amplitude maximales donneront les indices de ligne et de colonne du caractère souhaité, par exemple, le numéro 3 ressemble.
    image

Implémentation


Avant de se lancer dans une implémentation, nous répondons à la question - Arduino UNO aura-t-il suffisamment de performances pour nous?

Fréquence d'horloge: 16 MHz
Un cycle d'échantillonnage prend 13 cycles d'horloge
Valeur de pré-détartrage offrant la plus grande précision: 128

Il s'avère que 16 MHz / 13/128 ~ 9615 Hz - la fréquence d'échantillonnage souhaitée, ce qui signifie que vous pouvez travailler avec des fréquences allant jusqu'à 4,8 kHz.

Réglage ADC


Il existe plusieurs modes de fonctionnement ADC, les plus intéressants sont répertoriés ci-dessous (une liste complète dans la fiche technique du mot-clé ADCSRB)

  • lecture unique - en utilisant la méthode analogRead (), mais il s'agit d'un appel de blocage qui prend 100 µs, et en l'utilisant, il est impossible de fournir un taux d'échantillonnage constant
  • mode libre - dans ce mode, le cycle d'échantillonnage suivant commence immédiatement après la fin du précédent et la fréquence d'échantillonnage maximale est fournie
  • débordement de la minuterie - l'échantillonnage commence par un débordement de la minuterie, cela vous permet d'affiner la fréquence d'échantillonnage

Code de configuration ADC, pour plus de simplicité, j'ai utilisé le mode 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 

Traitement du signal


Dès que la gamme complète d'échantillons est tapée, nous désactivons l'interruption par l'ADC et calculons l'amplitude du spectre à l'aide de l'algorithme de Goertzel. Je ne concurrencerai pas dans la description de l'algorithme avec cette ressource exhaustive, mais je donnerai mon implémentation:

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

Les sinus et les cosinus ont été calculés précédemment pour des échantillons correspondant aux fréquences souhaitées. La version complète du code est ici .

Conclusions


Plus important encore, il s'est avéré et Arduino UNO a suffisamment de ressources pour un traitement sonore simple.


La principale leçon que j'ai apprise que l'ADC est une chose sensible, après avoir reconnu et envoyé avec succès le personnage à la console, j'ai passé une semaine à le déboguer pour travailler avec l'écran, car j'ai connecté la masse du microphone et le max7219 et tous les échantillons se sont transformés en bruit tout de suite.

Cela aurait-il pu être mieux? Oui, il serait plus correct de sélectionner la fréquence d'échantillonnage et le nombre d'échantillons de sorte que les fréquences souhaitées coïncident avec le réseau d'échantillonnage, cela empêcherait la propagation du spectre. Ces paramètres sont déjà f = 8 kHz, N = 205, auquel cas vous devez exécuter l'ADC non pas en mode libre, mais le dépassement de la temporisation, et la différence serait évidente.



Le cours touche à sa fin, mais il y a encore beaucoup d'idées.
Merci de votre attention.

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


All Articles