جدول المحتويات:

كيفية صنع واختبار DAC أفضل باستخدام ESP32: 5 خطوات
كيفية صنع واختبار DAC أفضل باستخدام ESP32: 5 خطوات

فيديو: كيفية صنع واختبار DAC أفضل باستخدام ESP32: 5 خطوات

فيديو: كيفية صنع واختبار DAC أفضل باستخدام ESP32: 5 خطوات
فيديو: How to use ESP32 WiFi and Bluetooth with Arduino IDE full details with examples and code 2024, يوليو
Anonim
كيفية صنع واختبار DAC أفضل باستخدام ESP32
كيفية صنع واختبار DAC أفضل باستخدام ESP32
كيفية صنع واختبار DAC أفضل باستخدام ESP32
كيفية صنع واختبار DAC أفضل باستخدام ESP32

يحتوي ESP32 على محولين رقمي إلى تناظري 8 بت (DACs). تسمح لنا DACs بإنتاج جهد تعسفي ضمن نطاق معين (0-3.3 فولت) مع دقة 8 بت. في Instructable ، سأوضح لك كيفية إنشاء DAC وتوصيف أدائها بالإضافة إلى مقارنتها بـ ESP32 DAC. تشمل مؤشرات الأداء التي سأبحثها

  • مستوى الضوضاء
  • عرض النطاق
  • لا خطية لا يتجزأ
  • اللاخطية التفاضلية

لاختبار هذه المؤشرات سأستخدم ADS1115.

من المهم ملاحظة أن تقييمك لجميع هذه المؤشرات سيكون فقط بنفس دقة جهازك المرجعي (في هذه الحالة ADS115). على سبيل المثال ، لا تتمتع ADS115 بدقة 16 بت عندما يتعلق الأمر بتعويض الجهد وكسبه. قد تصل هذه الأخطاء إلى 0.1٪. بالنسبة للعديد من الأنظمة ، يمكن تجاهل هذه الأخطاء عندما تكون الدقة المطلقة ذات أهمية محدودة.

اللوازم

  • ADS1115
  • مجلس ESP32
  • اللوح
  • أسلاك العبور
  • 5 كيلو أوم المقاوم
  • 1 مكثف ميكرو فاراد سيراميك

الخطوة 1: وضع اللوح

وضع اللوح
وضع اللوح

قم بتوصيل المسامير التالية

بين ESP32 و ADS1115

3v3 VDD

GND GND

GPIO22 SCL

GPIO21 SDA

في ADS1115

ADDR GND (ADS115)

صنع DAC

هناك العديد من الطرق لإنشاء DAC. أبسطها هو مرشح تمرير منخفض إشارة PWM بمقاوم ومكثف. كان بإمكاني إضافة جهاز op-amp هنا كمخزن مؤقت ولكني أردت أن أبقي الأمور بسيطة. هذا التصميم بسيط ورخيص التنفيذ مع أي متحكم يدعم PWM. لن أخوض في نظرية التصميم هنا (google PWM DAC).

فقط قم بتوصيل GPIO255 KOhm المقاوم 1 microFarad Capacitor gnd

قم الآن بتوصيل سلك توصيل من النقطة التي يلتقي فيها المقاوم بالمكثف بـ A0 على ADS115.

الخطوة الثانية: قم بتقييم الإشارة إلى مستوى الضوضاء

قم بتقييم الإشارة إلى مستوى الضوضاء
قم بتقييم الإشارة إلى مستوى الضوضاء

لتقييم مستوى الضوضاء ، ما عليك سوى تشغيل البرنامج النصي أدناه. لتقييم هذا ، نترك ببساطة DAC عند قيمة ثابتة ونقيس كيفية تذبذب الجهد بمرور الوقت.

نظرًا لتصميم DAC ، ستكون الضوضاء أكبر عندما تكون إشارة PWM في دورة عمل بنسبة 50 ٪. لذلك هذا هو المكان الذي سنقيم فيه ذلك. سنقوم أيضًا بتقييم ESP32 عند نفس مستوى الإشارة هذا. سنقوم أيضًا بتصفية ESP32 DAC بنفس مرشح تمرير منخفض لجعل القياس قابلاً للمقارنة.

بالنسبة لي كان الإخراج واضحا. كان تصميم PWM> 6dB أفضل SNR (وهذا أفضل مرتين). فوز واضح لـ DAC الجديدة. يتمثل أحد الارتباك الطفيف في وجود فلاتر مضمنة في ADC تعمل بالتأكيد على تحسين نسبة الإشارة إلى الضوضاء (SNR). لذلك قد يكون من الصعب تفسير القيم المطلقة. إذا كنت قد استخدمت مرشحًا من الدرجة الثانية ، فلن يكون هذا هو الحال.

على أي حال رمز أدناه

#يشمل

# تضمين إعلانات Adafruit_ADS1115 ؛ // مكتبة adafruit لـ adc int16_t adc0 ؛ // إعداد باطل (باطل) {Serial.begin (115200) ؛ // بدء تشغيل ads.setGain التسلسلي (GAIN_TWO) ؛ // 2x كسب +/- 2.048V 1 بت = 0.0625mV ads.begin () ؛ // start adc float M = 0 ؛ // متوسط التعويم الأولي Mp = 0 ؛ // previouos يعني تعويم S = 0 ؛ // الأولي Variance float Sp = 0 ؛ // التباين السابق const int reps = 500 ؛ // عدد التكرارات int n = 256 ؛ // عدد العينات ledcSetup (0 ، 25000 ، 8) ؛ // ضبط تردد pwm = 25000 هرتز بدقة 8 بت ledcAttachPin (25 ، 0) ؛ // ضبط pwm على دبوس 25 ledcWrite (0 ، 128) ؛ // اضبطه على نصف دورة العمل (أكبر ضوضاء) تأخير (3000) ؛ // انتظر تسوية الوقت تعويم snrPWM [ممثلين] ؛ // مصفوفة من snrs لـ PWM float snrDAC [ممثلين] ؛ // مجموعة snrs لـ DAC لـ (int i = 0؛ i <reps؛ i ++) {// loope over repititions for (int k = 1؛ k <(n + 1)؛ k ++) {// loope over sample adc0 = ads.readADC_SingleEnded (0) ، // احصل على القراءة M = Mp + (adc0 - Mp) / k ؛ // حساب المتداول يعني Mp = M ؛ // تعيين المتوسط السابق S = Sp + (adc0 - Mp) * (adc0 - M) ؛ // حساب التباين المتداول Sp = S ؛ // تعيين التباين السابق} // snr في dB snrPWM = 20 * log10 (3.3 / (sqrt (S / n) *.0625 *.001)) ؛ // إعادة تعيين القيم M = 0 ؛ النائب = 0 ؛ S = 0 ؛ س = 0 ؛ } ledcDetachPin (25) ؛ // فصل PWM من دبوس 25 dacWrite (25 ، 128) ؛ // الكتابة إلى تأخير DAC (3000) ؛ // انتظر لتسوية لـ (int i = 0؛ i <reps؛ i ++) {// نفس حلقة PWM لـ (int k = 1؛ k <(n + 1)؛ k ++) {adc0 = ads.readADC_SingleEnded (0) ؛ M = Mp + (adc0 - Mp) / k ؛ النائب = م ؛ S = Sp + (adc0 - Mp) * (adc0 - M) ؛ س = S ؛ } snrDAC = 20 * log10 (3.3 / (sqrt (S / n) *.0625 *.001)) ؛ م = 0 ؛ النائب = 0 ؛ S = 0 ؛ س = 0 ؛ } // رسم SNRs على رسم بياني واحد لـ (int i = 1؛ i <reps؛ i ++) {Serial.print ("PWM_SNR (dB):")؛ Serial.print (snrPWM ) ، Serial.print ("،") ؛ Serial.print ("ESP32_SNR (ديسيبل):") ؛ Serial.println (snrDAC ) ، }} حلقة باطلة (باطلة) {}

الخطوة 3: اللاخطية التكاملية واللاخطية التفاضلية

اللاخطية التكاملية واللاخطية التفاضلية
اللاخطية التكاملية واللاخطية التفاضلية

يعتبر اللاخطي المتكامل مقياسًا لمقدار الانحراف تقريبًا بين جهد خرج DAC والخط المستقيم. كلما كان هذا أكبر كلما كان أسوأ …

التفاضلية اللاخطية هي مقياس لمدى انحراف التغيير الملحوظ في الجهد (من رمز إلى التالي) عما يمكن توقعه من خط مستقيم.

النتائج هنا كانت حقا مثيرة للاهتمام. بادئ ذي بدء ، كلاهما يحتوي على خطأ أقل من 0.5 رطل (بدقة 8 بت) وهو أمر جيد ولكن PWM لديه خطي متكامل أفضل بكثير. كلاهما لهما تفاضل غير خطي قابل للمقارنة لكن ESP32 DAC به بعض الارتفاعات الغريبة للغاية. علاوة على ذلك ، فإن طريقة PWM لها بعض البنية للأخطاء. بشكل أساسي يتجاوز ويقلل من الجهد الصحيح بطريقة متناوبة.

شكوكي هو أن هذا خطأ تقريب غريب في كيفية إنتاج إشارة PWM 8 بت على ESP32.

تتمثل إحدى طرق تصحيح ذلك في التنقل بسرعة بين رمزين متجاورين (على سبيل المثال 128 ، 129) باستخدام PWM. باستخدام مرشح تمرير منخفض تماثلي ، فإن متوسط الأخطاء الناتجة يصل إلى الصفر. لقد قمت بمحاكاة هذا في البرنامج واختفت بالفعل كل الأخطاء. الآن طريقة PWM خطية بدقة 16 بت!

يوجد أدناه أي شخص رمز إنشاء البيانات. سيكون الإخراج على الشاشة التسلسلية بتنسيق.csv. فقط قم بنسخه إلى ملف نصي لمزيد من المعالجة.

#يشمل

# تضمين إعلانات Adafruit_ADS1115 ؛ / * استخدم هذا مع إصدار 16 بت * / int16_t adc0؛ إعداد باطل (باطل) {Serial.begin (115200) ؛ ads.setGain (GAIN_ONE) ؛ // 2x كسب +/- 2.048V 1 بت = 1mV 0.0625mV ads.begin () ؛ إعداد ledc (0 ، 25000 ، 8) ؛ ledcAttachPin (25 ، 0) ؛ Serial.println ("متوقع ، مرصود") ؛ ledcWrite (0 ، 2) ؛ تأخير (3000) ؛ لـ (int i = 2 ؛ i <255 ؛ i ++) {ledcWrite (0 ، i) ؛ تأخير (100) ؛ adc0 = ads.readADC_SingleEnded (0) ، توقع تعويم = (i / 256.0 * 3.3) / 4.096 * 32767 ؛ Serial.print (متوقع) ؛ Serial.print ("،") ؛ Serial.println (adc0) ؛ }} حلقة باطلة (باطلة) {}

الخطوة 4: عرض النطاق الترددي

عرض النطاق
عرض النطاق

سأقوم بتعريف النطاق الترددي كما هو الحال هنا على أنه التردد الذي ينخفض فيه خرج DAC بمقدار 3 ديسيبل. هذه اتفاقية وتعسفية إلى حد ما. على سبيل المثال ، عند نقطة 6 ديسيبل ، ستستمر DAC في إخراج إشارة ستكون فقط ~ 50 ٪ من السعة.

لقياس هذا ، نقوم ببساطة بتمرير موجات جيبية بتردد متزايد من DAC إلى ADC وقياس انحرافها المعياري. ليس من المستغرب أن تكون نقطة 3dB عند 30 هرتز (1 / (2 * pi * 5000 * 1e-6)).

يمكن لـ ESP32 عمل عينة 1 ميجا في الثانية. هذا فوز عملي لـ ESP32. اتساعها لا يتحلل على الإطلاق في منطقة اختبار عرض النطاق الترددي 100 هرتز.

يمكن للكود أدناه اختبار عرض النطاق الترددي لـ PWM DAC.

#يشمل

# تضمين إعلانات Adafruit_ADS1115 ؛ / * استخدم هذا لإصدار 16 بت * / int16_t adc0؛ int16_t adc1 ؛ إعداد باطل (باطل) {float M؛ تعويم Mp = 0 ؛ تعويم S = 0 ؛ تعويم Sp = 0 ؛ Serial.begin (115200) ؛ ads.setGain (GAIN_ONE) ؛ // 1x كسب +/- 4.096V 1 بت = 2mV 0.125mV ads.begin () ؛ إعداد ledc (0 ، 25000 ، 8) ؛ ledcAttachPin (25 ، 0) ؛ تأخير (5000) ؛ Serial.println ("التردد ، السعة") ؛ لـ (int i = 1 ؛ i <100 ؛ i ++) {بداية طويلة غير موقعة = ميلي () ؛ T طويلة بدون توقيع = مللي () ؛ س = 0 ؛ S = 0 ؛ م = 0 ؛ النائب = 0 ؛ كثافة العمليات ك = 1 ؛ معيار تعويم بينما ((T - start) <1000) {int out = 24 * sin (2 * PI * i * (T - start) / 1000.0) + 128 ؛ ledcWrite (0 ، خارج) ؛ adc0 = ads.readADC_SingleEnded (0) ، M = Mp + (adc0 - Mp) / k ؛ النائب = م ؛ S = Sp + (adc0 - Mp) * (adc0 - M) ؛ س = S ؛ T = مللي () ؛ ك ++ ؛ } إذا (i == 1) {norm = sqrt (S / k) ؛ } Serial.print (i) ؛ Serial.print ("،") ؛ Serial.println (sqrt (S / k) / norm، 3) ؛ ك = 0 ؛ }} حلقة باطلة (باطلة) {}

وسيختبر هذا الرمز عرض النطاق الترددي لـ ESP32. تأكد من إزالة المكثف وإلا ستكون النتائج هي نفسها لكلتا الطريقتين.

#يشمل

# تضمين إعلانات Adafruit_ADS1115 ؛ / * استخدم هذا مع إصدار 16 بت * / int16_t adc0 ؛ int16_t adc1 ؛ إعداد باطل (باطل) {float M؛ تعويم Mp = 0 ؛ تعويم S = 0 ؛ تعويم Sp = 0 ؛ Serial.begin (115200) ؛ ads.setGain (GAIN_ONE) ؛ // 1x كسب +/- 4.096V 1 بت = 2mV 0.125mV ads.begin () ؛ تأخير (5000) ؛ Serial.println ("التردد ، السعة") ؛ لـ (int i = 1 ؛ i <100 ؛ i ++) {بداية طويلة غير موقعة = ميلي () ؛ T طويلة بدون توقيع = مللي () ؛ س = 0 ؛ S = 0 ؛ م = 0 ؛ النائب = 0 ؛ كثافة العمليات ك = 1 ؛ معيار تعويم بينما ((T - start) <1000) {int out = 24 * sin (2 * PI * i * (T - start) / 1000.0) + 128 ؛ dacWrite (25 ، خارج) ؛ adc0 = ads.readADC_SingleEnded (0) ، M = Mp + (adc0 - Mp) / k ؛ النائب = م ؛ S = Sp + (adc0 - Mp) * (adc0 - M) ؛ س = S ؛ T = مللي () ؛ ك ++ ؛ } إذا (i == 1) {norm = sqrt (S / k) ؛ } Serial.print (i) ؛ Serial.print ("،") ؛ Serial.println (sqrt (S / k) / norm، 3) ؛ ك = 0 ؛ }} حلقة باطلة (باطلة) {}

الخطوة 5: ختام الأفكار

يفوز تصميم DAC الجديد في الخطية والضوضاء ولكنه يفقد عرض النطاق الترددي. اعتمادًا على تطبيقك ، قد يكون أحد هذه المؤشرات أكثر أهمية من الآخر. مع إجراءات الاختبار هذه ، يجب أن تكون قادرًا على اتخاذ هذا القرار بموضوعية!

أيضًا ، أعتقد أنه من الجدير الإشارة هنا إلى أنه نظرًا لأن إخراج PWM منخفض الضوضاء ، مع خطية استثنائية ، يجب أن يكون من الممكن إنشاء DAC بدقة أعلى بكثير مع إخراج PWM (ربما بدقة 16 بت). هذا سيأخذ بعض العمل. حتى ذلك الحين ، أطلب منك وداعا!

موصى به: