Beispiel: Ertrag JEDES Hybrid-Insel-Wechselrichters ermitteln

Welche Geräter können mit dieser Anzeige benutzt werden?
Laderegler, Wallboxen, Batterie-Management-Systeme, WLAN Schalter mit Tasmota Firmware und Wechselrichter

Moderator: Ulrich

Antworten
gzi
Beiträge: 156
Registriert: Mo 16. Jan 2023, 20:43
Hat sich bedankt: 20 Mal
Danksagung erhalten: 30 Mal

Beispiel: Ertrag JEDES Hybrid-Insel-Wechselrichters ermitteln

Beitrag von gzi »

Hallo Leute,
der Ertrag einer Hybrid-Insel-Wechselrichter PV-Anlage ergibt sich aus der für die Insel gelieferten Energie abzüglich der aus dem Netz in Zeiten niedriger PV-Leistung und Batteriestandes bezogenen Energie.

Um das zu ermitteln, habe ich vor den AC-Eingang meines Wechselrichters und nach dem AC-Ausgang je einen SDM230M Stromzähler eingebunden:
SDM230M.JPG
SDM230M.JPG (28.77 KiB) 235 mal betrachtet
Die Geräte sind recht günstig (ca. 40€) und verfügen über einen Modbus RTU Anschluss. Sie können recht einfach parallel an ein Modbus TCP WLAN Gateway, angeschlossen werden und können so von der Solaranzeige ausgelesen werden. Ich habe beide Geräte mit einem Elfin EW11 in einer Unterverteilung montiert. Der Raspi mit der Solaranzeige liest die Stromzählerdaten via WLAN.

Für den SDM230 gibt es im Solaranzeige-Image eine Reglerdatei. Leider hat der Code dort für mich nicht funktioniert. Es könnte sein, dass die Firmware des SDM230 verändert wurde. Nach einer Reihe von Experimenten bei denen mir der CAS Modbus Scanner gute Dienste geleistet hat, habe ich selber Code geschrieben, den ich in meine user_device.php (siehe hier; dort habe ich auch das Elfin EW11 WLAN Gateway beschrieben) integriert habe.

Der Code verlangt keine Einträge in der INI Datei. Die Parametrisierung findet in der user_device.php Datei statt:

Code: Alles auswählen

// 1.6 Must-Energy Wechselrichter / SDM230 Stromzähler
// 
$SDM_IP = "x.x.x.x";	 // IP-Adresse des TCP Gateway zum SDM230
$SDM_Port = "502"; 	 // Modbus-TCP Standard-Port
$SDM_Adresse1 = "02"; // Stromzähler Netzstrom; Modbus Geräte ID, wie am Display des Geräts eingestellt
$SDM_Adresse2 = "03"; // Stromzähler Solarstrom; Modbus Geräte ID, wie am Display des Geräts eingestellt

$SDM_InfluxDB = "Insel";
$SDM_Measurement = "Einspeisung";
Hier ist der Code zum Auslesen der beiden Stromzähler via WLAN TCP/IP Gateway:

Code: Alles auswählen

// 6. Must Energy Hybrid-Insel-Wechselrichter / SDM 230 Stromzähler via Modbus TCP auslesen
//
//  Das Auslesen der SDM 230 Stromzähler 
//  erfolgt via Elfin EW11 Modbus/WLAN Interface und das Modbus TCP Protokoll
//
//  Dazu wird an die RS 485/Modbus RTU Schnittstelle des SDM230
//  ein Modbus TCP WLAN Adapter angeschlossen (z.B. Elfin EW11). Damit 
//  kann die Solaranzeige den Stromzähler via WLAN auslesen. Es gibt 2 Stromzähler
//  links, Modbus-Adresse 2: 	misst Netzbezug des Hybrid-Wechselrichters
//  rechts, Modbus-Adresse 3: 	misst den vom Wechselrichter für die Insel generierten Strom
//

$aktuelleDaten = array();
$RemoteDaten = true;
$Device = "ME"; // ME = Smart Meter
$Version = "";
$Start = time();  // Timestamp festhalten
$funktionen->log_schreiben("-------------   Start user_device.php SDM230, Wechselrichter -------------------------- ","|--",5);
$WR_IP = $SDM_IP;
$WR_Port = $SDM_Port;

try {
	$USB1 = fsockopen( $WR_IP, $WR_Port, $errno, $errstr, 10 ); // 10 Sekunden Timeout
  
	if (!is_resource($USB1)) {
		$funktionen->log_schreiben( "Kein Kontakt zum Elfin Modbus TCP Gateway ".$WR_IP."  Port: ".$WR_Port, "XX ", 3 );
		$funktionen->log_schreiben( "Exit.... ", "XX ", 3 );
		throw new Exception("Konnte TCP-Connection zum Elfin nicht öffnen. ");
	}
	$FunktionsCode = "04";
	$RegisterAnzahl = "0002"; // in hexstring
	$DatenTyp = "Float32" ;
	$Timebase = 10000;
	
	
// 6.1 Stromzähler Netzstrom auslesen

	$funktionen->log_schreiben( "Trace 6.1 - Stromzähler Netzstrom auslesen", "   ", 7 );
		
	$GeraeteAdresse = str_pad( dechex( $SDM_Adresse1 ), 2, "0", STR_PAD_LEFT ); // Modbus Geräte ID

	$SDMregisters =	array(
	"Netz_Spannung_V" => "0000",
	"Netz_Strom_A" => "0006",
	"Netz_Bezug_W" => "0012",
	"Netz_Scheinleistung_VA" => "0018",
	"Netz_Blindleistung_VAr" => "0024",
	"Netz_Leistungsfaktor" => "0030",
	"Netz_Frequenz_Hz" => "0070",
	"Netz_Bezug_KWh" => "0072",
	"Netz_total_W" => "0084",
	"Netz_max_W" => "0088",
	"Netz_Strombedarf_A" => "0258", 
	"Netz_max_Strombedarf_A" => "0264",
	"Netz_total_KWh" => "0342",
	"Netz_total_seit_Reset_KWh" => "0384");
	foreach ($SDMregisters AS $feldname => $adresse) {
		$rc = $funktionen->modbus_tcp_lesen( $USB1, $GeraeteAdresse, $FunktionsCode, $adresse, $RegisterAnzahl, $DatenTyp, $Timebase ) ; 
		$funktionen->log_schreiben($adresse.": ".$feldname."=".$rc["Wert"],"   ",8);
		$aktuelleDaten[$feldname] = $rc["Wert"];
	}
  
// 6.2 Stromzähler Insel auslesen

	$funktionen->log_schreiben( "Trace 6.2 - Stromzähler Insel auslesen", "   ", 7 );
	
	$GeraeteAdresse = str_pad( dechex( $SDM_Adresse2 ), 2, "0", STR_PAD_LEFT ); // Modbus Geräte ID

	$SDMregisters =	array(
	"Insel_Spannung_V" => "0000",
	"Insel_Strom_A" => "0006",
	"Insel_Bezug_W" => "0012",
	"Insel_Scheinleistung_VA" => "0018",
	"Insel_Blindleistung_VAr" => "0024",
	"Insel_Leistungsfaktor" => "0030",
	"Insel_Frequenz_Hz" => "0070",
	"Insel_Bezug_KWh" => "0072",
	"Insel_total_W" => "0084",
	"Insel_max_W" => "0088",
	"Insel_Strombedarf_A" => "0258", 
	"Insel_max_Strombedarf_A" => "0264",
	"Insel_total_KWh" => "0342",
	"Insel_total_seit_Reset_KWh" => "0384");
	foreach ($SDMregisters AS $feldname => $adresse) {
		$rc = $funktionen->modbus_tcp_lesen( $USB1, $GeraeteAdresse, $FunktionsCode, $adresse, $RegisterAnzahl, $DatenTyp, $Timebase ) ; 
		$funktionen->log_schreiben($adresse.": ".$feldname."=".$rc["Wert"],"   ",8);
		$aktuelleDaten[$feldname] = $rc["Wert"];
	}
	
// 6.3 abgeleitete Daten berechnen

	$funktionen->log_schreiben( "Trace 6.3 - abgeleitete Daten berechnen", "   ", 7 );
	
	$aktuelleDaten["Solar_Leistung_W"] = $aktuelleDaten["Insel_Bezug_W"] - $aktuelleDaten["Netz_Bezug_W"];
	$aktuelleDaten["Solar_Ertrag_KWh"] = $aktuelleDaten["Insel_Bezug_KWh"] - $aktuelleDaten["Netz_Bezug_KWh"];

// 6.4 Query für das Schreiben in die influxDB zusammenstellen
	
	$funktionen->log_schreiben( "Trace 6.4 - Query zusammenstellen", "   ", 7 );
	
	$zq = "";
	foreach($aktuelleDaten as $key => $value) {
		$zq .= ",".$key."=".$value;
	}
	$zq = $SDM_Measurement." ".substr($zq,1)." ".$zentralerTimestamp."\n";
	$aktuelleDaten["ZusatzQuery"] = $zq; 
	$funktionen->log_schreiben("Zentraler Timestamp: ".$zentralerTimestamp,"   ",8);
	$aktuelleDaten["zentralerTimestamp"] = $zentralerTimestamp;

	$FehlermeldungText = "";

	$aktuelleDaten["Regler"] = $Regler;
	$aktuelleDaten["Objekt"] = $Objekt;
	$aktuelleDaten["Firmware"] = "SDM230";
	//$aktuelleDaten["zentralerTimestamp"] = ($aktuelleDaten["zentralerTimestamp"]+10);

// 6.5 optionale Nachbearbeitung der Smart-Meter Daten
	
	$funktionen->log_schreiben( "Trace 6.5 - Nachbearbeitung", "   ", 7 );
	
	if ( file_exists ("/var/www/html/SDM230_meter_math.php")) {
		include 'SDM230_meter_math.php';  // Falls etwas neu berechnet werden muss.
	}
	$funktionen->log_schreiben(var_export($aktuelleDaten,1),"   ",8);
	
// 6.6 Smart-Meter Daten optional an den hauseigenen MQTT Broker übergeben
	
	$funktionen->log_schreiben( "Trace 6.6 - MQTT", "   ", 7 );
	
	if ($MQTT) {
		$funktionen->log_schreiben("MQTT Daten zum [ $MQTTBroker ] senden.","   ",1);
		require($Pfad."/mqtt_senden.php");
	}

// 6.7 Zeitpunkte definieren
	
	$funktionen->log_schreiben( "Trace 6.7 - Zeit", "   ", 7 );
	
	$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");

// 6.8 Smart-Meter Daten in influxDB ablegen
	
	$funktionen->log_schreiben( "Trace 6.8 - Daten in InfluxDB", "   ", 7 );
	
	$aktuelleDaten["InfluxAdresse"] = $InfluxAdresse;
	$aktuelleDaten["InfluxPort"] = $InfluxPort;
	$aktuelleDaten["InfluxUser"] =  $InfluxUser;
	$aktuelleDaten["InfluxPassword"] = $InfluxPassword;
	$aktuelleDaten["InfluxDBName"] = $InfluxDBName;
	$aktuelleDaten["InfluxDaylight"] = $InfluxDaylight;
	$aktuelleDaten["InfluxDBLokal"] = $SDM_InfluxDB;
	$aktuelleDaten["InfluxSSL"] = $InfluxSSL;
	$aktuelleDaten["Demodaten"] = false;
	
	if ($InfluxDB_remote) {
		// Daten sollen in remote DB geschrieben werden
		if ($RemoteDaten) {
			$rc = $funktionen->influx_remote_test();
			if ($rc) {
				$rc = $funktionen->influx_remote($aktuelleDaten);
				if ($rc) {
					$RemoteDaten = false;
				}
			} else {
				$RemoteDaten = false;
			}
		}
		if ($InfluxDB_local) {
			// Daten sollen zusätzlich lokal abgelegt werden
			$rc = $funktionen->influx_local($aktuelleDaten);
		}
	} else {
		// Daten sollen nur lokal abgelegt werden
		$rc = $funktionen->influx_local($aktuelleDaten);
	}

	$funktionen->log_schreiben( "Ende Abschnitt 6 - SDM230", "   ", 5 );
} catch(\Throwable $ex) {
	$USB1 = false;

	$funktionen->log_schreiben( "Socket==false. Kein Kontakt zum Smart-Meter ".$WR_IP."  Port: ".$WR_Port, "XX ", 3 );
	$funktionen->log_schreiben( "Exit.... ", "XX ", 3 );
	for ($Ui = 1; $Ui <= count( $User_Key ); $Ui++) {
		$rc = $funktionen->send_cached_message( $API_Token[$Ui], $User_Key[$Ui], $Device."-Gerät SDM230/Elfin EW11 ".$WR_IP.":".$WR_Port." nicht erreichbar.".$errno.$errstr, 0, "", $Messengerdienst[$Ui], "YmdH" );
	}
}
Das Auslesen beider Stromzähler dauert so etwa 12 Sekunden. Die Zeit kann man verkürzen, indem man aufs Auslesen von Netzfrequenz, Blindleistung etc. verzichtet.

In Grafana habe ich dann das so dargestellt:
grafana.JPG
Raspi 3B, Hybrid Must PV18-3024 VHM, Hoymiles HM-800 , Nachteinspeisung, Flex-BKW, AhoyDTU, Smart Meter DTSU666-H, DIY Akku 6,7 KWh, DalyBMS2MQTT, Victron2MQTT,Architektur, HomeMatic CCU. Autor: Solaranlage Do-It-Yourself

Antworten

Zurück zu „Regler, Wallboxen und Wechselrichter“