Sommario:

Conosci la regolazione ADC di ESP32?: 29 passaggi
Conosci la regolazione ADC di ESP32?: 29 passaggi

Video: Conosci la regolazione ADC di ESP32?: 29 passaggi

Video: Conosci la regolazione ADC di ESP32?: 29 passaggi
Video: Microcontrollori per Maker, QUALE USARE e COME SCEGLIERE? Confronto Arduino ATMEGA ATtiny ESP STM32 2024, Luglio
Anonim
Image
Image
Risorse utilizzate
Risorse utilizzate

Oggi parlerò di un problema più tecnico, ma penso che tutti coloro che lavorano con ESP32 dovrebbero saperlo: il problema della regolazione della lettura dell'ADC (convertitore analogico-digitale). Lo trovo importante perché quando si esegue una "misura", soprattutto con uno strumento dotato di uscita analogica, bisogna essere assolutamente certi che la lettura venga eseguita correttamente.

Nel video di oggi, quindi, effettueremo misurazioni utilizzando il "convertitore analogico-digitale" dell'ESP32, osserveremo le discrepanze di conversione e applicheremo un metodo di regolazione/calibrazione dell'ADC.

Passaggio 1: cos'è un convertitore AD?

Un convertitore AD è un circuito in grado di tradurre una quantità analogica (continua) in valori digitali (discreti). Che cosa significa? Significa che mentre i valori digitali possono assumere solo valori discreti formati dalla combinazione di zero e uno, una grandezza analogica può assumere qualsiasi valore all'interno di un intervallo. Ad esempio, se misurassimo la tensione di una cella AA ideale, potremmo trovare qualsiasi valore compreso tra 0V e 1,5V, poiché questa è una quantità analogica. Lo stato di uscita di una lampada ideale deve assumere solo due stati (spento o acceso), che è una grandezza discreta. Poiché i microcontrollori funzionano utilizzando questa logica discreta, abbiamo bisogno di un circuito in grado di tradurre una quantità analogica in digitale (o discreta).

Passaggio 2: risorse utilizzate

• Una scheda Lolin32 Lite v1.0.0

• Un oscilloscopio Tektronix TDS1001C per l'acquisizione

• Un cavo USB per ESP32

• Un oscilloscopio Hantek DSO4102C come generatore di segnale

Passaggio 3: ADC ESP32

ESP32 ADC
ESP32 ADC

Secondo i dati Espressif, i chip ESP32 possono presentare una differenza di +/- 6% da un chip all'altro nei risultati misurati.

Inoltre, la conversione NON ha una risposta lineare per ogni intervallo disponibile per la lettura. Espressif fornisce un metodo per la calibrazione e suggerisce agli utenti di implementare altri metodi se lo ritengono necessario per ottenere la precisione desiderata.

Effettueremo un'acquisizione dei dati e, da questa, mostreremo le risposte dell'ADC e un esempio di applicazione di un processo matematico per leggere la regolazione.

Esistono diversi modi (più semplici o più complessi) per eseguire queste correzioni. Sta a te valutare il più appropriato per il tuo progetto.

Quello mostrato qui avrà uno scopo illustrativo e cercherà di affrontare punti interessanti che possono essere osservati durante le regolazioni.

Passaggio 4: circuito utilizzato

Circuito utilizzato
Circuito utilizzato

Ho usato un oscilloscopio con un generatore di segnale che arriva fino a 25 MHz, l'Hantek DSO4102C. Abbiamo generato un'onda che è stata letta dall'ESP A/D e dall'oscilloscopio. I dati raccolti sono stati registrati in csv e in un foglio di calcolo, che lascerò alla fine dell'articolo per il download.

Passaggio 5: segno utilizzato

Segno usato
Segno usato

Abbiamo scelto un segnale trapezoidale a bassa frequenza che consente l'accesso alle rampe che attraversano l'intero range di conversione. Ciò consente un gran numero di campioni su queste rampe.

Passaggio 6: dati ottenuti dall'oscilloscopio

Dati ottenuti dall'oscilloscopio
Dati ottenuti dall'oscilloscopio

L'immagine della cattura è stata eseguita dall'oscilloscopio. I dati sono stati archiviati in un file CSV. Notare la leggera curvatura sulle rampe di salita e di discesa del segnale.

Passaggio 7: dati ottenuti dall'oscilloscopio (file csv in Excel)

Dati ottenuti dall'oscilloscopio (file csv in Excel)
Dati ottenuti dall'oscilloscopio (file csv in Excel)

Abbiamo i campionamenti qui.

Passaggio 8: dati ottenuti dall'ADC

Dati ottenuti dall'ADC
Dati ottenuti dall'ADC

Modificando la velocità di trasferimento della seriale, possiamo visualizzare i dati catturati dall'ADC. Osservare la deformazione del segnale trapezoidale.

Dati osservati sul plotter seriale Arduino IDE

Passaggio 9: dati ottenuti da ADC - Excel

Dati ottenuti da ADC - Excel
Dati ottenuti da ADC - Excel

Utilizzando una tariffa più alta e il terminale seriale, possiamo acquisire i valori e applicarli in Excel per i nostri confronti.

Passaggio 10: confronto delle rampe di salita

Confronto delle rampe di salita
Confronto delle rampe di salita

Confrontiamo le due rampe di salita delle due catture.

Notare la curvatura che si verifica su entrambe le rampe.

Nota anche che per la stessa rampa abbiamo molti più campioni dell'ESP32 rispetto all'oscilloscopio.

Passaggio 11: eguagliare il numero di campioni

Eguagliare il numero di campioni
Eguagliare il numero di campioni
Eguagliare il numero di campioni
Eguagliare il numero di campioni

Poiché ESP32 ha fornito un numero maggiore di campioni rispetto all'oscilloscopio, è necessario equiparare questi valori, poiché serviranno da indice per confrontare le due curve.

Per questo, faremo un confronto diretto.

Abbiamo 305 campioni per la rampa dell'oscilloscopio e 2365 campioni per la rampa ADC.

Poiché le rampe sono dello stesso range, possiamo dire che abbiamo circa 7,75 campioni dell'ADC per ogni oscilloscopio.

Moltiplicando l'indice di ciascun campione dell'oscilloscopio si ha la stessa curva, ma con indici equivalenti all'ADC e ai dati ridistribuiti.

Per riempire i dati mancanti per le nuove posizioni, applicheremo una curva che si adatta statisticamente ai dati noti.

Passaggio 12: colmare le lacune - Linea di tendenza

Colmare le lacune - Linea di tendenza
Colmare le lacune - Linea di tendenza
Colmare le lacune - Linea di tendenza
Colmare le lacune - Linea di tendenza

Selezionando i dati conosciuti (puntini blu), cliccando e poi cliccando con il tasto destro, selezioniamo: “Aggiungi linea di Trend…”

Nella finestra che appare, selezioniamo il tipo Polinomio (l'ordine 2 sarà sufficiente).

Abbiamo anche controllato le opzioni "Visualizza equazione nel grafico" e "Visualizza valore R-quadrato nel grafico".

Facciamo clic su "Chiudi".

Passaggio 13: riempire gli spazi vuoti - Curva polinomiale di grado 2

Riempire gli spazi vuoti - Curva polinomiale di grado 2
Riempire gli spazi vuoti - Curva polinomiale di grado 2

Excel ci fornisce due nuove informazioni; l'equazione del secondo ordine che meglio si adatta ai dati e l'equazione R-quadrato che quantifica questa adeguatezza.

Ricorda solo che più vicino a 1, più appropriata è l'equazione.

Non approfondiamo la matematica coinvolta, usiamola solo come strumento.

Passaggio 14: Colmare le lacune - Valutare la funzione

Riempiamo le lacune di campionamento con i dati generati dall'equazione. E poi, confrontali punto per punto.

y = -9E-08x2 + 0, 0014x + 0, 1505

R² = 0, 9999

Tensione dell'oscilloscopio = -9E-08 * indice2 + 0, 0014 * indice + 0, 1505

Passaggio 15: conversione della tensione dell'oscilloscopio in un valore equivalente da confrontare con l'ADC

Conversione della tensione dell'oscilloscopio in un valore equivalente da confrontare con l'ADC
Conversione della tensione dell'oscilloscopio in un valore equivalente da confrontare con l'ADC

Approfittiamone per trasformare anche il valore della tensione dell'oscilloscopio in un valore ADC equivalente.

Poiché il valore più alto ottenuto nell'ADP dell'ESP32 è stato 4095, che equivale alla lettura di 2.958V per lo stesso indice, possiamo dire che:

Ogni volt nelle misurazioni dell'oscilloscopio equivale a circa 1384,4 unità dell'AD. Pertanto, possiamo moltiplicare tutte le misurazioni dell'oscilloscopio per questo valore.

Passaggio 16: confronto delle due rampe ottenute

Confrontando le due rampe ottenute
Confrontando le due rampe ottenute

Visualizzazione delle differenze ottenute nelle due letture.

Passaggio 17: comportamento della differenza di lettura dell'ADC (ERRORE)

Comportamento della differenza di lettura dell'ADC (ERRORE)
Comportamento della differenza di lettura dell'ADC (ERRORE)

La curva seguente mostra come si comporta la differenza nella lettura dell'ADC in funzione della misurazione. Questa raccolta di dati ci permetterà di trovare una funzione di correzione.

Per trovare questa curva, tracciamo semplicemente la differenza trovata in ciascuna misura in funzione di ogni possibile posizione AD (da 0 a 4095).

Passaggio 18: Comportamento della differenza di lettura dell'ADC - Trovare una funzione di correzione

Comportamento della differenza di lettura dell'ADC - Trovare una funzione di correzione
Comportamento della differenza di lettura dell'ADC - Trovare una funzione di correzione

Possiamo determinare in Excel una funzione di correzione aggiungendo una linea di tendenza, ora di grado superiore, fino a quando non si adatta sufficientemente ai nostri dati.

Passaggio 19: utilizzo di altro software

Utilizzo di altro software
Utilizzo di altro software
Utilizzo di altro software
Utilizzo di altro software
Utilizzo di altro software
Utilizzo di altro software
Utilizzo di altro software
Utilizzo di altro software

Altro software interessante per la determinazione delle curve è PolySolve, che può essere utilizzato direttamente al link: https://arachnoid.com/polysolve/ o scaricato come applicazione Java.

Consente l'applicazione di regressioni polinomiali di grado superiore e la consegna della funzione formattata, nonché altre funzionalità.

Per utilizzarlo è sufficiente inserire i dati nella prima casella di testo. I dati devono seguire l'ordine X, Y separati da una virgola o tab. Prestare attenzione nell'utilizzare correttamente il punto come punto decimale.

Verrà visualizzato un grafico nella casella successiva se i dati inseriti sono formattati correttamente.

Ecco come è andata la nostra curva di errore ADC.

Questa finestra presenterà il risultato della regressione, inclusi i dati di adeguatezza della funzione, che a loro volta possono avere il loro output formattato in diversi modi: come una funzione C/C++, un elenco di coefficienti, una funzione scritta in Java, ecc.

Nota: prestare attenzione ai separatori decimali

Passaggio 20: costanti e impostazione ()

Segnalo qui il GPIO utilizzato per la cattura analogica. Inizializzo la porta seriale, così come il pin determinato per l'acquisizione analogica.

const int pin_leitura = 36; //GPIO usato per la cattura analógica void setup() { Serial.begin(1000000); //Iniziando una porta seriale somente para debug pinMode(pin_leitura, INPUT); //Pino utilizado para captura analógica }

Passaggio 21: Loop () e la funzione di correzione

Effettuiamo la cattura della tensione regolata e stampiamo i valori con o senza le correzioni corrette.

void loop() { int valor_analogico = analogRead(pin_leitura); //realiza a captura da tensão ajustada //Serial.print(valor_analogico + f(valor_analogico)); //imprime os valores para debug (COM CORREÇÃO) Serial.print(valor_analogico); //primime os valores para debug (SEM CORREÇÃO) Serial.print(", "); Serial.print(4095);//cria uma linha para marcar o valor máximo de 4095 Serial.print(", "); Serial.println(0); //cria uma linha para marcar o valor mínimo de 0 }

Notare nella riga 12 che abbiamo la possibilità di stampare i dati con l'aggiunta della funzione differenza f (analog_value).

Passaggio 22: utilizzo della funzione di correzione PolySolve

Qui, usiamo la funzione PolySolve all'interno dell'IDE di Arduino.

/* Modalità: normale Grado polinomiale 6, 2365 x, y coppie di dati Coefficiente di correlazione (r^2) = 9, 907187626418e-01 Errore standard = 1, 353761109831e+01 Formato di output: funzione C/C++: Copyright © 2012, P. Lutus -- https://www.arachnoid.com. Tutti i diritti riservati. */ doppia f(doppia x) { return 2.202196968876e+02 + 3.561383996027e-01 * x + 1.276218788985e-04 * pow(x, 2) + -3.470360275448e-07 * pow(x, 3) + 2.082790802069e- 10 * pow(x, 4) + -5.306931174991e-14 * pow(x, 5) + 4.787659214703e-18 * pow(x, 6); }

Nota la modifica virgola per punto come separatore decimale.

Passaggio 23: Acquisizione con correzione - Seriale plotter

Cattura con correzione - Seriale plotter
Cattura con correzione - Seriale plotter

Passaggio 24: costo computazionale

Costo computazionale
Costo computazionale
Costo computazionale
Costo computazionale

Per eseguire calcoli polinomiali, è necessario che il processore gestisca questo compito. Ciò può comportare ritardi nell'esecuzione, a seconda del codice sorgente e della potenza di calcolo disponibile.

Qui vediamo una tabella dei risultati di un test che utilizza polinomi a più gradi. Notare la differenza tra le volte in cui è stata utilizzata la funzione pow() e quando non lo è stata.

Passaggio 25: codice di prova - Setup () e Loop Start ()

Qui abbiamo il codice utilizzato nel nostro test.

void setup() { Serial.begin(1000000); //Iniziando una porta serial somente para debug } void loop() { float valor_analogico = 500.0; //um valor arbtrario float quantidade = 10000.0; //quantità di contatori float = 0.0; //contador de chamadas

Passaggio 26: codice di prova - Loop () ed elaborazione

Ho usato la funzione micros() per ottenere il valore in microsecondi.

//============= inizio o processo float agora = micros(); //marca o instante inicial while (contador < quantidade) { //v(valor_analogico); //funzione vazia //r(valor_analogico); //funzione con ritorno //f0(valor_analogico); //grau 0 //f1(valor_analogico); //grau 1 //f2(valor_analogico); //grau 2 //f3(valor_analogico); //grau 3 //f4(valor_analogico); //grau 4 //f5(valor_analogico); //grau 5 //f6(valor_analogico); //grau 6 //f13_semPow(valor_analogico); //grau 13º SEM a função POW //f13_comPow(valor_analogico); //grau 13º COM a função POW contador++; } agorà = (micros() - agorà) / quantidade; //determina o intervalo que se passou para cada iteração //============= finaliza o process

Passaggio 27: Codice di prova - Ciclo () - Risultati

Stampiamo il valore restituito dalla funzione di grado 13 con e senza POW per il confronto, nonché l'intervallo di elaborazione.

//imprime o valor retornado da função de grau 13 com e sem POW para comparação Serial.print(f13_semPow(valor_analogico)); //grau 13º SEM a função POW Serial.print(" - "); Serial.print(f13_comPow(valor_analogico)); //grau 13º COM a função POW Serial.print(" - "); //imprime o intervallo do processamento Serial.println(agora, 6); }

Passaggio 28: Codice di prova - Funzioni utilizzate

Funzioni vuote (solo con ritorno) di grado 0 e 1.

//FUNÇÃO VAZIAdoppio v(doppio x) { } //FUNÇÃO SOMENTE COM RETORNO doppio r(doppio x) { return x; } //FUNÇÃO DE GRAU 0 double f0(doppio x) { return 2.202196968876e+02; } //FUNÇÃO DE GRAU 1 double f1(doppio x) { return 2.202196968876e+02 + 3.561383996027e-01 * x; }

Funzioni di grado 2, 3 e 4.

//FUNÇÃO DE GRAU 2doppio f2(doppio x) { return 2.202196968876e+02 + 3.561383996027e-01 * x + 1.276218788985e-04 * pow(x, 2); } //FUNÇÃO DE GRAU 3 double f3(doppio x) { return 2.202196968876e+02 + 3.561383996027e-01 * x + 1.276218788985e-04 * pow(x, 2) + -3.470360275448e-07 * pow(x, 3); } //FUNÇÃO DE GRAU 4 double f4(doppio x) { return 2.202196968876e+02 + 3.561383996027e-01 * x + 1.276218788985e-04 * pow(x, 2) + -3.470360275448e-07 * pow(x, 3) + 2.082790802069e-10 * pow(x, 4); }

Funzioni di grado 5 e 6.

//FUNÇÃO DE GRAU 5doppio f5(doppio x) { return 2.202196968876e+02 + 3.561383996027e-01 * x + 1.276218788985e-04 * pow(x, 2) + -3.470360275448e-07 * pow(x, 3) + 2.082790802069e-10 * pow(x, 4) + -5.306931174991e-14 * pow(x, 5); } //FUNÇÃO DE GRAU 6 double f6(doppio x) { return 2.202196968876e+02 + 3.561383996027e-01 * x + 1.276218788985e-04 * pow(x, 2) + -3.470360275448e-07 * pow(x, 3) + 2.082790802069e-10 * pow(x, 4) + -5.306931174991e-14 * pow(x, 5) + 4.787659214703e-18 * pow(x, 6); }

Funzione di grado 13 utilizzando il POW.

//FUNÇÃO DE GRAU 13 USANDO O POWdouble f13_comPow(double x) { return 2, 161282383460e+02 + 3, 944594843419e-01 * x + 5, 395439724295e-04 * pow(x, 2) + -3, 968558178426e-06 * pow(x, 3) + 1, 047910519933e-08 * pow(x, 4) + -1, 479271312313e-11 * pow(x, 5) + 1, 220894795714e-14 * pow(x, 6) + -6, 136200785076e-18 * pow(x, 7) + 1, 910015248179e-21 * pow(x, 8) + -3, 566607830903e-25 * pow(x, 9) + 5, 000280815521e-30 * pow(x, 10) + 3, 434515045670e-32 * pow(x, 11) + -1, 407635444704e-35 * pow(x, 12) + 9, 871816383223e-40 * pow(x, 13); }

Funzione di grado 13 senza utilizzare POW.

//FUNÇÃO DE GRAU SEM USAR O POWdouble f13_semPow(double x) { return 2, 161282383460e+02 + 3, 944594843419e-01 * x + 5, 395439724295e-04 * x * x + -3, 968558178426e-06 * x * x * x + 1, 047910519933e-08 * x * x * x * x + -1, 479271312313e-11 * x * x * x * x * x + 1, 220894795714e-14 * x * x * x * x * x * x + -6, 136200785076e-18 * x * x * x * x * x * x * x + 1, 910015248179e-21 * x * x * x * x * x * x * x * x + -3, 566607830903e- 25 * x * x * x * x * x * x * x * x * x + 5, 000280815521e-30 * x * x * x * x * x * x * x * x * x * x + 3, 434515045670e- 32 * x * x * x * x * x * x * x * x * x * x * x + -1, 407635444704e-35 * x * x * x * x * x * x * x * x * x * x * x * x + 9, 871816383223e-40 * x * x * x * x * x * x * x * x * x * x * x * x * x; }

Passaggio 29: file

Scarica i file:

PDF

IO NO

Foglio di calcolo

Consigliato: