Apr 022015
 

Oggi vedremo come usare Arduino per misurare il consumo di corrente in modo non invasivo. Ok, lo ammetto, non è un argomento particolarmente innovativo, c’è infatti in rete un progetto ben più completo, il famoso OpenEnergyMonitor, dove potete attingere ad un sacco di informazioni, ma è da molto tempo che ho comprato un sensore di corrente non invasivo e non ho ancora avuto l’opportunità di provarlo per cui approfitto di questa prova per scrivere un articolo anche perchè leggere tutta la documentazione dell’O.E.M, peraltro tutta in inglese, non è certo ciò che l’utente medio cerca di fare.

Il sensore

Il sensore in mio possesso è il SCT 013-030 che potete vedere nella figura qui vicino. E’ formato da una sorta di pinza apribile. Nel foro deve essere inserito il cavo dove transita la corrente che vogliamo misurare, dopodiché la pinza viene chiusa senza danneggiare il cavo stesso. Bisogna però fare alcune premesse importanti. Questo sensore è in grado di misurare unicamente correnti AC (alternate), infatti la variazione nel tempo della corrente in transito crea un campo elettromagnetico direttamente proporzionale alla corrente stessa, ed è questo che viene misurato dal sensore. Bisogna però chiarire cosa intendiamosct01330 per “cavo ove passa la corrente da misurare”. Se ad esempio voleste misurare la corrente assorbita dai dispositivi connessi ad una ciabatta, non potete semplicemente mettere la pinza attorno al cavo di alimentazione della ciabatta. Dentro quel cavo, infatti, ci saranno tre conduttori, uno di massa, una fase ed un neutro. Nella fase e neutro il passaggio della corrente avviene nelle due direzioni opposte per cui, dato che i campi magnetici che si generano dipendono anche dalla direzione in cui transita la corrente, si formeranno due campi elettromagnetici opposti che si annullano uno con l’altro. E’ per questo che la misura deve essere fatta solamente su uno dei due conduttori per cui, se proprio volete misurare l’assorbimento della ciabatta, siete costretti ad esporre uno dei due conduttori o creare una piccola prolunga a cui possiamo facilmente accedervi.

Questo sensore misura correnti da 0 a 30A generando un segnale da 0 a +1V. Si noti che si tratta di un’intera famiglia di sensori che vanno da 5 a 100A, questo è quello da 30. Già questi due dati ci permettono due considerazioni preliminari. In primo luogo 30A sono assolutamente esagerati per una normale abitazione con un normale contratto da 3kW dove con un carico puramente resistivo non riusciamo a superare i 15A. Io in realtà ho un contratto da 4.5KW/h per cui potrei arrivare sui 20A, ciò però non toglie che per l’utilizzo medio è un sensore sin troppo grande ed il risultato finale è una perdita di precisione sul range realmente misurato. Se non fosse chiaro facciamo un esempio chiarificatore. A 30A questo sensore genera una tensione di 1V per cui se ipoteticamente il nostro consumo massimo reale fosse di 15A il sensore a quel valore produrrà una tensione di circa 0.5V. Questo significa che tutta la fascia da 0.5 a 1V non sarà mai utilizzata per cui andiamo a sfruttare solamente il 50% della scala a disposizione con dimezzamento della precisione su quella realmente sfruttata.

La seconda considerazione riguarda l’output del sensore che è una tensione alternata da -1 a 1 V che istintivamente potremmo pensare di leggere con gli ingressi analogici di Arduino. Questi però possono leggere solamente tensioni fra 0 e 5V per cui occorre qualche aggiustamento. Faccio notare che prima avevo detto che il sensore risponde con una tensione da 0 a 1V corrispondenti alla scala da 0 a 30A, ora invece ho detto che il segnale del sensore oscilla da -1 a +1V, questo perchè la corrente cambia segno 50 volte al secondo, quindi il campo elettromagnetico generato inverte la sua direzione con la stessa frequenza e con conseguente inversione anche del segnale in uscita dal sensore. Nella realtà perciò abbiamo un segnale -1 / +1V corrispondenti alla scala -30 / +30A.

Trasformiamo la tensione.

Come dicevamo la tensione prodotta dal sensore non può essere letta direttamente da Arduino in quanto riporta anche valori negativi . Come facciamo a modificare questa tensione? Semplice aggiungiamo una tensione in serie per aumentarne il valore base e far rientrare le letture nel range che Arduino è in grado di leggere. Più precisamente usiamo un partitore di tensione fatto da due resistori uguali per cui a partire dalla tensione 5V di Arduino ne otteniamo una di 2.5V. In questo modo passiamo da -1 / +1 a 1.5 / 3.5V, valori che sono facilmente leggibili dagli ingressi analogici di Arduino.

schemapinzaamperometricaSulla sinistra troviamo il sensore di corrente che è rappresentato dal generatore V1 e dal resistore di carico (burden resistor) R1 che è di 62Ω ed è integrato nella pinza. Vediamo che un capo del sensore andrà collegato ad un ingresso analogico di Arduino mentre l’altro capo sarà collegato al partitore di tensione. V2 non è altro è che i 5V di Arduino. Potete inoltre vedere nella figura i due resistori identici (potete mettere valori anche sino a 10K senza problemi) che portano la tensione a 2.5V ed un piccolo condensatore da 10μF utile per attenuare piccole fluttuazioni residue della tensione in uscita. Tutto qui? Si tutto qui, con un sensore, due resistori ed un piccolo condensatore siete già in grado di creare il vostro piccolo lettore di corrente.

Accennavamo che il sensore da 30A per un normale contratto da 3kW è un po’ esagerato, vediamo ora che precisione possiamo raggiungere con questo sensore. Purtroppo il sensore in uscita fornisce solamente 1V di escursione per cui dei 1024 valori campionabili da Arduino possiamo sfruttarne solamente 204.8 (5:1=1024:x). Quindi se 30A sono divisibili in 204.8 parti, ognuna di essa rappresenta 0.146A che a 220V diventano quasi 32.2W, ossia questo sensore, su Arduino UNO, utilizzato come spiegato sopra è in grado di misurare assorbimenti a passi di circa 32W.

Teoria e calcoli….

In questa fase dell’articolo ero molto indeciso se parlare o meno di teoria, calcoli, soluzioni, etc, etc. La risposta questa volta è stata no, almeno non in modo approfondito. No perchè sul sito di OpenEnergyMonitor c’è spiegato già tutto e in modo molto approfondito, non ha nessun senso fare una semplice traduzione del lavoro altrui. Ci sono però alcuni semplici concetti da conoscere, giusto per poter poi capire che il risultato voluto non è magari ciò che ci aspettavamo. Ci tengo a sottolineare che questo è un articolo base che vuole affrontare in maniera semplice l’argomento per cui per forza di cose sarò un po’ superficiale.

La cosa principale che dovremmo sapere è che per una misura accurata della potenza occorre la misura non solo della corrente assorbita, che facciamo con il sensore descritto, ma anche del voltaggio che c’è nel medesimo istante in cui campioniamo l’assorbimento di corrente. Per essere ancora più pignoli, dovremmo effettuare numerosi campionamenti lungo almeno un’intero periodo (lunghezza dell’onda formata dalla semionda positiva e negativa) ed effettuare una media quadratica dei valori ottenuti. Vi faccio notare che a 50Hz il periodo dura 0,02 secondi, per cui dovrebbe già iniziare a chiarirsi il fatto che in quel brevissimo tempo dobbiamo fare tutta una serie di campionamenti e calcoli che il nostro buon Arduino potrebbe fare un po’ di fatica a seguire. In realtà Arduino, da un punto di vista strettamente teorico, ha un convertitore analogico-digitale (ADC) in grado di campionare a 9,6kHz, ossia in un solo secondo riesce ad eseguire 9600 misurazioni, ognuna delle quali dura 104μs. Nella realtà oltre all’acquisizione vera e propria del segnale dobbiamo anche occuparci di fare dei calcoli con i dati ottenuti per cui la velocità reale si abbassa. OpenEnergyMonitor dichiara ad esempio di effettuare circa 100 campionamenti se viene misurata solo la corrente o 50 se viene misurata sia la corrente che la tensione.

Ma torniamo al nostro progetto. Abbiamo detto che in questa prima esperienza vogliamo fare le cose nel modo più semplice e chiaro possibile per cui la tensione la diamo per fissa a 220V. E’ giusto però precisare ancora una cosa. Abbiamo prima detto che la potenza per un carico resistivo è data dal prodotto di corrente x tensione.  Purtroppo però i carichi di un’abitazione non sono tutti al 100% resistivi, ci sono anche componenti capacitive ed induttive che portano ad uno sfasamento temporale fra il picco di tensione e di corrente che porta ad una modifica della potenza.  In questo caso la misura della tensione ci permetterebbe di capire quando c’è il picco di tensione e quello di corrente e calcolare lo sfasamento delle due con una migliorata precisione della misura, motivo per cui il mancato calcolo della tensione porta ad un doppio errore di misurazione, sia sul valore vero e proprio, sia sullo sfasamento rispetto la corrente.

Cominciamo.

Come potete immaginare ho deciso di crearmi un sistema rudimentale ma funzionante e semplice da calibrare per chiunque, scritto da noi e sul quale abbiamo il totale controllo, credo che questa sia l’unica vera strada per capire davvero quello che stiamo facendo. Per prima cosa mi sono costruito una piccola prolunga con i 3 fili separati in modo da poter applicare la mia pinza amperometrica su uno dei cavi come potete vedere nella figura. Poi mi sono procurato un portalampada per poterci mettere delle lampadine ad incandescenza che come tali sono carichi resistivi ed hanno un consumo noto.prolungasgusciata Credo sia ovvio ma io ve lo dico ugualmente: warnig32 ATTENZIONE warnig32 perché la 220V è pericolosa! Se non sapete quel che fate non cimentatevi con questi esperimenti, potreste farvi mooolto male, piuttosto chiedete a qualche conoscente che vi può aiutare, ma non fate da soli; rischiare l’arresto cardiaco per giocare con Arduino e non vale proprio la pena.

La via più semplice.

Vi ho promesso un prototipo semplice semplice per cui in questa prima fase ci accontenteremo di un software funzionante da subito, anche se migliorabile.  Per prima cosa dobbiamo trovare il “punto zero”. Mi spiego meglio. Abbiamo detto che il sensore misura da -1 a +1, ma con il circuito su cui abbiamo collegato il sensore passiamo da 1.5 a 3.5V. Il problema è che si tratta di un’onda che sale e scende continuamente per 50 volte al secondo, ma a noi interessa di fatto il punto zero ed il picco. Ho cominciato facendo delle misurazioni con la sonda senza alcun carico, senza cavo dentro la pinza. In questo modo il sensore per forza di cose deve misurare zero (nessun carico) e la tensione che circola è solo quella del nostro partitore di tensione che quindi possiamo misurare con Arduino. Noi sappiamo che dovrebbe essere 2.5V, ma nella realtà non è detto che i due resistori usati siano del tutto identici per via della tolleranza, la temperatura, etc, per cui potremmo trovarci con valori leggermente sballati, anche perché non è detto che la tensione in uscita da Arduino sia esattamente di 5V. La teoria ci dice che Arduino ha 1024 valori possibili (da 0 a 1023, 10 bit) corrispondenti a voltaggi fra 0 e 5V, perciò i 2.5V teorici del partitore cadono esattamente a metà per cui dovrei ottenere una misurazione pari a 1024/2=512.  Con il seguente sketch possiamo misurare i valori massimo e minimo di una serie consecutiva di 500 misurazioni:

 

#define misure 500
double sensorValue;
int sensorPin=A1;
void setup()

{
  Serial.begin(9600);
  while (!Serial) {} // wait for serial port to connect. Needed for Leonardo only
}
void loop()

{
  double maxval=0;
  double minval=1023;
  for(int i=0;i<misure;i++)
  {
   sensorValue = analogRead(sensorPin);
   if(sensorValue>maxval) maxval=sensorValue;
   if(sensorValue<minval) minval=sensorValue;
  }
  Serial.print(minval);
  Serial.print(" - ");
  Serial.println(maxval);
  delay(500);

}

In realtà non è nulla di speciale, misura l’ingresso analogico A1  (sul quale ho collegato il sensore) e tiene traccia dei valori massimo e minimo misurati che poi li stampa sulla porta seriale. Senza carico ho ottenuto un valore minimo di 511 e massimo di 513. Potremmo pensarla come ad un valore medio di 512 sul quale abbiamo un’oscillazione di ±1 dovuta ad un’oscillazione residua della tensione sul partitore o al rumore di fondo. Vorrei però farvi notare che all’inizio avevamo calcolato che ogni unità misurata corrispondeva a circa 32W motivo per cui quella singola unità di rumore rappresenta un errore di base di circa 32W sulla misurazione finale. Chiaramente la componente di rumore che misuriamo senza carico sarà presente anche nella misurazione finale per cui ne terremo conto per sottrarla.

Riassumendo: stiamo creando un sistema che non misura la tensione, non tiene conto dello sfasamento fra tensione  e corrente ed ha un errore di base di circa 32W. Con questa premessa il modo migliore per proseguire è fare dei campionamenti seriati sufficientemente lunghi da coprire almeno 3 periodi completi e da questi tenere traccia dei valori minimo e massimo. Una volta ottenuto questo valore abbiamo il valore di “picco” di corrente, che però non deve essere confuso con i valori medi che normalmente vengono utilizzati. Ad esempio anche la nota tensione 220V è intesa quale valore medio mentre il picco supera i 311V. Allo stesso modo il valore di picco di corrente ottenuto dovrà essere diviso per 1.414 (radice quadrata di 2) per ottenere il valore medio a noi familiare. Ho fatto i primi test con una lampada da 100W ed ho ripetuto la misurazione ottenendo valori minimi di 507 e massimi di 517 che potremmo perciò riferire ad un’oscillazione di 4 unità sul rispettivo valore basale massimo che abbiamo calcolato prima. Considerando che dai calcoli fatti all’inizio ogni unità rappresenta 0.146A, otteniamo 0.584A che a 220V corrispondono a quasi 129W. Ora, indipendentemente dalla correttezza del valore di 220V (a casa mia il multimetro segna 218V), questo è un valore di picco e dobbiamo dividerlo per 1.414 ottenendo 90.8W (talora ottengo un’unità in più raggiungendo 113.5W).

Vediamo lo sketch:

#define misure 576
#define taratura 513
double sensorValue;
int sensorPin=A1;

void setup()
{
  Serial.begin(9600);
  while (!Serial) {} // wait for serial port to connect. Needed for Leonardo only
}
void loop()
{
  double maxval=0;
  double Vmax=0;
  for(int z=0;z<misure;z++)
  {
   sensorValue = analogRead(sensorPin);
   if(sensorValue>maxval) maxval=sensorValue;
  }  
  Serial.print(“Max unit: “);
  Serial.print(maxval);
  Serial.print(” / Consumo: “);
  Serial.print((maxval-taratura)*0.146*220/1.414);
  Serial.println(” W”);
  delay(500);
}

Il listato qui sopra non è molto differente da quello precedente. Non fà nulla di particolare se non eseguire delle misure seriate e tenere traccia dei picchi massimi. Una volta stabilito qual’è il picco sottrae il valore di taratura prima calcolato ed effettua le conversioni che abbiamo descritto prima ottenendo il valore in Watt. Per semplicità ho utilizzato solamente il picco positivo che però non è detto essere simmetrico con quello negativo.

Con questo abbiamo terminato il nostro primo semplice prototipo. Abbiamo chiarito agli inizi che non sarebbe stato un campione di precisione ma in modo estremamente semplice abbiamo creato qualcosa di funzionante e abbastanza preciso vista la tipologia di sensore impiegato e la rudimentalità del software. Con carichi di 100W abbiamo un errore di circa il 10-11%, passando a 300W l’errore oscilla fra il 2 e 9% circa (misurazioni di 272.59 e 295.30).

Come potete immaginare ci sono delle possibilità di migliorare la precisione del sistema. Attualmente sto finendo di sviluppare un sistema più preciso, basato quasi esclusivamente su modifiche software che mi hanno portato ad un errore su carichi da 100W inferiori all’1%, cosa che si ripete su carichi da 300W migliorando perciò la precisione anche di 10 volte.

Ci sono numerose cose che si possono fare per migliorare la precisione della misurazione, dall’utilizzo della media quadratica anzichè il puro livello di picco, alla calibrazione automatica del “livello zero”, al sovracampionamento del segnale e alla modifica del fattore di “prescaling” del convertitore analogico-digitale. Il discorso però è molto complesso e merita un intero articolo, forse anche più di uno, per cui ho preferito separare questa prima parte introduttiva dal resto in modo da scrivere articoli a crescente difficoltà. Questo era il più semplice, ma già ci permette di avere qualcosa di funzionante per cui se pensate che vi possa bastare potete fermarvi anche qui, altrimenti spero che possiate apprezzare il prossimo articolo.

  23 Responses to “Arduino per il monitoraggio del consumo elettrico – parte 1: introduzione – it”

  1.  

    Salve, prima di tutto vorrei complimentarmi con lei per l’ottimo post scritto, e dato che anche io ho realizzato lo stesso progetto, vorrei sapere come ha collegato la pinza al piccolo circuito per trasformare la tensione considerato che la pinza ha un’uscita jack. Grazie per l’attenzione e cordiali saluti.

  2.  

    esiste un modo per determinare il verso della corrente con questo sensore?

    Grazie

  3.  

    Buonasera Stefano, Veramente complimenti per il progetto. Molto carino e utile. Ho visto anche le altre versioni. Ottima spigazione e dedizione :-). GRAZIE a prescindere prima di tutto 🙂 🙂

    Ero interessato a provare la parte4

    Però ho una domanda sul prototipo della parte 1 ovvero questa.
    Il mo arduino UNO, in fase di taratura, pinza a vuoto senza il cavo VAC220V da “monitorare”, legge una minval = 0 ( Anche se raramente segna valori vari che oscillano da 0 a 25 o più)
    come maxval trà i 700 ed i 900.

    Eppure ho fatto il circuito con 2 resistori da 4700 hom e un C da 10 micro. Misurando la VCC al partitore ho esattamente 2.5 V ….. non riesco a comprendere perchè non mi trovo i valori di 512 o 513 descritti sopra …..

    Andando avanti anche con il resto del codice e con anche la parte2 da Lei egregiamente spiegata, ho sempre un risultato di migliaia di WATT su un carico misurato a pinza di 40w (lampadina).

    Volevo realizzare la parte4, ma mi sono fermato a questi problemi prima di andare avanti.

    Grazie mille
    Saluti

    •  

      Con un carico di soloi 40W dovresti si e no notare la presenza del carico stesso (almeno con questa versione del software) per cui sia i valori minimo che massimo dovrebbero attestarsi intorno al 512 e non da 0 a 700-900. Se con il tester misuri correttamente 2.5V, mi sorge il dubbio che tu stia leggendo sul pin analogico sbagliato (tipo che hai collegato il circuito ad A1 e leggi su A3, giusto per fare un esempio). Puoi accertarti di non essere incappato in questo semplice errore? Hai una foto da inviarmi su info@mcmajan.com?

  4.  

    Ho visto l’articolo di OEM dove si parla di inserire una resistenza burden da 33ohm e le simmetriche da un valore di 10k ad un max di 470k, il sensore è un YHDC SCT-013-000 100A, può funzionare anche con il 30A descritto qui? Grazie, Giorgio

  5.  

    Salve,

    attenzione a utilizzare le lampadine a incandescenza come campione o per test di carico. La loro resistenza a freddo è molto minore della resistenza che hanno a regime in funzionamento perché varia considerevolmente (anche di 10 volte!) in funzione della temperatura del filamento e della possibilità che hanno di dissipare il calore. Questo fenomeno causa addirittura degli effetti di sfasamento fra il flusso luminoso e la corrente. Vedi, per es. http://www.labtrek.it/torzo/Lamp_Ipot.pdf

    Ciao.

  6.  

    Ciao MC,
    sto cercando di ripercorrere paro – paro la tua strada ma già dal primo sketch, per trovare lo zero, rilevo un comportamento anomalo.

    Ho fatto il circuito col partitore (ho provato varie resistenze con varie tolleranze da 470 ohm ai 10K) ma rilevo un rumore di fondo che è abbastanza ampio.
    I valori che rilevo sono min 507 – Max 513 ovvero 510 +/- 3 ( abbastanza lontano dal tuo +/-1 che mi sembra un errore accettabile) e la situazione peggiora se provo con un arduino MKR1000 che ha una tensione di alimentazione di 3.3v.

    Ho anche inserito un condensatorino tra AREF e GND (che ho letto che puo’ alleviare il rumore di fondo) ma la situazione non cambia

    Sto alimentando Arduino da USB, tu stavi alimentando da trasformatore a presa 9V ?

    Da cosa può dipendere il fatto che trovo un errore per lo zero triplo rispetto a te ?

    •  

      Ciao, mi rispondo da solo ^_^
      Oggi tornato a casa da lavoro ho verificato che se alimento arduino da USB ho i valori sopra detti, mentre se collego anche la presa normale 9v 1A i valori sono in linea con quelli che hai detto nel tuo post!!
      Per fortuna ho scovato l’inghippo!!

      •  

        Cavoli, ero al lavoro e non riuscivo a risponderti. Comunque ti confermo che la fonte di alimentazione è molto importante. Nella mia esperienza posso dirti che alimentando da PC il rumore è alto, non adatto a questo scopo. Io di solito uso un alimentatore usb per telefono che è molto stabile, in altri casi ho usato un alimentatore dedicato. Comunque mi fa piacere che hai risolto da solo, è bello vedere persone che usano il cervello.

  7.  

    Ciao Stefano, complimenti per le info e la dovizia di particolari. Anche io sto cercando di cimentarmi con il controllo dell’energia di casa. Ho seguito con attenzione sia Home Energy Monitor System, sia il tuo post (in italiano 😉 ), ma non capisco dove sia il mio problema e spero che tu, visto che hai più esperienza di me, riesca a darmi un’indicazione corretta.
    Premetto che uso un CT diverso, ma i calcoli sono calcoli: il mio CT è CSI-0100 del i-tech, 20A di picco, 100 spire, schema con burden da 5 ohm (io ho fatto dei test anche con 7.5 ohm), partitore da 10KOhm, un piccolo elettrolitico da 10uF, ma in uscita non ottengo nulla di interessante in continua: sempre e solo 1.65V (lavoro con 3.3V): al contrario in alternata ottengo circa 8mV se collego una lampada da 18W, 50mV se collego un phon, che diventano 300mV e 600mV a seconda della temperatura.
    Non ho ancora effettuato alcun collegmanto ad Arduino, tutte le prove sono con il circuito del CT, il filo attraverso in CT ed i pochi componenti. Non capisco.
    Ah. lo schema elettrico dopo il CT è identico al tuo !

    Ciao e grazie.
    PS: ho fatto delle prove anche con i raddrizzatori di precisione (sia in tensione singola che in duale), ma sempre nulla di fatto.

  8.  

    buongiorno, è possibile aver una spiegazione del perchè viene utilizzzato questo if if(sensorvalue>maxval)? grazie

  9.  

    Senza un log completo non posso saperlo, non ho nulla in mano per poter rispondere. Vai su file -> impostazioni e su “Mostra output dettagliato” attiva almeno l’opzione “compilazione”, copi l’intero log e lo metti qui fra i commenti così posso leggerlo.