Modbus RTU an Huawei SUN2000-8KTL-M1

Hallo zusammen,

vielleicht kann / möchte mir jemand helfen.

ich habe eine PV-Anlage installiert bekommen und habe meine Wärmepumpen-Heizung so umgebaut, dass ich über die Shelly-Cloud meine Zusatz-Heizungen in beiden Heizkreisen manuell zuschalten kann entweder 2 KW oder 4 KW jeweils … so weit so gut. im Büro sitzen, das Wetter sehend und die APP auf dem Handy … das funktioniert. ich möchte aber das etwas mehr automatischer haben.

Habe jetzt einen MEGA daliegen, einen Pegeladapter für den Modbus …. habe auch ein Programm gefunden, das mir aber mehr Fehler als brauchbare Daten liefert, von 10 Abfragen liefert 1 Abfrage verarbeitbare Werte.

Mir fehlt zum einen die Übersicht der abzufragenden Adressen im System und eben ein fehlerfrei laufendes Programm das über den Modbus die Huawei SUN abfagt. Angeschlossen habe ich den MODBUS am DTSU-6666-h ….

Gerne höre ich aus der Gruppe

Martin

Spezifiziere "MEGA" genauer.
Willst Du mit einem Arduino MEGA2560 und geeigneten Adapter über MOD-BUS Daten aus der PV Anlage lesen?

Zeig mal das Programm und die Verdrahtung.
Grüße Uwe

#include <ModbusMaster.h>

#define MAX485_DE      3     // DE MAX485 pin on the Arduino
#define MAX485_RE_NEG  2     // RE MAX485 pin on the Arduino, can be the same as DE

ModbusMaster node;            // Creates a Modbus node named node.

void preTransmission() {              // Mandatory to setup the MAX485 properly, even if used only for reception
    digitalWrite(MAX485_RE_NEG, 1);
    digitalWrite(MAX485_DE, 1);
}

void postTransmission() {             // Same
    digitalWrite(MAX485_RE_NEG, 0);
    digitalWrite(MAX485_DE, 0);
}

void setup() {
    pinMode(MAX485_RE_NEG, OUTPUT);   // Sets the pins as outputs (they will set RE and DE on or off to tell the MAX485 if its reading or writing)
    pinMode(MAX485_DE, OUTPUT);


    digitalWrite(MAX485_RE_NEG, 0);    // Init in receive mode by defining both to 0. If you need to transmit you need to define both to 1, thats why they can be both on the same pin.
    digitalWrite(MAX485_DE, 0);  

    Serial2.begin(9600, SERIAL_8N1);  // Starts the serial communication on Serial2 (TX2, RX2), 9600 baud, 8 bits - No parity - 1 stop bit

    node.begin(11, Serial2);          // We begin the node on address 11 (can be different on your side, read your documentation) through Serial2

    Serial.begin(9600);               // Starts the serial monitor on USB (Serial0)
    Serial.println("Starting Modbus Transaction:");
    
    node.preTransmission(preTransmission);    // Init stuff
    node.postTransmission(postTransmission);
}

void printData(const char* name, int registerAddress, const char* unit) {   // Creates a function with 3 parameters
    uint8_t result = node.readHoldingRegisters(registerAddress, 2);         // Stores the 2 bytes of the register at the address we chose

    if (result == node.ku8MBSuccess) {                    // If there is something in result, it works
        uint16_t data1 = node.getResponseBuffer(0);       // Stores the lower register in data1
        uint16_t data2 = node.getResponseBuffer(1);       // Stores the upper register in data2

        uint32_t combinedValue = (static_cast<uint32_t>(data1) << 16) | data2;  // Combines both registers to get full register

        float value;                                      // Interprets the combined value as a float
//                Serial.println(combinedValue); 
        memcpy(&value, &combinedValue, sizeof(float));

        Serial.print(name);
        Serial.print(" : ");
        Serial.print(value, 2); // prints with 2 decimals, set as you need
        Serial.print(" ");
        Serial.println(unit);
    } else {                    // If there is nothing in result, it doesn't work
        Serial.print("Failed to read ");
        Serial.println(name);
    }
}

void loop() {
    printData("Ua", 2110, "V");
    printData("Ub", 2112, "V");
    printData("Uc", 2114, "V");
    printData("Ia", 2102, "A");
    printData("Ib", 2104, "A");
    printData("Ic", 2106, "A");
    printData("Pa", 2128, "W");
    printData("Pb", 2130, "W");
    printData("Pc", 2132, "W");
    Serial.println("---------------------");  // Separation

    delay(1000); // Waits 1 second before reading again
}

Laut Meiner Doku ist Ua 0x2006. Man beachte das 0x

Zeige mal die ModbusDoku die du benutzt

Die Adressen sehen mir auch falsch aus:

Und mir scheint auch das zusammenbauen falsch zu sein.
Im Manual wird zwar in Table 11 von Word gesprochen, aber 4 word sind ein 32bit-Wert (Siehe Note 1) damit ist das word eigentlich ein byte. Und mir fehlt der Scaler. Bei V und P 0,01 und bei A 0,001.

berichtige mal die Adressen auf 0x2008 bis 0x2018 und las Dir schon in der Abfrage die Rohdaten ausgeben.

ja da wäre halt interessant, welchen Fehler du bekommst.
Gib dir das aus.

z.B.

Serial.print(F("Error: 0x")); Serial.println(result, HEX);

dann wie schon angesprochen, nimm mal nur eine Adresse aus dem PDF ... 2110 steht da nicht drinnen. 0x2006 könnte funktionieren.

Wenn nicht, poste deinen neuen Code, poste die komplette Ausgabe vom Serial Monitor.

Hallo zusammen,

danke für die Hilfe so weit! Habe die Adressen geändert und habs laufen lassen, hatte keine ‘Fehl-Lesung’.

ich hab mir das jetzt angeschaut und nach zuschalten meiner Flanschheizung auch gesehen, dass entweder 1Phase um 2000W hochgeht … oder im anderen Fall die beiden anderen Phasen um je 2000W …. das passt so weit.

Allerdings stelle ich jetzt fest, dass ich für mein Vorhaben vermutlich den falschen Datenlieferanten habe.

Wie geschrieben, ich möchte je nach Leistung über die Panel von oben, dem jeweiligen Akku-Stand bzw die Akku-Ladeleistung die Verbraucher zuschalten.

Da bin ich dann wahrscheinlich beim DTSU eher falsch .. vermutlich muss ich an den Wechselrichter??

Also muss ich Wechselrichterunterlagen suchen, und dort nach den Abfrageadressen schauen? richtig?

Martin

Das hängt von deiner Beschaltung ab. Du hast ja auch noch Eigenverbrauch durch das Haus. Du musst irgendwie ermitteln, wie viel ins Netz noch eingespeist wird.

Wäre, wenn das Vorzeichen negativ ist.

Die Problematik ist die Summe der zugeschalteten Verbraucher so zu prioriesieren, dass die nicht sofort abgeschaltet werden, wenn die Summen aller Aussenleiter nicht für die Eigenversorgung reichen.