- LiFePO4 Speicher Test         
RSS-Feed anzeigen

hoerbi1

Huawei Wechselrichter auslesen RS485 Modbus mit Arduino

Bewerten
Hallo Miteinander, ich habe für Euch ein vielleicht einfaches Problem zu lösen.

Ich habe einen Smart Power Meter (Huawei DTSU666-H 250 A/50mA) welcher in Verbindung mit meinem Wechselrichter steht (Huawei SUN2000 12KTL)
Das Protokoll ist ein RS485.
Weiß wer von Euch welchen Register ich da hernehmen muss? Ich verzweifle schön langsam und habe alle Varianten durch.
Ich benötige lediglich den Wert "Aktive Power" Mit der Adresse 40525. (Benötige ich da den HEX Wert oder nur 0525?)
Am Smartmeter ist die Communication-Address: 11 - jedoch wo füge ich das ein?
Am Ende des Beitrags hänge ich die entsprechenden Daten von Huawei an.

Vielen Dank falls sich jemand erbarmt um mich... vielen vielen Dank

Code:
#include <ModbusMaster.h>
#include <SoftwareSerial.h>

#define MAX485_TX_ENABLE  7  // EIA-485 transmit control pin; MAX485 Module PIN DE and RE
#define EIA485_RX         9  // EIA-485 serial receive pin ; MAX485 Module PIN RO
#define EIA485_TX        10  // EIA-485 serial transmit pin ; MAX485 Module PIN DI

ModbusMaster node;
SoftwareSerial RS485Serial(EIA485_RX, EIA485_TX); // Hier wird der serielle Port beschrieben

void preTransmission() {
  digitalWrite(MAX485_TX_ENABLE, true);// Vor der Übertragung wird Pin 7 auf High gesetzt.
}

void postTransmission() {
  digitalWrite(MAX485_TX_ENABLE, false);// Nach der Übertragung wieder auf Low
}


void setup() {

  
  pinMode(MAX485_TX_ENABLE, OUTPUT);
  digitalWrite(MAX485_TX_ENABLE, false);

  Serial.begin(9600);
  RS485Serial.begin(9600); //Baudrate des Sensors auf 9600

  node.begin(1, RS485Serial);//Start der seriellen Schnittstelle, Slave ID 1 //???????????? Huwaei DTH666 says 11?????
  node.preTransmission(preTransmission);
  node.postTransmission(postTransmission);

  Serial.print("Hoerb1 KW ");// Bezeichnung meines Sensors
}


void loop() {
float result;
//uint16_t result;


  result = node.readInputRegisters(0525, 1);//Funktion : Read Input Registers, Modbus Adressen 2 //???????? no idea if it is right
 if (result == node.ku8MBSuccess)
  {
    
    Serial.print("Active Power: ");
    Serial.println(node.getResponseBuffer(0)*0.1,1);// 1. Part????????????
    Serial.println(node.getResponseBuffer(1)*0.1,1); // 2. Part???????????
    Serial.println(" kw");


  }
  else {
  Serial.print("Fehler beim Auslesen des Sensors\n");
  }

  delay(2000);//Aktualisierung alle 2 Sekunden
}
Klicke auf die Grafik für eine größere Ansicht

Name:	b35deff9c441e0e271828915f15a6e6df6872cdf.jpg
Hits:	717
Größe:	90,1 KB
ID:	35779
Klicke auf die Grafik für eine größere Ansicht

Name:	grafik(2).png
Hits:	456
Größe:	38,4 KB
ID:	35780
Klicke auf die Grafik für eine größere Ansicht

Name:	grafik(3).jpg
Hits:	405
Größe:	59,6 KB
ID:	35781
https://www.solarmarkt.ch/herstimg/3...rDTSU666-H.pdf
https://www-file.huawei.com/~/media/...0150715_JP.pdf

"Huawei Wechselrichter auslesen RS485 Modbus mit Arduino" bei Twitter speichern "Huawei Wechselrichter auslesen RS485 Modbus mit Arduino" bei Facebook speichern "Huawei Wechselrichter auslesen RS485 Modbus mit Arduino" bei Mister Wong speichern "Huawei Wechselrichter auslesen RS485 Modbus mit Arduino" bei YiGG.de speichern "Huawei Wechselrichter auslesen RS485 Modbus mit Arduino" bei Google speichern "Huawei Wechselrichter auslesen RS485 Modbus mit Arduino" bei del.icio.us speichern "Huawei Wechselrichter auslesen RS485 Modbus mit Arduino" bei Webnews speichern "Huawei Wechselrichter auslesen RS485 Modbus mit Arduino" bei My Yahoo speichern

Kategorien
Kategorielos

Kommentare

  1. Avatar von Meyenfelder
    Hallo hoerbi1,
    hatte das gleiche Problem und habe jetzt eine Lösung gefunden:
    Zum Auslesen der Smartmeterwerte genügt es die Kommunikation zwischen WR SUN 2000 und Smartmeter SM DTSU666-H einfach mitzulesen.
    WR fragt den SM mehrmals pro Sekunde ab. Habe den Verkehr mitgeschnitten und nach einigem Suchen die richtigen Stellen im Datensatz gefunden.
    Wichtig ist auch einen entsprechenden Peglewandler von RS485 auf TTL (0-5 Volt) zu verwenden. Habe das Modul von Pollin LC-TTL-MAX485 für 2 Euro benutzt.
    Komunikation läuft mit 9600 Bd, 8n1. Hier ein Auszug aus dem Datensatz:



    Anforderung vom WR an Zähler:
    0B03 Teilnehmer Adresse 0B->11 Kommando Register Lesen 03
    0836 Adresse 0836 hex -> 2102 dez
    0050 50 hex -> 80 dez es werden 80 Register a 2 Byte, 160 Byte angefordert
    A732 CRC

    Antwort vom Zähler an WR:
    0B Teilnehmer Adresse 0B -> 11 ist Adresse des DTSU666-H am Modbus
    03 Kommando Register Lesen 03
    A0 A0 hex -> 160 dez Byte die gesendet werden

    2102 2104 2106 2108 2110 2112 2114 2116
    4094 DD2F 4094 FDF4 40AA 5E35 4366 E666 4367 6666 4365 999A 4367 CCCD 43C7 F333 32 Bytes

    2118 2120 2122 2124 2126 2128 2130 2132 ab Adresse 2126, 49. - 52. Byte sind C551 899A = -3352,6 Watt
    43C7 999A 43C7 C000 43C8 8CCD 4247 E148 C551 899A C484 CCCD C484 ACCD C499 9666 Aktuelle Leistung in Watt, negativ = Export
    #### ####
    2134 2136
    C317 E666 C2B8 CCCD C205 999A C1D0 CCCD 4552 4B33 4485 A000 4485 1CCD 4499 D333

    2150 2158
    BF7E F9DB BF7E 353F BF7E F9DB BF7F 7CEE C502 C28F C430 FC29 C435 4A3D C424 BF5C

    2166 2170 2174
    4153 851F 41B0 51EC 4133 851F 42A3 051F 4503 9614 4436 7EB8 4438 1852 4439 2000
    0CF1 CRC


    Auswertung funktioniert dann so:
    Auf Zeichenfolge 0B 03 A0 Hex warten, dann 48 Byte verwerfen, die Bytes 49 - 52 sind die Leistung als Fliesskommazahl.

    Falls Du noch Probleme hast, bitte hier melden.

    Gruß Meyenfelder
  2. Avatar von Meyenfelder
    Sorry bin neu hier im Roboternetz,
    die Formatierung mit mehreren Leerzeichen hat nicht funktioniert.
    Hier nochmal als Code:

    Code:
    Anforderung vom WR an Zähler:
    0B03   Teilnehmer Adresse 0B->11 Kommando Register Lesen 03
    0836   Adresse 0836 hex -> 2102 dez   
    0050   50 hex -> 80 dez es werden 80 Register a 2 Byte, 160 Byte angefordert
    A732   CRC
    
    Antwort vom Zähler an WR:
    0B       Teilnehmer Adresse 0B -> 11 ist Adresse des DTSU666-H am Modbus
    03       Kommando Register Lesen 03
    A0       A0 hex -> 160 dez Byte die gesendet werden
    
    2102      2104      2106      2108       2110      2112      2114      2116         
    4094 DD2F 4094 FDF4 40AA 5E35 4366 E666  4367 6666 4365 999A 4367 CCCD 43C7 F333       32 Bytes
    
    2118      2120      2122      2124       2126      2128      2130      2132            ab Adresse 2126, 49. - 52. Byte sind C551 899A = -3352,6 Watt
    43C7 999A 43C7 C000 43C8 8CCD 4247 E148  C551 899A C484 CCCD C484 ACCD C499 9666       Aktuelle Leistung in Watt, negativ = Export
                                             #### ####
    2134      2136
    C317 E666 C2B8 CCCD C205 999A C1D0 CCCD  4552 4B33 4485 A000 4485 1CCD 4499 D333
    
    2150                                     2158
    BF7E F9DB BF7E 353F BF7E F9DB BF7F 7CEE  C502 C28F C430 FC29 C435 4A3D C424 BF5C
    
    2166                2170                 2174
    4153 851F 41B0 51EC 4133 851F 42A3 051F  4503 9614 4436 7EB8 4438 1852 4439 2000 
    0CF1     CRC

    Bei https://forum.huawei.com/enterprise/...mypfk1cl6f.png

    gibt es die Registerliste des DTSU666-H, bei Bedarf kann man da auch Spannungen, Ströme, Exportierte und Importierte
    Arbeit aus dem Datensatz rauslesen.

    Hoffentlich jetzt besser verständlich
    Meyenfelder
  3. Avatar von jak1983
    Hallo,

    ich bin gerade auf der Suche nach dieser Lösung und habe diesen Forumseintrag gefunden.
    Ich möchte mit einem Arduino Mega die Kommunikation zwischen Sun2000-10KTL-M1 und dem SmartMeter mitloggen und die "Active Power" weiterverwenden.
    Ich habe mir folgenden Pegelwandler bei Amazon besorgt
    https://www.amazon.de/ANGEEK-MAX485-...s%2C130&sr=8-8

    Ist diese Anschlussbelegung richtig?

    MAX485 Module
    GND GND Arduino
    VCC 5V Arduino
    A RS485 A
    B RS485 B
    DI Pin 9 Arduino
    DE Pin 7 Arduino
    RE Pin 7 Arduino
    RO Pin 9 Arduino

    Ich hoffe ihr seid noch aktiv im Forum und könnt mir damit weiterhelfen.

    mfg
    Hannes
  4. Avatar von per48or
    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);
    
    }
  5. Avatar von RaspiGebe
    Hallo, Super Erklärung von Meyenfelder, besten Dank. Hatte die gleiche Aufgabenstellung und dann mit mit einem Raspberry Pico und Micropython umgesetzt.

    Hänge aktuell aber noch an dem Auslesen des aktuellen Ladezustandes des Huawei Luna2000 Akkus, hab mir schon nen Wolf gesucht. Bräuchte lediglich noch die Adresse des Akkus auf dem RS485 Bus und das Register mit dem Ladezustand (aktuelle Kapazität in %) des Akkus. So wie es aussieht, werden bei mir lediglich zwei Adressen auf dem Bus mit dem Kommando 03 gehandelt: 05 und 0B =11 und weil 11 ja das Smartmeter ist und ausser WR, Smartmeter nur noch der Akku auf dem Bus hängt, denke ich dass 05 der Akku sein müsste. Allerdings gibt es hier deutlich mehr Traffic wie es mit dem Smartmeter der Fall ist, verschiedenste Abfragen und Antworten, da hänge ich aktuell noch, wie ich an die interessanten Register komme...

    Habe jetzt auch Dokumente gefunden bzw. vom Huawei Support bekommen, da ist beschrieben, dass die für mich interessanten Werte des Akkus im Bereich 37000, 38000 bzw. 47000 liegen. Diesen Adressbereich gibt es allerdings bei mir nicht in der Kommunikation der Komponenten, da haben die Nachrichten mit Bezug auf die Adresse 5 Anforderungen im Bereich 30100, 32200 und 39500 gesendet. Ich denke so eine Auflistung von Meyenfelder in Bezug auf den Akku würde mir da sehr helfen, weiss bloss nicht wo ich diese Info herkriege, oder ich interpretiere die Adressen falsch. Aber beim Smartmeter hat es ja schliesslich auch geklappt... Der Huawei Support kommt da leider nur mit Phrasen daher und zeigt kein wirkliches Interesse, mir bei dem Problem weiterzuhelfen

    Ohne Meyenfleders Erklärung und den Kontext auf das Register 2102 hätte ich es auch nicht geschafft, die aktuelle Power aus den Nachrichten auszulesen. Die Register Defintionen von Huawei hab ich jetzt schon xmal gelesen, komme damit aber nicht klar, weil diese einfach nicht mit den Daten und Adressen meines Traffics übereinstimmen. Entweder gibts da noch einen Offset oder Umsetzungsfaktor, aber den kenne ich leider nicht und konnte da auch noch kein entsprechendes Verhältnis erkennen...

    Hier mal ein Auszug aus dem Traffic Adresse 05 und Command 03:

    0503 9a4c 001b
    0503 9a4c 001b
    0503 36 000027
    0503 9a4c 001b
    0503 36 000027
    0503 7d33 0009
    0503 12 000102
    0503 16 00011e
    0503 9a4c 001b
    0503 36 000027
    0503 9a4c 001b
    0503 36 000027
    0503 7d33 0009
    0503 12 000102
    0503 7d51 001b
    0503 36 000000
    0503 9a4c 001b
    0503 36 000027
    0503 7595 000b
    0503 16 00011e
    0503 75c7 0005
    0503 0a 000000
    0503 7b66 000f
    0503 7dc9 0009
    0503 12 000102
    0503 9a4c 001b
    0503 36 000027
    0503 9a4c 001b
    0503 36 000027
    0503 7d33 0009
    0503 12 000102
    0503 9a4c 001b
    0503 36 000027
    0503 788c 0001
    0503 9a4c 001b
    0503 36 000027
    0503 7d00 001f
    0503 3e56 3130
    0503 9a4c 001b
    0503 36 000027
    Aktualisiert: 12.08.2023 um 09:24 von RaspiGebe

12V Akku bauen