Hall an Alle.
Muss als erstes sagen:
Ich bin ein Blutiger Anfänger.
Ich will mit einem ESP8266 (später SSD1306 erweitern) die Werte aus meinem Wechselrichter E3DC per MODBUS auslesen.
Dazu habe ich einen Beispiel Sketch angepasst.
Leider werden da negative Werte nicht dargestellt
Wie macht man das?
/*
Modbus-Arduino Example - Master Modbus IP Client (ESP8266/ESP32)
Read Holding Register from Server device
(c)2018 Alexander Emelianov (a.m.emelianov@gmail.com)
https://github.com/emelianov/modbus-esp8266
*/
#ifdef ESP8266
#include <ESP8266WiFi.h>
#else
#include <WiFi.h>
#endif
#include <ModbusIP_ESP8266.h>
IPAddress remote(192, 168, xxx, xxx); // Address of Modbus Slave device
const int LOOP_COUNT = 10;
ModbusIP mb; //ModbusIP object
void setup() {
Serial.begin(115200);
WiFi.begin("SSID", "PAS");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
mb.client();
}
uint16_t AKKU = 0;
uint16_t SOLAR = 0;
uint16_t NETZ = 0;
uint8_t show = LOOP_COUNT;
void loop() {
if (mb.isConnected(remote)) { // Check if connection to Modbus Slave is established
mb.readHreg(remote, 40082, &AKKU); // Batterie Ladung in % Initiate Read Coil from Modbus Slave
mb.readHreg(remote, 40067, &SOLAR); //PV Leistung Watt
mb.readHreg(remote, 40073, &NETZ); //Netz Bezug/Einspeisung
} else {
mb.connect(remote); // Try to connect if no connection
}
mb.task(); // Common local Modbus task
delay(100); // Pulling interval
if (!show--) { // Display Slave register value one time per second (with default settings)
Serial.print("Akku in % : ");
Serial.println(AKKU);
Serial.print("Solar in W : ");
Serial.println(SOLAR);
Serial.print("Netz in W : ");
Serial.println(NETZ);
show = LOOP_COUNT;
}
}
Hier die Ausgabe vom Serieller Monitor
Akku in % : 99
Solar in W : 208
Netz in W : 65533
Akku in % : 99
Solar in W : 208
Netz in W : 2
Akku in % : 99
Solar in W : 208
Netz in W : 7
Akku in % : 99
Solar in W : 208
Netz in W : 65523
Akku in % : 99
Solar in W : 209
Netz in W : 2
Akku in % : 99
Solar in W : 212
Netz in W : 0
Akku in % : 99
Solar in W : 211
Netz in W : 3
Akku in % : 99
Solar in W : 209
Netz in W : 1
Akku in % : 99
Solar in W : 210
Netz in W : 1
Akku in % : 99
Solar in W : 210
Netz in W : 8
Akku in % : 99
Solar in W : 211
Netz in W : 65522
Akku in % : 99
Solar in W : 213
Netz in W : 6
Akku in % : 99
Solar in W : 209
Netz in W : 5
Die Negative Werte vom Netz in W : werden 5stellig angezeigt.
Hallo fony.
Das war auch bei mir die erste Idee, aber dann gabs die Fehlermeldung:
Compilation error: no matching function for call to 'ModbusIP::readHreg(IPAddress&, int, int16_t*)'
Auch sint16_t geht nicht.
Compilation error: no matching function for call to 'ModbusIP::readHreg(IPAddress&, int, sint16_t*)'
Ich vermute das die "ModbusIP_ESP8266.h" das nicht unterstützt.
Gibt es sonst noch Möglichkeiten?
Oder andere Bibliotheken dafür?
Hab es noch nicht ausprobiert, aber in der Beschreibung ist der Integer als " uint8_t " beschrieben.
Vielleicht ist meine Skepsis auch unberechtigt! Ich werde berichten.
Dann bekommst keine Negative werte
Wurde in die .h schauen wo ist uint8_t und den auf int umstellen, kann sein dass das ist in der .ccp drinnen.
Kaput machst du nix, notfalls funktioniert nicht.
Vielleicht hat @noiasca eine Idee Er kennt sich sehr gut aus mit Modbus. Hast eine Protokoll Liste mit allen Adressen und was für werte sollen kommen?
Dan stelle den Link hier rein.
Ich meine @noiasca hat sogar eine Modbus Lib geschrieben, bin mir aber nicht sicher.
Uh, die ist aber alt, die Doku! Es gibt eine Version 2.20 von E3DC/Hager Energy, die du über das alte Portal unter Downloads herunterladen kannst.
Ich habe selber eine S10 und lese die über Modbus aus. Ich benutze dafür meine eModbus-Library, mit der du auf dem ESP8266 einen ModbusClientTCPasync bauen könntest.
Hallo,
das Problem ist Ja eigentlich deine Lib. Die negativen Werte des Umrichters werden wegen der vorzeichenlosen Werte der Lib vermutlich falsch interpretiert.
Versuch mal eine Hilfsvariable zu verwenden sowas in der Art. Ich weiß das ist Murks
uint16_t NETZ = 65533;
int16_t netz;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println();
Serial.println(NETZ);
netz = NETZ;
Serial.println(netz);
}
void loop() {
// put your main code here, to run repeatedly:
}
Hallo und besten Dank für die Hilfe! @Rentner Dein Tipp ist einfach, aber genial.
Es Funktioniert!
@Miq1 Mit deinem Vorschlag muss ich mich in Ruhe beschäftigen. (Bei schlechtem Wetter oder kalte Jahreszeit.) Ist für mich noch schwierig das für den Arduino sofort umzusetzen.
Und an alle die es interessiert wie mein erster Prototyp für meine weitere Projekte aussieht,
hier der Code:
/*
Basier aus dem Beispiel von:
Modbus-Arduino Example - Master Modbus IP Client (ESP8266/ESP32)
(c)2018 Alexander Emelianov (a.m.emelianov@gmail.com)
https://github.com/emelianov/modbus-esp8266
*/
#ifdef ESP8266
#include <ESP8266WiFi.h>
#else
#include <WiFi.h>
#endif
#include <ModbusIP_ESP8266.h>
// Für SSD1306 Display
#include <Wire.h>
#include "SSD1306Wire.h"
SSD1306Wire display(0x3c, 12, 14); // SDA-D6, SCL-D5 für Onboard Display
IPAddress remote(192, 168, ###, ###); // E3DC IP Addresse (Modbus Slave-Gerät)
const int LOOP_COUNT = 10; // Abruf Interval 10 = 1Sec.
ModbusIP mb; //ModbusIP object
// Variablen
uint16_t SOLAR = 0;
uint16_t HAUS = 0;
uint16_t NETZ = 65535;
int16_t netz = NETZ;
uint16_t AKKU = 0;
uint8_t show = LOOP_COUNT;
void setup() {
Serial.begin(115200);
WiFi.begin("W-LAN SSID", "Passwort");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
mb.client();
display.init();
display.setI2cAutoInit(true);
display.flipScreenVertically();
display.setFont(ArialMT_Plain_16);
display.setTextAlignment(TEXT_ALIGN_LEFT);
}
void loop() {
if (mb.isConnected(remote)) { // Check if connection to Modbus Slave is established
// Register 400## aus Modbus auslesen
mb.readHreg(remote, 40067, &SOLAR); //PV Leistung Watt
mb.readHreg(remote, 40071, &HAUS); //PV Leistung Watt
mb.readHreg(remote, 40073, &NETZ); //Netz Bezug/Einspeisung ohne negativen Vorzeichen
mb.readHreg(remote, 40082, &AKKU); // Batterie Ladung in %
} else {
mb.connect(remote); // Verbindung herstellen
}
mb.task(); // Gemeinsame lokale Modbus-Aufgabe
delay(100);
if (!show--) { // Slave-Registerwert anzeigen (LOOP_COUNT = 10)
netz= (NETZ -65536); // Umrechnung Netz Bezug/Einspeisung mit negativen Vorzeichen
Serial.println("Solar: " + String(SOLAR) + (" W"));
Serial.println("Eig. Verb. : " + String(HAUS) + (" W"));
Serial.println("Netz: " + String(netz) + (" W"));
Serial.println("Akku: " + String(AKKU) + (" %"));
Serial.println("NETZ R: " + String(NETZ) + (" -RohDaten"));
Serial.println(" ");
show = LOOP_COUNT;
display.clear();
display.drawString(0, 0, "Akku: " + String(AKKU)+("%"));
display.drawString(0, 15, "PV: " + String(SOLAR)+("W"));
display.drawString(0, 30, "Netz: " + String(netz)+("W"));
display.drawString(0, 45, "Eig.Vrb: " + String(HAUS)+("W"));
display.display();
// Da ein OLED Display zum einbrennen neigt, sollte man eine bedingte Aktivierung programmieren!
// display.displayOff();
// display.displayOff();
}
}