فهرست مطالب:

نحوه ایجاد و آزمایش 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 دارای 2 مبدل 8 بیتی دیجیتال به آنالوگ (DAC) است. این DAC ها به ما امکان می دهند ولتاژهای دلخواه را در محدوده خاصی (0-3.3V) با 8 بیت وضوح تولید کنیم. در این دستورالعمل ، من به شما نشان می دهم که چگونه یک DAC بسازید و عملکرد آن را مشخص کنید و همچنین آن را با ESP32 DAC مقایسه کنید. شاخص های عملکردی که من بررسی می کنم شامل می شوند

  • سطح نویز
  • پهنای باند
  • غیر خطی یکپارچه
  • غیر خطی بودن افتراقی

برای آزمایش این شاخص ها از ADS1115 استفاده می کنم.

توجه به این نکته ضروری است که ارزیابی شما از همه این شاخص ها فقط به اندازه دستگاه مرجع شما (در این مورد ADS115) دقیق خواهد بود. به عنوان مثال ، ADS115 هنگام تنظیم ولتاژ و افزایش آن از دقت 16 بیتی برخوردار نیست. این خطاها ممکن است به اندازه 0.1 large باشد. برای بسیاری از سیستم ها ، این خطاها را می توان نادیده گرفت که دقت مطلق نگران کننده باشد.

تدارکات

  • ADS1115
  • برد ESP32
  • تخته نان
  • سیم های جهنده
  • مقاومت 5 کیلو اهم
  • 1 خازن سرامیکی میکرو فراد

مرحله 1: چیدن Breadboard

گذاشتن تخته نان
گذاشتن تخته نان

پین های زیر را سیم کشی کنید

بین 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 وصل کنید.

مرحله 2: ارزیابی سیگنال تا سطح نویز

ارزیابی سیگنال تا سطح نویز
ارزیابی سیگنال تا سطح نویز

برای ارزیابی سطح سر و صدا کافی است اسکریپت زیر را اجرا کنید. برای ارزیابی این امر ، ما به سادگی DAC را در یک مقدار ثابت می گذاریم و نحوه نوسان ولتاژ را در طول زمان اندازه گیری می کنیم.

با توجه به طراحی DAC ، نویز زمانی بیشتر می شود که سیگنال PWM در چرخه کار 50 باشد. بنابراین این جایی است که ما آن را ارزیابی می کنیم. ما همچنین ESP32 را در همان سطح سیگنال ارزیابی می کنیم. ما همچنین ESP32 DAC را با همان فیلتر کم گذر فیلتر می کنیم تا اندازه گیری قابل مقایسه باشد.

برای من خروجی روشن بود. طراحی PWM دارای SNR> 6dB بهتر بود (که 2 برابر بهتر است). یک پیروزی واضح برای DAC جدید. یک اشتباه کوچک این است که فیلترهایی در ADC تعبیه شده اند که قطعاً SNR را تقویت می کنند. بنابراین تفسیر مقادیر مطلق ممکن است دشوار باشد. اگر از فیلتر درجه دوم استفاده می کردم ، اینطور نبود.

به هر حال کد زیر است

#عبارتند از

#شامل تبلیغات Adafruit_ADS1115 ؛ // کتابخانه adafruit برای adc int16_t adc0؛ // void setup (void) {Serial.begin (115200)؛ // شروع ads.setGain سریال (GAIN_TWO) ؛ // 2 برابر افزایش +/- 2.048V 1 بیت = 0.0625mV ads.begin ()؛ // شروع adc float M = 0؛ // میانگین اولیه شناور Mp = 0؛ // previouos به معنی شناور S = 0؛ // واریانس اولیه float Sp = 0؛ // واریانس قبلی const int reps = 500؛ // تعداد تکرار int n = 256؛ // تعداد نمونه ledcSetup (0 ، 25000 ، 8) ؛ // تنظیم pwm frequecny = 25000 هرتز با وضوح 8 بیت ledcAttachPin (25 ، 0) ؛ // تنظیم pwm روی پین 25 ledcWrite (0 ، 128) ؛ // آن را روی نیم چرخه (بیشترین سر و صدا) تاخیر (3000) تنظیم کنید ؛ // منتظر زمان حل و فصل شناور snrPWM [تکرار]؛ // آرایه snrs برای PWM float snrDAC [تکرار] ؛ // آرایه snrs برای DAC برای (int i = 0؛ i <reps؛ i ++) {// حلقه تکرارها برای (int k = 1؛ k <(n+1)؛ k ++) {// حلقه نمونه ها 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؛ Mp = 0؛ S = 0 ؛ Sp = 0 ؛ } ledcDetachPin (25) ؛ // جدا کردن PWM از پین 25 dacWrite (25 ، 128) ؛ // ارسال به تاخیر DAC (3000) ؛ // منتظر بمانید تا (int i = 0 ؛ i <تکرار ؛ i ++) {// همانند حلقه PWM برای (int k = 1 ؛ k <(n+1) ؛ k ++) {adc0 = ads.readADC_SingleEnded (0)؛ M = Mp + (adc0 - Mp) / k ؛ Mp = M ؛ S = Sp + (adc0 - Mp) * (adc0 - M) ؛ Sp = S ؛ } snrDAC = 20 * log10 (3.3 / (sqrt (S / n) *.0625 *.001)) ؛ M = 0 ؛ Mp = 0؛ S = 0 ؛ Sp = 0 ؛ } // SNR ها را روی یک نمودار برای (int i = 1؛ i <reps؛ i ++) {Serial.print ("PWM_SNR (dB):")؛ Serial.print (snrPWM ) ؛ Serial.print ("،") ؛ Serial.print ("ESP32_SNR (dB):")؛ Serial.println (snrDAC ) ؛ }} حلقه خالی (خالی) {}

مرحله 3: غیر خطی یکپارچه و غیر خطی افتراقی

غیر خطی یکپارچه و غیر خطی افتراقی
غیر خطی یکپارچه و غیر خطی افتراقی

غیر خطی یکپارچه معیاری برای اندازه گیری میزان انحراف بین ولتاژ خروجی DAC شما و یک خط مستقیم است. هرچه این بزرگتر باشد بدتر است…

غیرخطی بودن دیفرانسیل اندازه گیری تقریباً میزان تغییر مشاهده شده در ولتاژ (از یک کد به کد دیگر) از آنچه از یک خط مستقیم انتظار می رود است.

نتایج اینجا واقعاً جالب بود. اول از همه ، هر دو دارای خطای کمتر از 0.5lsb (با وضوح 8 بیتی) هستند که خوب است ، اما PWM خطی انتگرالی بسیار بهتری دارد. هر دو دارای غیر خطی متفاوت هستند اما ESP32 DAC دارای خوشه های بسیار عجیبی است. علاوه بر این ، روش PWM ساختار خطاها را دارد. اساساً ولتاژ صحیح را به صورت متناوب ، بیش از حد بالا می برد و کم می کند.

گمان من این است که این خطای عجیب و غریب در نحوه تولید سیگنال 8 بیتی PWM در ESP32 است.

یک راه برای تصحیح این امر این است که به سرعت بین دو کد مجاور (مانند 128 ، 129) با PWM چرخه بزنید. با استفاده از فیلتر پایین گذر آنالوگ ، خطاهای حاصله به طور متوسط به صفر می رسد. من این را در نرم افزار شبیه سازی کردم و در واقع همه خطاها ناپدید شدند. در حال حاضر روش PWM خطی دارد که دقیقاً 16 بیت است!

هر کسی که کد تولید داده را در زیر مشاهده کنید. خروجی بر روی مانیتور سریال با فرمت.csv خواهد بود. برای پردازش بیشتر کافی است آن را در یک فایل متنی کپی کنید.

#عبارتند از

#شامل تبلیغات Adafruit_ADS1115 ؛ / * این را برای نسخه 16 بیتی استفاده کنید */ int16_t adc0؛ void setup (void) {Serial.begin (115200)؛ ads.setGain (GAIN_ONE) ؛ // 2 برابر افزایش +/- 2.048V 1 بیت = 1mV 0.0625mV ads.begin ()؛ ledcSetup (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 3dB کاهش می یابد تعریف کنم. این یک قرارداد و تا حدی خودسرانه است. به عنوان مثال ، در نقطه 6dB ، DAC هنوز سیگنالی را خروجی می دهد که دامنه آن فقط 50 ~ خواهد بود.

برای اندازه گیری این امر ، ما به سادگی امواج سینوسی را با فرکانس فزاینده ای از DAC به ADC منتقل کرده و انحراف استاندارد آنها را اندازه گیری می کنیم. جای تعجب نیست که نقطه 3dB در 30Hz (1/(2*pi*5000*1e-6)) است.

ESP32 می تواند 1 مگا نمونه در ثانیه انجام دهد. این یک پیروزی ضعیف برای ESP32 است. دامنه آن در منطقه آزمایشی پهنای باند 100 هرتز به هیچ وجه تحلیل نمی رود.

کد زیر می تواند پهنای باند PWM DAC را آزمایش کند.

#عبارتند از

#شامل تبلیغات Adafruit_ADS1115 ؛ / * این را برای نسخه 16 بیتی استفاده کنید */ int16_t adc0؛ int16_t adc1؛ void setup (void) {float M؛ شناور Mp = 0 ؛ شناور S = 0 ؛ شناور Sp = 0 ؛ Serial.begin (115200) ؛ ads.setGain (GAIN_ONE) ؛ // 1 برابر افزایش +/- 4.096V 1 بیت = 2mV 0.125mV ads.begin ()؛ ledcSetup (0 ، 25000 ، 8) ؛ ledcAttachPin (25 ، 0) ؛ تأخیر (5000) ؛ Serial.println ("فرکانس ، دامنه") ؛ برای (int i = 1؛ i <100؛ i ++) {شروع طولانی بدون علامت = millis ()؛ طولانی بدون علامت T = millis ()؛ Sp = 0 ؛ S = 0 ؛ M = 0 ؛ Mp = 0؛ int k = 1 ؛ هنجار شناور ؛ در حالی که ((T - شروع) <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 ؛ Mp = M ؛ S = Sp + (adc0 - Mp) * (adc0 - M) ؛ Sp = S ؛ T = millis ()؛ k ++ ؛ } if (i == 1) {norm = sqrt (S / k)؛ } Serial.print (i)؛ Serial.print ("،") ؛ Serial.println (sqrt (S / k) / norm، 3)؛ k = 0 ؛ }} حلقه خالی (خالی) {}

و این کد پهنای باند ESP32 را آزمایش می کند. مطمئن شوید که خازن را برداشته اید وگرنه نتایج هر دو روش یکسان خواهد بود.

#عبارتند از

#شامل تبلیغات Adafruit_ADS1115 ؛ / * این را برای نسخه 16 بیتی استفاده کنید */ int16_t adc0؛ int16_t adc1؛ void setup (void) {float M؛ شناور Mp = 0 ؛ شناور S = 0 ؛ شناور Sp = 0 ؛ Serial.begin (115200) ؛ ads.setGain (GAIN_ONE) ؛ // 1 برابر افزایش +/- 4.096V 1 بیت = 2mV 0.125mV ads.begin ()؛ تأخیر (5000) ؛ Serial.println ("فرکانس ، دامنه") ؛ برای (int i = 1؛ i <100؛ i ++) {شروع طولانی بدون علامت = millis ()؛ طولانی بدون علامت T = millis ()؛ Sp = 0 ؛ S = 0 ؛ M = 0 ؛ Mp = 0؛ int k = 1 ؛ هنجار شناور ؛ در حالی که ((T - شروع) <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 ؛ Mp = M ؛ S = Sp + (adc0 - Mp) * (adc0 - M) ؛ Sp = S ؛ T = millis ()؛ k ++ ؛ } if (i == 1) {norm = sqrt (S / k)؛ } Serial.print (i)؛ Serial.print ("،") ؛ Serial.println (sqrt (S / k) / norm، 3)؛ k = 0 ؛ }} حلقه خالی (خالی) {}

مرحله پنجم: بستن افکار

طراحی جدید DAC بر اساس خطی بودن و نویز برنده می شود اما در پهنای باند از دست می دهد. بسته به کاربرد شما ، یکی از این شاخص ها ممکن است از دیگری مهمتر باشد. با این روش های آزمایش ، باید بتوانید آن تصمیم را به طور عینی بگیرید!

همچنین ، من فکر می کنم در اینجا شایان ذکر است که چون خروجی PWM نویز کمی دارد ، با خطی استثنایی باید بتوان DAC با وضوح بسیار بالاتر را با خروجی PWM (شاید حتی دقت 16 بیت) ساخت. این کار کمی طول می کشد تا آن زمان ، به شما سلام می گویم!

توصیه شده: