Sommario:
- Forniture
- Passaggio 1: stendere il tagliere
- Passaggio 2: valutare il livello del segnale in base al rumore
- Passaggio 3: non linearità integrale e non linearità differenziale
- Passaggio 4: larghezza di banda
- Passaggio 5: pensieri conclusivi
Video: Come realizzare e testare un DAC migliore con ESP32: 5 passaggi
2024 Autore: John Day | [email protected]. Ultima modifica: 2024-01-30 10:00
L'ESP32 ha 2 convertitori da digitale ad analogico (DAC) a 8 bit. Questi DAC ci permettono di produrre tensioni arbitrarie entro un certo intervallo (0-3,3V) con 8 bit di risoluzione. In questo Instructable, ti mostrerò come costruire un DAC e caratterizzare le sue prestazioni, oltre a confrontarlo con il DAC ESP32. Gli indici di prestazione che esaminerò includono
- Livello di rumore
- Larghezza di banda
- Non linearità integrale
- Non linearità differenziale
Per testare questi indici userò l'ADS1115.
È importante notare che la tua valutazione di tutti questi indici sarà accurata solo quanto il tuo dispositivo di riferimento (in questo caso l'ADS115). Ad esempio, l'ADS115 non ha una precisione a 16 bit quando si tratta di offset e guadagno di tensione. Questi errori possono raggiungere lo 0,1%. Per molti sistemi, questi errori possono essere ignorati quando l'accuratezza assoluta è di scarsa importanza.
Forniture
- ADS1115
- Scheda ESP32
- tagliere
- cavi per ponticelli
- Resistenza da 5 kOhm
- 1 condensatore ceramico micro-Farad
Passaggio 1: stendere il tagliere
Collegare i seguenti pin
Tra ESP32 e ADS1115
3v3 VDD
GND GND
GPIO22 SCL
GPIO21 SDA
All'ADS1115
ADDR GND (ADS115)
Realizzare il DAC
Esistono molti modi per realizzare un DAC. Il più semplice è filtrare passa basso un segnale PWM con un resistore e un condensatore. Avrei potuto aggiungere un amplificatore operazionale qui come buffer, ma volevo mantenere le cose semplici. Questo design è semplice ed economico da implementare con qualsiasi microcontrollore che supporti il PWM. Non esaminerò qui la teoria del design (google PWM DAC).
Basta collegare GPIO255 KOhm resistore 1 microFarad Condensatore gnd
Ora collega un ponticello dal punto in cui il resistore incontra il condensatore ad A0 sull'ADS115.
Passaggio 2: valutare il livello del segnale in base al rumore
Per valutare il livello di rumore è sufficiente eseguire lo script sottostante. Per valutare ciò lasciamo semplicemente il DAC ad un valore fisso e misuriamo come la tensione oscilla nel tempo.
A causa del design del DAC, il rumore sarà maggiore quando il segnale PWM è al 50% del ciclo di lavoro. Pertanto è qui che lo valuteremo. Valuteremo anche ESP32 a questo stesso livello di segnale. Filtriamo anche il DAC ESP32 con lo stesso filtro passa basso in modo da rendere comparabile la misurazione.
Per me l'output era chiaro. Il design PWM aveva un SNR migliore di >6dB (che è 2 volte migliore). Una chiara vittoria per il nuovo DAC. Una leggera confusione è che ci sono filtri integrati nell'ADC che stanno decisamente migliorando l'SNR. Quindi i valori assoluti possono essere difficili da interpretare. Se avessi usato un filtro di secondo ordine non sarebbe stato così.
Comunque il codice è sotto
#includere
#include annunci Adafruit_ADS1115; // libreria adafruit per adc int16_t adc0; // void setup(void) { Serial.begin(115200); // Avvia serial ads.setGain(GAIN_TWO); // Guadagno 2x +/- 2.048V 1 bit =0.0625mV ads.begin(); // inizia adc float M = 0; // media iniziale float Mp = 0; // precedente media float S = 0; // Varianza iniziale float Sp = 0; // varianza precedente const int reps = 500; // numero di ripetizioni int n = 256; // numero di campioni ledcSetup(0, 25000, 8); // imposta pwm frequecny =25000 Hz con una risoluzione di 8 bit ledcAttachPin(25, 0); // imposta pwm sul pin 25 ledcWrite(0, 128); // impostalo su half duty cycle (più grande rumore) delay (3000); // attende il tempo di assestamento float snrPWM[reps]; // array di snrs per PWM float snrDAC[reps]; // array di snrs per DAC for (int i = 0; i < reps; i++) { // loop sulle ripetizioni for (int k = 1; k < (n + 1); k++) { // loop sui campioni adc0 = ads.readADC_SingleEnded(0); // ottiene la lettura M = Mp + (adc0 - Mp) / k; // calcola la media mobile Mp = M; // imposta la media precedente S = Sp + (adc0 - Mp) * (adc0 - M); // calcola la varianza mobile Sp = S; // imposta la varianza precedente } // snr in dB snrPWM = 20 * log10(3.3 / (sqrt(S / n) *.0625 *.001)); //reimposta i valori M = 0; Mp = 0; S = 0; Sp = 0; } ledcDetachPin(25); // stacca PWM dal pin 25 dacWrite(25, 128); // scrive su DAC delay(3000); // aspetta di accontentarsi di (int i = 0; i < reps; i++) { // uguale al ciclo PWM per (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; } // traccia gli SNR su un grafico 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); } } ciclo vuoto (vuoto) { }
Passaggio 3: non linearità integrale e non linearità differenziale
La non linearità integrale è una misura approssimativa di quanta deviazione c'è tra la tensione di uscita del DAC e una linea retta. Più è grande e peggio è…
La non linearità differenziale è una misura approssimativa di quanto il cambiamento osservato nella tensione (da un codice all'altro) si discosta da quanto ci si aspetterebbe da una linea retta.
I risultati qui sono stati davvero interessanti. Prima di tutto, entrambi hanno un errore inferiore a 0,5 lsb (a una risoluzione di 8 bit), il che è buono, ma il PWM ha una linearità integrale molto migliore. Entrambi hanno una non linearità differenziale comparabile, ma il DAC ESP32 ha alcuni picchi molto strani. Inoltre, il metodo PWM ha una struttura per gli errori. Essenzialmente supera e non raggiunge la tensione corretta in modo alternato.
Il mio sospetto è che si tratti di uno strano errore di arrotondamento nel modo in cui viene prodotto un segnale PWM a 8 bit su ESP32.
Un modo per correggere questo è quello di scorrere rapidamente tra due codici adiacenti (ad esempio 128, 129) con il PWM. Con un filtro passa-basso analogico, gli errori risultanti saranno in media pari a zero. L'ho simulato nel software e in effetti tutti gli errori sono scomparsi. Ora il metodo PWM ha una linearità precisa a 16 bit!
Anywho il codice per generare i dati è sotto. L'output sarà sul monitor seriale in formato.csv. Basta copiarlo in un file di testo per un'ulteriore elaborazione.
#includere
#include annunci Adafruit_ADS1115; /* Usalo per la versione a 16 bit */ int16_t adc0; void setup(void) { Serial.begin(115200); ads.setGain(GAIN_ONE); // Guadagno 2x +/- 2,048 V 1 bit = 1 mV 0,0625 mV ads.begin(); ledcSetup(0, 25000, 8); ledcAttachPin(25, 0); Serial.println("Atteso, Osservato"); ledcWrite(0, 2); ritardo (3000); for (int i = 2; i < 255; i++) { ledcWrite(0, i); ritardo(100); adc0 = ads.readADC_SingleEnded(0); float atteso = (i / 256,0 * 3,3) / 4,096 * 32767; Serial.print (previsto); Serial.print(", "); Serial.println(adc0); } } ciclo vuoto (vuoto) { }
Passaggio 4: larghezza di banda
Definirò la larghezza di banda come qui come la frequenza alla quale l'uscita del DAC scende di 3dB. Questa è una convenzione e, in una certa misura, arbitraria. Ad esempio, al punto 6dB, il DAC emetterà ancora un segnale che sarà solo ~50% di ampiezza.
Per misurarlo, passiamo semplicemente le onde sinusoidali a una frequenza crescente dal DAC all'ADC e misuriamo la loro deviazione standard. Non sorprende che il punto 3dB sia a 30Hz (1/(2*pi*5000*1e-6)).
L'ESP32 può eseguire 1 Mega campione al secondo. Questa è una vittoria a mani basse per ESP32. La sua ampiezza non decade affatto nella regione di prova della larghezza di banda di 100Hz.
Il codice seguente può testare la larghezza di banda del DAC PWM.
#includere
#include annunci Adafruit_ADS1115; /* Usalo per la versione a 16 bit */ int16_t adc0; int16_t adc1; void setup(void) { float M; float Mp = 0; galleggiante S = 0; flottante Sp = 0; Serial.begin(115200); ads.setGain(GAIN_ONE); // 1x guadagno +/- 4,096 V 1 bit = 2 mV 0,125 mV ads.begin(); ledcSetup(0, 25000, 8); ledcAttachPin(25, 0); ritardo (5000); Serial.println("Frequenza, Ampiezza "); for (int i = 1; i < 100; i++) { inizio lungo senza segno = millis(); unsigned long T = millis(); Sp = 0; S = 0; M = 0; Mp = 0; intk = 1; norma galleggiante; while ((T - inizio) < 1000) { int out = 24 * sin(2 * PI * i * (T - inizio) / 1000,0) + 128; ledcWrite(0, uscita); 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) / norm, 3); k = 0; } } ciclo vuoto (vuoto) { }
E questo codice testerà la larghezza di banda ESP32. Assicurati di rimuovere il condensatore o i risultati saranno gli stessi per entrambi i metodi.
#includere
#include annunci Adafruit_ADS1115; /* Usalo per la versione a 16 bit */ int16_t adc0; int16_t adc1; void setup(void) { float M; float Mp = 0; galleggiante S = 0; flottante Sp = 0; Serial.begin(115200); ads.setGain(GAIN_ONE); // 1x guadagno +/- 4,096 V 1 bit = 2 mV 0,125 mV ads.begin(); ritardo (5000); Serial.println("Frequenza, Ampiezza "); for (int i = 1; i < 100; i++) { inizio lungo senza segno = millis(); unsigned long T = millis(); Sp = 0; S = 0; M = 0; Mp = 0; intk = 1; norma galleggiante; while ((T - inizio) < 1000) { int out = 24 * sin(2 * PI * i * (T - inizio) / 1000,0) + 128; dacWrite(25, uscita); 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; } } ciclo vuoto (vuoto) { }
Passaggio 5: pensieri conclusivi
Il nuovo design DAC vince sulla linearità e sul rumore ma perde sulla larghezza di banda. A seconda dell'applicazione, uno di questi indici può essere più importante dell'altro. Con queste procedure di test, dovresti essere in grado di prendere obiettivamente questa decisione!
Inoltre, penso che valga la pena sottolineare qui che, poiché l'uscita PWM è a basso rumore, con una linearità eccezionale dovrebbe essere possibile costruire un DAC a risoluzione molto più elevata con l'uscita PWM (forse anche con precisione a 16 bit). Ci vorrà un po' di lavoro. Fino ad allora, ti dico addio!
Consigliato:
Come Realizzare la Migliore Multipresa: 4 Passaggi
Come realizzare la migliore ciabatta: come realizzare la migliore ciabatta - Protezione contro i fulmini - Soppressione del rumore - Assorbe le sovratensioni
Come utilizzare Tinkercad per testare e implementare il tuo hardware: 5 passaggi (con immagini)
Come utilizzare Tinkercad per testare e implementare il tuo hardware: La simulazione del circuito è una tecnica in cui il software per computer simula il comportamento di un circuito o sistema elettronico. I nuovi progetti possono essere testati, valutati e diagnosticati senza dover effettivamente costruire il circuito o il sistema. La simulazione del circuito può essere un
Come realizzare un video a schermo diviso in quattro passaggi: 4 passaggi (con immagini)
Come realizzare un video a schermo diviso in quattro passaggi: spesso vediamo una stessa persona in una scena due volte in uno spettacolo televisivo. E per quanto ne sappiamo, l'attore non ha un fratello gemello. Abbiamo anche visto che due video di canto vengono messi su uno schermo per confrontare le loro abilità canore. Questo è il potere di sp
Come testare i transistor bipolari se si dispone di un multimetro analogico: 4 passaggi
Come testare i transistor bipolari se si dispone di un multimetro analogico: sappiamo come funziona il transistor ma alcuni di noi non sanno davvero come testare il componente stesso. Al giorno d'oggi, la maggior parte dei multimetri digitali ha prese fornite per testarli, ma cosa farai se avessi quelli vecchi analogici/ad ago? Questa è una simulazione
Come Realizzare un Robot Autonomo che Gioca a Basket Usando un IRobot Creato come Base: 7 Passaggi (con Immagini)
Come creare un robot autonomo che gioca a basket utilizzando un IRobot Create come base: questa è la mia voce per la sfida iRobot Create. La parte più difficile di tutto questo processo per me è stata decidere cosa avrebbe fatto il robot. Volevo dimostrare le fantastiche funzionalità di Create, aggiungendo anche un tocco di robo. Tutto il mio