Innholdsfortegnelse:
- Rekvisita
- Trinn 1: Legge ut brødbrettet
- Trinn 2: Vurder signal til støynivå
- Trinn 3: Integral ikke -linearitet og differensiell ikke -linearitet
- Trinn 4: Båndbredde
- Trinn 5: Avslutte tanker
Video: Hvordan lage og teste en bedre DAC med ESP32: 5 trinn
2024 Forfatter: John Day | [email protected]. Sist endret: 2024-01-30 11:21
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
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å
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
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
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:
Hvordan lage en Linux -oppstartsdisk (og hvordan du bruker den): 10 trinn
Hvordan lage en Linux Boot Drive (og hvordan du bruker den): Dette er en enkel introduksjon om hvordan du kommer i gang med Linux, spesielt Ubuntu
Hvordan gjøre høyttaleren din bedre !: 4 trinn
Hvordan gjøre høyttaleren din bedre !: Jeg vil gjøre høyttaleren bedre fordi jeg har dette problemet der høyttaleren min ikke har noen rekkevidde. For eksempel, når jeg er i bassenget mitt og svømmer til den andre siden, kan jeg ikke høre musikken som spilles fra den ene siden til den andre. Jeg synes dette er spesielt fordi jeg tror
Hvordan lage en delt skjermvideo med fire trinn: 4 trinn (med bilder)
Hvordan lage en delt skjermvideo med fire trinn: Vi ser ofte en samme person vise i en scene to ganger i et TV -spill. Og så vidt vi vet har ikke skuespilleren en tvillingbror. Vi har også sett at to sangvideoer blir satt på en skjerm for å sammenligne sangferdighetene sine. Dette er kraften til spl
Hvordan teste bipolare transistorer hvis du har et analogt multimeter: 4 trinn
Slik tester du bipolare transistorer hvis du har et analogt multimeter: Vi vet hvordan transistoren fungerer, men noen av oss vet egentlig ikke hvordan vi skal teste selve komponenten. I dag har de fleste digitale multimetre stikkontakter for å teste dem, men hva vil du gjøre hvis du har de gamle analoge/nåltypene? Dette er en sim
Hvordan lage en besteforeldres kalender & Utklippsbok (selv om du ikke vet hvordan du skal utklippsbok): 8 trinn (med bilder)
Hvordan lage en besteforeldres kalender & Utklippsbok (selv om du ikke vet hvordan du skal utklippsbok): Dette er en veldig økonomisk (og mye verdsatt!) Feriegave til besteforeldre. Jeg laget 5 kalendere i år for mindre enn $ 7 hver. Materialer: 12 flotte bilder av barnet ditt, barn, nieser, nevøer, hunder, katter eller andre slektninger 12 forskjellige stykker