tobiasfaust / solaxmodbusgateway Goto Github PK
View Code? Open in Web Editor NEWModbus RTU to MQTT Gateway
License: GNU General Public License v3.0
Modbus RTU to MQTT Gateway
License: GNU General Public License v3.0
Habe das Problem dass die Sensoren beim Deye nur im Mqtt Explorer zu finden sind und nicht in Mqtt als Gerät mit den Sensoren. Muss bei allen Sensoren/Werten ein state_topic erstellen um diese überhaupt zu HA zu bekommen. Wenn dies geschehen ist werden die Werte mal angezeigt mal springen sie auf 0.
Ich habe heute mehrfach Binaries mit Gitpod erzeugt. Für v3.1.1 und 3.2.0. Letztere Version ist überhaupt nicht funktionsfähig, v3.1.1 zeigt keine Einstellungen in der "Item Config" Liste:
Außerdem wird in der Konsole folgender Fehler gezeigt:
Ich habe das auf 3 verschiedenen Devices getestet, alle zu Beginn via "ERASE" zurückgesetzt. Eines der 3 Devices hat vorher problemlos funktioniert.
I've flashed the Firmware ... I only got the Accesss Point: AP_ModbusGateway" and the password from your Wiki is not correct.
Please check it. Thanks.
Hi,
you might want to update the description in the wiki for the Board HW-97. In the description you are mentioning that DI and RO need to be connected together but actually it is DE and RE (like in the schematics). Another point is that the RTS Pin should be DI5 according to the schematics but in the firmware the default setting is D18.
Unfortunatly I can't get it to work. Flashed the firmware on the ESP but no values from the Solax are showing up. I replaced the cable the ESB and the HW-97 Board. I'll give it a try with another RS485 Converter Board the next days..
Hallo, ich habe den Adapter am Com-Anschluss eines QCells- WR (baugleich X3 - Hybrid). Bis zu einigen Updates im ioBroker lief die Modbus-Kommunikation sehr gut. Der Adapter ist über sein Webinterface zu erreichen, alle Werte werden angezeigt, ich kann keinen Fehler in den Einstellungen finden. Trotzdem meldet ioBroker Verbindungsfehler. Auch der Radzio! Modbus Master Simulator kann keine Verbindung herstellen. Da im Interface alles richtig angezeigt wird, gehe ich von einer fehlerfreien Verbindung vom WR zum Adapter aus. Wie bekomme ich eine Verbindung?
Hallo Tobias,
zunächst vielen Dank für das tolle Projekt.
Ich habe ein Problem das mir immer nur die gleichen Werte geliefert werden und bin mir nicht ganz sicher ob im Modbus Protokoll zwischen dem X1 und dem X1 mini G3 unterschiede sind.
Ich habe ein HW97 HalfDuplex Board genommen und den GPIO5 für DE/RE aber die LEDs blinken auch nicht.
Ich habe die Default Baudrate belassen, könnte das schon ein Problem sein? Ansonsten wüsste ich nicht was beim wiring noch falsch sein könnte.
Vielen Dank
Gruß
Ben
Since the last version the ESP WifiManager didn´t support Wlan Passwords with special characters like:
if i change my wlan password to normal alphabetic and numeric charakters everythings works like before.
Dont see any Deye Inverter to select. Is the support for this over?
v3.1 dont get any Values and the Web interface is lighly broken.
Hallo Tobias,
vielen Dank für dieses geniale Tool.
Ich habe neben einem X1 noch einen X3-Mic am Start, leider lassen sich mit Deinem Tool dort keine schlüssigen Daten auslesen.
Siehst Du eine Chance das zu implementieren damit man die Daten auslesen kann?
Danke
Hallo,
ich habe einen Solax X3-8.0-T-D. Klappt es mit dem auch?
Als Laie habe ich nun einen fertigen Adapter eines Users gekauft, die mittels eines Lan-Splitters zusammen mit einem SmartMeter im Zählerschrank an den WR angeschlossen.
Ich bekomme aber leider keine Daten vom WR bzw. in "Raw Data" nur "Undefined".
siehe hier (mit Screenshots): https://www.photovoltaikforum.com/thread/177671-solax-x3-mic-modbus/?pageNo=3
I have attached the Modbus register PDF I obtained from Solax for the X1 Boost G3.0/G3.1/G3.2, my inverter has a serial number starting XB32 which may indicate a Gen3.2. I have access to the Cloud but would prefer to access the data locally. I have connected to the inverter's RS485 wires via an EW11 which converts to Modbus TCP but while I can communicate the signals back show as invalid in Modbus poll but at least communication is there. The HEX register list in the PDF looks to match the ones posted in Benjamin's ESPHome from this forum thread which you started. https://community.home-assistant.io/t/universal-solar-inverter-over-modbus-rs485-to-mqtt-formally-solax-no-pocket-wifi/483606/4
Solax Power X1-BOOST Single phase inverter Modbus-RTU comms protocolV1.0 - Public version.pdf
The Gateway repeatedly loses connection to the Growatt SPH inverter. So far about every 7 days. The problem exists with 3 different installations, all with Growatt SPH inverters.
In case the connection is broken:
the TX/RX Leds of the MAX485 Module TTL Switch continue to work as if sending and receiving
e.g. if the baud rate setting is incorrect, no RX LED lights up
RS485 icon in the display is off, normally the growatt shows an icon in the display with an active RS485 connection,
A hardware reset fixes the problem
Hallo zusammen,
danke an alle für die Mühen die Software zu stricken.
Ich habe das Problem, das mit dem USB-Kabel alles über WiFi nach dem flashen funktioniert. Die rote LED am ESP32 blinkt kurz und findet das Netz. Ich kann über den Browser die Web-Site aufrufen. Jedoch abgekoppelt vom USB-Port des PC mit Platform.io ist keine WiFi-Verbindung möglich, auch nicht unter 192.168.4.1". Die rote LED blinkt immer im gleichen Takt vor sich hin. Ich nutze 3.1.1. Wo könnte der Fehler liegen?
Danke.
Herbert
Hat zufällig jemand schon mal die register.h für einen Solax Mic Pro angepasst? Mit der normalen Solax-Mic Konfiguration kann ich den WR leider nicht überreden, Daten auszugeben.
I noticed that the document called Solax-Hybrid-X1X3-G4-ModbusTCPRTU-V3.21-English_0622-public-version.pdf
in the docs directory is truncated.
I have been using register definitions in Solax-Hybrid X1&X3-G3 ModbusTCP&RTU V3.21- English.pdf to write to registers using simple test code for function 0x06 for single register and multiple registers using function code 0x10 and it works.
For some time, it kept returning a slave fault response abnormal code 4 and I suspected it was some kind of security issue. I haven't found anyone at Solax who really knows anything about any of this. I then asked my inverter installer engineer for the administration 4 digit code that needs entering into the front panel on the inverter so I could look at the advanced settings not usually available to a user. I hoped that this might allow me to write data. Once I was able to access advanced settings on the inverter control panel, the code for writing data to registers started to work without returning an error.
I had not changed the test code so think you might need the advanced settings 4 digit code number that a normal user would not necessarily have. I haven't seen an error since and can't reproduce the errors now.
I'm not 100% confident off my findings but thought that you may have experienced the same problem if you tried to write data to registers using function code 0x06 or 0x10? Have you tried it yet?
Hallo erstmal,:)
Ist es möglich über dieses Gateway auch andere/mehrere Daten aus den WR zu bekommen. Wenn ja wo finde ich die Register Daten.
alle die ich getestet habe stimmen irgendwie nicht mit dem überein was ich angezeigt bekomme.
In der Register.h Datei steht zb bei 'GridFrequency' die Positionen '77, 78'
Und ich bekomme auch die richtigen Werte.
Jedoch finde ich kein Register wo es so dokumentiert wäre.
Sind die Positionen in der Register.h Datei nicht gleich Register?
Mit freundlichen Grüßen
hi tobias,
this software works great, except for the case when i reboot my router, the wifi doesn't reconnect automatically... is there a solution?
thanks a lot
Mit freundlichen Grüßen
Hans
Hallo Tobias,
zunächst einmal mein Lob an deine tolle Software.
Ich habe einen Solax X3-PRO-G2 und in der Modbus Config "Solax-MIC" eingestellt.
Über die Com-Schnittstelle des ESP32 kommen folgende Meldungen
Request queue data to inverter 0x01 0x04 0x00 0x78 0x00 0x77 0x30 0x35
Read Data from Queue
0x01 0x84 0x02 0xC2 0xC1
Dataframe invalid
Scheinbar versteht der X3-PRO-G2 die Kommandos nicht.
Kannst Du mir weiterhelfen?
Viele Grüße Wilfried
Hi,
ich habe den Adapter an einen Deye 12k angeschlossen, und es werden auch Werte übertragen. Allerdings springen die Werte bei jeder zweiten oder dritten Aktualisierung auf absolut unplausible Values.
Beispiel: PV-Leistung in Watt: 1. Akt = 1200W (ok) ; 2. Akt = 1289W (ok) ; 3.Akt = 400000W (falsch) ; 4. Akt = 1270W (ok)
Das passiert mit allen Werten nach 2 oder drei Aktualisierungszyklen.
Da ich nicht wirklich bewandert bin in diesen Themen wäre ich für jede Hilfe dankbar. In irgendeinem anderen Thread hatte ich auch mal gelesen, dass "Beta-Tester" für den Deye gesucht werden... :-) Hier bin ich ...
Gruß Lukas
Hallo Tobias,
habe dein Projekt umgestzt und mit dem Deye 12k verbunden, kann Daten sehen, werden auch zum Iobroker per MQTT übertragen.
Was mich wundert ist das dieInverter Serialnummer von meinem Deye nicht angezeigt wird.
Muss ich da noch irgendwas einstellen?
Gruß
Antonio
First of all : Thanks for the great stuff here!
I am trying to add my Inverter and am running in to some issues that i don't know how to solve:
This is what i have:
In parts things work but:
I nearly made it...
Here the latest log file:
Log2.txt
And the Response i got with the test program.
TestResponse.txt
register_h.TXT
I would appreciate your help..
Moin zusammen,
ich bin neu hier und versuche mein nächstes Projekt in FHEM.
Ich habe den ESP32 so vorbereitet, dass ich den an den WR anklemmen kann.
Wurde vlt. schon ein register.h für den MOD tl3 XH angepasst und könnte die mit zur Verfügung stellen?
Hello, recently I got a QHome ESS hyb G3 System. According to some posts in the web, the QVolt inverter is very similar to Solax X3 hyb G4 (a re-labelled Solax inverter but is firmware identical?). I am searching for a possibility to get live data via RS485 modbus interface and to use it with FHEM. In the FHEM forum I got attention to your great project. Unfortunately the decimal values from the 32 bit register are much too high when choosing Solax X3. I had a look in the documentation of the register of the Solax X1/X3 hyb G4 (V3.21) which I found in the docs folder. Obviously the first two Bytes of the 32 bit register represent LSB and the next two Bytes MSB. In my opinion I have to exchange LSB and MSB to get correctly calculated decimal values. I checked that with the tool in raw data folder and the results were in line with the QCell App. What do you think about that? I want to check that for a longer period but I am not familiar with Github and Gitpod to change register.h properly. Would you kindly add a new inverter "QVolt HYB-G3-3P" in register.h? Here are the terms and positions, which were checked and evaluated with raw data tool besides "OffGrid" values:
"QVolt HYB-G3-3P": {
"config": {
"RequestLiveData": [
["#ClientID", "0x04", "0x00", "0x00", "0x00", "0x77"],
["#ClientID", "0x04", "0x00", "0x78", "0x00", "0x77"]
],
"RequestIdData": ["#ClientID", "0x03", "0x00", "0x00", "0x00", "0x14"],
"ClientIdPos": 0,
"LiveDataFunctionCodePos": 1,
"LiveDataFunctionCode": "0x04",
"IDDataFunctionCodePos": 1,
"IdDataFunctionCode": "0x03",
"LiveDataStartsAtPos": 3,
"IdDataStartsAtPos": 3,
"LiveDataErrorPos": 1,
"LiveDataErrorCode": "0x84",
"IdDataErrorPos": 1,
"IdDataErrorCode": "0x83",
"LiveDataSuccessPos": 1,
"LiveDataSuccessCode": "0x04",
"IdDataSuccessPos": 1,
"IdDataSuccessCode": "0x03"
},
"data": {
"livedata": [
{
"position": [215, 216],
"name": "GridVoltage_R",
"realname": "Grid Voltage L1",
"datatype": "float",
"factor": 0.1,
"unit": "V"
},
{
"position": [217, 218],
"name": "GridCurrent_R",
"realname": "Grid Current L1",
"datatype": "float",
"factor": 0.1,
"unit": "A"
},
{
"position": [219, 220],
"name": "GridPower_R",
"realname": "Grid Power L1",
"datatype": "integer",
"unit": "W"
},
{
"position": [221, 222],
"name": "GridFrequency_R",
"realname": "Grid Frequency L1",
"datatype": "float",
"factor": 0.01,
"unit": "Hz"
},
{
"position": [223, 224],
"name": "GridVoltage_S",
"realname": "Grid Voltage L2",
"datatype": "float",
"factor": 0.1,
"unit": "V"
},
{
"position": [225, 226],
"name": "GridCurrent_S",
"realname": "Grid Current L2",
"datatype": "float",
"factor": 0.1,
"unit": "A"
},
{
"position": [227, 228],
"name": "GridPower_S",
"realname": "Grid Power L2",
"datatype": "integer",
"unit": "W"
},
{
"position": [229, 230],
"name": "GridFrequency_S",
"realname": "Grid Frequency L2",
"datatype": "float",
"factor": 0.01,
"unit": "Hz"
},
{
"position": [231, 232],
"name": "GridVoltage_T",
"realname": "Grid Voltage L3",
"datatype": "float",
"factor": 0.1,
"unit": "V"
},
{
"position": [233, 234],
"name": "GridCurrent_T",
"realname": "Grid Current L3",
"datatype": "float",
"factor": 0.1,
"unit": "A"
},
{
"position": [235, 236],
"name": "GridPower_S",
"realname": "Grid Power L3",
"datatype": "integer",
"unit": "W"
},
{
"position": [237, 238],
"name": "GridFrequency_T",
"realname": "Grid Frequency L3",
"datatype": "float",
"factor": 0.01,
"unit": "Hz"
},
{
"position": [9, 10],
"name": "PvVoltage1",
"realname": "Pv Voltage 1",
"datatype": "float",
"factor": 0.1,
"unit": "V"
},
{
"position": [11, 12],
"name": "PvVoltage2",
"realname": "Pv Voltage 2",
"datatype": "float",
"factor": 0.1,
"unit": "V"
},
{
"position": [13, 14],
"name": "PvCurrent1",
"realname": "Pv Current 1",
"datatype": "float",
"factor": 0.1,
"unit": "A"
},
{
"position": [15, 16],
"name": "PvCurrent2",
"realname": "Pv Current 2",
"datatype": "float",
"factor": 0.1,
"unit": "A"
},
{
"position": [19, 20],
"name": "InverterTemperature",
"realname": "Inverter Temperature",
"datatype": "integer",
"unit": "°C"
},
{
"position": [23, 24],
"name": "PowerDC1",
"realname": "Power DC 1",
"datatype": "integer",
"unit": "W"
},
{
"position": [25, 26],
"name": "PowerDC2",
"realname": "Power DC 2",
"datatype": "integer",
"unit": "W"
},
{
"position": [43, 44],
"name": "BatVoltage",
"realname": "Battery Voltage",
"datatype": "float",
"factor": 0.1,
"unit": "V"
},
{
"position": [45, 46],
"name": "BatCurrent",
"realname": "Battery Current",
"datatype": "float",
"factor": 0.1,
"unit": "A"
},
{
"position": [47, 48],
"name": "BatPower",
"realname": "Battery Power",
"datatype": "integer",
"unit": "W"
},
{
"position": [51, 52],
"name": "BatTemp",
"realname": "Battery Temperature",
"datatype": "integer",
"unit": "°C"
},
{
"position": [59, 60],
"name": "BatCapacity",
"realname": "Battery Capacity",
"datatype": "integer",
"unit": "%"
},
{
"position": [63, 64, 61, 62],
"name": "OutputEnergyCharge",
"realname": "Output Energy Charge",
"datatype": "float",
"factor": 0.1,
"unit": "kWh"
},
{
"position": [67, 68],
"name": "OutputEnergyChargeToday",
"realname": "Output Energy Charge Today",
"datatype": "float",
"factor": 0.1,
"unit": "kWh"
},
{
"position": [71, 72, 69, 70],
"name": "InputEnergyCharge",
"realname": "Input Energy Charge",
"datatype": "float",
"factor": 0.1,
"unit": "kWh"
},
{
"position": [73, 74],
"name": "InputEnergyChargeToday",
"realname": "Input Energy Charge Today",
"datatype": "float",
"factor": 0.1,
"unit": "kWh"
},
{
"position": [145, 146, 143, 144],
"name": "feedinPower",
"realname": "FeedIn Power to Grid",
"datatype": "integer",
"unit": "W"
},
{
"position": [149, 150, 147, 148],
"name": "feedinEnergyTotal",
"realname": "FeedIn Energy Total to Grid",
"datatype": "float",
"factor": 0.01,
"unit": "kWh"
},
{
"position": [153, 154, 151, 152],
"name": "consumEnergyTotal",
"realname": "ConsumEnergy Total from Grid",
"datatype": "float",
"factor": 0.01,
"unit": "kWh"
},
{
"position": [163, 164],
"name": "EnergyTodayToGrid",
"realname": "Today Energy to Grid",
"datatype": "float",
"factor": 0.1,
"unit": "kWh"
},
{
"position": [169, 170, 167, 168],
"name": "EnergyTotalToGrid",
"realname": "Total Energy to Grid",
"datatype": "float",
"factor": 0.1,
"unit": "kWh"
},
{
"position": [280, 281, 278, 279],
"name": "OnGridRunTime",
"realname": "OnGrid RunTime",
"datatype": "float",
"factor": 0.1,
"unit": "h"
},
{
"position": [284, 285, 282, 283],
"name": "OffGridRunTime",
"realname": "OffGrid RunTime",
"datatype": "float",
"factor": 0.1,
"unit": "h"
},
{
"position": [294, 295, 292, 293],
"name": "OffGridYieldTotal",
"realname": "OffGrid Yield Total",
"datatype": "float",
"factor": 0.1,
"unit": "kWh"
},
{
"position": [294, 295],
"name": "OffGridYieldToday",
"realname": "OffGrid Yield Today",
"datatype": "float",
"factor": 0.1,
"unit": "kWh"
},
{
"position": [296, 297],
"name": "EChargeToday",
"realname": "ECharge Today",
"datatype": "float",
"factor": 0.1,
"unit": "kWh"
},
{
"position": [300, 301, 298, 299],
"name": "EChargeTotal",
"realname": "ECharge Total",
"datatype": "float",
"factor": 0.1,
"unit": "kWh"
},
{
"position": [304, 305, 302, 303],
"name": "SolarEnergyTotal",
"realname": "SolarEnergy Total",
"datatype": "float",
"factor": 0.1,
"unit": "kWh"
},
{
"position": [306, 307],
"name": "SolarEnergyToday",
"realname": "SolarEnergy Today",
"datatype": "float",
"factor": 0.1,
"unit": "kWh"
},
{
"position": [312, 313, 310, 311],
"name": "EnergyFeedin",
"realname": "EnergyFeedin Today",
"datatype": "float",
"factor": 0.01,
"unit": "kWh"
},
{
"position": [316, 317, 314, 315],
"name": "EnergyConsum",
"realname": "EnergyConsum Today",
"datatype": "float",
"factor": 0.01,
"unit": "kWh"
}
],
"id": [
{
"position": [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
"name": "InverterSN",
"realname": "Inverter SerialNumber",
"datatype": "string"
},
{
"position": [17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30],
"name": "FactoryName",
"realname": "Factory Name",
"datatype": "string"
},
{
"position": [31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42],
"name": "ModuleName",
"realname": "Module Name",
"datatype": "string"
}
]
}
},
Hi Tobias,
i tried to setup the ESP32 by flashing the firmware.bin.
Am I doing sth wrong here? I'm new and not sure how to start other than flashing the firmware.bin.
From the wiki I could not assume sth other than doing that step.
Normally I use Arduino for small scripts which I flash so GPIO is no issue.
Thank you!
Viele Grüße
Toni
Hello,
You have realized a great project!
Unfortunately, changes in the Modbus settings are not accepted!
I have tested the recommended RS485 adapter with a Modbus logger software and the hardware works with 9600 baud!
Unfortunately I'm not a programmer. I hope the baud rate can be changed in a future version.
Hi Tobias,
ich habe für meinen X1-Mini in Gitpod die Register.h Datei editiert bei Solax-Mic von 0x40 auf 0x20
wie kann ich diese Datei nun compilieren, so dass ich eine .bin File zum flashen erhalte?
Does anyone has implemented the SolaX Mini inverters?
I have an old one (without display, only LEDs) and a newer one with the status display.
And... What has to be configured in the menu to communicate with the ESP? Does the SolaXModbusGateway simulates a meter?
This is the only thing I could enter in the menu.
I would like to implement these inverters in my Venus OS (Victron Energy) as AC inverters.
The wiring wiki link page https://github.com/tobiasfaust/SolaxModbusGateway/blob/master/wiring-the-circuit comes up with a 404 error.
I was checking it because the last time I looked, you had changed added information about the GND pin which was useful. The pin number was correct for the Solax X1 Hybrid but the ground pin is different for other inverters. It is important to point this out for obvious reasons.
Hallo Tobias,
erst einmal Glückwunsch zu einem super Projekt.
Gibt es eine Möglichkeit den X3-MIC-G2 ebenfalls auszulesen oder scheitert dies an der RS485 Schnittstelle des Inverters?
Hi,
can you please check the code for the following problem.
Only the first 26 items can be selected. All others are not saved.
If you want to send a value further down via MQTT, this does not work.
I can also provide my register.h for SolaX / Q.Home. In it, all values up to item 480 are currently displayed correctly.
Best regards
Ich habe versucht die v3.2.0 auf einen ESP32-S2 mini zu bringen. Inklusive littlefs.bin. Das funktioniert grundsätzlich, WIFI lässt sich konfigurieren und das Device ist dann in meinem LAN erreichbar. Allerdings sieht die Oberfläche anders aus. Statt der Tabelle mit gelbem Hintergrund scheint alles ohne Formatierung auf dem Bildschirm zu stehen. Außerdem lassen sich Änderungen an den Settings nicht abspeichern, mit einem "speichern" springt alles wieder auf 'Default'.
Die v3.2.0 ist mit dem ESP32-S2 (nagelneu aus der Tüte!) nicht verwendbar.
Hi,
ich bin gerade am versuchen wie ich den Growatt MOD hinbekomme und habe ebenfalls die 3.1.1 genommen, mit dieser bekomme ich keine RAW Life Data angezeigt.
Reproduktion:
Firmware.bin (v3.0) initial installiert... dann im web menü auf update -> neue 3.1.1 firmware aus releases -> keine RAW Life Daten mehr.
Nehme ich wieder die Firmware 3.0 geht wieder alles.
In the function void modbus::QueryQueueToInverter()
there is missing code before the delay(100); which causes no data to be returned.
RS485Serial->flush();
delay(100);
if (rwtype == WRITE) {
Pin pin_RTS needs to be set to receive before the delay(100);
Without doing this, no data is returned in function ReceiveSetData.
I tend to avoid using delay() because I suspect this causes problems in some of my code because of blocking.
To avoid bocking yield in a timeout loop. It's just personal preference. delay(100) works.
Code should be something like:-
RS485Serial->flush();
digitalWrite(this->pin_RTS, RS485Receive); // init Receive
unsigned long timeout=millis()+100;
while (millis()<=timeout) { yield(); }
//delay(100);
if (rwtype == WRITE) {
My test setup took much longer to wire up than first predicted. It is working now.
I have a Growatt SPH3000 and Solax X1 Hybrid working now so in a position to test things for you.
Hello.
This is a nice project, but waaaaay to comprehensive for my needs. It would be enough, to read the total produced energy out and have this value displayed on a little LCD or 'even' on a HTML-page via asyncwebserver.
I have run the test-script on a ESP32 and got at least some answer from the inverter: "07"
Not via the serial port (can't get the PC to the inverter), but on the LCD. The code was modified a bit and I don't even know if it can display the whole serial number of the inverter this way.
`#include <LiquidCrystal_I2C.h>
#include <Arduino.h>
#define RX 16 // UART2 RX
#define TX 17 // UART2 TX
#define RTS_pin 5 // RS485 Direction control
#define RS485Transmit HIGH
#define RS485Receive LOW
// set the LCD number of columns and rows
int lcdColumns = 16;
int lcdRows = 2;
//LCD SCL: Pin 22; SDA: Pin 21
// set LCD address, number of columns and rows
// if you don't know your display address, run an I2C scanner sketch
LiquidCrystal_I2C lcd(0x27, lcdColumns, lcdRows);
void setup(){
// initialize LCD
lcd.init();
// turn on LCD backlight
lcd.backlight();
pinMode(RTS_pin, OUTPUT);
digitalWrite(RTS_pin, RS485Receive);
// Start the built-in serial port, for Serial Monitor
Serial.begin(115200);
Serial.println("Test RS485 Connection");
lcd.setCursor(0, 0);
lcd.print("Test RS485");
// Start the Modbus serial Port
Serial2.begin(19200, SERIAL_8N1, RX, TX);
delay(1000);
while(Serial2.available())
{
Serial.print(Serial2.read(), HEX);
Serial.print(" ");
}
delay(1000);
}
uint16_t Calc_CRC(uint8_t* message, uint8_t len) {
//Calc the raw_msg_data_byte CRC code
uint16_t crc = 0xFFFF;
for (int pos = 0; pos < len; pos++) {
crc ^= (uint16_t)message[pos]; // XOR byte into least sig.byte of crc
for (int i = 8; i != 0; i--) { // Loop over each bit
if ((crc & 0x0001) != 0) { // If the LSB is set
crc >>= 1; // Shift right and XOR 0xA001
crc ^= 0xA001;
}
else // Else LSB is not set
crc >>= 1; // Just shift right
}
}
return crc;
}
String Hex2String(uint8_t num) {
char hexCar[2];
sprintf(hexCar, "0x%02X", num);
return hexCar;
}
void loop(){
byte request[] = {0x01,
0x03,
0x00,
0x00,
0x00,
0x07, // 0x0D - 14 stellen, Inverter + Modulname
0x00,
0x00
}; //
uint16_t crc = Calc_CRC(request, sizeof(request)-2);
request[sizeof(request)-1] = highByte(crc);
request[sizeof(request)-2] = lowByte(crc);
Serial.println("Schreibe Daten ....");
for(uint8_t i=0; i<sizeof(request); i++){
Serial.print(Hex2String(request[i]));Serial.print(' ');
}
Serial.println("");
digitalWrite(RTS_pin, RS485Transmit);
Serial2.write(request, sizeof(request));
Serial2.flush();
digitalWrite(RTS_pin,RS485Receive);
delay(100);
Serial.println("Lese Daten ....");
while(Serial2.available())
{
Serial.print(Serial2.read(), HEX);
Serial.print(" ");
lcd.setCursor(0, 1);
lcd.print(Serial2.read(), HEX);
}
Serial.println("");
delay(2000);
}`
How would the request to the inverter has to be changed, to read the total energy? Is this even possible with this code?
Best regards, Mathias
Hallo Tobias,
der Deye WR liefert ja Temperaturwerte zurück, bei denen man den Wert 1000 abziehen muss. Habe ich hier irgendwie die Möglichkeit das umzusetzen innerhalb deiner Software?
Gruß
Georg
HI PLEASE WHICH IDE YOU USED IN THIS PROJECT?
Hi!
I am a Newbie with ESP32 and shopped any from AZ Del.... following Link
https://www.az-delivery.de/en/products/esp32-developmentboard
Is there anything incompatible?
Thanks for Help
Is there a possibility to include the "Pace BMS" to the software?
Many cheap battery storages use the pace bms.
The protocol is Modbus RTU via RS485.
Addr | Description | Len | R/W | Type | Unit | |
---|---|---|---|---|---|---|
0 | Current | 2 | R | int16 | 10mA | |
1 | Voltage of pack | 2 | R | uint16 | 10mV | |
2 | State of charge | 2 | R | uint8 | % | 0~100% |
3 | SOH | 2 | R | uint8 | % | 0~100% |
4 | Remain capacity | 2 | R | uint16 | 10mAH | |
5 | Full capacity | 2 | R | uint16 | 10mAH | |
6 | Design capacity | 2 | R | uint16 | 10mAH | |
7 | Charging cycles count | 2 | R | uint16 | ||
9 | Warning flag | 2 | R | uint16 | Hex | See ^1 |
10 | Protection flag | 2 | R | uint16 | Hex | See ^2 |
11 | Status/Fault flag | 2 | R | uint16 | Hex | See ^3 |
12 | Balance status | 2 | R | uint16 | Hex | |
15 | Cell voltage 1 | 2 | R | uint16 | mV | |
16 | Cell voltage 2 | 2 | R | uint16 | mV | |
17 | Cell voltage 3 | 2 | R | uint16 | mV | |
18 | Cell voltage 4 | 2 | R | uint16 | mV | |
19 | Cell voltage 5 | 2 | R | uint16 | mV | |
20 | Cell voltage 6 | 2 | R | uint16 | mV | |
21 | Cell voltage 7 | 2 | R | uint16 | mV | |
22 | Cell voltage 8 | 2 | R | uint16 | mV | |
23 | Cell voltage 9 | 2 | R | uint16 | mV | |
24 | Cell voltage 10 | 2 | R | uint16 | mV | |
25 | Cell voltage 11 | 2 | R | uint16 | mV | |
26 | Cell voltage 12 | 2 | R | uint16 | mV | |
27 | Cell voltage 13 | 2 | R | uint16 | mV | |
28 | Cell voltage 14 | 2 | R | uint16 | mV | |
29 | Cell voltage 15 | 2 | R | uint16 | mV | |
30 | Cell voltage 16 | 2 | R | uint16 | mV | |
31 | Battery temperature 1 | 2 | R | int16 | 0.1 ℃ | |
32 | Battery temperature 2 | 2 | R | int16 | 0.1 ℃ | |
33 | Battery temperature 3 | 2 | R | int16 | 0.1 ℃ | |
34 | Battery temperature 4 | 2 | R | int16 | 0.1 ℃ | |
35 | MOSFET temperature | 2 | R | int16 | 0.1 ℃ | or invalid |
36 | Environment temperature | 2 | R | int16 | 0.1 ℃ | or invalid |
60 | Pack OV alarm | 2 | RW | uint16 | mV | |
61 | Pack OV protection | 2 | RW | uint16 | mV | |
62 | Pack OV release protection | 2 | RW | uint16 | mV | |
63 | Pack OV protection delay time | 2 | RW | uint8 | 0.1S | 1~255 |
64 | Cell OV alarm | 2 | RW | uint16 | mV | |
65 | Cell OV protection | 2 | RW | uint16 | mV | |
66 | Cell OV release protection | 2 | RW | uint16 | mV | |
67 | Cell OV protection delay time | 2 | RW | uint8 | 0.1S | 1~255 |
68 | Pack UV alarm | 2 | RW | uint16 | mV | |
69 | Pack UV protection | 2 | RW | uint16 | mV | |
70 | Pack UV release protection | 2 | RW | uint16 | mV | |
71 | Pack UV protection delay time | 2 | RW | uint8 | 0.1S | 1~255 |
72 | Cell UV alarm | 2 | RW | uint16 | mV | |
73 | Cell UV protection | 2 | RW | uint16 | mV | |
74 | Cell UV release protection | 2 | RW | uint16 | mV | |
75 | Cell UV protection delay time | 2 | RW | uint8 | 0.1S | 1~255 |
76 | Charging OC alarm | 2 | RW | uint16 | A | |
77 | Charging OC protection | 2 | RW | uint16 | A | |
78 | Charging OC protection delay time | 2 | RW | uint8 | 0.1S | 1~255 |
79 | Discharging OC alarm | 2 | RW | uint16 | A | |
80 | Discharging OC protection | 2 | RW | uint16 | A | |
81 | Discharging OC protection delay time | 2 | RW | uint8 | 0.1S | 1~255 |
82 | Discharging OC-2 protection | 2 | RW | uint16 | A | |
83 | Discharging OC-2 protection delay time | 2 | RW | uint8 | 0.025S | 1~255 |
84 | Charging OT alarm | 2 | RW | int16 | 0.1 ℃ | |
85 | Charging OT protection | 2 | RW | int16 | 0.1 ℃ | |
86 | Charging OT release protection | 2 | RW | int16 | 0.1 ℃ | |
87 | Discharging OT alarm | 2 | RW | int16 | 0.1 ℃ | |
88 | Discharging OT protection | 2 | RW | int16 | 0.1 ℃ | |
89 | Discharging OT release | 2 | RW | int16 | 0.1 ℃ | |
90 | Charging UT alarm | 2 | RW | int16 | 0.1 ℃ | |
91 | Charging UT protection | 2 | RW | int16 | 0.1 ℃ | |
92 | Charging UT release protection | 2 | RW | int16 | 0.1 ℃ | |
93 | Discharging UT alarm | 2 | RW | int16 | 0.1 ℃ | |
94 | Discharging UT protection | 2 | RW | int16 | 0.1 ℃ | |
95 | Discharging UT release protection | 2 | RW | int16 | 0.1 ℃ | |
96 | MOSFET OT alarm | 2 | RW | int16 | 0.1 ℃ | or invalid parameters in BMS-4820 |
97 | MOSFET OT protection | 2 | RW | int16 | 0.1 ℃ | or invalid parameters in BMS-4820 |
98 | MOSFET OT release protection | 2 | RW | int16 | 0.1 ℃ | or invalid parameters in BMS-4820 |
99 | Environment OT alarm | 2 | RW | int16 | 0.1 ℃ | or invalid parameters in BMS-4820 |
100 | Environment OT protection | 2 | RW | int16 | 0.1 ℃ | or invalid parameters in BMS-4820 |
101 | Environment OT release protection | 2 | RW | int16 | 0.1 ℃ | or invalid parameters in BMS-4820 |
102 | Environment UT alarm | 2 | RW | int16 | 0.1 ℃ | or invalid parameters in BMS-4820 |
103 | Environment UT protection | 2 | RW | int16 | 0.1 ℃ | or invalid parameters in BMS-4820 |
104 | Environment UT release protection | 2 | RW | int16 | 0.1 ℃ | or invalid parameters in BMS-4820 |
105 | Balance start cell voltage | 2 | RW | uint16 | mV | |
106 | Balance start delta voltage | 2 | RW | uint16 | mV | |
107 | Pack full-charge voltage | 2 | RW | uint16 | mV | |
108 | Pack full-charge current | 2 | RW | uint16 | mA | |
109 | Cell sleep voltage | 2 | RW | uint16 | mV | |
110 | Cell sleep delay time | 2 | RW | uint16 | min | |
111 | Short circuit protect delay time | 2 | RW | uint8 | 25uS | Max 500uS |
112 | SOC alarm threshold | 2 | RW | uint8 | % | 0~100% |
113 | Charging OC-2 protection | 2 | RW | uint16 | A | |
114 | Charging OC-2 protection delay time | 2 | RW | uint8 | 0.025S | 1~255 |
150 | Version information | 20 | R | uint16 | ASCII | |
160 | Model SN | 20 | RW | uint16 | ASCII | BMS Manufacturer |
170 | PACK SN | 20 | RW | uint16 | ASCII | PACK Manufacturer |
Die via MQTT übertragene IP Adresse wird abgeschnitten wenn alle 4 Felder 3-stellig sind. Die IP-Adresse 192.168.xyz.abc kommt dann als 192.168.xyz.ab an. Wenn ich die IP-Adresse um eine Stelle kürze wird auch die letzte Stelle übertragen. In meinem Beispiel funktionieren also also 192.168.xy.abc oder 192.168.x.abc.
how can I change to static IP ? maybe there will be an update with an adjustment
great job and thank you
Solax X3 Ultra is a new inverter
See attached current modbus protocol
(Solax)Hybrid X1&X3 IES&ULTRA ModbusTCP&RTU V3.29-English_231012.pdf
Hallo,
nach einen kompletten neuflashen des ESP32 lief es ca. 10 Tage ohne Probleme, Jedoch bekomme ich jetzt seit 3 Tagen keine Werte mehr vom Wechselrichter per Modbus.
Weboberfläche und MQTT gehen.
_
_```
Typ | Raw Data |
---|---|
RawData of ID-Data | |
RawData of Live-Data | undefined undefined undefined undefined undefined undefined undefined undefined undefinedundefined undefined undefined undefined undefined undefined undefined undefined undefined |
_
Is it planned to have an ethernet port of this gateway for the WT32-ETH01 board? I know this is a niche request but some people have only ethernet access to their solar inverters.
Is there something planned?
I recently discovered your SolaxModbusGateway work. I congratulate you on your very interesting high quality work.
Based on my experience trying to use this tool, I have a number of suggestions for you that if implemented would make it easier to use.
In the modbus::init() function it would be useful to be able to set the serial2 RX and TX pins using private class variables in modbus.h to set the pins.
On the ESP32 board I use, the default pins for Serial2 are in use for other purposes so the default pins can't be used.
For example in modbus.cpp :-
Serial2.begin(this->Baudrate,SERIAL_8N1,this->RXpin,this->TXpin);
A -> Pin 4
B -> Pin 5
A -> Pin 4
B -> Pin 5
GND -> Pin 6 Solax X1 Hybrid
Another thing I noticed is that you do not use an RS485 direction control pin. I'm not sure why it works in your situation without it. It doesn't work with the RS485 breakout board that I used because there is no direction control.
Although I have been using microcontrollers for a long time, RS485 is new to me so there could be something that I don't understand.
On the TTL to RS485 breakout board I have, it is necessary to set the direction control pin correctly.
In simple test programs it works well using the direction pin. If I don't use the direction pin, it doesn't work.
For your configuration I can only assume that you use a special board that automatically handles the direction for you?
It would be useful if it could be programmed to work with a more basic RS485 board. The RS485 board I have is shown on this page :-
https://microcontrollerslab.com/rs485-serial-communication-esp32-esp8266-tutorial/
In my case, I connect the RE and DE pins together and connect them to a direction pin on the ESP32.
Whenever you want to transmit the program takes to direction pin HIGH and when receiving data, put the direction pin LOW.
One I use the direction pin in test programs, then transferring data between two ESP32 devices is straight forward.
In your test application test_RS485_Solax_ESP32.INO, you have comments that looks like you have tried something like this.
//#define RX 17 // D1 =5 // 10 //Serial Receive pin
//#define TX 16 // D2 = 4 //Serial Transmit pin
//#define RTS_pin 9 //RS485 Direction control
//#define RS485Transmit HIGH
//#define RS485Receive LOW
The final suggestion I have is that an implementation writing to the Solax X1 Hybrid write registers from MQTT would be very useful for my application and maybe for other people.
I have to keep a number of inverters synchronized with the same configuration so having each ESP32 subscribe to an MQTT topic so it can receive a configuration from the MQTT broker would be a useful function. The ESP32 could then write changes to the inverter registers.
I can potentially help with work like this because I have reasonable programming skills although I have never used GitHub before.
regards
Steve
Hallo Tobias,
ich mochte meinen Growatt WR SPH über Modbus auslesen. Da ich mich mit Modbus nicht auskenne, habe ich mir bei eBay ein komplettes Modul gekauft. Der Typ hatte mir geschrieben, dass alles für meinen WR eingestellt ist. Habe gekauft und nichts funktioniert. Er meldet sich nicht mehr, na ja er hat ja das Geld :-(
Ich habe mich etwas eingelesen und hier deine Antworten gelesen. Du hast geschrieben, dass auf dem "RS485 to TTL" Modul RX und TX blinken müssen. Das passiert nicht. Ich wollte wissen, ob der WR überhaupt etwas sendet. Habe mir dazu einen USB Stick gekauft und siehe da, mit der richtigen Software und den korrekten Einstellungen antwortet der WR.
A+ und B- habe ich genauso mit dem „RS485 to TTL" Modul verbunden. Ich kann mich anmelden und die RAW Data senden. Dann müsste doch TX blinken, was nicht funktioniert.
Der Typ hatte mir geschrieben, dass der WR die Daten sendet , wenn bei RAW Data etwas angezeigt wird. Es wird immer etwas angezeigt, auch wenn der RJ45 Stecker im WR nicht eingesteckt ist.
Kannst du mir bitte einen Tipp geben, wie ich weiter machen kann?
Danke Ciao thomas
could you please add Solax X1-Boost/Air/Mini
thanks
hallo Tobias,
ist es auch möglich Werte im Inverter zu verändern, und wenn ja was muß ich denn da über mqtt schicken?
Irgend wo habe ich mal gelesen das es mit deiner Software geht, jetzt konnte ich dazu nichts mehr finden.
Es wäre top, wenn ich bei meinem Solax x3 g4 die Max-Einspeiseleistung ändern könnte, auch wäre das Ein- und Ausschalten des Inverters nicht schlecht.
danke
Gruß
Hans
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.