Mit ESP8266 vom E3DC negative Werte darstellen

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 :sleepy:
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.

Setze Deinen Code und die Ausgaben bitte in Codetags. Wie das geht, steht hier.

Gruß Tommy

Mach mal das als int, uint16_t bedeutet vorzeichenlosen int.

Was zum lesen

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?

Wurde mit der versuchen.

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.

Das ist der Link:
ModuBus-Dokumentation_2016-08-05.pdf

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.

Hier gibt es ein einfaches Beispiel dazu

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 :wink:


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:

}

Ausgabe auf Monitor

65533
-3

Hallo und besten Dank für die Hilfe!
@Rentner Dein Tipp ist einfach, aber genial.
Es Funktioniert! :+1:

@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(); 

  }
 
}


This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.