Cuprins:

Cum să faci și să testezi un DAC mai bun cu ESP32: 5 pași
Cum să faci și să testezi un DAC mai bun cu ESP32: 5 pași

Video: Cum să faci și să testezi un DAC mai bun cu ESP32: 5 pași

Video: Cum să faci și să testezi un DAC mai bun cu ESP32: 5 pași
Video: Voltmetru cu ESP32 2024, Noiembrie
Anonim
Cum se realizează și se testează un DAC mai bun cu ESP32
Cum se realizează și se testează un DAC mai bun cu ESP32
Cum se realizează și se testează un DAC mai bun cu ESP32
Cum se realizează și se testează un DAC mai bun cu ESP32

ESP32 are 2 convertoare digitale-analogice pe 8 biți (DAC). Aceste DAC-uri ne permit să producem tensiuni arbitrare într-un anumit interval (0-3,3V) cu 8 biți de rezoluție. În acest Instructable, vă voi arăta cum să construiți un DAC și să-i caracterizez performanța, precum și să-l compar cu ESP32 DAC. Indicii de performanță pe care îi voi analiza includ

  • Nivel de zgomot
  • Lățime de bandă
  • Neliniaritatea integrală
  • Neliniaritatea diferențială

Pentru a testa acești indici, voi folosi ADS1115.

Este important să rețineți că evaluarea tuturor acestor indici va fi la fel de exactă ca dispozitivul dvs. de referință (în acest caz ADS115). De exemplu, ADS115 nu are precizie pe 16 biți când vine vorba de decalajul și câștigul său de tensiune. Aceste erori pot ajunge la 0,1%. Pentru multe sisteme, aceste erori pot fi ignorate atunci când precizia absolută este de îngrijorare limitată.

Provizii

  • ADS1115
  • Placa ESP32
  • panou de masă
  • fire jumper
  • Rezistor de 5 kOhm
  • 1 condensator ceramic micro-Farad

Pasul 1: așezarea panoului de calcul

Așezarea tablei
Așezarea tablei

Sârmați următorii pini

Între ESP32 și ADS1115

3v3 VDD

GND GND

GPIO22 SCL

GPIO21 SDA

La ADS1115

ADDR GND (ADS115)

Realizarea DAC

Există multe modalități de a crea un DAC. Cea mai simplă este să filtrați low-pass un semnal PWM cu un rezistor și un condensator. Aș fi putut adăuga un op-amp aici ca tampon, dar am vrut să păstrez lucrurile simple. Acest design este simplu și ieftin de implementat cu orice microcontroler care acceptă PWM. Nu voi trece prin teoria proiectării aici (google PWM DAC).

Doar conectați rezistorul GPIO255 KOhm 1 condensator microFarad gnd

Acum conectați un cablu jumper din punctul în care rezistența întâlnește condensatorul la A0 pe ADS115.

Pasul 2: evaluați nivelul semnalului la zgomot

Evaluează nivelul semnalului la zgomot
Evaluează nivelul semnalului la zgomot

Pentru a evalua nivelul de zgomot pur și simplu rulați scriptul de mai jos. Pentru a evalua acest lucru, lăsăm pur și simplu DAC la o valoare fixă și măsurăm modul în care tensiunea oscilează în timp.

Datorită designului DAC, zgomotul va fi cel mai mare atunci când semnalul PWM este la 50% ciclu de funcționare. Prin urmare, aici o vom evalua. De asemenea, vom evalua ESP32 la același nivel de semnal. De asemenea, vom filtra ESP32 DAC cu același filtru trece jos, astfel încât să facem măsurarea comparabilă.

Pentru mine rezultatul a fost clar. Designul PWM avea un SNR> 6dB mai bun (de 2 ori mai bun). O victorie clară pentru noul DAC. O ușoară confuzie este că există filtre încorporate în ADC care îmbunătățesc cu siguranță SNR. Deci, valorile absolute pot fi dificil de interpretat. Dacă aș fi folosit un filtru de ordinul doi, nu ar fi cazul.

Oricum codul este mai jos

#include

#include anunțuri Adafruit_ADS1115; // biblioteca adafruit pentru adc int16_t adc0; // void setup (void) {Serial.begin (115200); // Porniți serial ads.setGain (GAIN_TWO); // 2x câștig +/- 2.048V 1 bit = 0.0625mV ads.begin (); // începe adc float M = 0; // float mediu inițial Mp = 0; // previouos înseamnă plutitor S = 0; // floare de variație inițială Sp = 0; // const anterioară varianță rep rep = 500; // numărul de repetiții int n = 256; // numărul de mostre ledcSetup (0, 25000, 8); // setează frecvența pwm = 25000 Hz la 8 biți rezoluție ledcAttachPin (25, 0); // setează pwm pe pinul 25 ledcWrite (0, 128); // setați-l la jumătate din ciclul de funcționare (cel mai mare zgomot) întârziere (3000); // așteptați timpul de decontare float snrPWM [reps]; // matrice de snrs pentru PWM float snrDAC [repetări]; // matrice de snrs pentru DAC pentru (int i = 0; i <reps; i ++) {// bucla peste repetiții pentru (int k = 1; k <(n + 1); k ++) {// bucla peste mostre adc0 = ads.readADC_SingleEnded (0); // obțineți citirea M = Mp + (adc0 - Mp) / k; // calculează media rulantă Mp = M; // setați media anterioară S = Sp + (adc0 - Mp) * (adc0 - M); // calculați varianța de rulare Sp = S; // setați varianța anterioară} // snr în dB snrPWM = 20 * log10 (3.3 / (sqrt (S / n) *.0625 *.001)); // resetează valorile M = 0; Mp = 0; S = 0; Sp = 0; } ledcDetachPin (25); // detașează PWM de pinul 25 dacWrite (25, 128); // scrie la întârziere DAC (3000); // așteptați să vă mulțumiți cu (int i = 0; i <reps; i ++) {// la fel ca bucla PWM pentru (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; } // trasați SNR-uri pe un grafic pentru (int i = 1; i <reps; i ++) {Serial.print ("PWM_SNR (dB):"); Serial.print (snrPWM ); Serial.print (","); Serial.print ("ESP32_SNR (dB):"); Serial.println (snrDAC ); }} bucla void (nul) {}

Pasul 3: neliniaritatea integrală și neliniaritatea diferențială

Neliniaritatea integrală și neliniaritatea diferențială
Neliniaritatea integrală și neliniaritatea diferențială

Neliniaritatea integrală este o măsură a cât de multă deviație există între tensiunea de ieșire DAC și o linie dreaptă. Cu cât este mai mare, cu atât este mai rău …

Neliniaritatea diferențială este o măsură a cât de mult deviază modificarea observată a tensiunii (de la un cod la altul) de la ceea ce s-ar aștepta de la o linie dreaptă.

Rezultatele aici au fost cu adevărat interesante. În primul rând, ambele au o eroare mai mică de 0,5 lb (la o rezoluție de 8 biți), ceea ce este bun, dar PWM are o linearitate integrală mult mai bună. Ambele au neliniaritate diferențială comparabilă, dar ESP32 DAC are niște vârfuri foarte ciudate. Mai mult, metoda PWM are o anumită structură a erorilor. În esență, depășește și depășește tensiunea corectă într-un mod alternativ.

Suspectul meu este că aceasta este o eroare de rotunjire ciudată în modul în care un semnal PWM pe 8 biți este produs pe ESP32.

O modalitate de a corecta acest lucru este de a parcurge rapid între două coduri adiacente (de exemplu 128, 129) cu PWM. Cu un filtru analog low-pass, erorile rezultate vor fi la zero. Am simulat acest lucru în software și într-adevăr toate erorile au dispărut. Acum metoda PWM are o linearitate care este precisă la 16 biți!

Oricine codul care generează datele este mai jos. Ieșirea va fi pe monitorul serial în format.csv. Doar copiați-l într-un fișier text pentru procesare ulterioară.

#include

#include anunțuri Adafruit_ADS1115; / * Utilizați acest lucru pentru versiunea pe 16 biți * / int16_t adc0; configurare nulă (nulă) {Serial.begin (115200); ads.setGain (GAIN_ONE); // 2x câștig +/- 2.048V 1 bit = 1mV 0.0625mV ads.begin (); ledcSetup (0, 25000, 8); ledcAttachPin (25, 0); Serial.println („Așteptat, observat”); ledcWrite (0, 2); întârziere (3000); for (int i = 2; i <255; i ++) {ledcWrite (0, i); întârziere (100); adc0 = ads.readADC_SingleEnded (0); float expected = (i / 256.0 * 3.3) / 4.096 * 32767; Serial.print (așteptat); Serial.print (","); Serial.println (adc0); }} bucla void (nul) {}

Pasul 4: Lățime de bandă

Lățime de bandă
Lățime de bandă

Voi defini lățimea de bandă aici ca frecvența la care ieșirea DAC scade cu 3dB. Aceasta este o convenție și, într-o anumită măsură, arbitrară. De exemplu, la punctul 6dB, DAC va emite în continuare un semnal, acesta va fi doar ~ 50% amplitudine.

Pentru a măsura acest lucru, trecem pur și simplu unde sinusoidale la o frecvență crescândă de la DAC la ADC și măsurăm abaterea lor standard. În mod surprinzător, punctul 3dB este la 30Hz (1 / (2 * pi * 5000 * 1e-6)).

ESP32 poate face 1 Mega probă pe secundă. Aceasta este o victorie simplă pentru ESP32. Amplitudinea sa nu se descompune deloc în regiunea de testare a lățimii de bandă de 100Hz.

Codul de mai jos poate testa lățimea de bandă PWM DAC.

#include

#include anunțuri Adafruit_ADS1115; / * Utilizați acest lucru pentru versiunea pe 16 biți * / int16_t adc0; int16_t adc1; void setup (void) {float M; plutitor Mp = 0; plutitor S = 0; plutitor Sp = 0; Serial.begin (115200); ads.setGain (GAIN_ONE); // 1x câștig +/- 4.096V 1 bit = 2mV 0.125mV ads.begin (); ledcSetup (0, 25000, 8); ledcAttachPin (25, 0); întârziere (5000); Serial.println ("Frecvență, amplitudine"); for (int i = 1; i <100; i ++) {unsigned long start = millis (); nesemnat lung T = milis (); Sp = 0; S = 0; M = 0; Mp = 0; int k = 1; norma float; while ((T - start) <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 = milis (); k ++; } if (i == 1) {norm = sqrt (S / k); } Serial.print (i); Serial.print (","); Serial.println (sqrt (S / k) / norm, 3); k = 0; }} bucla void (nul) {}

Și acest cod va testa lățimea de bandă ESP32. Asigurați-vă că îndepărtați condensatorul sau rezultatele vor fi aceleași pentru ambele metode.

#include

#include anunțuri Adafruit_ADS1115; / * Utilizați acest lucru pentru versiunea pe 16 biți * / int16_t adc0; int16_t adc1; void setup (void) {float M; plutitor Mp = 0; plutitor S = 0; plutitor Sp = 0; Serial.begin (115200); ads.setGain (GAIN_ONE); // 1x câștig +/- 4.096V 1 bit = 2mV 0.125mV ads.begin (); întârziere (5000); Serial.println ("Frecvență, amplitudine"); for (int i = 1; i <100; i ++) {unsigned long start = millis (); nesemnat lung T = milis (); Sp = 0; S = 0; M = 0; Mp = 0; int k = 1; norma float; while ((T - start) <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 = milis (); k ++; } if (i == 1) {norm = sqrt (S / k); } Serial.print (i); Serial.print (","); Serial.println (sqrt (S / k) / norm, 3); k = 0; }} bucla void (nul) {}

Pasul 5: închiderea gândurilor

Noul design DAC câștigă pe liniaritate și zgomot, dar pierde pe lățimea de bandă. În funcție de aplicația dvs., unul dintre acești indici poate fi mai important decât celălalt. Cu aceste proceduri de testare, ar trebui să puteți lua în mod obiectiv această decizie!

De asemenea, cred că merită să subliniez aici că, deoarece ieșirea PWM are un zgomot redus, cu o liniaritate excepțională, ar trebui să fie posibil să se construiască un DAC cu rezoluție mult mai mare cu ieșirea PWM (poate chiar o precizie pe 16 biți). Asta o să meargă puțin. Până atunci, ți-l adjud!

Recomandat: