Vediamo come realizzare un semplice dispositivo per leggere la produzione di un impianto fotovoltaico e caricare i dati su un server online. La lettura manuale degli inverter di un impianto fotovoltaico è una procedura scomoda e tediosa ma è possibile automatizzare l'estrazione dei dati di produzione poichè molti inverter dispongono di interfaccia RS485. Grazie a tale interfaccia è possibile collegare un piccolo dispositivo elettronico in grado di interrogare gli inverter ad intervalli regolari e memorizzarli o inviarli ad un server remoto. I dati possono poi essere letti da smartphone o computer desktop da qualsiasi parte del mondo!
Un impianto fotovoltaico consiste di un insieme di pannelli, uno o più inverter, il contatore di produzione e quello di scambio:
L'inverter funziona autonomamente ma controllarne il corretto funzionamento è di primaria importanza per evitare cali di produzione e intervenire tempestivamente per guasti e malfunzionamenti. L'interfaccia RS485 mette a disposizione un numero di dati interessanti tra i quali:
Lo schema di base del progetto è abbastanza semplice. Siccome la stragrande maggioranza degli inverter usa RS485 ho optato per NodeMCU, un minicomputer da 7 euro (7 euro!) che dispone di interfaccia seriale, un certo numeri di GPIO programmabili e un potente modulo WiFi. NodeMCU può essere programmato per connettersi alla rete WiFi di casa e può ricevere o inviare dati ad un server remoto. Si programma esattamente come una scheda Arduino e non dispone di sistema operativo o programmi vari come un Raspberry Pi. Questa caratteristica lo rende perfetto al nostro scopo perchè l'imperativo in questo caso è l'affidabilità: un Raspberry Pi sarebbe stato altrettanto capace ma essendo un computer vero e proprio è soggetto ad aggiornamenti improvvisi, corruzioni del filesystem, blocchi inaspettati di sistema e chi più ne ha più ne metta. NodeMCU è più simile ad un microcontrollore che ad un vero PC: esegue un solo programma nella sua memoria flash, non ha una SD card che può deteriorarsi nel tempo e se viene a mancare la corrente si azzera tutto e riparte da capo senza problemi.
La scheda NodeMCU ha una seriale UART TTL che non è direttamente compatibile con RS485, è quindi necessario un secondo modulo in grado di convertire l'UART TTL del NodeMCU in un segnale RS485 adatto all'inverter. Queste schede di conversione si trovano a pochi centesimi su ebay o amazon.
NodeMCU dialoga con l'inverter tramite il modulo di conversione RS485, preleva i dati di produzione e li invia in wifi al server remoto. Un semplice script PHP nel server riceve i dati, li elabora e produce una pagina HTML consultabile da qualsiasi smartphone Android/iPhone o PC desktop
L'intervallo di interrogazione e di caricamento dei dati nel server è totalmente configurabile, 1 minuto è più che sufficiente. Lo script PHP può essere configurato per inviare email in caso di guasto o temperatura eccessiva degli inverter o semplicemente per notificare l'utente a fine giornata della produzione totale. La pagina HTML è estremamente semplice e mostra i dati cosi' come vengono acquisiti dalla scheda NodeMCU:
Ogni blocco corrisponde ad un inverter e contiene i dati di produzione. Il blocco è verde quando tutto è ok, diventa rosso in caso di guasto o temperatura eccessiva.
Il cervello del progetto è questa piccola scheda, NodeMCU, un minicomputer da 7 euro in grado di connettersi in WiFi alla rete di casa, implementa tutto lo stack TCP/IP per l'invio e ricezione di dati a server remoti, possiede 16 GPIO programmabili, una UART bidirezionale, un'altra UART solo in trasmissione, interfaccia pr SD card (opzionale) e interfaccia SPI:
Ecco i dettagli della piedinatura:
La scheda si programma tramite USB esattamente come Arduino, basta scaricare l'IDE ufficiale Arduino, installare la libreria ESP8266 (NodeMCU è essenzialmente una dev board per ESP8266) e configurare l'ambiente di sviluppo per la programmazione. Ecco un'ottima guida per iniziare. La seriale UART è mappata ai pin RX/TX e purtroppo non possono essere usati direttamente per dialogare con l'inverter che accetta RS485. Fortunatamente l'unica sostanziale differenza tra seriale UART e RS485 è soltanto nel livello fisico e non quello di protocollo percui un semplice convertitore è tutto quello che serve
Questo convertitore a basso costo trasforma il segnale UART del NodeMCU in un segnale RS485 e viceversa.
I pin A e B andranno collegati ai corrispondenti piedini A e B degli inverter nella classica configurazione in cascata mentre all'altro lato i piedini RO, DI, DE, RE andranno collegati alla scheda NodeMCU. I pin RO (Out) e DI (In) vanno collegati rispettivamente ai pin RX e TX della scheda NodeMCU. DE e RE sono piedini speciali utilizzati per abilitare la lettura o la scrittura sul doppino RS485. DE abilita il driver interno di scrittura e va impostato ad 1 quando si vuole transmettere un pacchetto dati verso gli inverter. RE abilita l'ascolto e va impostato a 0 quando si vuole ricevere un pacchetto di risposta da uno degli inverter. Siccome DE è attivo alto e RE attivo basso e siccome la comunicazione con gli inververter è half-duplex (botta e risposta con un solo master) è possibile collegare tra loro questi due pin e comandarli con un unico GPIO della scheda NodeMCU. Quando vogliamo inviare un pacchetto dati agli inverter basterà alzare il GPIO ad 1 , quando vogliamo ricevere lo impostiamo basso
Il circuito è estremamente semplice, la scheda NodeMCU viene alimentata tramite USB da un normale alimentatore a 5v (assicuriamoci che riesca a fornire almeno 1000mA di corrente, altrimenti il driver RS485 non riuscirà a comunicare con gli inverter). I piedini TX/RX della scheda sono collegati a RO/DI del convertirore RS485. Il GPIO5 comanda la scrittura / ricezione dei dati ed è collegato ai piedini RE/DE del convertitore. Il convertitore è alimentato a 3.3V dalla scheda NodeMCU stessa. I pin A e B del convertitore vanno agli inverter
Il convertitore è alimentato a 3.3v per renderlo compatibile con i livelli elettrici dell' UART del NodeMCU, che sono a 0-3.3v. La tensione massima prodotta dal convertitore RS485 sarà di 3.3v che è perfettamente sufficiente per dialogare con gli inverter (lo standard RS485 prevede un minimo di 1.5v, alcuni dispositivi accettano fino a 200mV):
Ecco una foto dei due moduli collegati tra loro, a sinistra la scheda NodeMCU, a destra il convertitore RS485 collegato al doppino che va agli inverter
Gli inverter utilizzano una variante del protocollo MODBUS in modalità half-duplex. Ciò significa che ad ogni istante di tempo c'è solo un dispositivo che "parla" sulla linea mentre gli altri "ascoltano". Esiste un solo master ossia la scheda NodeMCU, tutti gli inverter sono slave. Il protocollo è di tipo "botta e risposta" cioè il master invia una richiesta e uno slave (un inverter) risponde: gli inverter non iniziano mai di loro iniziativa a dialogare con il master, è sempre e solo il master che interroga e riceve (eventualmente) una risposta.
Una trasmissione si compone di un singolo pacchetto MODBUS che include 7 campi:
Esistono 4 tipi diversi di comandi:
Il comando RICHIESTA DATI DI PRODUZIONE viene inviato dal master (NodeMCU) ad intervalli regolari e contiene l'indirizzo di destinazione dell'inverter che vogliamo interrogare. Il payload è vuoto. L'inverter risponderà con un pacchetto simile contenente i dati di produzione. Nel caso degli inverter Solartec si tratta di un payload di esattamente 90 byte che contiene temperatura, corrente, tensione, produzione giornaliera, produzione totale e molto altro. La corretta decodifica di questo payload va fatta caso per caso e dipende dal modello di inverter. Ogni inverter ha il suo indirizzo univoco (receiver address) ma come viene assegnato questo indirizzo? Lo vediamo nel prossimo comando.
Il comando ASSEGNAZIONE INDIRIZZO è inviato dal master in broadcast (non abbiamo ancora un indirizzo specifico al quale inviare il pacchetto!) e contiene nel payload il numero seriale dell'inverter e l'indirizzo che vogliamo assegnare, ad esempio:
1003BW0063, 0x0012
Ossia assegnamo l'indirizzo 0x0012 all'inverter con numero seriale 1003BW0063. L'inverter con questo seriale (e solo lui) risponderà affermativamente con un ulteriore pacchetto modbus nel quale payload sarà di nuovo specificato l'indirizzo richiesto, a conferma dell'avvenuta associazione.
Il master non fa altro che inviare una richiesta di associazione per tutti gli inverter che conosce (la lista dei numeri seriali). Ma come fa il master a sapere la lista dei seriali? Ci sono due modi possibili. O la codifichiamo la lista nel firmware della scheda NodeMCU, soluzione non esattamente flessibile, oppure usiamo il prossimo comando.
Il comando RICHIESTA NUMERO SERIALE è inviato dal master ad intervalli regolari per "cercare" nuovi inverter sulla linea e richiederne il codice seriale. Siccome gli inverter possono accendersi e spegnersi continuamente per via delle differenti condizioni atmosferiche o semplicemente alla sera, è necessario inviare questo pacchetto ad intervalli regolari, tipo ogni 10 secondi, e vedere quali nuovi inverter sono disponibili in linea. Il payload è vuoto e l'indirizzo di destinazione è broadcast. Non appena un inverter si accende (tipo al mattino) riceverà questo pacchetto e risponderà con il proprio seriale (nel payload della risposta ovviamente). Il master procederà quindi ad assegnare un indirizzo e poi a ciclare continuamente con le richieste di produzione.
Questo comando è inviato dal master al primo riavvio tre o quattro volte di fila per resettare gli inverter e annullare eventuali associazioni indirizzo precedenti. In questo modo tutti gli inverter saranno di nuovo disponibili a farsi assegnare un nuovo indirizzo. Se non inviassimo questo comando all'avvio del master, potremmo cadere nel caso sfortunato in cui il master si riavvia per qualche motivo (ad esempio una interruzione momentanea dell'alimentazione), perde memoria degli indirizzi degli inverter, ma gli inverter stessi non accettano ulteriori associazioni indirizzo perchè ne hanno già uno impostato.
Andiamo ora a vedere il firmware della scheda NodeMCU. Il firmware è scritto in C e contiene tutto il codice per dialogare con gli inverter tramite protocollo MODBUS e per inviare i dati al backend remoto PHP.
Il cuore del firmware è questo ciclo infinito che colleziona i dati dagli inverter e poi li invia in HTTP al server remoto
void loop()
{
int u = 0;
delay(1000);
// get data from inverters
getdata();
// upload data online
upload();
}
La fase di setup imposta la seriale TX/RX del NodeMCU, il GPIO 2 per selezionare il modo trasmissione / ricezione dei dati, alloca la memoria e invia 3 comandi di reset per resettare le associazioni indizzo-inverter.
void setup()
{
Serial.begin(9600);
pinMode(gpiod2, OUTPUT);
delay(1000);
memset(inverters, 0, sizeof(inverters));
sendpacket(0, 4, 0); // reset
sendpacket(0, 4, 0); // reset
sendpacket(0, 4, 0); // reset
}
La funzione GetData() non fa altro che ciclare su tutti gli inverter attuamente conosciuti e ne richiede i dati di produzione:
void getdata()
{
int discover = 1;
for(int slot = 0; slot < MAX_INVERTERS; slot++) { if(discover) { discovernew(); discover = 0; } if(inverters[slot] != 0) { discover = 1; t_inverter* ptr = inverters[slot]; sendpacket(ptr->address, 0x0102, 0); // data request
int res = readpacket();
if(res > 0)
{
// copy payload
ptr->lastdatalen = res;
for(int p = 0; p < res; p++) ptr->lastdata[p] = payload[p];
}
else if(res == -1) // timeout
{
ptr->retry++;
if(ptr->retry == MAX_RETRY)
{
free(ptr);
inverters[slot] = 0;
}
}
}
}
}
La funzione GetNew() invece si inframezza alle richieste di produzione e prova a cercare nuovi inverter da aggiungere alla lista di quelli già conosciuti:
int discovernew()
{
int slot = nextempty();
if(slot < 0) return -1; // no more space left sendpacket(0, 0x0000, 0); // serial request int res = readpacket(); if(res > 0)
{
// choose address
int address = slot + 1;
char name[1024];
// copy name
for(int n = 0; n < res; n++) name[n] = payload[n]; name[res] = 0; sendhttp("found:" + String(name)); // build payload payload[res] = address & 0xff; sendpacket(0, 0x0001, res + 1); // pairing request res = readpacket(); if(res == 1) // payload must be 1 byte long { // confirmed t_inverter* ptr = (t_inverter*)malloc(sizeof(t_inverter)); ptr->retry = 0;
ptr->address = address;
strcpy(ptr->name, name);
inverters[slot] = ptr;
return 1;
}
}
return -1;
}
Le funzioni accessorie sendpacket(), readpacket() e sendhttp() sono usate rispettivamente per inviare un pacchetto MODBUS sulla linea, riceverne uno di risposta, e per inviare i dati di produzione al server remoto tramite protocollo standard HTTP. Username e password della rete WiFi sono codificati nel firmware cosi come l'indirizzo remoto della pagina PHP; una soluzione più sofisticata potrebbe prevedere una modalità di configurazione via USB nella quale specificare tutti questi parametri.
La scheda NodeMCU completa del convertitore RS485 può essere alimentata direttamente dalla porta USB di uno degli inverter. Se gli inverter non hanno una porta USB basta usare un normale caricatore del telefono da almeno 1000mA.
Ovviamente deve essere presente un segnale WiFi. Se la rete non fosse presente in prossimità degli inverter è necessario portare il doppino RS485 all'interno dell'abitazione o in prossimità, nessun problema considerando che è possibile coprire un chilometro e mezzo con RS485 a 9600 baud. Il trasmettitore funziona in completa autonomia, si collega automaticamente alla rete WiFi e si ricollega in caso di connessione internet temporaneamente assente. Nel server una semplice pagina PHP riceve i dati di produzione e ripropone gli stessi dati nel browser:
La pagina HTML può essere aperta da smartphone, tablet o PC desktop da qualsiasi parte del mondo senza essere nelle vicinanze degli inverter. Inoltre è possibile configurare il server in modo tale da inviare email a fine giornata con il totale della produzione oppure email di notifica in caso di guasti o temperatura eccessiva.
Dato che me lo avete chiesto in tantissimi, ho deciso di pubblicare tutti i sorgenti (firmware NodeMCU e server PHP) sulla mia pagina GitHub. Ovviamente il progetto è aperto a pull request per miglioramenti (es. supportare più tipi di inverter, altri protocolli, pagina HTML più moderna, etc..)
https://github.com/gianlucag/Solarino
Ciao Giorgio, grazie. Lato server è un semplice script PHP che riceve l'upload HTTP POST, decodifica i dati e li memorizza in un file di testo. E' la parte del sistema che non dipende dagli inverter, RS485 o da NodeMCU. Semplicemente prende il pacchetto dati inviato da NodeMCU e aggiorna il file di testo sul server. Il file di testo è poi riletto quando accedi alla pagina con un browser. Trovi una buona guida qui -> http://www.html.it/pag/62463/le-richieste-http-get-e-post/
Ciao Gianluca. Complimenti per il lavoro fatto. Il mio raspberry che funge da log collector dell'inverter non è la soluzione ottimale in quanto ogni tanto le SSD si corrompono. Vorrei replicare la tua soluzione, è possibile avere i sorgenti completi? Grazie Matteo
Ciao Gianlica, perchè non hai messo lo sketch di Arduino e anche lo script in PHP in allegato?? Lo chiedo perché sono molto interessato al progetto.
Ciao Matteo, certo! Il RasberryPi non è adatto in questi casi perchè troppo delicato: tenta di aggiornarsi in continuazione, deteriora col tempo la SD card, può andare in blocco e soprattutto non gradisce interruzioni di corrente (non si riavvia da solo). Ti passo i sorgenti ma considera che il mio sistema è progettato intorno ad uno specifico modello di inverter (Soltec)
Ciao Thomas, ti passo i sorgenti ma considera che il sistema è progettato intorno ad uno specifico modello di inverter (Soltec)
OK Grazie. Dove li trovo i sorgenti ?
Ciao Gianluca, ho un setup molto simile al tuo, potresti passarmi i sorgenti? Grazie mille!
Ciao Alessandro, nel post descrivo il firmware abbastanza nei dettagli, almeno le parti critiche. Non credo che il sistema ti funzionerebbe se ti passassi il .bin da flashare nel micro
Ciao, volevo chiederti se puoi passarmi i sorgenti, sto cercando di fare la stessa cosa a casa mia!
grazie per la gentilezza!
Ciao Gianluca . Grazie mille per il tuo interessantissimo articolo.Progetto veramente interessante ,
Vorrei utilizzare una wemos d1 mini con il covrertitore rs485 per leggere i dati del mio inverter abb, purtroppo non ho ancora dimestichezza con il software e le librerie da installare sulla Wemos. Se mi potessi trasmettere il sorgente te ne sarei veramente grato.
Saluti Antonio.
Ciao Antonio, il firmware che vedi nell'articolo è tutto quello che serve. L'unica funzione che manca è la costruzione del pacchetto MODBUS perchè è specifica del mio modello di inverter. Ogni inverter ha il suo protocollo specifico quindi sarebbe inutile includerla. Devi intercettare il segnare RS485 prodotto da un lettore compatibile e quindi interpretare i dati
Complimenti per il lavoro pubblicato.
Vorrei implementare il tuo progetto a casa mia, potrei avere il sorgente d caricare nel NodeMcu?
Grazie in anticipo
Ciao Gianluca, per caso ho trovato il tuo progetto in internet, penso sia quello che faccia esattamente al caso mio e vorrei avere la possibilità di poterlo provare a casa. Come faccio a ricevere il sorgente?
Grazie.
Grazie e mille Gianluca , speriamo di farcela.
Buona Serata e ancora complimenti
Ciao Gianluca vorrei sapere se oltre a leggere dati dal fotovoltaico posso leggere dati da un misuratore consumi (potenza, energia, corrente...) con uscita rs485. Grazie
Ciao Francesco, si, il codice è riadattabile per qualsiasi altro device RS485. L'importante è che comunichi sempre con lo stesso formato modbus, questo andrebbe verificato. In ogni caso, anche se il misuratore di consumi dovesse utilizzare un altro tipo di protocollo, il codice è sempre valido, basta solo modificare la funzione che crea il pacchetto dati
Ciao Gianluca è possibile un contatto in pvt? Suppongo hai la mia mail. Grazie, Francesco.
Ciao Gianluca, mi invieresti lo sketch di Arduino e anche lo script in PHP? Per il protocollo lascia pure quello per il tuo inverter come esempio, poi mi arrangio io a modificarlo. Grazie e complimenti!
Ciao Gianluca, è possibile farti qualche domanda via mail? Grazie, Claudio.
Hi Gianluca. Thank you for your interesting project.
Is possible to get full source? Thank you very much Pavel.
Ciao Gianluca, vorrei provare il tuo progetto, mi puoi inviare i sorgenti? Grazie, Claudio
Buona Sera Gianluca posso avere i sorgenti dell tuo programa, magari dieto anche una donazione .
Grazie
Ciao Gianluca, ho letto con attenzione il tuo articolo e sono rimasto senza parole. Ho un impiantino home made a casa e vorrei provare a replicare il tuo sistema. Chiedo anche io, se posso, i sorgenti compresi lato server dove non ho molta dimestichezza, ed è da poco che sto approcciando con arduino. Considera che ho inverter come quello pubblicato quindi andrebbe bene anche la funzione di costruzione del pacchetto MODBUS.
Approfitto del triste momento che stiamo attraversando per dedicare un pochino di tempo in più alle mie passioni. Ti ringrazio comunque di tutto il materiale che hai e che metterai a disposizione di tutti,
Un caro saluto, Stefano.
Ciao Stefano!
Trovi tutti i sorgenti (firmware NodeMCU e server PHP) sulla mia pagina GitHub
https://github.com/gianlucag/Solarfi
Ciao Mario!
Trovi tutti i sorgenti (firmware NodeMCU e server PHP) sulla mia pagina GitHub
https://github.com/gianlucag/Solarfi
Ciao Claudio!
Trovi tutti i sorgenti (firmware NodeMCU e server PHP) sulla mia pagina GitHub
https://github.com/gianlucag/Solarfi
Hello Pavel!
Please find the source code (NodeMCU firmware and PHP server) on my GitHub page
https://github.com/gianlucag/Solarfi
Ciao Attilio!
Trovi tutti i sorgenti (firmware NodeMCU e server PHP) sulla mia pagina GitHub
https://github.com/gianlucag/Solarfi
Ciao gianluca e complimenti, a questo punto vorrei chiederti se e possibile eseguire una lettura dei quadri di campo anche loro con comunicazione rs485
Ciao Emanuele,
Ovviamente si ma occorre conoscere il protocollo di comunicazione dei quadri di campo
Ciao Gianluca
Vorrei leggere degli inverter nei campi fotovoltaici da 1 MW, e possibile con questa soluzione?
Mi piacerebbe sapere come grazie
@emanueleimpianto@gmail.com Ciao Emanuele, il sistema funziona solo con inverter che utilizzano un particolare dialetto del MODBUS quindi non saprei dirti se puoi adattarlo o meno. Sicuramente devono utilizzare una linea RS485. Se mandi il modello dell'inverter posso vedere se utilizza lo stesso protocollo o meno.
@Gianluca (ADMIN)
Il protocollo rs485 è presente su tutti i ns inverter , ad esempio abbiamo i siemens, gli abb , general ecc... ma tutti sono rs485.
Per i contatori e possibile leggere i protocoli 1.8.0 esempio
@emanueleimpianto@gmail.com
Che intendi per protocollo 1.8.0.? Purtroppo ogni vendor usa un protocollo proprietario o un dialetto di protocolli più blasonati (modbus etc..). Rs485 è solo il livello fisico di trasporto dei pacchetti, poi come sono codificati questi pacchetti dipende dal particolare tipo di inverter. I vendor tendono a comportarsi cosi per poter vendere il proprio sistema di logging. L'unica è provare a vedere nelle specifiche tecniche se esiste qualche riferimento al protocollo utilizzato e in caso aggiungerlo ai protocolli supportati dal mio firmware.
@Gianluca (ADMIN) ciao Gianluca il protocollo che mi chiedi può essere ad esempio questo:
RS485 half duplex + equipotenziale
+
9600 bps / 38400 bps
bit dati - nessuna parità - 1 bit di Stop
MODBUS e SAC
2500 Vrms minuto.
500m
Slave. Risponde soltanto ai comandi
Da 01 a 32 protocollo MODBUS e SAC
32
10 cifre numeriche che, tramite identificazione
Molto interessante. Se potessi postare anche il codice per leggere i dati da web te ne sarei molto grato.