Talaan ng mga Nilalaman:

Paano Gumawa at Sumubok ng isang Mas Mahusay na DAC Sa ESP32: 5 Mga Hakbang
Paano Gumawa at Sumubok ng isang Mas Mahusay na DAC Sa ESP32: 5 Mga Hakbang
Anonim
Paano Gumawa at Sumubok ng isang Mas Mahusay na DAC Sa ESP32
Paano Gumawa at Sumubok ng isang Mas Mahusay na DAC Sa ESP32
Paano Gumawa at Sumubok ng isang Mas Mahusay na DAC Sa ESP32
Paano Gumawa at Sumubok ng isang Mas Mahusay na DAC Sa ESP32

Ang ESP32 ay mayroong 2 8-bit Digital sa Mga Analogue Converter (DAC). Pinapayagan kami ng mga DAC na ito na gumawa ng di-makatwirang mga voltages sa loob ng isang tiyak na saklaw (0-3.3V) na may 8 piraso ng resolusyon. Sa Instructable na ito, ipapakita ko sa iyo kung paano bumuo ng isang DAC at makilala ang pagganap nito pati na rin ihambing ito sa ESP32 DAC. Ang mga indeks ng pagganap na titingnan ko ay kasama

  • Antas ng Ingay
  • Bandwidth
  • Integral nonlinearity
  • Pagkakaiba-iba ng hindi linyaridad

Upang subukan ang mga indeks na ito gagamitin ko ang ADS1115.

Mahalagang tandaan na ang iyong pagtatasa sa lahat ng mga indeks na ito ay magiging tumpak lamang bilang iyong sanggunian na aparato (sa kasong ito ang ADS115). Halimbawa, ang ADS115 ay walang 16-bit na katumpakan pagdating sa boltahe na offset at makakuha. Ang mga error na ito ay maaaring kasing laki ng 0.1%. Para sa maraming mga system, ang mga error na ito ay maaaring balewalain kapag ang ganap na kawastuhan ay may limitadong pag-aalala.

Mga gamit

  • ADS1115
  • Lupon ng ESP32
  • breadboard
  • jumper wires
  • 5 kOhm Resistor
  • 1 micro-Farad ceramic capacitor

Hakbang 1: Paglalagay ng Breadboard

Paglalagay ng Breadboard
Paglalagay ng Breadboard

Wire ang mga sumusunod na pin

Sa pagitan ng ESP32 at ng ADS1115

3v3 VDD

GND GND

GPIO22 SCL

GPIO21 SDA

Sa ADS1115

ADDR GND (ADS115)

Paggawa ng DAC

Maraming paraan upang makagawa ng isang DAC. Ang pinakasimpleng ay ang low-pass filter ng isang PWM signal na may resistor at isang capacitor. Maaari akong magdagdag ng isang op-amp dito bilang isang buffer ngunit nais kong panatilihing simple ang mga bagay. Ang disenyo na ito ay simple at murang ipatupad sa anumang microcontroller na sumusuporta sa PWM. Hindi ako dumaan sa teorya ng disenyo dito (google PWM DAC).

Ikonekta lamang ang GPIO255 KOhm risistor 1 microFarad Capacitor gnd

Ngayon ikonekta ang isang jumper wire mula sa punto kung saan ang risistor ay nakakatugon sa kapasitor sa A0 sa ADS115.

Hakbang 2: Suriin ang Antas ng Signal sa Antas ng Ingay

Suriin ang Antas ng Signal sa Antas ng Ingay
Suriin ang Antas ng Signal sa Antas ng Ingay

Upang masuri ang antas ng ingay patakbuhin lamang ang script sa ibaba. Upang masuri ito ay iiwan lamang namin ang DAC sa isang nakapirming halaga at sukatin kung paano ang boltahe ay nag-oscillate sa paglipas ng panahon.

Dahil sa disenyo ng DAC, ang ingay ay magiging pinakamalaki kapag ang signal ng PWM ay nasa 50% na cycle ng tungkulin. Samakatuwid dito natin susuriin ito. Susuriin din namin ang ESP32 sa parehong antas ng signal. Susuriin din namin ang ESP32 DAC na may parehong mababang pass pass filter upang maihambing ang pagsukat.

Para sa akin malinaw ang output. Ang disenyo ng PWM ay nagkaroon ng> 6dB mas mahusay na SNR (mas mabuti iyon ng 2 beses). Isang malinaw na panalo para sa bagong DAC. Ang isang bahagyang nakalito ay ang mga filter na naka-built sa ADC na tiyak na nagpapahusay sa SNR. Kaya't ang mga ganap na halaga ay maaaring mahirap bigyang kahulugan. Kung gumamit ako ng isang pangalawang-order na filter hindi ito ang kaso.

Gayunpaman ang code ay nasa ibaba

# isama

# isama ang Adafruit_ADS1115 mga ad; // adafruit library para sa adc int16_t adc0; // void setup (void) {Serial.begin (115200); // Start serial ads.setGain (GAIN_TWO); // 2x gain +/- 2.048V 1 bit = 0.0625mV ads.begin (); // start adc float M = 0; // initial mean float Mp = 0; // previouos mean float S = 0; // initial Variance float Sp = 0; // dating variance const int reps = 500; // number of repitions int n = 256; // bilang ng mga sample ledcSetup (0, 25000, 8); // set pwm frequecny = 25000 Hz sa 8 bit resolusyon ledcAttachPin (25, 0); // set pwm sa pin 25 ledcWrite (0, 128); // itakda ito sa kalahating duty cycle (pinakamalaking ingay) pagkaantala (3000); // maghintay para sa pag-aayos ng oras float snrPWM [reps]; // array of snrs for PWM float snrDAC [reps]; // array of snrs for DAC for (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); // get reading M = Mp + (adc0 - Mp) / k; // compute rolling mean Mp = M; // itakda ang dating ibig sabihin S = Sp + (adc0 - Mp) * (adc0 - M); // compute rolling variance Sp = S; // itakda ang dating pagkakaiba-iba} // snr in dB snrPWM = 20 * log10 (3.3 / (sqrt (S / n) *.0625 *.001)); // reset halaga M = 0; Mp = 0; S = 0; Sp = 0; } ledcDetachPin (25); // detach PWM mula sa pin 25 dacWrite (25, 128); // sumulat sa pagkaantala ng DAC (3000); // wait to settle for (int i = 0; i <reps; i ++) {// same as PWM loop for (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; } // plot SNRs sa isang grap para sa (int i = 1; i <reps; i ++) {Serial.print ("PWM_SNR (dB):"); Serial.print (snrPWM ); Serial.print (","); Serial.print ("ESP32_SNR (dB):"); Serial.println (snrDAC ); }} void loop (void) {}

Hakbang 3: Integral na Hindi Linya at Pagkakaiba ng Hindi Pagkakaiba

Integral Nonlinearity at Pagkakaibang Hindi Linearity
Integral Nonlinearity at Pagkakaibang Hindi Linearity

Ang integral nonlinearity ay isang sukat ng halos kung magkano ang paglihis sa pagitan ng iyong DAC output boltahe at isang tuwid na linya. Ang mas malaki ito ay ang mas masahol na ito ay …

Ang kaugalian na hindi paggalaw ay isang sukatan ng halos kung magkano ang naobserbahang pagbabago sa boltahe (mula sa isang code hanggang sa susunod) lumihis mula sa inaasahan mula sa isang tuwid na linya.

Ang mga resulta dito ay talagang nakawiwili. Una sa lahat, kapwa may mas mababa sa 0.5lsb error (sa resolusyon na 8-bit) na mabuti ngunit ang PWM ay may mas mahusay na integral linearity. Parehong may maihahambing na di-pagkakasunod na pagkakaiba ngunit ang ESP32 DAC ay may ilang mga kakaibang mga spike. Ano ang higit pa, ang pamamaraan ng PWM ay may ilang istraktura sa mga error. Mahalagang i-overshoot at i-undershoot nito ang tamang boltahe sa isang alternating fashion.

Ang aking hinala ay ito ay isang kakaibang error sa pag-ikot sa kung paano ang isang 8-bit PWM signal ay ginawa sa ESP32.

Ang isang paraan upang maitama ito ay mabilis na ikot sa pagitan ng dalawang katabing mga code (hal. 128, 129) sa PWM. Sa pamamagitan ng isang analogue lowpass filter, ang mga nagresultang mga error ay average sa zero. Ginawa ko ito sa software at sa katunayan lahat ng mga error ay nawala. Ngayon ang pamamaraan ng PWM ay may linearity na tumpak sa 16-bit!

Anumang ang code upang makabuo ng data ay nasa ibaba. Ang output ay nasa serial monitor sa format na.csv. Kopyahin lamang ito sa isang text file para sa karagdagang pagproseso.

# isama

# isama ang Adafruit_ADS1115 mga ad; / * Gamitin ito para sa 16-bit na bersyon * / int16_t adc0; void setup (void) {Serial.begin (115200); ads.setGain (GAIN_ONE); // 2x gain +/- 2.048V 1 bit = 1mV 0.0625mV ads.begin (); ledcSetup (0, 25000, 8); ledcAttachPin (25, 0); Serial.println ("Inaasahan, Naobserbahan"); ledcWrite (0, 2); pagkaantala (3000); para sa (int i = 2; i <255; i ++) {ledcWrite (0, i); pagkaantala (100); adc0 = ads.readADC_SingleEnded (0); inaasahan na float = (i / 256.0 * 3.3) / 4.096 * 32767; Serial.print (inaasahan); Serial.print (","); Serial.println (adc0); }} void loop (void) {}

Hakbang 4: Bandwidth

Bandwidth
Bandwidth

Tutukuyin ko ang bandwidth dito bilang dalas kung saan ang output ng DAC ay bumaba ng 3dB. Ito ay isang kombensiyon at, sa isang degree, arbitrary. Halimbawa, sa 6dB point, ang DAC ay maglalabas pa rin ng isang senyas magiging ~ 50% amplitude lang ito.

Upang sukatin ito, ipinapasa lamang namin ang mga sine alon sa isang pagtaas ng dalas mula sa DAC patungong ADC at sukatin ang kanilang karaniwang paglihis. Hindi nakakagulat, ang 3dB point ay nasa 30Hz (1 / (2 * pi * 5000 * 1e-6)).

Ang ESP32 ay maaaring gumawa ng 1 Mega sample bawat segundo. Ito ay isang hands-down na panalo para sa ESP32. Ang amplitude nito ay hindi nabubulok sa lahat sa rehiyon ng pagsubok na 100Hz.

Maaaring subukan ng code sa ibaba ang bandwidth ng PWM DAC.

# isama

# isama ang Adafruit_ADS1115 mga ad; / * Gamitin ito para sa 16-bit na bersyon * / int16_t adc0; int16_t adc1; walang bisa ang pag-setup (walang bisa) {float M; float Mp = 0; float S = 0; float Sp = 0; Serial.begin (115200); ads.setGain (GAIN_ONE); // 1x gain +/- 4.096V 1 bit = 2mV 0.125mV ads.begin (); ledcSetup (0, 25000, 8); ledcAttachPin (25, 0); pagkaantala (5000); Serial.println ("Dalas, Amplitude"); para sa (int i = 1; i <100; i ++) {unsigned long start = millis (); unsigned mahabang T = millis (); Sp = 0; S = 0; M = 0; Mp = 0; int k = 1; float norm; habang ((T - simula) <1000) {int out = 24 * sin (2 * PI * i * (T - start) / 1000.0) + 128; ledcWrite (0, out); adc0 = ads.readADC_SingleEnded (0); M = Mp + (adc0 - Mp) / k; Mp = M; S = Sp + (adc0 - Mp) * (adc0 - M); Sp = S; T = millis (); k ++; } kung (i == 1) {norm = sqrt (S / k); } Serial.print (i); Serial.print (","); Serial.println (sqrt (S / k) / norm, 3); k = 0; }} void loop (void) {}

At susubukan ng code na ito ang bandwidth ng ESP32. Tiyaking aalisin ang capacitor o ang mga resulta ay pareho para sa parehong pamamaraan.

# isama

# isama ang Adafruit_ADS1115 mga ad; / * Gamitin ito para sa 16-bit na bersyon * / int16_t adc0; int16_t adc1; walang bisa ang pag-setup (walang bisa) {float M; float Mp = 0; float S = 0; float Sp = 0; Serial.begin (115200); ads.setGain (GAIN_ONE); // 1x gain +/- 4.096V 1 bit = 2mV 0.125mV ads.begin (); pagkaantala (5000); Serial.println ("Dalas, Amplitude"); para sa (int i = 1; i <100; i ++) {unsigned long start = millis (); unsigned mahabang T = millis (); Sp = 0; S = 0; M = 0; Mp = 0; int k = 1; float norm; habang ((T - simula) <1000) {int out = 24 * sin (2 * PI * i * (T - start) / 1000.0) + 128; dacWrite (25, out); adc0 = ads.readADC_SingleEnded (0); M = Mp + (adc0 - Mp) / k; Mp = M; S = Sp + (adc0 - Mp) * (adc0 - M); Sp = S; T = millis (); k ++; } kung (i == 1) {norm = sqrt (S / k); } Serial.print (i); Serial.print (","); Serial.println (sqrt (S / k) / norm, 3); k = 0; }} void loop (void) {}

Hakbang 5: Mga Saloobin sa Pagsara

Ang bagong disenyo ng DAC ay nanalo sa linearity at ingay ngunit natalo sa bandwidth. Nakasalalay sa iyong aplikasyon ang isa sa mga indeks na ito ay maaaring mas mahalaga kaysa sa iba. Sa mga pamamaraang pagsubok na ito, dapat mong ma-objective na magpasya!

Gayundin, sa palagay ko sulit na ituro dito na dahil ang output ng PWM ay mababa ang ingay, na may pambihirang linearity dapat posible na bumuo ng isang mas mataas na resolusyon na DAC sa output ng PWM (marahil kahit na 16-bit na katumpakan). Magagawa na ang trabaho. Hanggang sa ngayon, ina-bid ko sa iyo ang adieu!

Inirerekumendang: