Come misurare la corrente elettrica con Arduino Uno (amperometro)
Introduzione
La corrente elettrica (I) è un flusso di elettroni che scorre in un conduttore, può essere misurata attraverso un resistore noto.
Dalla relazione data dal rapporto della tensione, che cade ai capi del resistore, e il suo valore di resistenza nota come legge di Ohm:
Questa equazione afferma che la corrente elettrica (I) che scorre attraverso il resistore noto (R) è direttamente proporzionale alla tensione elettrica (V) che cade ai suoi capi, e inversamente proporzionale al valore del resistore noto (R).
Per evitare che il resistore utilizzato per la misura della corrente assorbita da un determinato circuito, influenzi il suo funzionamento, è importante scegliere un resistore appropriato in base alle specifiche dell’applicazione e alla corrente massima che si vuole misurare.
Una resistenza troppo alta provoca una caduta di tensione eccessiva sul resistore, che potrebbe ridurre la tensione applicata al circuito al di sotto del limite minimo consentito per il suo corretto funzionamento.
Se il valore del resistore e/o la corrente da misurare sono troppo bassi, la tensione che cade ai capi del resistore è di scarsa entità e in queste condizioni, la tensione da misurare potrebbe essere troppo bassa da non consentire una misura precisa a causa di una limitata risoluzione.
In queste condizioni, anche piccoli errori nella misura della tensione potrebbero portare a grandi errori nella misura della corrente.
Il resistore usato per la misura della corrente è anche definito: resistore di shunt.
Per selezionare uno shunt idoneo per una determinata applicazione, è importante considerare anche la potenza massima che può dissipare.
Se la corrente che scorre attraverso lo shunt è elevata, la potenza che deve dissipare potrebbe superare la sua capacità massima e verificarsi un surriscaldamento eccessivo che può danneggiarlo in modo irrimediabile.
Pertanto, è importante selezionare uno shunt che abbia una potenza massima di dissipazione adeguata in base alla corrente massima che si prevede di misurare.
Per esempio se il nostro circuito assorbe una corrente massima di 10 A e il valore di resistenza dello shunt è di 0,01 Ω la potenza che deve dissipare è data dalla relazione:
E’ buona pratica scegliere uno shunt che abbia una capacità di dissipazione termica maggiorata del 50% rispetto alla potenza massima attesa.
In questo caso, sarebbe quindi opportuno selezionare uno shunt con una capacità di dissipazione termica di almeno 1,5 W.
Spesso, sul contenitore dello shunt vengono applicate delle alette in alluminio per migliorare la sua capacità di dissipazione dell’energia termica.
Infatti, in questo modo, si aumenta la superfice del contenitore a contatto con l’aria che facilita la dispersione del calore generato.
In questo modo, la potenza generata dal resistore viene distribuita in modo uniforme sullo shunt di corrente, evitando che il calore si concentri in un punto specifico.
La tensione che cade sullo shunt deve essere molto bassa, poiché non deve interferire sul funzionamento del circuito a cui è collegata.
Ad esempio, se il valore del resistore di shunt è di 0,01 ohm, la tensione di shunt generata per una corrente di 1 A sarebbe di soli 10 mV.
L’utilizzo di un amplificatore differenziale può aumentare significativamente la dinamica e la risoluzione del segnale da misurare.
Grazie a questa tecnica, è possibile ottenere una maggiore precisione nella misura della corrente elettrica, anche con tensioni di shunt molto basse.
La risoluzione del convertitore ADC di Arduino Uno è di 10 bits, il che significa che il valore di tensione rilevato può essere diviso in 1023 parti uguali e possiamo discriminare una tensione di:
Se consideriamo l’esempio riportato in precedenza, con una corrente massima di 3 A, sullo shunt possiamo avere una caduta massima di 30 mV.
Se amplifichiamo questa tensione per 100, otteniamo una tensione di 3 V per una corrente di 3 A.
Se abbiamo un aumento di soli 4,8mV sullo shunt (il minimo valore che riusciamo a discriminare con l’ADC di Arduino Uno) sappiamo che si ha in corrispondenza un aumento di 4,8mA, il che significa che abbiamo una risoluzione di 4,8mA.
Senza approfondire la spiegazione sul comportamento degli amplificatori differenziale, si può affermare che il guadagno di un amplificatore operazionale retro azionato dipende dal valore dei resistori di retroazione.
Tuttavia, una spiegazione dettagliata sul comportamento degli amplificatori differenziali sarà fornita in un altro post.
La relazione che descrive il guadagno dell’amplificatore operazionale, con retroazione negativa, è la seguente:
Per ottenere un guadagno di circa 100, abbiamo usato la coppia di resistori:
Codice
#include <Adafruit_SSD1306.h> // libreria Adafruit per il display SSD1306 int width = 128; // dimensioni del display OLED che stiamo usando int height = 32; Adafruit_SSD1306 oled(width, height, &Wire, -1); int ADCpin = A0; definiamo il pin d'ingresso per la lettura della tensione unsigned long ADC; int Rfeedback = 100000; // valore del resistore di retro azione int RGND = 1000; // resistor GND value float current, opAmpmV, shuntmV, gain; void setup() { Serial.begin(115200); oled.begin(SSD1306_SWITCH CAPVCC, 0x3C); oled.clearDisplay(); oled.setTextColor(WHITE); oled.setTextSize(1); oled.display(); gain = 1.0 + Rfeedback/RGND; // calcolo del guadagno dell'amplificatore } void loop() { ADC = 0; for (int i=0; i<100; i++) // ripetiamo la lettura per 100 volte per poi fare la media { ADC = ADC + analogRead(ADCpin); delay(10); } ADC = ADC/100; // media della lettura opAmpmV = ADC*5000.0/1023.0; // tensione all'uscita dell'operazionale in mV shuntmV = opAmpmV / gain; // tensione sullo shunt current = shuntmV/0.01; //misura della corrente oled.clearDisplay(); oled.setCursor(0,0); // oled.print("current");oled.print(current,0); oled.println(" mA"); oled.print("shunt mV ");oled.println(shuntmV,0); oled.print("opamp mV ");oled.println(opAmpmV,0); oled.print("ADC ");oled.println(ADC); oled.display(); delay(1000); }
#include <Adafruit_SSD1306.h>
Questa riga di codice include la libreria “Adafruit_SSD1306.h”, che è una libreria per il display OLED SSD1306 prodotto da Adafruit. La libreria fornisce una serie di funzioni che semplificano l’utilizzo del display OLED, come ad esempio la scrittura di testo, la visualizzazione di immagini e la gestione della luminosità del display.
int width = 128; int height = 32;
Queste due righe di codice definiscono le dimensioni del display OLED. In particolare, “width” indica la larghezza del display in pixel, mentre “height” indica l’altezza del display in pixel.
Nel codice sorgente, queste variabili sono utilizzate per configurare il display OLED.
Adafruit_SSD1306 oled(width, height, &Wire, -1);
Questa riga di codice crea un oggetto “oled” della classe “Adafruit_SSD1306”, che rappresenta il display OLED collegato ad Arduino.
Il costruttore della classe “Adafruit_SSD1306” richiede quattro parametri: “width” e “height” che indicano le dimensioni del display, “&Wire” che indica l’interfaccia I2C utilizzata per comunicare con il display e “-1” che indica il pin di reset del display (se necessario).
Quindi, il codice crea un oggetto “oled” con le dimensioni specificate (128×32 pixel), utilizzando l’interfaccia I2C “Wire” e non specificando un pin di reset per il display.
oled.begin(SSD1306_SWITCH CAPVCC, 0x3C);
“begin()” è una funzione della classe “Adafruit_SSD1306” che inizializza il display OLED e lo configura con i parametri specificati.
Il primo parametro della funzione “begin()” indica il tipo di alimentazione del display (“SSD1306_SWITCH_CAPVCC” specifica la tensione di alimentazione.
gain = 1.0 + Rfeedback/RGND;
Calcolo del guadagno dell’amplificatore
for (int i=0; i<100; i++) // ripetiamo la lettura per 100 volte per poi fare la media { ADC = ADC + analogRead(ADCpin); delay(10); }
Si esegue una lettura tramite l’ADC sul pin ADCpin (A0). Il codice inizia con un ciclo “for” che esegue il suo corpo 100 volte, incrementando la variabile “i” ad ogni iterazione.
All’interno del ciclo “for”, la funzione “analogRead()” viene chiamata per leggere il valore di tensione analogica presente sul pin ADCpin e questo valore viene aggiunto alla variabile “ADC”. La funzione “delay(10)” fa una pausa di 10 millisecondi prima di continuare con la prossima iterazione del ciclo “for”.
In sintesi, questo codice esegue la lettura del valore analogico dal pin ADC per 100 volte, sommando ogni lettura alla variabile “ADC” e introducendo un breve ritardo tra ogni lettura.
Questa iterazione ha lo scopo di effettuare una media di più letture analogiche per ottenere un valore più stabile e preciso.
ADC = ADC/100;
In questa istruzione calcoliamo la media dei valori letti in precedenza.
opAmpmV = ADC*5000.0/1023.0;
Converte il valore ADC, ottenuto dalle letture analogiche nel codice precedente, in una tensione in millivolts (mV).
Nella formula, il valore 5000.0 rappresenta la tensione di riferimento di 5 volt fornita all’ADC, mentre il valore 1023.0 rappresenta il massimo valore ADC possibile, che si ottiene quando la tensione di ingresso all’ADC è uguale alla tensione di riferimento.
Il risultato viene quindi assegnato alla variabile “opAmpmV”.
shuntmV = opAmpmV / gain;
Dividendo “opAmpmV” per “gain”, si ottiene la tensione “shuntmV” ai capi del resistore shunt.
current = shuntmV/0.01;
Poiché il resistore shunt genera una caduta di tensione proporzionale alla corrente che attraversa il carico, il valore di tensione “shuntmV” ottenuto dal codice precedente può essere utilizzato per calcolare la corrente attraverso il carico.
In particolare, se il resistore shunt ha una resistenza nota, la corrente può essere calcolata utilizzando la legge di Ohm, cioè I = V / R, dove V è la tensione ai capi del resistore shunt e R è la sua resistenza.
Conclusioni
In caso di dubbi o domande, non esitate a scrivermi nel form qui di seguito.
Buon lavoro!