Indholdsfortegnelse:

Sådan laver og tester du en bedre DAC med ESP32: 5 trin
Sådan laver og tester du en bedre DAC med ESP32: 5 trin

Video: Sådan laver og tester du en bedre DAC med ESP32: 5 trin

Video: Sådan laver og tester du en bedre DAC med ESP32: 5 trin
Video: Output DC or AC Voltage using MCP4725 DAC with LCD and PWM to Voltage Converter with Arduino 2024, November
Anonim
Sådan laver og tester du en bedre DAC med ESP32
Sådan laver og tester du en bedre DAC med ESP32
Sådan laver og tester du en bedre DAC med ESP32
Sådan laver og tester du en bedre DAC med ESP32

ESP32 har 2 8-bit digitale til analoge omformere (DAC'er). Disse DAC'er giver os mulighed for at producere vilkårlige spændinger inden for et bestemt område (0-3.3V) med 8 bits opløsning. I denne Instructable vil jeg vise dig, hvordan du bygger en DAC og karakteriserer dens ydeevne samt sammenligner den med ESP32 DAC. De præstationsindekser, jeg vil se på, inkluderer

  • Støjniveau
  • Båndbredde
  • Integreret ikke -linearitet
  • Differentiel ikke -linearitet

For at teste disse indeks vil jeg bruge ADS1115.

Det er vigtigt at bemærke, at din vurdering af alle disse indekser kun vil være lige så præcis som din referenceenhed (i dette tilfælde ADS115). For eksempel har ADS115 ikke 16-bit præcision, når det kommer til spændingsforskydning og forstærkning. Disse fejl kan være så store som 0,1%. For mange systemer kan disse fejl ignoreres, når absolut nøjagtighed er begrænset bekymret.

Forbrugsvarer

  • ADS1115
  • ESP32 Board
  • brødbræt
  • jumper ledninger
  • 5 kOhm modstand
  • 1 mikro-Farad keramisk kondensator

Trin 1: Udlægning af brødbrættet

Udlægning af brødbrættet
Udlægning af brødbrættet

Tilslut følgende stifter

Mellem ESP32 og ADS1115

3v3 VDD

GND GND

GPIO22 SCL

GPIO21 SDA

På ADS1115

ADDR GND (ADS115)

Fremstilling af DAC

Der er mange måder at lave en DAC på. Det enkleste er at lavpasfiltrere et PWM-signal med en modstand og en kondensator. Jeg kunne have tilføjet en op-amp her som en buffer, men ville gerne holde tingene enkle. Dette design er enkelt og billigt at implementere med enhver mikrokontroller, der understøtter PWM. Jeg vil ikke gå igennem teorien om designet her (google PWM DAC).

Tilslut bare GPIO255 KOhm modstand 1 microFarad kondensator gnd

Tilslut nu en jumperledning fra det punkt, hvor modstanden møder kondensatoren til A0 på ADS115.

Trin 2: Vurder signal til støjniveau

Vurder signal til støjniveau
Vurder signal til støjniveau

For at vurdere støjniveauet skal du blot køre scriptet herunder. For at vurdere dette forlader vi simpelthen DAC'en med en fast værdi og måler, hvordan spændingen svinger over tid.

På grund af DAC's design vil støjen være størst, når PWM -signalet er på 50% driftscyklus. Derfor er det her, vi vil vurdere det. Vi vil også vurdere ESP32 på samme signalniveau. Vi filtrerer også ESP32 DAC med det samme lavpasfilter for at gøre målingen sammenlignelig.

For mig var output klart. PWM -designet havde> 6dB bedre SNR (det er 2 gange bedre). En klar sejr til nyt DAC. En lille forvirring er, at der er filtre indbygget i ADC'en, der absolut forbedrer SNR. Så de absolutte værdier kan være svære at fortolke. Hvis jeg havde brugt et andetordens filter, ville dette ikke være tilfældet.

Anyway -koden er herunder

#omfatte

#inkludere Adafruit_ADS1115 annoncer; // adafruit bibliotek til adc int16_t adc0; // void setup (void) {Serial.begin (115200); // Start seriel ads.setGain (GAIN_TWO); // 2x gain +/- 2.048V 1 bit = 0.0625mV ads.begin (); // begynde adc float M = 0; // initial middelværdi float Mp = 0; // previouos betyder float S = 0; // initial Variance float Sp = 0; // tidligere varians const int reps = 500; // antal gentagelser int n = 256; // antal prøver ledcSetup (0, 25000, 8); // sæt pwm frequecny = 25000 Hz ved 8 bit opløsning ledcAttachPin (25, 0); // sæt pwm på pin 25 ledcWrite (0, 128); // indstil den til en forsinkelse på halv driftscyklus (største støj) (3000); // vent på afregningstid float snrPWM [reps]; // array af snrs til PWM float snrDAC [reps]; // array af snrs for DAC for (int i = 0; i <reps; i ++) {// loope over repititions for (int k = 1; k <(n+1); k ++) {// loope over prøver adc0 = ads.readADC_SingleEnded (0); // læs M = Mp + (adc0 - Mp) / k; // beregne rullende middelværdi Mp = M; // sæt tidligere middelværdi S = Sp + (adc0 - Mp) * (adc0 - M); // beregne rullende varians Sp = S; // indstil tidligere varians} // snr i dB snrPWM = 20 * log10 (3.3 / (sqrt (S / n) *.0625 *.001)); // nulstil værdier M = 0; Smp. = 0; S = 0; Sp = 0; } ledcDetachPin (25); // løsne PWM fra pin 25 dacWrite (25, 128); // skriv til DAC forsinkelse (3000); // vent med at nøjes med (int i = 0; i <reps; i ++) {// samme som PWM -loop for (int k = 1; k <(n+1); k ++) {adc0 = ads.readADC_SingleEnded (0); M = Mp + (adc0 - Mp) / k; Smp. = M; S = Sp + (adc0 - Mp) * (adc0 - M); Sp = S; } snrDAC = 20 * log10 (3.3 / (sqrt (S / n) *.0625 *.001)); M = 0; Smp. = 0; S = 0; Sp = 0; } // plot SNR'er på en graf for (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) {}

Trin 3: Integreret ikke -linearitet og differentiel ikke -linearitet

Integreret ikke -linearitet og differentiel ikke -linearitet
Integreret ikke -linearitet og differentiel ikke -linearitet

Den integrerede ikke -linearitet er et mål for omtrent hvor stor afvigelse der er mellem din DAC udgangsspænding og en lige linje. Jo større dette er, jo værre er det …

Den differentielle ulinearitet er et mål for omtrent hvor meget den observerede ændring i spændingen (fra en kode til den næste) afviger fra, hvad man kunne forvente af en lige linje.

Resultaterne her var virkelig interessante. Først og fremmest har begge mindre end 0,5lsb fejl (ved 8-bit opløsning), hvilket er godt, men PWM har meget bedre integreret linearitet. Begge har sammenlignelig differentiel ulinearitet, men ESP32 DAC har nogle meget underlige pigge. Desuden har PWM -metoden en vis struktur til fejlene. I det væsentlige overskyder og undersøger den den korrekte spænding på skiftende vis.

Min mistanke er, at dette er en underlig afrundingsfejl i, hvordan et 8-bit PWM-signal produceres på ESP32.

En måde at korrigere for dette på er hurtigt at skifte mellem to tilstødende koder (f.eks. 128, 129) med PWM. Med et analogt lavpasfilter vil de resulterende fejl i gennemsnit være nul. Jeg simulerede dette i software, og alle fejlene forsvandt faktisk. Nu har PWM-metoden linearitet, der er nøjagtig til 16-bit!

Hvem som helst koden til generering af dataene er nedenfor. Outputtet vil være på den serielle skærm i.csv -format. Bare kopier den til en tekstfil til videre behandling.

#omfatte

#inkludere Adafruit_ADS1115 annoncer; / * Brug dette til 16-bit versionen */ 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 ("Forventet, observeret"); ledcWrite (0, 2); forsinkelse (3000); for (int i = 2; i <255; i ++) {ledcWrite (0, i); forsinkelse (100); adc0 = ads.readADC_SingleEnded (0); float forventet = (i / 256,0 * 3,3) / 4,096 * 32767; Serial.print (forventet); Serial.print (","); Serial.println (adc0); }} void loop (void) {}

Trin 4: Båndbredde

Båndbredde
Båndbredde

Jeg vil definere båndbredde som her som den frekvens, ved hvilken output fra DAC falder med 3dB. Dette er en konvention og til en vis grad vilkårlig. For eksempel vil DAC ved 6dB -punktet stadig udsende et signal, det vil bare være ~ 50% amplitude.

For at måle dette passerer vi simpelthen sinusbølger med en stigende frekvens fra DAC til ADC og måler deres standardafvigelse. Ikke overraskende er 3dB-punktet ved 30Hz (1/(2*pi*5000*1e-6)).

ESP32 kan udføre 1 megaprøve i sekundet. Dette er en praktisk gevinst for ESP32. Dens amplitude henfalder slet ikke i 100Hz -båndbredde -testområdet.

Koden herunder kan teste PWM DAC -båndbredden.

#omfatte

#inkludere Adafruit_ADS1115 annoncer; / * Brug dette til 16-bit versionen */ int16_t adc0; int16_t adc1; void setup (void) {float M; flyde Mp = 0; flyde 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); forsinkelse (5000); Serial.println ("Frekvens, Amplitude"); for (int i = 1; i <100; i ++) {usigneret lang start = millis (); usigneret lang T = millis (); Sp = 0; S = 0; M = 0; Smp. = 0; int k = 1; flyde norm; mens ((T - start) <1000) {int ud = 24 * sin (2 * PI * i * (T - start) / 1000.0) + 128; ledcWrite (0, ud); adc0 = ads.readADC_SingleEnded (0); M = Mp + (adc0 - Mp) / k; Smp. = M; S = Sp + (adc0 - Mp) * (adc0 - M); Sp = S; T = millis (); k ++; } hvis (i == 1) {norm = sqrt (S / k); } Serial.print (i); Serial.print (","); Serial.println (sqrt (S / k) / norm, 3); k = 0; }} void loop (void) {}

Og denne kode vil teste ESP32 -båndbredden. Sørg for at fjerne kondensatoren, ellers vil resultaterne være de samme for begge metoder.

#omfatte

#inkludere Adafruit_ADS1115 annoncer; / * Brug dette til 16-bit versionen */ int16_t adc0; int16_t adc1; void setup (void) {float M; flyde Mp = 0; flyde S = 0; float Sp = 0; Serial.begin (115200); ads.setGain (GAIN_ONE); // 1x gain +/- 4.096V 1 bit = 2mV 0.125mV ads.begin (); forsinkelse (5000); Serial.println ("Frekvens, Amplitude"); for (int i = 1; i <100; i ++) {usigneret lang start = millis (); usigneret lang T = millis (); Sp = 0; S = 0; M = 0; Smp. = 0; int k = 1; flyde norm; mens ((T - start) <1000) {int out = 24 * sin (2 * PI * i * (T - start) / 1000.0) + 128; dacWrite (25, ud); adc0 = ads.readADC_SingleEnded (0); M = Mp + (adc0 - Mp) / k; Smp. = M; S = Sp + (adc0 - Mp) * (adc0 - M); Sp = S; T = millis (); k ++; } hvis (i == 1) {norm = sqrt (S / k); } Serial.print (i); Serial.print (","); Serial.println (sqrt (S / k) / norm, 3); k = 0; }} void loop (void) {}

Trin 5: Luk tanker

Det nye DAC -design vinder på linearitet og støj, men taber på båndbredde. Afhængigt af din anvendelse kan et af disse indeks være vigtigere end det andet. Med disse testprocedurer skulle du være i stand til objektivt at træffe den beslutning!

Jeg synes også, det er værd at påpege her, at fordi PWM-output er lav støj, med exceptionel linearitet, burde det være muligt at konstruere en meget højere opløsning DAC med PWM-output (måske endda 16-bit præcision). Det tager noget arbejde. Indtil da byder jeg adieu!

Anbefalede: