vielen Dank an Meyenfelder für die Idee und die Infos dazu! Ich habe das nun an meiner Huawei-Anlage (SUN2000-4.6KTL-L1) auch umgesetzt. Zusätzlich hab ich noch einen Batteriespeicher (LG RESU 10H) der leider keine Ladezustandsanzeige besitzt, der hängt am gleichen Bus (Adr15). Leider gibts vom LG Resu dazu keine Doku, daher hab ich das Protokoll mitgeschrieben und analysiert, die beiden für mich wichtigen Werte (Ladezustand und Ladeleistung) hab ich gefunden, siehe Code. Im Programm warte ich bis beide Geräte vom Master abgefragt wurden (passiert ca 1x/sek), werte die entsprechenden Register aus und stelle dann alle Werte an einem Nextion-Display dar. Ich verwende einen Arduino Pro Mini mit einer 2€ RS485-Adapterplatine. Die RS485-Platine darf nur empfangen, also sind die Pins !RE und DE beide auf GND. Der RO-Pin geht auf Arduino RX. Den Arduino-TX-Pin verwende ich zum Senden der Daten an das Nextion-Display. hier mein Arduino-Code, vielleicht hilft das dem einen oder anderen als Basis: (Falls jemand das Nextion-File auch haben will, gerne per PN) Code: const int BUFFER_SIZE = 160; char buf[BUFFER_SIZE]; float Wirkleistung; int Ladeleistung_raw; //Teiler1000 int Ladezustand_raw; //Teiler2 float Ladeleistung; float Ladezustand; unsigned long lastread_zaehler; unsigned long lastread_akku; unsigned long lesetimeout; byte recbuf; boolean gelesen_zaehler=false; boolean gelesen_akku=false; void setup() { Serial.begin(9600); } void loop() { bytelesen(); if (recbuf == 0x0B) { //Adr 11=Stromzähler DTSU666-H bytelesen(); if (recbuf == 0x03) { //03=Kommando Register lesen bytelesen(); if (recbuf == 0xA0) { //0xA0=160 Bytes Daten Serial.readBytes(buf, 160); ((byte*)&Wirkleistung)[3]=buf[48]; //ab 25. Register Wirkleistung % (float) ((byte*)&Wirkleistung)[2]=buf[49]; ((byte*)&Wirkleistung)[1]=buf[50]; ((byte*)&Wirkleistung)[0]=buf[51]; Wirkleistung=Wirkleistung/1000.0; //in kW lastread_zaehler=millis(); gelesen_zaehler=true; } } } if (recbuf== 0x0F) { //Adr 15=LG Resu bytelesen(); if (recbuf == 0x03) { //03=Kommando Register lesen bytelesen(); if (recbuf == 0x38) { //0x38=56 Bytes Daten Serial.readBytes(buf, 56); ((byte*)&Ladeleistung_raw)[1]=buf[4]; //3. Register Ladeleistung_raw W (kw Teiler1000) ((byte*)&Ladeleistung_raw)[0]=buf[5]; ((byte*)&Ladezustand_raw)[1]=buf[40]; //21. Register Ladezustand_raw % (Teiler2) ((byte*)&Ladezustand_raw)[0]=buf[41]; Ladeleistung=Ladeleistung_raw/1000.0; Ladezustand=Ladezustand_raw/2.0; lastread_akku=millis(); gelesen_akku=true; } } } if(gelesen_zaehler&&gelesen_akku){ digitalWrite(13,HIGH); nextion(); while(Serial.available()){ //Puffer löschen bevor neuer Leseversuch recbuf=Serial.read(); } //Serial.end(); //Serial.begin(9600); gelesen_zaehler=false; gelesen_akku=false; digitalWrite(13,LOW); } if(millis()>lastread_zaehler+10000){ Wirkleistung=0.0; nextion(); lastread_zaehler=millis(); } if(millis()>lastread_akku+10000){ Ladeleistung=0.0; Ladezustand=0.0; nextion(); lastread_akku=millis(); } } void bytelesen(){ //warten auf nächstes Byte und lesen, max 1s warten (nicht blockierend) lesetimeout=millis(); while(!Serial.available() && (millis()<lesetimeout+1000)){} recbuf=Serial.read(); } void nextion(){ //alle Werte aufs Display schreiben Serial.print("t2.txt="); Serial.write(0x22); Serial.print(Ladezustand,1); Serial.print("%"); Serial.write(0x22); Serial.write(0xFF); Serial.write(0xFF); Serial.write(0xFF); Serial.print("j0.val="); Serial.print(Ladezustand,0); Serial.write(0xFF); Serial.write(0xFF); Serial.write(0xFF); Serial.print("j0.pco="); if(Ladezustand>60){ Serial.print("2016"); //gn } else if (Ladezustand>30){ Serial.print("64512"); //or } else { Serial.print("63488"); //rt } Serial.write(0xFF); Serial.write(0xFF); Serial.write(0xFF); Serial.print("t1.txt="); Serial.write(0x22); Serial.print(Ladeleistung,2); Serial.print("kW"); Serial.write(0x22); Serial.write(0xFF); Serial.write(0xFF); Serial.write(0xFF); Serial.print("t0.txt="); Serial.write(0x22); Serial.print(Wirkleistung,2); Serial.print("kW"); Serial.write(0x22); Serial.write(0xFF); Serial.write(0xFF); Serial.write(0xFF); Serial.print("g0.dir="); if(Ladeleistung>=0){ Serial.print("1"); //nach links } else { Serial.print("0"); //nach rechts } Serial.write(0xFF); Serial.write(0xFF); Serial.write(0xFF); Serial.print("g2.dir="); if(Ladeleistung>=0){ Serial.print("2"); //nach unten } else { Serial.print("3"); //nach oben } Serial.write(0xFF); Serial.write(0xFF); Serial.write(0xFF); Serial.print("g1.dir="); if(Wirkleistung<0){ Serial.print("0"); //nach rechts } else { Serial.print("1"); //nach links } Serial.write(0xFF); Serial.write(0xFF); Serial.write(0xFF); }
const int BUFFER_SIZE = 160; char buf[BUFFER_SIZE]; float Wirkleistung; int Ladeleistung_raw; //Teiler1000 int Ladezustand_raw; //Teiler2 float Ladeleistung; float Ladezustand; unsigned long lastread_zaehler; unsigned long lastread_akku; unsigned long lesetimeout; byte recbuf; boolean gelesen_zaehler=false; boolean gelesen_akku=false; void setup() { Serial.begin(9600); } void loop() { bytelesen(); if (recbuf == 0x0B) { //Adr 11=Stromzähler DTSU666-H bytelesen(); if (recbuf == 0x03) { //03=Kommando Register lesen bytelesen(); if (recbuf == 0xA0) { //0xA0=160 Bytes Daten Serial.readBytes(buf, 160); ((byte*)&Wirkleistung)[3]=buf[48]; //ab 25. Register Wirkleistung % (float) ((byte*)&Wirkleistung)[2]=buf[49]; ((byte*)&Wirkleistung)[1]=buf[50]; ((byte*)&Wirkleistung)[0]=buf[51]; Wirkleistung=Wirkleistung/1000.0; //in kW lastread_zaehler=millis(); gelesen_zaehler=true; } } } if (recbuf== 0x0F) { //Adr 15=LG Resu bytelesen(); if (recbuf == 0x03) { //03=Kommando Register lesen bytelesen(); if (recbuf == 0x38) { //0x38=56 Bytes Daten Serial.readBytes(buf, 56); ((byte*)&Ladeleistung_raw)[1]=buf[4]; //3. Register Ladeleistung_raw W (kw Teiler1000) ((byte*)&Ladeleistung_raw)[0]=buf[5]; ((byte*)&Ladezustand_raw)[1]=buf[40]; //21. Register Ladezustand_raw % (Teiler2) ((byte*)&Ladezustand_raw)[0]=buf[41]; Ladeleistung=Ladeleistung_raw/1000.0; Ladezustand=Ladezustand_raw/2.0; lastread_akku=millis(); gelesen_akku=true; } } } if(gelesen_zaehler&&gelesen_akku){ digitalWrite(13,HIGH); nextion(); while(Serial.available()){ //Puffer löschen bevor neuer Leseversuch recbuf=Serial.read(); } //Serial.end(); //Serial.begin(9600); gelesen_zaehler=false; gelesen_akku=false; digitalWrite(13,LOW); } if(millis()>lastread_zaehler+10000){ Wirkleistung=0.0; nextion(); lastread_zaehler=millis(); } if(millis()>lastread_akku+10000){ Ladeleistung=0.0; Ladezustand=0.0; nextion(); lastread_akku=millis(); } } void bytelesen(){ //warten auf nächstes Byte und lesen, max 1s warten (nicht blockierend) lesetimeout=millis(); while(!Serial.available() && (millis()<lesetimeout+1000)){} recbuf=Serial.read(); } void nextion(){ //alle Werte aufs Display schreiben Serial.print("t2.txt="); Serial.write(0x22); Serial.print(Ladezustand,1); Serial.print("%"); Serial.write(0x22); Serial.write(0xFF); Serial.write(0xFF); Serial.write(0xFF); Serial.print("j0.val="); Serial.print(Ladezustand,0); Serial.write(0xFF); Serial.write(0xFF); Serial.write(0xFF); Serial.print("j0.pco="); if(Ladezustand>60){ Serial.print("2016"); //gn } else if (Ladezustand>30){ Serial.print("64512"); //or } else { Serial.print("63488"); //rt } Serial.write(0xFF); Serial.write(0xFF); Serial.write(0xFF); Serial.print("t1.txt="); Serial.write(0x22); Serial.print(Ladeleistung,2); Serial.print("kW"); Serial.write(0x22); Serial.write(0xFF); Serial.write(0xFF); Serial.write(0xFF); Serial.print("t0.txt="); Serial.write(0x22); Serial.print(Wirkleistung,2); Serial.print("kW"); Serial.write(0x22); Serial.write(0xFF); Serial.write(0xFF); Serial.write(0xFF); Serial.print("g0.dir="); if(Ladeleistung>=0){ Serial.print("1"); //nach links } else { Serial.print("0"); //nach rechts } Serial.write(0xFF); Serial.write(0xFF); Serial.write(0xFF); Serial.print("g2.dir="); if(Ladeleistung>=0){ Serial.print("2"); //nach unten } else { Serial.print("3"); //nach oben } Serial.write(0xFF); Serial.write(0xFF); Serial.write(0xFF); Serial.print("g1.dir="); if(Wirkleistung<0){ Serial.print("0"); //nach rechts } else { Serial.print("1"); //nach links } Serial.write(0xFF); Serial.write(0xFF); Serial.write(0xFF); }