Definisi angka berdasarkan telinga: implementasi pada Arduino

Dalam artikel ini, saya akan terus mewujudkan inspirasi saya dalam pekerjaan laboratorium No. 3 yang sudah di setrika. Kita berbicara tentang mendeteksi angka dengan suara dalam mode panggilan nada pada Arduino menggunakan algoritma Goertzel.

Untuk mengimplementasikan ini, saya menggunakan Arduino UNO, mikrofon electret ( adafruit ) dan layar 8x8 dengan driver MAX7219.

Rencana aksi


  • Diskritkan jumlah sampel yang cukup (menggunakan program dari artikel sebelumnya, saya yakin 256 sudah cukup).
  • Temukan amplitudo dari respons frekuensi yang sesuai dengan frekuensi yang diinginkan yang menyandikan karakter.
  • Dua nilai maksimum amplitudo akan memberikan indeks baris dan kolom dari karakter yang diinginkan, misalnya, seperti gambar 3.
    gambar

Implementasi


Sebelum memulai implementasi, kami menjawab pertanyaan - apakah Arduino UNO memiliki kinerja yang cukup untuk kami?

Frekuensi Jam: 16MHz
Satu siklus pengambilan sampel membutuhkan 13 siklus clock
Nilai prescaler memberikan akurasi paling tinggi: 128

Ternyata 16 MHz / 13/128 ~ 9615 Hz - frekuensi sampling yang diinginkan, yang berarti Anda dapat bekerja dengan frekuensi hingga 4,8 kHz.

Tuning ADC


Ada beberapa mode operasi ADC, yang paling menarik tercantum di bawah ini (daftar lengkap dalam datasheet untuk kata kunci ADCSRB)

  • baca tunggal - menggunakan metode analogRead (), tetapi ini adalah panggilan pemblokiran yang membutuhkan 100Ξs, dan menggunakannya tidak mungkin untuk memberikan laju pengambilan sampel yang konstan
  • mode bebas lari - dalam mode ini, siklus pengambilan sampel berikutnya dimulai segera setelah akhir yang sebelumnya dan frekuensi pengambilan sampel maksimum disediakan
  • timer overflow - sampling dimulai dengan timer overflow, ini memungkinkan Anda untuk menyempurnakan frekuensi sampling

Kode pengaturan ADC, untuk kesederhanaan saya menggunakan mode bebas-lari.

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 

Pemrosesan sinyal


Segera setelah array penuh sampel diketik, kami mematikan interupsi oleh ADC dan menghitung amplitudo spektrum menggunakan algoritma Goertzel. Saya tidak akan bersaing dalam deskripsi algoritma dengan sumber daya yang lengkap ini, tetapi saya akan memberikan implementasi saya:

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

Sine dan cosinus sebelumnya dihitung untuk sampel yang sesuai dengan frekuensi yang diinginkan. Versi lengkap kode ada di sini .

Kesimpulan


Yang paling penting, ternyata dan sumber daya UNO Arduino cukup untuk pemrosesan suara yang sederhana.


Pelajaran utama yang saya pelajari bahwa ADC adalah hal yang sensitif, setelah berhasil mengenali dan mengirim karakter ke konsol, saya menghabiskan satu minggu men-debug-nya untuk bekerja dengan tampilan, karena saya menghubungkan ground mikrofon dan max7219 dan semua sampel langsung berubah menjadi noise.

Mungkinkah ini lebih baik? Ya, akan lebih tepat untuk memilih frekuensi sampling dan jumlah sampel sehingga frekuensi yang diinginkan bertepatan dengan kisi sampling, ini akan mencegah penyebaran spektrum. Parameter tersebut sudah f = 8 kHz, N = 205, dalam hal ini Anda perlu menjalankan ADC tidak dalam mode bebas-lari, tetapi timer meluap, dan perbedaannya akan jelas.



Kursus ini hampir berakhir, tetapi masih ada banyak ide.
Terima kasih atas perhatian anda

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


All Articles