PV Wechselrichter auslesen

Hallo,

Ich bekomme eine PV Anlage installiert. Dort ist ein Huawei Sun2000-10KTL verbaut.

Ich möchte nun Steckdosen im Haus schalten, die nur an sind, wenn Sonne Scheint oder der Akku voll ist, bzw wenn mehr Energie da ist, als verbraucht wird.

Kennt sich jemand damit aus? Gibt es Anleitungen dafür? ich finde so leider nur ganze Produkte, die sowas übernehmen.

Hast Du schon mal nach einem Datenblatt und einem Handbuch gesucht?
Weisst Du denn, was Du tatsächlich bekommst?
Laut DaBla geht so ziemlich alles:

Wenn RS485, dann brauchst das Protokoll dazu.
Wir haben hier einige bereits ans laufen bekommen.

Ja, ich würde gerne RS485 nehmen. Genau das mit dem Protokoll ist ja mein Problem. Habe da noch nichts zu gefunden.

RS485 ist in der Regel Modbus RTU. Schau mal, ob du irgendwo eine Modbus-Registerliste o.ä. für deine Steuerung bekommst.

SmartLogger ModBus Interface Definitions.pdf (760,9 KB)

Ich bin mal so frei.... Mehr ist nicht zu finden...

Besser geht es doch nicht! Da steht alles drin, was man braucht.
Die Beschreibung ist zwar für Modbus TCP, aber dadurch ändern sich die Register ja nicht.

@McKaiver Was für eine MCU willst du denn einsetzen? Beim ESP32 würde ich dir meine eModbus-Lib auf Github empfehlen... :smile:

wenn es das richtige Datenblatt ist (wäre vom TO noch zu bestätigen), dann steht imho alles wesentliche Drinnen.

RO signals support only the 0X03 instruction.

Wenn die Modbus Master Lib von DocWalker eingesetzt wird (für Modbus-RTU mit RS485), kann ich vermutlich helfen, wenn bekannt ist, auf welchem Microcontroller das laufen soll.

Der ESP32 wäre eine Überlegung.

Ich habe noch einen und damit kann ich den direkt ins Wlan einbinden.

Damit könntest du dann deine PV auslesen. Wie schaltest Du die Steckdosen?

Per UDP befehlen? Sobald ich die Daten im Controller habe ist der Rest trivial denke ich.

Ich werf mich mal nochmal rein.
Es gibt eine aktuellere Interface Definition, mit Angabe des WR.
Solar-Inverter-Modbus-Interface-Definitions 12ktl.pdf (1,1 MB)
(Das 12 ist auch 10, 20 etc.pp.)
Herkunft: Modbus Huawei SUN2000 / LUNA2000 - Javierin.com (Achtung Spanisch)

Das kann Deepl. :wink:

Gruß Tommy

Hast du die Steckdosen schon, oder ist das bisher nur die Idee? Die meisten Funksteckdosen sprechen entweder chinesisch (werden über eine China-App gesteuert) oder man flasht Tasmota oder eine andere alternative Firmware darauf. Meine sprechen z. B. auch Modbus TCP.

Nein, hab da noch gar nichts, könnte mir auch eine mehrfachsteckdose mit vorschaltgerät vorstellen. Ist also absolut flexibel

Ich persönlich bevorzuge einzelne Zwischensteckdosen mit eigenem WLAN-Controller, die sind am flexibelsten einsetzbar.
Es gibt welche bis 16A, die auch den Strom messen können. Drin steckt oft ein ESP8266- Derivat, das man mit etwas Bastelei selbst programmieren kann.
Wenn du da Interesse hast, habe ich auch was auf Lager. SmartDose, Github

oh, das klingt Super! Allerdings werde ich mir da noch einiges an Know How aneignen müssen...

Das werde ich aber in Gedanken behalten.

so, habe mir nun eine Gosund SP1 bestellt.

nun aber für mich als Verständniss, da ich noch nicht mit MODBus gearbeitet habe:
ich verbinde meinen uC als Slave per RS485 mit dem Wechselrichter.
Sende dann Werte/Adressen an den Master und er antwortet dann in mit bestimmten Informationen?

hier der Auschnitt:

also reicht es, wenn ich dann im Controller folgendes mache?

Serial.write(37004); 
...
if (Serial.available()) {
    int Ladung = Serial.read(); 
}
...
Serial.write(37001); 
...
if (Serial.available()) {
    int laedt = Serial.read(); 
}
...
if (laedt >=0 && Ladung >= 95) {
   schaltedosenan();
}

nein, das ist schon etwas umfangreicher.
Modbus ist ein Protokoll mit Function Codes und Prüfziffern.
Außerdem ist RS485 meist halfduplex, das heißt du brauchst einen Pin zum mitteilen, ob du senden oder empfangen willst.

Daher beginnst du am besten mit einer Library. Zwei wurden dir schon empfohlen.

mit der doc Walker sieht es ca so aus - muss aber auf deine Register angepasst werden.

/*******************************************************

  Modbus Client Example D 485halfduplex
  Read EPSOLAR - corrected version

  This Modbus Client
  - reads registers from Modbus Servers periodically

  based on an idea

  RS485_HalfDuplex.pde - example using ModbusMaster library to communicate
  with EPSolar LS2024B controller using a half-duplex RS485 transceiver.

  This example is tested against an EPSolar LS2024B solar charge controller.
  See here for protocol specs:
  https://github.com/tekk/Tracer-RS485-Modbus-Blynk-V2/blob/master/doc/1733_modbus_protocol.pdf

  hardware
  - a MAX485-TTL adapter

  by noiasca
  2022-07-31  OK - tested with Arduino MEGA

 *******************************************************/


/* *******************************************************
   Serial Interface
 * **************************************************** */
// if you don't have enough HW Serial (i.e. on an UNO)
// you are forced to use SoftwareSerial or AltSoftSerial
//include <SoftwareSerial.h>
//constexpr uint8_t rxPin = 2;                   // for Softserial
//constexpr uint8_t txPin = 3;
//SoftwareSerial mySerial(rxPin, txPin);

// On a Mega you can simply use
// a Reference to an existing HW Serial:
HardwareSerial &mySerial = Serial3;

/* **************************************************** *
   Modbus
 * **************************************************** */
#include <ModbusMaster.h>                        // Modbus Master 2.0.0 by Doc Walker - install with Library Manager
constexpr uint8_t modbusEnablePin = 5;           // The GPIO used to control the MAX485 TX pin. Set to 255 if you are not using RS485 or a selfsensing adapter
constexpr uint32_t modbusBaud = 115200;          // use slow speeds with SoftSerial
constexpr uint16_t modbusRestTx = 15000;         // rest time between transmissions - microseconds
uint32_t modbusPreviousTx = 0;                   // timestamp of last transmission - microseconds
ModbusMaster serverA;                            // instantiate ModbusMaster object - slave - node

// this function will be called before the client transmits data
void preTransmission()
{
  while (micros() - modbusPreviousTx < modbusRestTx)   // check last transmission end and wait if the call was to early
  {
    yield();                                           // wait some time and allow background tasks
  }
  digitalWrite(modbusEnablePin, HIGH);
}

// this function will be called after the transmission
void postTransmission()
{
  digitalWrite(modbusEnablePin, LOW);
  modbusPreviousTx = micros();         // remember last timestamp
}

// do all the settings for the Modbus
void modbusInit()
{
  mySerial.begin(modbusBaud);                     // initialize Modbus communication baud rate
  serverA.begin(1, mySerial);                     // communicate with Modbus server ID over the given Serial interface
  pinMode(modbusEnablePin, OUTPUT);               // Init enable pins for modbus master library
  digitalWrite(modbusEnablePin, LOW);
  serverA.preTransmission(preTransmission);       // Callbacks allow us to configure the RS485 transceiver correctly
  serverA.postTransmission(postTransmission);
}

// getdata from Modubs Server(Slave) and print to Serial
void requestData()
{
  constexpr uint16_t interval = 5000;             // interval of modbus requests
  static uint32_t previousMillis = -interval;     // timestamp of last request
  static uint8_t actual = 0;                      // actual iteration
  uint32_t currentMillis = millis();

  if (currentMillis - previousMillis > interval)  // set the interval in ms
  {
    previousMillis = currentMillis;
    uint16_t reg = 0x3100;
    int result;
    result = serverA.readInputRegisters(reg, 8);  // request from startregster, n Registers
    if (result == serverA.ku8MBSuccess)           // do something if read is successfull
    {
      Serial.print(F("Charging equipment input V:     ")); Serial.println(serverA.getResponseBuffer(0x00) / 100.0f);
      Serial.print(F("Charging equipment input A:     ")); Serial.println(serverA.getResponseBuffer(0x01) / 100.0f);
      Serial.print(F("Charging equipment input W:     ")); Serial.println((serverA.getResponseBuffer(0x02) + ((uint32_t)serverA.getResponseBuffer(0x03) << 16)) / 100.0f); // cast and brackets
      Serial.print(F("Charging equipment output V:    ")); Serial.println(serverA.getResponseBuffer(0x04) / 100.0f);
      Serial.print(F("Charging equipment output A:    ")); Serial.println(serverA.getResponseBuffer(0x05) / 100.0f);
      Serial.print(F("Charging equipment output W:    ")); Serial.println((serverA.getResponseBuffer(0x06) + ((uint32_t)serverA.getResponseBuffer(0x07) << 16)) / 100.0f); // cast and brackets
    }
    else
    {
      Serial.print(F(" ServerA no success register ")); Serial.print(reg, HEX); Serial.print(F(" result=")); Serial.println(result, HEX);
    }
  }
}

/* **************************************************** *
   setup and loop
 * **************************************************** */

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Modbus Client Example D 485 halfduplex"));

  modbusInit();
}

void loop()
{
  requestData();
}

Vielen Dank, momentan ist es noch theoretisch, da die Anlage übernächste Woche installiert wird, dann werde ich das nochmal praktisch durchführen.

Mach dich vertraut mit dem Datenblatt und suche dir die Register die für deine Auswertung notwendig sind.

Dann schau, nach welche Zugriffe dafür notwendig sind (= mit welchen Function Codes diese Modbus Register abgefragt werden müssen).

Wird sowieso noch spannend, denn bei 37001 wäre ich der Meinung das ist "FC4 Read input register" weil diese für Adresse von 30001 bis 39999 bis gelten.
Und der "FC3 Read Multiple Holding register" eigentlich nur für die 40001 bis 49999 geht.