تعريف الأرقام عن طريق الأذن: التنفيذ على اردوينو

في هذه المقالة ، سأستمر في تجسيد إلهامي في العمل المختبري رقم 3 الموجود بالفعل في الغدة. نحن نتحدث عن اكتشاف رقم عن طريق الصوت في وضع الاتصال بالألوان على Arduino باستخدام خوارزمية Goertzel.

لتنفيذ ذلك ، استخدمت Arduino UNO ، وميكروفون electret ( adafruit ) وشاشة 8 × 8 مع برنامج التشغيل MAX7219.

خطة العمل


  • تخليص عدد كاف من العينات (باستخدام البرنامج من المادة السابقة كنت مقتنعا أن 256 بما فيه الكفاية).
  • ابحث عن سعة استجابة التردد المقابلة للترددات المرغوبة التي تشفر الحروف.
  • ستعطي قيمتا الحد الأقصى للسعة مؤشرات للصف والعمود للحرف المرغوبة ، على سبيل المثال ، يبدو الشكل 3.
    الصورة

التنفيذ


قبل الشروع في التنفيذ ، نجيب على السؤال - هل سيكون لدى Arduino UNO أداء كاف لنا؟

تردد الساعة: 16 ميجا هرتز
تستغرق دورة أخذ العينات 13 دورة على مدار الساعة
قيمة Prescaler توفير أكبر قدر من الدقة: 128

اتضح 16 ميغاهيرتز / 13/128 ~ 9615 هرتز - تردد أخذ العينات المطلوب ، مما يعني أنه يمكنك العمل مع ترددات تصل إلى 4.8 كيلو هرتز.

ضبط ADC


هناك العديد من أوضاع تشغيل ADC ، والأكثر إثارة للاهتمام هي المذكورة أدناه (قائمة كاملة في ورقة البيانات للكلمة الرئيسية ADCSRB)

  • قراءة واحدة - باستخدام طريقة analogRead () ، ولكن هذه مكالمة حظر تتطلب 100 ثانية ، واستخدامها يستحيل توفير معدل ثابت لأخذ العينات
  • وضع التشغيل الحر - في هذا الوضع ، تبدأ دورة أخذ العينات التالية مباشرة بعد نهاية الدورة السابقة ويتم توفير الحد الأقصى لتردد أخذ العينات
  • تجاوز الموقت - تبدأ عملية أخذ العينات بتجاوز سعة الموقت ، مما يتيح لك ضبط وتيرة أخذ العينات

رمز إعداد ADC ، من أجل البساطة استخدمت وضع التشغيل المجاني.

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 

معالجة الإشارات


بمجرد كتابة المجموعة الكاملة من العينات ، نقوم بإيقاف المقاطعة بواسطة ADC ونحسب سعة الطيف باستخدام خوارزمية Goertzel. لن أتنافس في وصف الخوارزمية مع هذا المورد الشامل ، لكنني سأقدم عملي:

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

تم حساب الجيوب وجيب التمام مسبقًا للعينات المقابلة للترددات المطلوبة. النسخة الكاملة من الكود هنا .

الاستنتاجات


الأهم من ذلك ، اتضح أن موارد Arduino UNO كافية لمعالجة الصوت البسيطة.


الدرس الرئيسي الذي تعلمته أن ADC شيء حساس ، بعد التعرف على الشخصية وإرسالها بنجاح إلى وحدة التحكم ، قضيت أسبوعًا في تصحيحه للعمل مع الشاشة ، لأنني قمت بتوصيل الأرض بالميكروفون و max7219 وتحولت جميع العينات إلى ضوضاء على الفور.

يمكن أن يكون أفضل؟ نعم ، سيكون من الأصح اختيار تردد أخذ العينات وعدد العينات بحيث تتزامن الترددات المطلوبة مع شعرية أخذ العينات ، وهذا سيمنع انتشار الطيف. هذه المعلمات هي بالفعل f = 8 كيلو هرتز ، N = 205 ، وفي هذه الحالة تحتاج إلى تشغيل ADC ليس في وضع التشغيل المجاني ، ولكن تجاوز سعة المؤقت ، وسيكون الفرق واضحًا.



تقترب الدورة من نهايتها ، ولكن لا تزال هناك العديد من الأفكار.
شكرا لاهتمامكم

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


All Articles