Growatt Shine-F, neue Firmware, Wie Wechselrichter mit Modbus Register auslesen?

Hallo,
ich bin aktuell am programmieren einer neuen Firmware für meinen Wifi-Stick welcher am Growatt Solarwechselrichter hängt.
Aus irgendeinem Grund hat sich dieser verabschiedet.
Ich bekomme zwar Ersatz von Growatt, möchte aber auf langer Sicht nicht in der China-Cloud meine Daten sehen.
Also habe ich den Stick zerlegt und einen ESP8266 entdeckt. Die benötigten Pin für RX und TX waren auch vorhanden.
Der Stick hängt mit USB am Wechselrichter. Alle wichtigen Bauteile sind also für eine Kommunikation vorhanden. Er lief ja vorher auch :slight_smile:

Was habe ich bis jetzt erreicht:
WLan ... läuft wieder
InFluxDB... Verbindung und Datenversendung an den Rasperry läuft. Testdaten werden in InfluxDB
Grafana ... läuft auf dem Rasperry

Was benötige ich jetzt noch? Das auslesen der Register mit Modbus.

Beispiel: float pv1voltage --- aus dem Wechselrichter aufrufen.

Auf dem Stick gibt es nur den USB-RS232 Converter. Einen RS485 gibt es nicht. Falls das wichtig sein sollte.

Hier noch mein Code welcher so eventuell nicht perfekt ist, aber er läuft.
Wie rufe ich Modbus auf und benutze es.

Gruß Ralf

Mein Code

#include <NTPClient.h>
#include <WiFiUdp.h>
#include <ModbusMaster.h>
#include <ESP8266WiFi.h>
#include <InfluxDbClient.h>
#include "setup.h"


const char* SSID = "xxx";
const char* PSK = "xxx";
const char* GATEWAY = "192.168.2.1"; 

#define INFLUXDB_URL "http://192.168.2.6:8086"
#define INFLUXDB_DB_NAME "solar"

#define DEVICE "Growatt"

WiFiClient espClient;


InfluxDBClient client(INFLUXDB_URL, INFLUXDB_DB_NAME);

#define LED_GN 0  // GPIO0
#define LED_RT 2  // GPIO2
#define LED_BL 16 // GPIO16


ModbusMaster growatt;


Point wechselrichter_batt_cap("batt_cap");
Point wechselrichter_batt_volt("batt_volt");

Point wechselrichter_modul_volt("modul_volt");
Point wechselrichter_modul_amp("modul_amp");
Point wechselrichter_modul_kw("modul_kw");

Point wechselrichter_ac_out_amp("ac_out_amp");
Point wechselrichter_ac_out_kw("ac_out_kw");

Point wechselrichter_ac_in_amp("ac_in_amp");
Point wechselrichter_ac_in_kw("ac_in_kw");


int letztestunde, aktuellestunde;
long batt_cap;
long batt_volt;
long modul_volt;
long modul_amp;
long modul_kw;
long ac_out_amp;
long ac_out_kw;
long ac_in_amp;
long ac_in_kw;



WiFiUDP ntpUDP;
const long utcOffsetInSeconds = 3600;
char daysOfTheWeek[7][12] = {"Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"};
NTPClient timeClient(ntpUDP, GATEWAY, utcOffsetInSeconds);

void setup() {
  Serial.begin(115200);
  setup_wifi();

  pinMode(LED_GN, OUTPUT);
  pinMode(LED_RT, OUTPUT);
  pinMode(LED_BL, OUTPUT);
  digitalWrite(LED_GN, LOW);
  digitalWrite(LED_RT, LOW);
  digitalWrite(LED_BL, LOW);

  //influxdb
  client.setConnectionParamsV1(INFLUXDB_URL, INFLUXDB_DB_NAME);

  wechselrichter_batt_cap.addTag("batt_cap", DEVICE);
  wechselrichter_batt_cap.addField("batt_cap", batt_cap);
  wechselrichter_batt_volt.addTag("batt_volt", DEVICE);
  wechselrichter_batt_volt.addField("batt_volt", batt_volt);

  wechselrichter_modul_volt.addTag("modul_volt", DEVICE);
  wechselrichter_modul_volt.addField("modul_volt", modul_volt);
  wechselrichter_modul_amp.addTag("modul_amp", DEVICE);
  wechselrichter_modul_amp.addField("modul_amp", modul_amp);
  wechselrichter_modul_kw.addTag("modul_kw", DEVICE);
  wechselrichter_modul_kw.addField("modul_kw", modul_kw);

  wechselrichter_ac_out_amp.addTag("ac_out_amp", DEVICE);
  wechselrichter_ac_out_amp.addField("ac_out_amp", ac_out_amp);
  wechselrichter_ac_out_kw.addTag("ac_out_kw", DEVICE);
  wechselrichter_ac_out_kw.addField("ac_out_kw", ac_out_kw);

  wechselrichter_ac_in_amp.addTag("ac_in_amp", DEVICE);
  wechselrichter_ac_in_amp.addField("ac_in_amp", ac_in_amp);
  wechselrichter_ac_in_kw.addTag("ac_in_kw", DEVICE);
  wechselrichter_ac_in_kw.addField("ac_in_kw", ac_in_kw);


}

void setup_wifi() {
  WiFi.begin(SSID, PSK);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    digitalWrite(LED_RT, HIGH); digitalWrite(LED_BL, LOW);
  }
  Serial.println(WiFi.localIP());


  if (client.validateConnection()) {
    Serial.print("Connected to InfluxDB: ");
    Serial.println(client.getServerUrl());
    timeClient.begin();

    
  } else {
    Serial.print("InfluxDB connection failed: ");
    Serial.println(client.getLastErrorMessage());
  }


}


void loop() {

 


//Zeit ermittelen 
  timeClient.update();
  Serial.println(timeClient.getFormattedTime());
  Serial.println(daysOfTheWeek[timeClient.getDay()]);
  Serial.println(", ");
  Serial.println(timeClient.getFormattedTime());
  aktuellestunde = timeClient.getHours();
  Serial.println(aktuellestunde);

if (aktuellestunde >  letztestunde){
     //S0 WeMos ausgelesen werden
    //danach an WeMos S0 Reset senden
  }

  Serial.println(batt_cap);
  while (WiFi.status() == WL_CONNECTED) {
    delay(500);
    

    digitalWrite(LED_BL, HIGH); digitalWrite(LED_RT, LOW);

    //Testwerte
    batt_cap = random(100);
    batt_volt = random(40, 56);
    modul_volt = random(420);
    modul_amp = modul_volt / 100;
    modul_kw = modul_volt * modul_amp;
    ac_out_amp = random(16);
    ac_out_kw = random(5000);
    ac_in_amp = random(16);
    ac_in_kw = random(3000);


    //wechselrichter_batt_cap.clearFields();
    wechselrichter_batt_cap.addField("batt_cap", batt_cap);
    wechselrichter_batt_volt.addField("batt_volt", batt_volt);
    wechselrichter_modul_volt.addField("modul_volt", modul_volt);
    wechselrichter_modul_amp.addField("modul_amp", modul_amp);
    wechselrichter_modul_kw.addField("modul_kw", modul_kw);
    wechselrichter_ac_out_amp.addField("ac_out_amp", ac_out_amp);
    wechselrichter_ac_out_kw.addField("ac_out_kw", ac_out_kw);
    wechselrichter_ac_in_amp.addField("ac_in_amp", ac_in_amp);
    wechselrichter_ac_in_kw.addField("ac_in_kw", ac_in_kw);


if (client.validateConnection()) {
    // Write point
    client.writePoint(wechselrichter_batt_cap);
    client.writePoint(wechselrichter_batt_volt);
    client.writePoint(wechselrichter_modul_volt);
    client.writePoint(wechselrichter_modul_amp);
    client.writePoint(wechselrichter_modul_kw);
    client.writePoint(wechselrichter_ac_out_amp);
    client.writePoint(wechselrichter_ac_out_kw);
    client.writePoint(wechselrichter_ac_in_amp);
    client.writePoint(wechselrichter_ac_in_kw);
    digitalWrite(LED_GN, !digitalRead(LED_GN));delay(10);digitalWrite(LED_GN, !digitalRead(LED_GN));
delay(5000);
}
  }

  }

Setze Deinen Code bitte in Codetags. Wie das geht, steht hier.
Das kannst DU auch noch nachträglich ändern.

Gruß Tommy

Danke Tommy,
hab es gefunden :slight_smile:

Bist Du sicher dass das Ding Modbus hat und nicht Serial?
Ist aber egal ohne Protokoll ----> schlechte Karten. Ist aber meine Meinung.

Gruß Bernhard

[edit]
Ganz bestimmt nicht.
Ich ziehe zurück.
Das Ding spricht Protokoll Modbus RTU
[/edit]

Hast Du einen Controller, der nicht ESP ist?
Und nen USB/Seriellen Adapter...
Dann baue ich Dir ggfls ein Input-Output für den Seriellen Monitor.

Auf Modbus komme ich nur, weil alles was ich jetzt gefunden habe darauf verweist.

https://github.com/otti/Growatt_ShineWiFi-S/tree/master/SRC/ShineWiFi-S_ModBus

Der in diesen Projekt verwendete Shine-X hat auch USB.
Nur spuckt der Code mir so viele Fehler und Warnungen aus, das ich meinen eigenen schreiben möchte.

Gruß Ralf

Kennst Du die jeweiligen abzufragenden Funktionsfelder?

Welsche ModbusMaster haste installiert? die 2.0.0 hat bei mir weniger Warnungen
Lese aber ein Tracer aus

@fony
bei mir ist 2.0.1 installiert.

@my_xy_projekt
ich habe eine PDF welche die Regiter, Funktionsfelder enthalten. Scheint mir jedenfalls.
1550402978050-growatt-pv-inverter-modbus-rs485-rtu-protocol-v3.05-客户版(1).pdf (462.4 KB)

:+1: :+1: es ist ja ganzer Protokoll :wink:

Lege deinen Sketch aus #1 zur Seite.
Starte einfach mal mit einem Beispiel aus der modbus Library und lies mal mit FunctionCode 4(Input Register) das Register 3 aus - und zwar nur 1 Register und schau was du zurück bekommst.

@noiasca
ok, mein Code scheint nicht ganz der Schrott zu sein :slight_smile: Also aufheben.
@my_xy_projekt
Ja ich hab noch einen Nano hier und Schnittstellen. Da bastle ich mir was.
Eventuell geht doch gleich ein Leonardo. der Hat die Schnittstelle doch auch mit drauf.
Muss ich mal schauen.

So,
ich komme da nicht weiter.
Auf den Bau der Testumgebung zum auslesen habe ich mal verzichtet.
Warum:

  1. es gibt bereits Software welche über Serieal und USB ausliest und dies selbständig feststellt.
  2. es gibt eine Software speziell für meinen Wechselrichter allerdings nur über RS485-Shield.

Ich könnte jetzt die Parameter und etwas Code aus Nr. 2 übernehmen. Dachte ich mir.
Wenn ich damit anfange, erhalte ich aber mit der Abfrage unten, nur 226 als Wert. Woran könnte das liegen?


 

Serial.begin(9600);
//while (!Serial);
// communicate with Modbus slave ID 1 over Serial (port 0)
mb.begin(1,Serial);
res = mb.readInputRegisters(55, 2); // dummy read total energy
delay(1000);
if( res == mb.ku8MBSuccess)
{
//Blablabla res übergebe ich weiter unten im Script
delay(1000);
}

So,
alles wird gut.
bin weiter und kann Daten lesen, und sichtbar machen.
Wie oben beschrieben, hatte ich ein bestehendes Projekt welches Daten vom selben Wechselrichtertyp über RS485 ausliest benutzen, abändern können.
Die Modbusdaten wurden da schön vorgearbeitet.
Den Code bring ich später noch hier rein.

Hallo, bin gerade selbst auch dabei einen SPH auslesen zu wollen aber komme nicht wirklich weiter mit dem Projekt von "otti" auf github und die inputregister bekomme ich absolut nicht ausgelesen. Die Holdingregister schon. hast du dein Projekt schon soweit das du es wie oben geschrieben teilen kannst? das wäre echt klasse!

Hier noch der letzte Stand der Firmware

Es muss in der setup.h die Zugangsdaten für das W-LAN und einige IP-Adressen eingetragen werden.
Wie auf einen Raspberry eine InfluxDB und Grafana aufgesetzt wird, findet ihr im Netz.
Die Webseite auf den Stick funktioniert noch nicht. Aktuell habe ich andere Projekte am laufen.
Wird sicher noch kommen.

Shine-F.zip (270.5 KB)

1 Like

Google hat mich bei meiner Suche unter anderem auch hierher geschickt. Zu den Wechselrichtern mit USB-Anschluss scheint es wenig Infos im Netz zu geben.

Ich wollte mehr oder weniger das gleiche machen und habe daher kurzerhand auch mal ein Projekt aus der Taufe gehoben.

Wichtig zu wissen ist, dass der Wechselrichter am USB-Port einen USB=>Serial Adapter mit CH340 Chipsatz erwartet. Ich habe daher nicht meinen ShineLan-X zerlegt, sondern einen NodeMCU Lolin V3 benutzt, die "breitere" Version. Achtung V2 geht nicht, da der Chipsatz ein anderer ist.

Da mir bisher alle Projekte zu speziell für einen bestimmten Typ von Wechselrichter waren und grott nicht (zuverlässig) ohne Cloud funktioniert, musste ein Ersatz her.

Mein Projekt ist ein ModBus <=> MQTT Proxy, aber in der Art, dass man über MQTT den Request zum Lesen von Registern schickt und dann über MQTT die Antwort mit den Werten erhält. Man kann bis zu 64 Register auf einmal auslesen, bei mehr steigt der Wechselrichter aus und liefert ab dem 64sten Register nur noch den Wert 65535. Also muss man die Requests etwas aufteilen, um ihn nicht zu überfordern. Klappt aber sehr gut, ich lese 500 Register und die sind in einer halben Sekunde da, das ganze ein mal pro Miinute.

Das Projekt benutzt den WifiManager für die Konfiguration, dort kann man auch die MQTT-Parameter einstellen und es unterstützt OTA Updates (damit ich nicht immer in den Keller rennen muss :grinning:)

Das Projekt ist erst einen Tag jung, läuft aber sehr ordentlich. Vielleicht hilft es dem ein oder anderen ja weiter.

Achja, mein WR ist ein SPH-5000TL3 BH.

Hi, noch so ein Verrückter :slight_smile:
Ich überlege auch gerade ob ich mal einen NodeMCU Lolin V3 teste.
Mein Shine-F läuft super, ich könnte so aber auf das W-Lan verzichten.

Gruß Ralf

5 posts were split to a new topic: Abgespalten Growatt Shine-F, neue Firmware, Wie Wechselrichter mit Modbus Register auslesen?

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