Innholdsfortegnelse:

Hvordan lage og teste en bedre DAC med ESP32: 5 trinn
Hvordan lage og teste en bedre DAC med ESP32: 5 trinn

Video: Hvordan lage og teste en bedre DAC med ESP32: 5 trinn

Video: Hvordan lage og teste en bedre DAC med ESP32: 5 trinn
Video: Output DC or AC Voltage using MCP4725 DAC with LCD and PWM to Voltage Converter with Arduino 2024, November
Anonim
Hvordan lage og teste en bedre DAC med ESP32
Hvordan lage og teste en bedre DAC med ESP32
Hvordan lage og teste en bedre DAC med ESP32
Hvordan lage og teste en bedre DAC med ESP32

ESP32 har 2 8-biters digitale til analoge omformere (DAC). Disse DACene lar oss produsere vilkårlige spenninger innenfor et bestemt område (0-3.3V) med 8 bits oppløsning. I denne instruksjonsboken vil jeg vise deg hvordan du bygger en DAC og karakteriserer ytelsen, samt sammenligner den med ESP32 DAC. Ytelsesindeksene jeg vil se på inkluderer

  • Støynivå
  • Båndbredde
  • Integrert ikke -linearitet
  • Differensiell ikke -linearitet

For å teste disse indeksene vil jeg bruke ADS1115.

Det er viktig å merke seg at vurderingen av alle disse indeksene bare vil være like nøyaktig som referanseenheten din (i dette tilfellet ADS115). For eksempel har ADS115 ikke 16-bits presisjon når det gjelder spenningsforskyvning og forsterkning. Disse feilene kan være så store som 0,1%. For mange systemer kan disse feilene ignoreres når absolutt nøyaktighet er av begrenset betydning.

Rekvisita

  • ADS1115
  • ESP32 -bord
  • brødbrett
  • jumper ledninger
  • 5 kOhm motstand
  • 1 mikro-Farad keramisk kondensator

Trinn 1: Legge ut brødbrettet

Legge ut brødbrettet
Legge ut brødbrettet

Koble til følgende pinner

Mellom ESP32 og ADS1115

3v3 VDD

GND GND

GPIO22 SCL

GPIO21 SDA

På ADS1115

ADDR GND (ADS115)

Å lage DAC

Det er mange måter å lage en DAC på. Det enkleste er å lavpassfiltrere et PWM-signal med en motstand og en kondensator. Jeg kunne ha lagt til en op-amp her som en buffer, men ønsket å holde ting enkelt. Denne designen er enkel og billig å implementere med alle mikrokontroller som støtter PWM. Jeg kommer ikke til å gå gjennom teorien om designet her (google PWM DAC).

Bare koble til GPIO255 KOhm motstand 1 microFarad kondensator gnd

Koble nå en jumper wire fra det punktet hvor motstanden møter kondensatoren til A0 på ADS115.

Trinn 2: Vurder signal til støynivå

Vurder signal til støynivå
Vurder signal til støynivå

For å vurdere støynivået, bare kjør skriptet nedenfor. For å vurdere dette lar vi ganske enkelt DAC stå på en fast verdi og måler hvordan spenningen svinger over tid.

På grunn av utformingen av DAC vil støyen være størst når PWM -signalet er på 50% driftssyklus. Derfor er det her vi vil vurdere det. Vi vil også vurdere ESP32 på samme signalnivå. Vi vil også filtrere ESP32 DAC med det samme lavpassfilteret for å gjøre målingen sammenlignbar.

For meg var utgangen klar. PWM -designet hadde> 6dB bedre SNR (det er 2 ganger bedre). En klar seier for nye DAC. En liten forvirring er at det er filtre innebygd i ADC som definitivt forbedrer SNR. Så de absolutte verdiene kan være vanskelige å tolke. Hvis jeg hadde brukt et andre-ordens filter ville dette ikke vært tilfelle.

Uansett er koden nedenfor

#inkludere

#inkludere Adafruit_ADS1115 annonser; // adafruit bibliotek for adc int16_t adc0; // void -oppsett (void) {Serial.begin (115200); // Start serieannonser.setGain (GAIN_TWO); // 2x gain +/- 2.048V 1 bit = 0.0625mV ads.begin (); // begynne adc float M = 0; // initial gjennomsnittlig flyter Mp = 0; // previouos betyr flyte S = 0; // initial Variance float Sp = 0; // forrige varians const int reps = 500; // antall repetisjoner int n = 256; // antall prøver ledcSetup (0, 25000, 8); // sett pwm frekvens = 25000 Hz ved 8 bits oppløsning ledcAttachPin (25, 0); // sett pwm på pin 25 ledcWrite (0, 128); // sett den til halv driftssyklus (største støy) forsinkelse (3000); // vent på oppgjørstid float snrPWM [reps]; // rekke snrs for PWM float snrDAC [reps]; // rekke snrs for DAC for (int i = 0; i <reps; i ++) {// loope over repititions for (int k = 1; k <(n+1); k ++) {// loope over samples adc0 = ads.readADC_SingleEnded (0); // få lese M = Mp + (adc0 - Mp) / k; // beregne rullende gjennomsnitt Mp = M; // sett forrige gjennomsnitt S = Sp + (adc0 - Mp) * (adc0 - M); // beregne rullende varians Sp = S; // angi forrige varians} // snr i dB snrPWM = 20 * log10 (3.3 / (sqrt (S / n) *.0625 *.001)); // tilbakestill verdier M = 0; Smeltepunkt = 0; S = 0; Sp = 0; } ledcDetachPin (25); // koble PWM fra pin 25 dacWrite (25, 128); // skrive til DAC forsinkelse (3000); // vent med å ta til takke 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; Smeltepunkt = 0; S = 0; Sp = 0; } // plotte 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) {}

Trinn 3: Integral ikke -linearitet og differensiell ikke -linearitet

Integrert ikke -linearitet og differensiell ikke -linearitet
Integrert ikke -linearitet og differensiell ikke -linearitet

Den integrerte ikke -lineariteten er et mål på omtrent hvor mye avvik det er mellom DAC -utgangsspenningen og en rett linje. Jo større dette er, jo verre er det …

Differensiallinjæriteten er et mål på omtrent hvor mye den observerte endringen i spenningen (fra en kode til den neste) avviker fra det som kan forventes fra en rett linje.

Resultatene her var virkelig interessante. Først og fremst har begge mindre enn 0,5 lbs feil (ved 8-biters oppløsning) som er bra, men PWM har mye bedre integrert linearitet. Begge har sammenlignbar differensiell ikke -linearitet, men ESP32 DAC har noen veldig rare pigger. Dessuten har PWM -metoden en viss struktur for feilene. I hovedsak overskrider og overskrider den riktige spenningen på en vekslende måte.

Min mistanke er at dette er en merkelig avrundingsfeil i hvordan et 8-biters PWM-signal produseres på ESP32.

En måte å korrigere for dette på er å raskt bytte mellom to tilstøtende koder (f.eks. 128, 129) med PWM. Med et analogt lavpassfilter vil de resulterende feilene i gjennomsnitt være null. Jeg simulerte dette i programvare og faktisk forsvant alle feilene. Nå har PWM-metoden linearitet som er nøyaktig til 16-bits!

Hvem som helst koden for å generere dataene er nedenfor. Utgangen vil være på den serielle skjermen i.csv -format. Bare kopier den til en tekstfil for videre behandling.

#inkludere

#inkludere Adafruit_ADS1115 annonser; / * Bruk dette for 16-biters versjon */ int16_t adc0; void -oppsett (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, observert"); 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) {}

Trinn 4: Båndbredde

Båndbredde
Båndbredde

Jeg skal definere båndbredde som her som frekvensen som utgangen til DAC synker med 3dB. Dette er en konvensjon og til en viss grad vilkårlig. For eksempel, ved 6dB -punktet, vil DAC fortsatt sende et signal, det vil bare være ~ 50% amplitude.

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

ESP32 kan gjøre 1 megaprøve per sekund. Dette er en praktisk seier for ESP32. Amplituden forfaller ikke i det hele tatt i 100Hz båndbredde -testområdet.

Koden nedenfor kan teste PWM DAC -båndbredden.

#inkludere

#inkludere Adafruit_ADS1115 annonser; / * Bruk dette for 16-biters versjon */ int16_t adc0; int16_t adc1; void -oppsett (void) {float M; flyte Mp = 0; flyte S = 0; flyte 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 ++) {usignert lang start = millis (); usignert lang T = millis (); Sp = 0; S = 0; M = 0; Smeltepunkt = 0; int k = 1; flyte norm; mens ((T - start) <1000) {int out = 24 * sin (2 * PI * i * (T - start) / 1000.0) + 128; ledcWrite (0, ut); 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 koden vil teste ESP32 -båndbredden. Sørg for å fjerne kondensatoren, ellers blir resultatene de samme for begge metodene.

#inkludere

#inkludere Adafruit_ADS1115 annonser; / * Bruk dette for 16-biters versjon */ int16_t adc0; int16_t adc1; void -oppsett (void) {float M; flyte Mp = 0; flyte S = 0; flyte 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 ++) {usignert lang start = millis (); usignert lang T = millis (); Sp = 0; S = 0; M = 0; Smeltepunkt = 0; int k = 1; flyte norm; mens ((T - start) <1000) {int out = 24 * sin (2 * PI * i * (T - start) / 1000.0) + 128; dacWrite (25, ut); 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) {}

Trinn 5: Avslutte tanker

Den nye DAC -designen vinner på linearitet og støy, men taper på båndbredden. Avhengig av søknaden din kan en av disse indeksene være viktigere enn den andre. Med disse testprosedyrene bør du være i stand til objektivt å ta den beslutningen!

Jeg tror også det er verdt å påpeke her at fordi PWM-utgang er lav støy, med eksepsjonell linearitet, bør det være mulig å konstruere en mye høyere oppløsning DAC med PWM-utgang (kanskje til og med 16-bits presisjon). Det kommer til å ta litt arbeid. Inntil da sier jeg farvel!

Anbefalt: