Seite 1 von 2

SUN1000GITL/SUN2000GTIL Wechselrichter

Verfasst: Mi 26. Jan 2022, 15:02
von jens.wagner
Hallo Ulrich,

ich habe einen SUN1000GTIL WR im Einsatz und gesehen, dass dessen Unterstützung schon in Diskussion war aber auf Grund der nicht verfügbaren Doku nicht realisiert werden konnte.

Nun habe ich unter https://secondlifestorage.com/index.php ... 28/page-17 eine Art Protokollspezifikation gefunden, die zwar nicht vom Hersteller stammt, aber die meisten Parameter fürs Monitoring liefern sollte.

So schreibt dort ein User "Besides registers addresses 0 to 7 (basically the serial # of the box) there are only 6 other values:
Registers 43 (? no idea what I can do with this), 59 (a status), 60 (Day active Power), 63 (Total active power), 70 (Grid Voltage), 86 (Power out) and 109 (Battery/Collector voltage)."

was die Frage nach den vier interessanten Registern beantwortet, denn viel mehr macht das Ding ja nicht als (bei Bedarf über einen Stromzangensensor limitiert) wechelrichten. Das Ding hat einen RS232 Anschluss, dessen Belegung in dem Thread auch beschrieben ist und es gibt auch eine kleine Hilfe wie das verwendete Modusprotokoll aufgebaut ist (siehe angehängtes PDF hier).

Damit sollte sich meines Erachtens eine einfache Unterstützung dieser Geräte in der Solaranzeige realisieren lassen. Wäre sicher für viele Selbstbauer sehr interessant. Falls weitere Protokolldetails bekannt werden, kann man das ja ausbauen.

Viele Grüße,
Jens

Re: SUN1000GITL/SUN2000GTIL Wechselrichter

Verfasst: Mi 26. Jan 2022, 22:25
von Leon2079
Würde mich auch über eine Unterstützung freuen.

Re: SUN1000GITL/SUN2000GTIL Wechselrichter

Verfasst: So 6. Feb 2022, 13:48
von carverandi
Ich hätte auch interesse an der Anbindung

Re: SUN1000GITL/SUN2000GTIL Wechselrichter

Verfasst: Mi 9. Feb 2022, 22:58
von jens.wagner
So Leute,

ich habe das Ding heute Mal mit einem netten Modbus-Master-Programm von der ipc2u Website ausgelesen bekommen. Und dazu noch eine chinesische Protokoll-Spec im Netz gefunden und mit Google Translator übersetzt bekommen.

Also das Ding implementiert tatsächlich nur einen Teil der Eyebond Modbus Spezifikation aus Shenzen. Und zwar genau die bereits beschriebenen Parameter. Zusätzlich kann man noch die Seriennummer des Geräts und die Protokollversion auf den ersten Adressen auslesen, das war's dann aber.

Die Kommunikation ist denkbar einfach: Man braucht einen Adapter USB zu Seriell DB9 (Männchen am Adapterkabel, Weibchen am WR), stellt 9600 Baud, keine Parität und 1 Stoppbit ein und los geht's. Ganz normale RS232 Schnittstelle, keine Zauberei. Modbus RTU mit dem üblichen Datenformat und den üblichen CRC.

Vielleicht hat Ulrich ja einen Tipp welchen Reglertyp man da einfach modifizieren kann, dann setze ich mich da ran. Sollte machbar sein.

Viele Grüße,
Jens

Re: SUN1000GITL/SUN2000GTIL Wechselrichter

Verfasst: Do 10. Feb 2022, 09:21
von Leon2079
Klinkt sehr positiv danke Jens

Re: SUN1000GITL/SUN2000GTIL Wechselrichter

Verfasst: Do 10. Feb 2022, 10:13
von Ulrich
Hallo Jens,

jeder Wechselrichter hat bei dem Auslesen so seine Eigenheiten. Im Unterverzeichnis /var/www/html findest du alle Ausleseroutinen der jeweiligen Geräte. Die Datei sungrow.php z.B. ist die Routine für den Sungrow Wechselrichter. Dort musst du dir den Script heraus suchen, der am besten zu deinem Protokoll passt. Da jedoch jedes Gerät so seine speziellen Eigenheiten hat, wird es sehr schwierig sein, die richtige Datei zu finden.

Re: SUN1000GITL/SUN2000GTIL Wechselrichter

Verfasst: Do 10. Feb 2022, 21:10
von jens.wagner
Ulrich hat geschrieben:
Do 10. Feb 2022, 10:13
Hallo Jens,

jeder Wechselrichter hat bei dem Auslesen so seine Eigenheiten. Im Unterverzeichnis /var/www/html findest du alle Ausleseroutinen der jeweiligen Geräte. Die Datei sungrow.php z.B. ist die Routine für den Sungrow Wechselrichter. Dort musst du dir den Script heraus suchen, der am besten zu deinem Protokoll passt. Da jedoch jedes Gerät so seine speziellen Eigenheiten hat, wird es sehr schwierig sein, die richtige Datei zu finden.
Danke, das hatte ich schon gesehen. Werde mir mal was passendes raussuchen. Die Kostal Pico Datei sah auf den ersten Blick brauchbar aus. Zumindest habe ich den Code halbwegs verstanden.

Re: SUN1000GITL/SUN2000GTIL Wechselrichter

Verfasst: Mi 16. Feb 2022, 19:42
von jens.wagner
Also mit dem Programm modpoll habe ich schon mal getestet (Bedeutung im Kommentar ergänzt)
Aufruf:

Code: Alles auswählen

~/modpoll/arm-linux-gnueabihf/modpoll -b 9600 -p none -m rtu -a 1 -r 60 -c 28 -t 4 /dev/ttyUSB2
Wobei -b für Baudrate steht, -p none für keine Parität, -m rtu für das Modbus RTU Protokoll, -a 1 für Adresse 1, -r 60 Beginn bei Register 60 und -c 28 für 28 Zeilen lesen und -t 4 steht für "16-bit output (holding) register data type" und am Ende folgt das USB-Interface

Ausgabe (Bedeutung im Kommentar ergänzt, Zahlen in eckigen Klammern kennzeichnen das Register):

Code: Alles auswählen

[60]: 512  // Das ist eine Statusmeldung
[61]: 8 // 0,8 kWh Tagesleistung
[62]: 0
[63]: 0
[64]: 3552 // 355,2 kWh kumulierte WR-Leistung
[65]: 0
[66]: 0
[67]: 0
[68]: 0
[69]: 0
[70]: 0
[71]: 2378 // 237,8V aktuelle Netzspannung
[72]: 0
[73]: 0
[74]: 0
[75]: 0
[76]: 0
[77]: 0
[78]: 0
[79]: 0
[80]: 0
[81]: 0
[82]: 0
[83]: 0
[84]: 0
[85]: 0
[86]: 0
[87]: 36 // 3,6 W aktuelle WR-Leistung?

@Ulrich: Könntest du mir ein PHP-Skript als Template empfehlen? Oder schnell mal ein PHP-Skript für die paar Variablen zusammenstellen? Ich habe ein wenig Probleme, den Unterschied im Code zwischen den WR zu finden.

Re: SUN1000GITL/SUN2000GTIL Wechselrichter

Verfasst: Mi 16. Feb 2022, 21:46
von jens.wagner
Ich hoffe mal, dass folgender Code in etwa richtig ist

sun1000.php

Code: Alles auswählen

#!/usr/bin/php
<?php
/*****************************************************************************
//  Solaranzeige Projekt             Copyright (C) [2015-2020] [Ulrich Kunz]
//  modifiz. für SUN1000GTIL/SUN2000GTIL Wechselrichter [2022] [Jens Wagner]
//
//  Dieses Programm ist freie Software. Sie können es unter den Bedingungen
//  der GNU General Public License, wie von der Free Software Foundation
//  veröffentlicht, weitergeben und/oder modifizieren, entweder gemäß
//  Version 3 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
//
//  Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, daß es
//  Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE, sogar ohne
//  die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN
//  BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License.
//
//  Ein original Exemplar der GNU General Public License finden Sie hier:
//  http://www.gnu.org/licenses/
//
//  Dies ist ein Programmteil des Programms "Solaranzeige"
//
//  Es dient dem Auslesen des Wechselrichters Growatt über eine RS485
//  Schnittstelle mit USB Adapter. Protokoll Version 1  V3.5
//  Das Auslesen wird hier mit einer Schleife durchgeführt. Wie oft die Daten
//  ausgelesen und gespeichert werden steht in der user.config.php
//
//
*****************************************************************************/
$path_parts = pathinfo($argv[0]);
$Pfad = $path_parts['dirname'];
if (!is_file($Pfad."/1.user.config.php")) {
  // Handelt es sich um ein Multi Regler System?
  require($Pfad."/user.config.php");
}

require_once($Pfad."/phpinc/funktionen.inc.php");
if (!isset($funktionen)) {
  $funktionen = new funktionen();
}

// Im Fall, dass man die Device manuell eingeben muss
if (isset($USBDevice) and !empty($USBDevice)) {
  $USBRegler = $USBDevice;
}

$Tracelevel = 8;  //  1 bis 10  10 = Debug
$RemoteDaten = true;
$Start = time();  // Timestamp festhalten
$funktionen->log_schreiben("----------------------   Start  sun1000.php   --------------------- ","|--",6);

$funktionen->log_schreiben("Zentraler Timestamp: ".$zentralerTimestamp,"   ",8);
$aktuelleDaten = array();
$aktuelleDaten["zentralerTimestamp"] = $zentralerTimestamp;

setlocale(LC_TIME,"de_DE.utf8");


//  Hardware Version ermitteln.
$Teile =  explode(" ",$Platine);
if ($Teile[1] == "Pi") {
  $Version = trim($Teile[2]);
  if ($Teile[3] == "Model") {
    $Version .= trim($Teile[4]);
    if ($Teile[5] == "Plus") {
      $Version .= trim($Teile[5]);
    }
  }
}
$funktionen->log_schreiben("Hardware Version: ".$Version,"o  ",8);

switch($Version) {
  case "2B":
  break;
  case "3B":
  break;
  case "3BPlus":
  break;
  case "4B":
  break;
  default:
  break;
}

if (empty($WR_Adresse)) {
  $WR_ID = "01";
}
elseif(strlen($WR_Adresse) == 1)  {
  $WR_ID = str_pad(dechex($WR_Adresse),2,"0",STR_PAD_LEFT);
}
elseif(strlen($WR_Adresse) == 2)  {
  $WR_ID = str_pad(dechex(substr($WR_Adresse,-2)),2,"0",STR_PAD_LEFT);
}
else {
  $WR_ID = dechex($WR_Adresse);
}


$funktionen->log_schreiben("WR_ID: ".$WR_ID,"+  ",8);


$USB1 = $funktionen->openUSB($USBRegler);
if (!is_resource($USB1)) {
  $funktionen->log_schreiben("USB Port kann nicht geöffnet werden. [1]","XX ",7);
  $funktionen->log_schreiben("Exit.... ","XX ",7);
  goto Ausgang;
}

$i = 1;
do {
  $funktionen->log_schreiben("Die Daten werden ausgelesen...","+  ",9);

  /****************************************************************************
  //  Ab hier wird der Regler ausgelesen.
  //
  //  This is a map document of standard MODBUS RTU protocol for only
  //  for SUN1000GTIL/SUN200GTIL inverter
  //  Inverter Address: Must be set to 1.
  //  Communication baud rate: The default baud rate is 9600 bps, no parity
  //
  //
  ****************************************************************************/

  $Befehl["DeviceID"] = "01";
  $Befehl["BefehlFunctionCode"] = "04";
  $Befehl["RegisterAddress"] = "0000";
  $Befehl["RegisterCount"] = "0007";
  $rc = $funktionen->phocos_pv18_auslesen($USB1,$Befehl);
  $aktuelleDaten["Seriennummer"] = $funktionen->hex2string($rc["data"]);

  $Befehl["RegisterAddress"] = "003c";
  $Befehl["RegisterCount"] = "0001";
  $rc = $funktionen->phocos_pv18_auslesen($USB1,$Befehl);
  $aktuelleDaten["Tagesertrag"] = hexdec($rc["data"])/10;

  $Befehl["RegisterAddress"] = "0040";
  $Befehl["RegisterCount"] = "0001";
  $rc = $funktionen->phocos_pv18_auslesen($USB1,$Befehl);
  $aktuelleDaten["Gesamtertrag"] = hexdec($rc["data"])/10;

  $Befehl["RegisterAddress"] = "0070";
  $Befehl["RegisterCount"] = "0001";
  $rc = $funktionen->phocos_pv18_auslesen($USB1,$Befehl);
  $aktuelleDaten["Netzspannung"] = hexdec($rc["data"])/10;

  $Befehl["RegisterAddress"] = "0056";
  $Befehl["RegisterCount"] = "0001";
  $rc = $funktionen->phocos_pv18_auslesen($USB1,$Befehl);
  $aktuelleDaten["Ausgangsleistung"] = hexdec($rc["data"])/10;

  $Befehl["RegisterAddress"] = "006d";
  $Befehl["RegisterCount"] = "0001";
  $rc = $funktionen->phocos_pv18_auslesen($USB1,$Befehl);
  $aktuelleDaten["Batteriespannung"] = hexdec($rc["data"])/10;


  $aktuelleDaten["WattstundenGesamtHeute"] = ($aktuelleDaten["Tagesertrag"]);

  $funktionen->log_schreiben("Auslesen des Gerätes beendet.","   ",7);



  /****************************************************************************
  //  ENDE REGLER AUSLESEN      ENDE REGLER AUSLESEN      ENDE REGLER AUSLESEN
  ****************************************************************************/



  /**************************************************************************
  //  Falls ein ErrorCode vorliegt, wird er hier in einen lesbaren
  //  Text umgewandelt, sodass er als Fehlermeldung gesendet werden kann.
  //  Die Funktion ist noch nicht überall implementiert.
  **************************************************************************/
  $FehlermeldungText = "";

  $aktuelleDaten["Diag_Binary"] = base_convert(dechex($aktuelleDaten["Diag_Status"]),16,2);


  /****************************************************************************
  //  Die Daten werden für die Speicherung vorbereitet.
  ****************************************************************************/
  $aktuelleDaten["Regler"] = $Regler;
  $aktuelleDaten["Objekt"] = $Objekt;
  $aktuelleDaten["Produkt"] = "Goodwe";
  $aktuelleDaten["zentralerTimestamp"] = ($aktuelleDaten["zentralerTimestamp"]+10);


  if ($i == 1)
    $funktionen->log_schreiben(print_r($aktuelleDaten,1),"   ",8);


  /****************************************************************************
  //  User PHP Script, falls gewünscht oder nötig
  ****************************************************************************/
  if ( file_exists ("/var/www/html/sun1000_math.php")) {
    include 'sun1000_math.php';  // Falls etwas neu berechnet werden muss.
  }


  /**************************************************************************
  //  Alle ausgelesenen Daten werden hier bei Bedarf als mqtt Messages
  //  an den mqtt-Broker Mosquitto gesendet.
  //  Achtung! Die Übertragung dauert ca. 30 Sekunden!
  **************************************************************************/
  if ($MQTT and $i == 1) {
    $funktionen->log_schreiben("MQTT Daten zum [ $MQTTBroker ] senden.","   ",1);
    require($Pfad."/mqtt_senden.php");
  }


  /****************************************************************************
  //  Zeit und Datum
  ****************************************************************************/
  //  Der Regler hat keine interne Uhr! Deshalb werden die Daten vom Raspberry benutzt.
  $aktuelleDaten["Timestamp"] = time();
  $aktuelleDaten["Monat"]     = date("n");
  $aktuelleDaten["Woche"]     = date("W");
  $aktuelleDaten["Wochentag"] = strftime("%A",time());
  $aktuelleDaten["Datum"]     = date("d.m.Y");
  $aktuelleDaten["Uhrzeit"]      = date("H:i:s");




  /****************************************************************************
  //  InfluxDB  Zugangsdaten ...stehen in der user.config.php
  //  falls nicht, sind das hier die default Werte.
  ****************************************************************************/
  $aktuelleDaten["InfluxAdresse"] = $InfluxAdresse;
  $aktuelleDaten["InfluxPort"] = $InfluxPort;
  $aktuelleDaten["InfluxUser"] =  $InfluxUser;
  $aktuelleDaten["InfluxPassword"] = $InfluxPassword;
  $aktuelleDaten["InfluxDBName"] = $InfluxDBName;
  $aktuelleDaten["InfluxDaylight"] = $InfluxDaylight;
  $aktuelleDaten["InfluxDBLokal"] = $InfluxDBLokal;
  $aktuelleDaten["InfluxSSL"] = $InfluxSSL;
  $aktuelleDaten["Demodaten"] = false;


  /*********************************************************************
  //  Daten werden in die Influx Datenbank gespeichert.
  //  Lokal und Remote bei Bedarf.
  *********************************************************************/
  if ($InfluxDB_remote) {
    // Test ob die Remote Verbindung zur Verfügung steht.
    if ($RemoteDaten) {
      $rc = $funktionen->influx_remote_test();
      if ($rc) {
        $rc = $funktionen->influx_remote($aktuelleDaten);
        if ($rc) {
          $RemoteDaten = false;
        }
      }
      else {
        $RemoteDaten = false;
      }
    }
    if ($InfluxDB_local) {
      $rc = $funktionen->influx_local($aktuelleDaten);
    }
  }
  else {
    $rc = $funktionen->influx_local($aktuelleDaten);
  }




  if ($Wiederholungen <= $i or $i >= 6) {
      $funktionen->log_schreiben("Schleife ".$i." Ausgang...","   ",8);
      break;
  }
  if (is_file($Pfad."/1.user.config.php")) {
    // Ausgang Multi-Regler-Version
    $Zeitspanne = (9 - (time() - $Start));
    $funktionen->log_schreiben("Multi-Regler-Ausgang. ".$Zeitspanne,"   ",2);
    if ($Zeitspanne > 0) {
      sleep($Zeitspanne);
    }
    break;
  }
  else {
    $funktionen->log_schreiben("Schleife: ".($i)." Zeitspanne: ".(floor((56 - (time() - $Start))/($Wiederholungen-$i+1))
),"   ",9);
    sleep(floor((56 - (time() - $Start))/($Wiederholungen-$i+1)));
  }
  $i++;
} while (($Start + 54) > time());


if (isset($aktuelleDaten["Seriennummer"]) and isset($aktuelleDaten["Regler"])) {


  /*********************************************************************
  //  Jede Minute werden bei Bedarf einige Werte zur Homematic Zentrale
  //  übertragen.
  *********************************************************************/
  if (isset($Homematic) and $Homematic == true) {
    $funktionen->log_schreiben("Daten werden zur HomeMatic übertragen...","   ",8);
    require($Pfad."/homematic.php");
  }

  /*********************************************************************
  //  Sollen Nachrichten an einen Messenger gesendet werden?
  //  Bei einer Multi-Regler-Version sollte diese Funktion nur bei einem
  //  Gerät aktiviert sein.
  *********************************************************************/
  if (isset($Messenger) and $Messenger == true) {
    $funktionen->log_schreiben("Nachrichten versenden...","   ",8);
    require($Pfad."/meldungen_senden.php");
  }

  $funktionen->log_schreiben("OK. Datenübertragung erfolgreich.","   ",7);
}
else {
  $funktionen->log_schreiben("Keine gültigen Daten empfangen.","!! ",6);
}




Ausgang:

$funktionen->log_schreiben("----------------------   Stop   sun1000.php   --------------------- ","|--",6);

return;



?>

Re: SUN1000GITL/SUN2000GTIL Wechselrichter

Verfasst: Do 17. Feb 2022, 10:41
von jens.wagner
@Ulrich: Jetzt müsste wohl noch die Datei funktionen.inc.php im Include-Verzeichnis phpinc angepasst werden, am besten gleich mit einer Reglernummer, damit es in den offiziellen Release-Zweig kommt. Ist das korrekt so?