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.
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.
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.
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.
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
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?
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();
}
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.