SML Stromzähler - falsche Werte Wirkleistung wenn PV Einspeisung - 4er HEX Gruppe

Moin zusammen!
Ich bräuchte mal Hilfe von den PHP Spezis unter euch. Meinen Stromzähler lese ich mit folgendem Skript aus.

<?

if($_IPS['SENDER'] == "RegisterVariable")
{
// Wirkleistung (Wirk-Leistung Total) Obiskennung:1-0.16.7.0*255 Hex:01 00 10 07 00 FF
 if(strpos($_IPS['VALUE'], chr(0x01).chr(0x00).chr(0x10).chr(0x07).chr(0x00).chr(0xFF)) !== false)
 {
    $wirkleistung = explode(chr(0x01).chr(0x00).chr(0x10).chr(0x07).chr(0x00).chr(0xFF), $_IPS['VALUE']);
    SetValue(38307 , hexdec(Str2Hex(substr($wirkleistung[1], 7, 2))));
 }
 }
 Cutter_ClearBuffer(17638); 

function Str2Hex($daten)
{
 $hex = "";
  for($i=0; $i<strlen($daten); $i++)
   $hex .= sprintf("%02X ", ord($daten[$i]));
  return $hex;
}
function hex2str($hex)
{
 $str = "";
   for($i=0;$i<strlen($hex);$i+=2)
 $str .= chr(hexdec(substr($hex,$i,2)));
   return $str;
}
?>

Solange die PV Anlage nichts einspeist wird der korrekte Werte der Wirkleistung ausgelesen. Beginnt nun aber die Anlage Strom einzuspeisen, wird aus der 2er HEX Gruppe eine 4er HEX Gruppe. Der ausgelesen Wert liefert dann nur unplausible Zahlen. Am Stromzähler selbst abzulesen ist in diesem Moment die Wirkleistung aus Einspeisung PV abzüglich der Wirkleistung des Momentanverbrauchs. Ergebnis also keine negative Zahl.

Keine Einspeisung:

00 10 07 00 FF 01 01 62 1B 52 00 53 [b]03 52[/b]

Mit Einspeisung:

00 10 07 00 FF 01 01 62 1B 52 00 53 [b]0408[/b]

Hat jemand eine Idee/Lösung wie ich das Problem in den Griff bekomme???

Moin,

was ist denn das genau für ein SML Modell?
Frage nur zur Sicherheit: ist das denn ein Zähler mit dem man überhaupt Einspeisung messen kann?
Ob die Zahlen da nun mit oder ohne Leerstelle stehen ist m.A. nach egal.

Ich nutze quasi das gleiche Script wie du.
0352 würde bei mir bedeuten dass ich 850W beziehe, mit Einspeisung dann 1032W (0408)

Das mag durchaus plausibel sein, da das ja immer nur eine Momentaufnahme ist, hängt ja dann von deinem tatsächlichem Stromverbrauch und Erzeugung ab.

Ob die Werte valide sind oder nicht kann man m.M. nach nur feststellen wenn du zu einem definierten Zeitpunkt abliest was dein Bezug ist und was die PV gerade erzeugt. Dabei sollte möglichst keine oder nur ein definierter Verbraucher laufen (z.B. Fön oder Heizlüfter).

Update: ich entferne aus dem String immer noch die Leerzeichen bevor ich das aus Hex konvertiere:


    // Wirkleistung (Wirk-Leistung Total) Obiskennung:1-0.15.7.0*255 Hex:01 00 0F 07 00 FF
    if(strpos($_IPS['VALUE'], chr(0x01).chr(0x00).chr(0x10).chr(0x07).chr(0x00).chr(0xFF)) !== false)
    {
       $wirkleistung = explode(chr(0x01).chr(0x00).chr(0x10).chr(0x07).chr(0x00).chr(0xFF), $_IPS['VALUE'],2);
       $tmp= substr($wirkleistung[1], 7, 2);
       $tmp=Str2Hex($tmp);
       $tmp=str_replace(" ", "", $tmp);
       $tmp_wirk = hexdec($tmp);
      
       SetValue(37397, $tmp_wirk);
      
        }

VG, Lutz

SML Version ist 1.04. Wenn ich am Zählerdisplay die aktuelle Wirkleistung ablese ist das der Wert aus Einspeisung minus Verbrauch. Am Display passt der Wert also.
Ich hab mein Skript mal nach deiner Variante angepasst. Das Ergebnis ist leider das selbe :frowning:
Aktuell gibt mir das Skript Werte um die 54000W aus. Die PV produziert im Moment ca 13500W und der Verbrauch liegt bei ugf 2500W. Müsste also bei 11000W liegen und das zeigt der Zähler auf dem Display auch korrekt an.

Any ideas?

Moin zusammen,

mittlerweile habe ich 3 Stromzähler von 2 verschiedenen Herstellern verbaut. Alle 3 Zähler zeigen bei Einspeisung durch die PV Anlage diese falschen Werte für die momentane Wirkleistung an. Ich denke dass die Zähler Bezug - Einspeisung rechnen und somit ein negativer Wert das Ergebnis sein müsste.
Wie bekomme ich das in meinem Skript korrekt umgesetzt? Hat hier jemand eine Idee?

Ich führe hier mal mein Selbstgespräch fort…

Hab heute den SML Stream vom neuen Zähler (Typ EFR SGM-C4) bei Einspeisung und Bezug verglichen. Das Ergebnis sieht wie folgt aus:

SML wenn Wirkleistung Einspeisung höher als Bezug -> ausgegebener Wert unplausibel ~ 61000 Watt


77 07 01 00 10 07 00 FF 01 01 62 1B 52 00 53 [b]E4 50[/b]
77 07 01 00 10 07 00 FF 01 01 62 1B 52 00 53 [b]E3 6B[/b]
77 07 01 00 10 07 00 FF 01 01 62 1B 52 00 53 [b]E4 3F[/b]
77 07 01 00 10 07 00 FF 01 01 62 1B 52 00 53 [b]E3 12[/b]

SML wenn Wirkleistung Bezug höher als Einspeisung → ausgegebener Wert ist korrekt und deckt sich mit Wert auf dem Zählerdisplay


77 07 01 00 10 07 00 FF 01 01 62 1B 52 00 53 [b]09 FE[/b]
77 07 01 00 10 07 00 FF 01 01 62 1B 52 00 53 [b]09 F8[/b]
77 07 01 00 10 07 00 FF 01 01 62 1B 52 00 53 [b]09 F7[/b]
77 07 01 00 10 07 00 FF 01 01 62 1B 52 00 53 [b]0A 0C[/b]

Ich denke dass diese Funktion die Ursache für die falsche Berechnung der Wirkleistung ist wenn die Eispeisung höher als der Bezug ist

function Str2Hex($daten)
{
 $hex = "";
  for($i=0; $i<strlen($daten); $i++)
   $hex .= sprintf("%02X ", ord($daten[$i]));
  return $hex;
}

Da ich aber leider kein ITler bin hab ich 0,0 Ansatz wie ich das Thema lösen kann.

Im FHEM Forum hatte jemand den exakt gleichen Fall welcher vom Modulentwickler gelöst werden konnte.
Das hier war anscheinend das ausschlaggebende Problem

64841 Watt klingt verdächtig nach 216 - 695 , also 695 Watt Einspeisung. Läuft da ne Variable über?

Oder signed / unsigned ? -695W

Hier der Link zur Diskussion im FHEM Forum https://forum.fhem.de/index.php/topic,51948.msg440114.html#msg440114

Vielleicht findet sich ja noch jemand der mir weiterhelfen kann…

Schönen Abend einstweilen!

Hallo,
ist das Problem schom gelöst?

Ich lese mich auch gerade schwindelig…

in den Zählerdaten für meinen Einspeisezähler habe ich folgende Daten selektiert:
77
07 01 00 10 07 00 FF
01
01
62 1B
52 00
55 FF FF F6 D3
01
Es muss sich hier (FF FF F6 D3) um einen Negativ-Wert handeln. Leide reichen ab hier meine Kenntnisse für die Umrechnung nicht weit.
Ich habe es so verucht (Ergebnis scheint Plausibel:
$zaehlerW = (hexdec(bin2hex(substr($data,$pos,4)))-hexdec(‚ffffffff‘))*-1;
IF(hexdec(bin2hex(substr($data,$pos,4))) == 0) $zaehlerW = 0;

Bin ich da auf dem richtigen Weg oder gibt es eine bessere Lösung.

Gruß, Peter

Hallo,
ich habe in meinem Skript für die Umwandlung Hex dec folgende Funktion wegen dem Vorzeichen:

Vielleicht hilft euch das weiter:

hexdecs statt dexdec !!!

/**
   * converts a hex string to signed decimal number
   *
   * @param  hex string
   * $return decimal number
   */
  function hexdecs( $hex ) {
    // ignore non hex characters
    $hex = preg_replace('/[^0-9A-Fa-f]/', '', $hex);
    // converted decimal value:
    $dec = hexdec($hex);
    // maximum decimal value based on length of hex + 1:
    // number of bits in hex number is 8 bits for each 2 hex -> max = 2^n
    // use 'pow(2,n)' since '1 << n' is only for integers and therefore limited to integer size.
    $max = pow(2, 4 * (strlen($hex) + (strlen($hex) % 2)));
    // complement = maximum - converted hex:
    $_dec = $max - $dec;
    // if dec value is larger than its complement we have a negative value (first bit is set)
    return $dec > $_dec ? -$_dec : $dec;
  } 

Viele Grüße

Rudi

Hallo Rudi,
danke, genau dieses Script habe ich gestern abend auch gefunden. Konnte es aber wg. fehlender PV-Leistung nicht sofort testen. Funktioniert aber bestens.
viele Grüße
Peter

Hallo zusammen, super dass sich hier noch was tut. Könnte einer von euch vielleicht den Code posten in dem die Wirkleistung aus dem SML Stream ausgelesen wird? Verstehe nicht wie ich die Funktion dort „einbauen“ soll.

Danke und Grüße!

Hallo,
hier mal mein Scriptauszug:

<?php
//******************************************************************************
// 16773
// Photovoltaik ablesen ISKRA
// 1.8.0 Pos.133 Wirkenergie gesamt tariflos, Hexwert + 17 = 150
// 1.8.1 Pos.+24 Wirkenergie Bezug Tarif1 = NT 174
// 1.8.2 Pos.+24 Wirkenergie Bezug Tarif2 = HT
// .....
//
//******************************************************************************

//******************************************************************************
// Zählerwerte ermitteln
//******************************************************************************

$vortag		= GetValueFloat(55534);
$vorjahr	= GetValueFloat(51508);

$data       = $_IPS['VALUE'];                                      // 456 aus Cutter 912 bin2hex($_IPS['VALUE']);
$len        = strlen($data);                                       // len = 456

                                                                    //01 00 01 08 00 FF	= Pos.133 
                                                                    //= OBIS Kennzahl für Wirkenergie Bezug gesamt tariflos
$pos        = strpos($_IPS['VALUE'],chr(0x01).chr(0x00).chr(0x01).chr(0x08).chr(0x00).chr(0xFF));
$pos        = $pos+17;                                              // Start Zählerwert 8 Stellen hex gesamt
$zaehlerSU  = hexdec(bin2hex(substr($data,$pos,8)))/10000.0;

$pos        = $pos+24;                                              // 01.08.01 
$zaehlerNT  = hexdec(bin2hex(substr($data,$pos,8)))/10000.0;

$pos        = $pos+24;                                              // 01.08.02 
$zaehlerHT  = hexdec(bin2hex(substr($data,$pos,8)))/10000.0;

$pos        = $pos+24;                                              // Wirkenergie Einspeisung gesamt tariflos 02.08.00

$pos        = $pos+24;                                              // Wirkenergie Einspeisung Tarif1 02.08.01
$zaehlerE1  = hexdec(bin2hex(substr($data,$pos,8)))/10000.0;

$pos        = $pos+24;                                              // Wirkenergie Einspeisung Tarif2 02.08.02

$pos        = $pos+24;                                              // momentane Gesamtwirkleistung
$zaehlerW   = hexdecs(bin2hex(substr($data,$pos,4)))*-1;

$pos        = $pos+20;                                              // momentane Wirkleistung in Phase L1

$pos        = $pos+20;                                              // momentane Wirkleistung in Phase L2 

$pos        = $pos+20;                                              // momentane Wirkleistung in Phase L3 

//echo $zaehlerSU." - ".$zaehlerNT." - ".$zaehlerHT." - ".$zaehlerE1." - ".$zaehlerW;
//echo "\n".$len." : ".$data;

SPRT_SetRTS(51598, true);
SPRT_SetDTR(51598, false);

und nicht vergessen die function hexdecs (habe ich ans Ende eingefügt)

Grüße, Peter

Moin pitty,
danke fürs Teilen!! Nur leider hab ich keinen Plan wie ich das bei mir einbauen soll :man_shrugging:
Magst du dir mein Skript aus Beitrag 1 mal anschauen?

Danke!

versuche mal im 2. Befehl statt hexdec den neuen Befehl hexdecs zu verwenden.
Falls das nicht klappt, wie ist der Inhalt der Variable $wirkleistung[1] ?

Gruß, Peter

Du kannst auch mein Script voll übernehmen und nur noch die entsprechenden SetValue-Befehlen an Ende stellen. Vorher kannst du auch die echo-Befehle aktivieren und im Protokoll die Werte sehen.
Peter

@pitty genau das wars :man_facepalming: Vielen Dank fürs Helfen!!