Taula de continguts:

Com fer i provar un DAC millor amb ESP32: 5 passos
Com fer i provar un DAC millor amb ESP32: 5 passos

Vídeo: Com fer i provar un DAC millor amb ESP32: 5 passos

Vídeo: Com fer i provar un DAC millor amb ESP32: 5 passos
Vídeo: ✅ Errores al calibrar Driver A4988, ajuste Vref, conexión CNC Shield a Motor Pasos #7 2024, Desembre
Anonim
Com fer i provar un DAC millor amb ESP32
Com fer i provar un DAC millor amb ESP32
Com fer i provar un DAC millor amb ESP32
Com fer i provar un DAC millor amb ESP32

L'ESP32 té 2 convertidors digitals a analògics (DAC) de 8 bits. Aquests DAC ens permeten produir tensions arbitràries dins d’un determinat rang (0-3,3V) amb 8 bits de resolució. En aquest instructiu, us mostraré com construir un DAC i caracteritzar-ne el rendiment, així com comparar-lo amb el DAC ESP32. Els índexs de rendiment que examinaré inclouen

  • Nivell de soroll
  • Ample de banda
  • No linealitat integral
  • No linealitat diferencial

Per provar aquests índexs utilitzaré l’ADS1115.

És important tenir en compte que la vostra avaluació de tots aquests índexs només serà tan precisa com el vostre dispositiu de referència (en aquest cas l’ADS115). Per exemple, l'ADS115 no té precisió de 16 bits pel que fa al seu desplaçament i guany de tensió. Aquests errors poden arribar al 0,1%. Per a molts sistemes, es poden ignorar aquests errors quan la precisió absoluta preocupa poc.

Subministraments

  • ADS1115
  • Junta ESP32
  • taulell de pa
  • cables de pont
  • Resistència de 5 kOhm
  • 1 condensador ceràmic micro-Farad

Pas 1: Disposició del tauler de pa

Disposició de la taula de pa
Disposició de la taula de pa

Connecteu els passadors següents

Entre l’ESP32 i l’ADS1115

3v3 VDD

GND GND

GPIO22 SCL

GPIO21 SDA

A l’ADS1115

ADDR GND (ADS115)

Elaboració del DAC

Hi ha moltes maneres de fer un DAC. El més senzill és filtrar de pas baix un senyal PWM amb una resistència i un condensador. Podria haver afegit un amplificador operatiu aquí com a memòria intermèdia, però volia mantenir les coses senzilles. Aquest disseny és senzill i econòmic d’implementar amb qualsevol microcontrolador que admeti PWM. No vaig a passar per la teoria del disseny aquí (google PWM DAC).

Simplement connecteu la resistència GPIO255 KOhm 1 condensador microFarad gnd

Ara connecteu un cable de pont des del punt on la resistència es troba amb el condensador a A0 a l'ADS115.

Pas 2: avaluar el nivell de soroll i de senyal

Avaluar el nivell de senyal i soroll
Avaluar el nivell de senyal i soroll

Per avaluar el nivell de soroll, simplement executeu l'script següent. Per avaluar-ho, simplement deixem el DAC a un valor fix i mesurem com oscil·la el voltatge amb el pas del temps.

A causa del disseny del DAC, el soroll serà més gran quan el senyal PWM estigui al cicle de treball del 50%. Per tant, aquí és on ho valorarem. També avaluarem l’ESP32 en aquest mateix nivell de senyal. També filtrarem el ESP32 DAC amb el mateix filtre de pas baix per tal de fer la mesura comparable.

Per a mi la sortida era clara. El disseny PWM tenia un SNR> 6 dB millor (això és dues vegades millor). Una clara victòria per al nou DAC. Una petita confusió és que hi ha filtres integrats a l'ADC que definitivament milloren el SNR. Per tant, els valors absoluts poden ser difícils d’interpretar. Si hagués utilitzat un filtre de segon ordre, no seria així.

De totes maneres, el codi està a sota

#incloure

#include Adafruit_ADS1115 ads; // biblioteca adafruit per adc int16_t adc0; // void setup (void) {Serial.begin (115200); // Inicieu ads.setGain de sèrie (GAIN_TWO); // 2x guany +/- 2.048V 1 bit = 0,0625mV ads.begin (); // començar flotador adc M = 0; // float mitjà inicial Mp = 0; // previouos significa flotador S = 0; // Variació inicial flotant Sp = 0; // const variança anterior int reps = 500; // nombre de repeticions int n = 256; // nombre de mostres ledcSetup (0, 25000, 8); // configurar pwm frequecny = 25000 Hz a 8 bits de resolució ledcAttachPin (25, 0); // estableix pwm al pin 25 ledcWrite (0, 128); // Estableix-lo a la demora del cicle de treball (soroll més gran) (3000); // espera el temps de resolució flotant snrPWM [reps]; // matriu de snrs per a PWM float snrDAC [repeticions]; // array de snrs per a DAC per a (int i = 0; i <reps; i ++) {// bucle sobre repiticions per (int k = 1; k <(n + 1); k ++) {// bucle sobre mostres adc0 = ads.readADC_SingleEnded (0); // aconsegueix llegir M = Mp + (adc0 - Mp) / k; // calcular la mitjana de rotació Mp = M; // estableix la mitjana anterior S = Sp + (adc0 - Mp) * (adc0 - M); // calcular la variància de rotació Sp = S; // establir la variància anterior} // snr a dB snrPWM = 20 * log10 (3.3 / (sqrt (S / n) *.0625 *.001)); // restableix els valors M = 0; Mp = 0; S = 0; Sp = 0; } ledcDetachPin (25); // separar PWM del pin 25 dacWrite (25, 128); // escriure a DAC delay (3000); // espereu a conformar-vos amb (int i = 0; i <reps; i ++) {// igual que el bucle PWM per a (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; } // representar SNR en un gràfic per a (int i = 1; i <reps; i ++) {Serial.print ("PWM_SNR (dB):"); Serial.print (snrPWM ); Serial.print (","); Serial.print ("ESP32_SNR (dB):"); Serial.println (snrDAC ); }} bucle buit (buit) {}

Pas 3: No linealitat integral i no linealitat diferencial

No linealitat integral i no linealitat diferencial
No linealitat integral i no linealitat diferencial

La no linealitat integral és una mesura de la quantitat aproximada de desviació que hi ha entre la tensió de sortida del DAC i una línia recta. Com més gran sigui, pitjor és …

La no-linealitat diferencial és una mesura de la quantitat aproximada que el canvi observat en la tensió (d'un codi al següent) es desvia del que s'esperava d'una línia recta.

Els resultats aquí van ser realment interessants. En primer lloc, tots dos tenen un error de menys de 0,5 lliures (a una resolució de 8 bits), cosa que és bona, però el PWM té una linealitat integral molt millor. Tots dos tenen una no-linealitat diferencial comparable, però el ESP32 DAC té alguns pics molt estranys. A més, el mètode PWM té una certa estructura dels errors. Bàsicament supera i baixa la tensió correcta de manera alternativa.

La meva sospita és que es tracta d’un error d’arrodoniment estrany en com es produeix un senyal PWM de 8 bits a l’ESP32.

Una manera de corregir-ho és fer un cicle ràpid entre dos codis adjacents (per exemple, 128, 129) amb el PWM. Amb un filtre de pas baix analògic, els errors resultants seran de mitjana a zero. Ho vaig simular al programari i de fet van desaparèixer tots els errors. Ara el mètode PWM té una linealitat que és precisa fins a 16 bits.

A continuació es troba el codi per generar les dades. La sortida serà al monitor sèrie en format.csv. Simplement copieu-lo a un fitxer de text per processar-lo posteriorment.

#incloure

#include Adafruit_ADS1115 ads; / * Utilitzeu-lo per a la versió de 16 bits * / int16_t adc0; configuració buida (buida) {Serial.begin (115200); ads.setGain (GAIN_ONE); // 2x guany +/- 2.048V 1 bit = 1mV 0.0625mV ads.begin (); ledcSetup (0, 25000, 8); ledcAttachPin (25, 0); Serial.println ("Esperat, observat"); ledcWrite (0, 2); retard (3000); per a (int i = 2; i <255; i ++) {ledcWrite (0, i); retard (100); adc0 = ads.readADC_SingleEnded (0); float espera = (i / 256.0 * 3.3) / 4.096 * 32767; Serial.print (esperat); Serial.print (","); Serial.println (adc0); }} bucle buit (buit) {}

Pas 4: ample de banda

Ample de banda
Ample de banda

Definiré l’amplada de banda aquí com la freqüència a la qual la sortida del DAC cau en 3dB. Es tracta d’una convenció i, fins a cert punt, arbitrària. Per exemple, en el punt de 6 dB, el DAC encara emetrà un senyal que només tindrà un ~ 50% d'amplitud.

Per mesurar-ho, simplement passem ones sinusoïdals a una freqüència creixent del DAC a l'ADC i mesurem la seva desviació estàndard. No és sorprenent que el punt 3dB estigui a 30Hz (1 / (2 * pi * 5000 * 1e-6)).

L'ESP32 pot fer 1 Mega mostra per segon. Es tracta d’una victòria pràctica per a l’ESP32. La seva amplitud no decau en absolut a la regió de prova d’amplada de banda de 100Hz.

El codi següent pot provar l’amplada de banda PWM DAC.

#incloure

#include Adafruit_ADS1115 ads; / * Utilitzeu-lo per a la versió de 16 bits * / int16_t adc0; int16_t adc1; configuració buida (buida) {float M; flotador Mp = 0; flotador S = 0; flotador Sp = 0; Serial.begin (115200); ads.setGain (GAIN_ONE); // 1x guany +/- 4.096V 1 bit = 2mV 0.125mV ads.begin (); ledcSetup (0, 25000, 8); ledcAttachPin (25, 0); retard (5000); Serial.println ("Freqüència, amplitud"); for (int i = 1; i <100; i ++) {unsigned long start = millis (); sense signar llarg T = millis (); Sp = 0; S = 0; M = 0; Mp = 0; int k = 1; norma de flotació; mentre que ((T - inici) <1000) {int out = 24 * sin (2 * PI * i * (T - inici) / 1000.0) + 128; ledcWrite (0, fora); adc0 = ads.readADC_SingleEnded (0); M = Mp + (adc0 - Mp) / k; Mp = M; S = Sp + (adc0 - Mp) * (adc0 - M); Sp = S; T = millis (); k ++; } if (i == 1) {norma = sqrt (S / k); } Serial.print (i); Serial.print (","); Serial.println (sqrt (S / k) / norma, 3); k = 0; }} bucle buit (buit) {}

I aquest codi provarà l’amplada de banda ESP32. Assegureu-vos de treure el condensador o els resultats seran els mateixos per a tots dos mètodes.

#incloure

#include Adafruit_ADS1115 ads; / * Utilitzeu-lo per a la versió de 16 bits * / int16_t adc0; int16_t adc1; configuració buida (buida) {float M; flotador Mp = 0; flotador S = 0; flotador Sp = 0; Serial.begin (115200); ads.setGain (GAIN_ONE); // 1x guany +/- 4.096V 1 bit = 2mV 0.125mV ads.begin (); retard (5000); Serial.println ("Freqüència, amplitud"); for (int i = 1; i <100; i ++) {unsigned long start = millis (); sense signar llarg T = millis (); Sp = 0; S = 0; M = 0; Mp = 0; int k = 1; norma de flotació; mentre que ((T - inici) <1000) {int out = 24 * sin (2 * PI * i * (T - inici) / 1000.0) + 128; dacWrite (25, fora); adc0 = ads.readADC_SingleEnded (0); M = Mp + (adc0 - Mp) / k; Mp = M; S = Sp + (adc0 - Mp) * (adc0 - M); Sp = S; T = millis (); k ++; } if (i == 1) {norma = sqrt (S / k); } Serial.print (i); Serial.print (","); Serial.println (sqrt (S / k) / norma, 3); k = 0; }} bucle buit (buit) {}

Pas 5: clausura de pensaments

El nou disseny DAC guanya en linealitat i soroll, però perd en amplada de banda. Depenent de la vostra aplicació, un d’aquests índexs pot ser més important que l’altre. Amb aquests procediments de prova, hauríeu de poder prendre aquesta decisió objectivament.

A més, crec que val la pena assenyalar aquí que, atès que la sortida PWM és de poc soroll, amb una linealitat excepcional hauria de ser possible construir un DAC de resolució molt superior amb la sortida PWM (potser fins i tot una precisió de 16 bits). Això suposarà una mica de feina. Fins aleshores, us ho dic adéu!

Recomanat: