Elektronische Haushalts Zähler [eHZ] auslesen

Ja, ich weiß … ich darf es nicht von Hand starten. Aber so kam ich an das Ergebnis.

@Rainer: … jetzt - wo du es sagst … :wink:

Genau so sieht es bei mir aus (außer die Sache mit dem Comport … ist bei mir eben ein Client Socket weil Netzwerkmodul). Es funktioniert nicht.
Ich mache nochmal alles neu und berichte. grrr

Du brauchst nix neu machen. Mach deine Debug Fenster auf, dann siehst Du wo es klemmt.

Ich hatte zwischendurch mein debug-Fenster offen, daher die Annahme es wäre alles tipptopp. Nur übergeben hat er nichts. Ich habe nun alles neu eingerichtet … und was soll ich sagen?! :D:D:D
Es ist genau wie vorher, nur das es nun richtig läuft.

Nun habe ich noch zwei Kleinigkeiten:

  • das Script wird aktuell jede Sekunde ausgeführt. Wie kann ich es auf z.B. jede Minute „einbremsen“? Ereignis an RegVar dranhängen?
  • es wird die Zählernummer übergeben. Das ist in meinem Fall die „131811-5000938“. Übergeben wird allerdings nur die „131811“. Wie kann ich den Rest mitnehmen?

Wie kann ich es auf z.B. jede Minute "einbremsen

ClientSocket alle min aufmachen.

Wie kann ich den Rest mitnehmen

Script anpassen. :smiley:

for($i = 0; $i < count($string); $i++)
{
   $id = strstr($string[$i], "(", true);
   $value = strstr($string[$i], "(");
   $data = substr(trim($value), 1, -1);
   if(strstr($data, "-"))
   {
       SetValue($eHZdata[$id], (string)$data);
    }
    else
    {
       SetValue($eHZdata[$id], (float)$data);
    }
    
}

WOW … im Ernst, ich wollte mich grad selber reinfuchsen. Mir geht das nur immer nicht so einfach von der Hand. :o LÄUFT!
Meinst Du es macht Sinn den ClientSocket immer wieder auf und zu zu machen? Ich will nur nicht das die geloggten Daten zu viele werden.

Meinst Du es macht Sinn den ClientSocket immer wieder auf und zu zu machen?

Wo ist das Problem, ein Script mit CSCK_SetOpen(12345, true); IPS_ApplyChanges(12345); und ein Scripttimer mit CSCK_SetOpen(12345, false); IPS_ApplyChanges(12345);

Nein, das ist nicht was ich meine. Ich meine ob es sinnvoll oder unnütz ist.
Würdest DU DIR das so einrichten?

Was zählt denn der Zähler. Wenn es dir nur um einen Wert an Tag geht reicht es ihn einmal auszulesen. Das musst Du wissen. Ich lese meine Wechselstromzähler alle min aus. Ich werte darüber aber auch Maschinen aus.

da offensichtlich der Zähler den Versand von Daten initiiert (kann man die Intervalle anpassen?) bleibt Dir kaum eine andere Möglichkeit.

Eine Alternative gäbe es noch (falls Rainers Vorschlag zu techn. Problemen führen sollte): man könnte die ankommenden Daten in eine temporäre Variable (die nicht geloggt wird) aufintegrieren und daraus Minuten-(-oderwasauchimmer-)Durchschnittswerte bilden und erst diese in eine geloggte Variable schreiben.
Eine solche Lösung habe ich grade unter Mithilfe von Martin’s Schablone gebaut. Hier werden alle 3sec Daten aufgesammelt und dann in Minuten-Durchnittswerte umgewandelt.

DAS finde ich eine ausgesprochen gute Idee!
So kann man auch sehr flexibel mit den Daten umgehen … logging alle 1 min, alle 45 sek, alle 30 sek …
1000 Dank Euch Beiden!! Ihr habt mir heute sehr geholfen.

Hallo Raketenschnecke,

ich melde auch offiziell Interesse. Doch dein Link zu Schablone verweist auf das Profil des gleichnamigen Benutzers. Hast du ein Link zum Projekt?

Danke & Grüsse,
Axel

Hi Axel,

es gibt dazu noch keine Projektvorstellung. Die hier angesprochene Variante der Datenverarbeitung ist auch nur ein kleiner Teil des Projekts.

Das Ganze funktioniert folgendermaßen:

  1. Rohdaten vom Sensor werden durch ein Script entgegen genommen und in einer (Daten-)Variablen (Integer oder Float, je nach Daten) aufintegriert. Parallel schreibt das Script die Anzahl der Datensätze in eine 2. (Zähler)-Variable (Integer).
  2. nach einer definierten Anzahl von Scriptdurchläufen wird der bisher in der (Daten-)Variablen aufintegrierte Wert durch die Anzahl der Datensätze geteilt und in die eigentliche Zähler-Variable geschrieben, die in den (Daten-) und (Zähler-)Variablen gespeicherten Werte werden gleichzeitig auf 0 gesetzt.
  3. Das Spiel beginnt von vorn.

Hier mal mein Beispiel - in dem die Werte alle 3sec aus einem DS2450 ausgelesen und verarbeitet werden:

die ankommenden Werte vom DS2450 befinden sich in der Variable „Port 1 Rohdaten“ (werden automatisch von der DS2450-Instanz dort rein geschrieben). Sobald der Wert sich aktualisiert wird durch den Eventtrigger das Script „Rohdatenverarbeitung nach Martin Heinze“ zur Ausführung gebracht, welches die Rohdaten in der Variable „Niederschlagsmenge (temp)“ aufintegriert und die Anzahl der Datensätze in die Variable „Datensatz Zähler“ schreibt. Dein minütlichen Durchnittswerte werden dann vom selben Script in eine weitere Variabloe geschrieben die im Bild nicht zu sehen ist, diese Variable ist dann die „Zähler-.Variable“.

und hier das komplette Script (sehr speziell, noch nicht komplett dokumentiert) - für das Beispiel „eHZ-Auslesen“ müsste man den Part „2. Auswahl der Skalierung“ gegen eine Rohdatenzuweisung der Werte des eHZ ersetzten:


<?
/*=============================================================
skrRegensensor - Martin Heinzel/Andreas Felsch - 23.12.2011
Version: 0.2

Beschreibung:
das Script besteht aus folgenden Blöcken:

	1. Variablen-Deklaration
	2. Auswahl der Skalierung
	3. Aufintegrieren der Intensität
	4. Regenmenge und Niederschlagstatus für vorangegangene Minute ermitteln
	5. Funktion zum Skalieren der Werte
	
In diesem Script wird aus einer Niederschlagsintensität [mm/min] eine Niederschlagsmenge [l/m²] errechnet.
Durch Integration der Niederschlagsintensitäten wird die Niederschlagsmenge errechnet.
Die Niederschlagsmenge wird temporär in eine Variable [$id_Niederschlagsmenge] geschrieben.
Nach 1 Minute wird der in dieser Variable aufintegrierte Wert als Minutensumme in die eigentliche
Logging-Vaiable [$niederschlagszaehler_id] geschrieben.
Zusätzlich wird bei jedem Scriptdurchlauf der Niederschlagstatus (Niederschlag ja/nein) ermittelt
und in eine Statusvariable [$NS_Status_id] geschrieben.

Definition: Niederschlagsmenge [l/m²]
Die Gesamtheit der niedergegangenen flüssigen bzw. festen Niederschläge.
Angaben erfolgen in mm, d.h. 1 mm Niederschlag = 1 Liter pro Quadratmeter.

================================================================*/

	//=== 1. Variablen Deklaration ==============================================

	$id_Hardware                     =	51649 /*[Wetterdaten RS.loc\Thies Niederschlag-Sensor\Thies NS DS2450\Port 1 Rohdaten]*/;
	$id_Niederschlagsmenge         	=  55321 /*[Wetterdaten RS.loc\Thies Niederschlag-Sensor\Thies NS DS2450\Port 1 Rohdaten\Niederschlagsmenge (temp)]*/ ;
	$Intensitaet_Ink           		=  GetValue($id_Hardware);
	$Intensitaet               		=  0.0;
	$Niederschlagsmenge        		=  GetValueFloat($id_Niederschlagsmenge);
	$archive_handler_id 					=	58669 /*[Archive Handler]*/ ; 	// Archive Handler
	$ds2450_ns_id 							=	47398 /*[Wetterdaten RS.loc\Thies Niederschlag-Sensor\Thies NS DS2450]*/  ;
	$ds2450_intervall 					=	TMEX_GetInterval($ds2450_ns_id); // Abfrage des am DS2450 eingestellten Abfrageintervalls
	$ds2450_resolution 					=	TMEX_GetF20Resolution($ds2450_ns_id, 1); // Abfrage der eingestellten Auflösung am DS2450 Port1
	$teiler 									=	((pow(2, $ds2450_resolution)-1) / 5); //Ermittlung des Teilers (Schrittweite)
	$datensaetze_pro_minute				=	60/$ds2450_intervall;
	$Offset 									=	$teiler * 0.03; // Wert ab dem Niederschlag gemessen wird = Teiler + 3%
	$NS_Status_id                    =  51881 /*[Wetterdaten RS.loc\Thies Niederschlag-Sensor\Thies NS DS2450\Status\Niederschlag (Status)]*/ ;
	$NS_intensitaet_id               =  37450 /*[Wetterdaten RS.loc\Thies Niederschlag-Sensor\Thies NS DS2450\Intensität\Intensität (1 /Minute)]*/ ;
	$niederschlagszaehler_id			=  17989 /*[Wetterdaten RS.loc\Thies Niederschlag-Sensor\Thies NS DS2450\Menge\Menge ( mm)]*/ ;
	$Datensatz_zaehler_id            =  14488 /*[Wetterdaten RS.loc\Thies Niederschlag-Sensor\Thies NS DS2450\Port 1 Rohdaten\Datensatz Zähler]*/ ;
	$Datensatz_zaehler_val           =  getValueInteger($Datensatz_zaehler_id);

	if(!isset($IPS_EVENT)) $IPS_EVENT = 0;


//======================= Main =================================================


	//--- 2. Auswahl der Skalierung ------------------------------------------------
	Switch($Intensitaet_Ink)
	{
      case ($Intensitaet_Ink >= ((1*$teiler)+ $Offset) and $Intensitaet_Ink < (2*$teiler)):
          $Intensitaet    =    Scaling($Intensitaet_Ink, 1*$teiler, 2*$teiler, 0.0, 0.01)/$datensaetze_pro_minute;
      break;

      case ($Intensitaet_Ink >= (2*$teiler) and $Intensitaet_Ink < (3*$teiler)):
          $Intensitaet    =    Scaling($Intensitaet_Ink, 2*$teiler, 3*$teiler, 0.01, 0.1)/$datensaetze_pro_minute;
      break;

      case ($Intensitaet_Ink >= (3*$teiler) and $Intensitaet_Ink < (4*$teiler)):
          $Intensitaet    =    Scaling($Intensitaet_Ink, 3*$teiler, 4*$teiler, 0.1, 1.0)/$datensaetze_pro_minute;
      break;

      case ($Intensitaet_Ink >= (4*$teiler) and $Intensitaet_Ink <= (5*$teiler)):
          $Intensitaet    =    Scaling($Intensitaet_Ink, 4*$teiler, 5*$teiler, 1.0, 10.0)/$datensaetze_pro_minute;

	}

	//--- 3. Aufintegrieren der Intensität --------------------------------------
	$Niederschlagsmenge              += $Intensitaet;
	$Datensatz_zaehler_val           += 1;
	
	//------------- und in temp. Variable ablegen -------------------------------
	SetValueFloat($id_Niederschlagsmenge, $Niederschlagsmenge);       // aufintegrierte Regenmenge
	SetValueInteger($Datensatz_zaehler_id, $Datensatz_zaehler_val);   // Anzahl Datensätze

	//--- 4. Regenmenge und Niederschlagstatus für vorangegangene Minute ermitteln  ----------

	if ($Datensatz_zaehler_val > $datensaetze_pro_minute)
	{
		setValueInteger($Datensatz_zaehler_id, 0);   // wenn Zählerwert gößer als max. Anzahl Datensätze für 1 Minute dann auf Null setzen
		setValueFloat($id_Niederschlagsmenge, 0.0);  // und bisherige Regenmenge verwerfen
	}
	elseif ( $Datensatz_zaehler_val == $datensaetze_pro_minute)
	{
	   //--- Regenmenge/Intensität ermitteln und setzen -------------
		   $niederschlagszaehler_val 		=	getValueFloat($niederschlagszaehler_id) + $Niederschlagsmenge;
		   $intensitaet               	=  round($Niederschlagsmenge, 3);
		   
			setValueFloat($niederschlagszaehler_id, $niederschlagszaehler_val);
			SetValueFloat($NS_intensitaet_id, $intensitaet );
			setValueInteger($Datensatz_zaehler_id, 0);
			setValueFloat($id_Niederschlagsmenge, 0.0);
			
			//------------ debugging --------------------------
			/*
			echo "Regenmenge der letzten Minute ($Niederschlagsmenge mm) zu $niederschlagszaehler_val mm gesamt aufintegriert
";
			echo "Intensität der letzten Minute ($intensitaet mm/min)
";
			*/
		
		//--- Niederschlagsstatus ermitteln und setzen
			$Schwellwert_Niederschlag        =	(Scaling($teiler + $Offset, 1*$teiler, 2*$teiler, 0.0, 0.01)/$datensaetze_pro_minute) * $Datensatz_zaehler_val;
			//--- debugging -------------------------------------------------------------
			//echo "der Niederschlagsschwellwert liegt bei $Schwellwert_Niederschlag mm (Anzahl Datensätze $Datensatz_zaehler_val, Regenmenge $Niederschlagsmenge mm)
";

			if ($Niederschlagsmenge > $Schwellwert_Niederschlag)
				{
					setValueBoolean($NS_Status_id, true);
				}
				else
				{
				   setValueBoolean($NS_Status_id, false);
				}
	}

//======================= Main ENDE ============================================

//======================= Funktionen ===========================================

	//--- 5. Funktion zum Skalieren der Werte -----------------------------------
	function Scaling($In, $InUG, $InOG, $OutUG, $OutOG)
	   {
	   /*=============================================================
	   Scaling - Martin Heinzel - 21.09.2011
	   Version: 1.0

	   Beschreibung:
	   Diese Funktion scaliert einen Wert nach der Form:

	         ( ( In - In_Min )                            )
	   Out = (------------------- x ( Out_Max - Out_Min ) ) + Out_Min
	         (( In_Max - In_Min )                         )
	   ================================================================*/

	   return ($In - $InUG) / ($InOG - $InUG) * ($OutOG - $OutUG) + $OutUG;

	   }

//======================== Funktionen ENDE =====================================

?>

Hallo

Da mir dieser Thread und das Howto für SML von mr_cg bei meinem Projekt sehr weitergeholfen hat möchte ich meine Erkenntnisse hiermit auch weitergeben.

Ausgangsbasis:
1x Hager Zweitarif-eHz mit DIN-Ausgabe über Front-IR für die Wärmepumpe
1x EMH eHz mit SML-Ausgabe über Front-IR. Bezug PV-Anlage
1x EMH Zweirichtungs-eHz mit SML-Ausgabe über Front-IR. Haushaltsstrom.

Verwendete HW:
Als optische Kommunikationsköpfe (OKK) habe ich mich für die günstige Variante entschieden --> Sucht nach „Schnittstellenadapter Voltcraft Rs-232“ bei Conrad oder Voelkner. Der kostet jeweils 9,95€ und kann genauso viel wie die Teile für 70€ und mehr.
Um 3 COM-Ports anzuschließen hat mein Server leider nicht genügend Kapazitäten. Deswegen habe ich mich als COM-Adapter für die LAN-Variante Exsys EX-6034 entschieden. Derzeit verwende ich ihn mit der virtuelle COM-Port-SW und nicht über ClientSocket. Der Grund dafür ist das die OKKs über den DTR-Pin mit Strom versorgt wird und ich diesen SW-seitig über ClientSocket nicht schalten kann. Man müsste dann die OKKs anderweitig versorgen.

Umsetzung:
Die Umsetzung erhebt keine Anspruch darauf toll programmiert zu sein, sie soll einfach nur denjenigen weiterhelfen die ähnliche Probleme haben wie ich. Ausserdem sind die Skripte noch in ständiger Entwicklung :wink:
Ich starte alle x Sekunden ein Skript („Hole Zählerdaten“) das die OKKs einschaltet indem DTR eingeschaltet wird. Die Daten werden über den IO-Port, den Cutter und die Register Variable an ein Skript weitergegeben und dort ausgewertet. Die SML-Zähler haben jeweils einen eigenen Cutter und Skript für jede Funktion. Der DIN-Zähler von Hager wird mit einem Gesamtskript ausgelesen wie es hier gepostet wurde.

Probleme hat mir der Zweirichtungszähler von EMH gemacht. Der zeigt die aktuelle Leistung an die gerade durch den Zähler läuft. Egal in welche Richtung! Das versaut natürlich die ganzen Daten meines aktuellen Leitungswertes und muss mit Programmkonstrukten irgendwie umgangen werden. Ich habe bei der Support-Mailadresse von EMH angefragt aber nur eine unbefriedigende Antwort bekommen:
Aus Datenschutzgründen dürfen wir ihnen keine Auskunft erteilen. Bitte wenden sie sich an ihr EVU.
Ich umgehe das aktuell indem ich ein weiteres Skript starte das mir den aktuellen Leistungswert berechnet aus der PV-Leistung und der Haushaltsstromleistung. Ob Letzterer positiv oder negativ ist erfahre ich indem ich den Zählerstand „Verkauf“ des Haushaltszählers vergleiche und schaue ob er steigt. Wenn ja, dann fleißt der Strom ins Netz und ich muss die PV-Leistung subtrahieren. Da die Lösung nicht wirklich zufriedenstellt möchte ich das Skript aktuell noch nicht hier einstellen. Ich bin für bessere Lösungsvorschläge dankbar!

Ich hoffe ich kann dem ein oder anderen mit dieser Beschreibung weiterhelfen.

PHP.zip (3.72 KB)

Gesamt.jpg

Skripte.jpg

Stromzähler.JPG

Cuttereinstellungen.zip (179 KB)

Tolle Beschreibung! Danke für Deine Arbeit, ich habe den gleichen Zähler und das Projekt steht auch noch auf meiner Liste. Spart mir viel Arbeit.

Gern geschehen, ich habe auch schon oft von anderen profitiert. Jetzt kann ich auch mal was zurückgeben :slight_smile:

Danke für die Info, Link mußte ich aber entfernen.:wink:

IP-Symcon Community Forum - Ankündigungen im Forum : Allgemeine Diskussion

  1. Verbotene Inhalte

    Benutzer sind für die Rechtmäßigkeit der von ihm bereitgestellten Inhalte selbst verantwortlich
    keine pornografische, rechtlich fragwürdige, sexistische oder beleidigende Beiträge
    Werbung jeglicher Art (beinhaltet auch Links zu E-Bay Auktionen)

@ wolfsc
Beim Zweirichtungszähler wird normalerweise ein Flag (0, F) gesetzt welches anzeigt ob Leistung bezogen oder eingespeist wird. Bei meinem Hager Zähler ist dieses Flag vor den Datenbytes. Am besten zwei Frames (einmal Bezug, einmal Einspeisung) genau vergleichen.