SolarEdge Wechselrichter

Aus FHEMWiki


SolarEdge Wechselrichter
SolarEdge SE10k
Allgemein
Protokoll Modubus TCP
Typ Wechselrichter
Kategorie Energieverbrauchsmessung
Technische Details
Kommunikation Ethernet TCP
Kanäle 1 (bidiektional)
Betriebsspannung 750V DC; 230V 3xAC
Leistungsaufnahme Eigenverbrauch 2% (geschätzt)
Versorgung 230V~ 3xAC
Abmessungen 317x512x214 (mm)
Sonstiges
Modulname ModbusAttr
Hersteller Solaredge


SE10k von Solaredge in FHEM einbinden

Dieser Artikel beschreibt die Einbindung eines Solaredgewechselrichters SE10k in ein FHEM System über eine Ethernetverbindung mit Hilfe des Moduls ModbusAttr.


Vorbedingungen

FHEM läuft und hat genügend Platz für Modifikationen und Logfiles (ca. 100 MByte / Jahr).

Am Wechselrichter

Im zugehörigen Menu ist bereits der Port 502 eingestellt. Trotzdem muss dieser noch einmal aktiviert werden, da sonst Modbus TCP nicht aktiv wird. Hilfe da zu bietet die Installationsanleitung [1].
Es ist möglich, dass es auch nur 10 Minuten aktiv bleibt wenn er nicht angesprochen wird.

ModbusAttr Device in FHEM

in FHEM wird ein ModbusAttr angelegt

define SolarEdge ModbusAttr 1 30 192.168.178.36 TCP

danach alle Attribute aus dem unten stehenden list nach dem Verfahren: attr SolarEdge dev-h-defPoll 1

Mehr Daten sind im Sunspec Protokoll [2] zu finden

List von Device Solaredge in FHEM

Internals:
   BUSY       0
   DEF        1 30 192.168.178.36 TCP
   DEST       192.168.178.36:502
   DeviceName 192.168.178.36:502
   FD         91
   INTERVAL   600
   IODev      KeSolarEdge
   LASTOPEN   1523044866.65275
   MODBUSID   1
   ModuleVersion 3.7.3 - 22.12.2017
   NAME       KeSolarEdge
   NOTIFYDEV  global
   NR         354
   NTFY_ORDER 50-KeSolarEdge
   PARTIAL    
   PROTOCOL   TCP
   REQUESTHEX 00270000000601039c940001
   STATE      0 W; 1718 kWh
   TRIGGERTIME 1523048587.13296
   TRIGGERTIME_FMT 2018-04-06 23:03:07
   TYPE       ModbusAttr
   devioLoglevel 4
   nextOpenDelay 60
   QUEUE:
   READINGS:
     2018-04-06 22:53:07   AC-Energy       1717.665
     2018-04-06 22:53:07   AC-Energy-Scale 0
     2018-04-06 22:53:07   AC-Energy-Val   1717665
     2018-04-06 22:58:10   AC-Power        0
     2018-04-06 22:58:10   AC-Power-Scale  0
     2018-04-06 22:58:10   AC-Power-Val    0
     2018-04-06 22:53:07   DC-Current      0
     2018-04-06 22:53:07   DC-Current-Scale -32768
     2018-04-06 22:53:07   DC-Current-Val  65535
     2018-04-06 22:53:07   DC-Power        0
     2018-04-06 22:53:07   DC-Power-Scale  0
     2018-04-06 22:53:07   DC-Power-Val    0
     2018-04-06 22:53:07   DC-Voltage      0
     2018-04-06 22:53:07   DC-Voltage-Scale -1
     2018-04-06 22:53:07   DC-Voltage-Val  0
     2018-04-06 22:53:07   HeatSinkTemp    0
     2018-04-06 22:53:07   Status          2
     2018-04-06 22:53:07   Zustand         Nachtmodus
     2018-04-06 22:01:06   state           opened
   defptr:
     1:
   gotReadings:
     AC-Power-Scale 0
   helper:
     buffer     
     lid        1
     lrecv      1523048290.49688
     lsend      1523048290.48976
   lastRead:
     h40083     1523048290.48193
     h40084     1523048290.50143
     h40093     1523047987.08669
     h40095     1523047987.09043
     h40096     1523047987.09428
     h40097     1523047987.09784
     h40098     1523047987.10153
     h40099     1523047987.10505
     h40100     1523047987.10867
     h40101     1523047987.11226
     h40103     1523047987.1158
     h40107     1523047987.11994
Attributes:
   dev-h-combine 200
   dev-h-defPoll 1
   dev-h-defShowGet 1
   enableControlSet 1
   event-on-change-reading .*
   event-on-update-reading AC-Energy,AC-Energy-Scale,AC-Power-Scale,DC-Voltage-Scale,DC-Current-Scale,DC-Power-Scale,Status
   maxTimeoutsToReconnect 3
   obj-h40083-reading AC-Power-Val
   obj-h40084-reading AC-Power-Scale
   obj-h40084-unpack s>
   obj-h40093-len 2
   obj-h40093-reading AC-Energy-Val
   obj-h40093-unpack l>
   obj-h40095-reading AC-Energy-Scale
   obj-h40096-reading DC-Current-Val
   obj-h40097-reading DC-Current-Scale
   obj-h40097-unpack s>
   obj-h40098-reading DC-Voltage-Val
   obj-h40099-reading DC-Voltage-Scale
   obj-h40099-unpack s>
   obj-h40100-reading DC-Power-Val
   obj-h40101-reading DC-Power-Scale
   obj-h40101-unpack s>
   obj-h40103-reading HeatSinkTemp
   obj-h40103-unpack s>
   obj-h40107-reading Status
   room       Solar,SolarPV,SolarReport
   silentReconnect 1
   sortUpdate 1
   stateFormat {sprintf("%.0f W; %.0f kWh",ReadingsVal("KeSolarEdge","AC-Power",0),ReadingsVal("KeSolarEdge","AC-Energy",0))}
   userReadings AC-Energy:(AC-Energy-Scale.*) { 
  my $scale = ReadingsVal ("KeSolarEdge","AC-Energy-Scale",0);
  return (ReadingsVal ("KeSolarEdge","AC-Energy-Val",0) * ( 10 ** $scale) / 1000);;},
  
AC-Power:(AC-Power-Scale.*) { 
 my $scale = ReadingsVal ("KeSolarEdge","AC-Power-Scale",0);
 return (ReadingsVal ("KeSolarEdge","AC-Power-Val",0) * ( 10 ** $scale));;},

DC-Power:(DC-Power-Scale.*) { 
 my $scale = ReadingsVal ("KeSolarEdge","DC-Power-Scale",0);
 return (ReadingsVal ("KeSolarEdge","DC-Power-Val",0) * ( 10 ** $scale));;},
  
DC-Current:(DC-Current-Scale.*) {
 my $scale = ReadingsVal ("KeSolarEdge","DC-Current-Scale",0);
 return (ReadingsVal ("KeSolarEdge","DC-Current-Val",0) * ( 10 ** $scale));;},
  
DC-Voltage:(DC-Voltage-Scale.*) { 
 my $scale = ReadingsVal ("KeSolarEdge","DC-Voltage-Scale",0);
 return (ReadingsVal ("KeSolarEdge","DC-Voltage-Val",0) * ( 10 ** $scale));;},
 
Zustand:(Status.*) {
   my $Zus = ReadingsVal("KeSolarEdge","Status",0);
   my $rueck = ReadingsVal("KeSolarEdge","Zustand",0);
   if (($Zus == 2) and (InternalVal("KeSolarEdge","INTERVAL","") != 600)) {
     fhem("set KeSolarEdge interval 600");
	 $rueck = "Nachtmodus";
   }
   elsif  (InternalVal("KeSolarEdge","INTERVAL","") != 60) {
     fhem("set KeSolarEdge interval 60");
	 $rueck = "Tagmodus";
   }
   return ($rueck);;
 }
   webCmdLabel {sprintf("AC-Energy %.3f",ReadingsVal("Solaredge","AC-Energy",0));;}

Dummys anlegen

Zur Verwendung der "at"s werden Dummys benötigt

define dum_pv_energyday_log dummy 
define dum_pv_energyday_read dummy 
define dum_pv_energymonth_log dummy 
define dum_pv_energymonth_read dummy
define dum_pv_energytoday dummy
define dum_pv_energytomonth dummy
define dum_pv_energytoweek dummy
define dum_pv_energytoyear dummy
define dum_pv_energyweek_log dummy
define dum_pv_energyweek_read dummy
define dum_pv_energyyear_log dummy
define dum_pv_energyyear_read dummy
define dum_pvdcpower dummy
define dum_pvdcvolt dummy
define dum_pvenergy dummy
define dum_pvloss dummy
define dum_pvpower_log dummy 
define dum_pvpower_read dummy 

notify device in FHEM

Auslesen der Daten, getriggert vom ModbusAttr:

prg_solaredge

KeSolarEdge:DC-Power:.* {
  # 16.2.2018 Markus Loeben
  # liest Solaredge aus und füllt die Werte in dummys, damit sie weiter verwertet werden können
  my $ACE = ReadingsVal("KeSolarEdge","AC-Energy",0);
  Log 5, "at_solaredge: ACE " . $ACE;
  my $day = Value("dum_pv_energyday_read");
  Log 5, "at_solaredge: day " . $day;
  my $week = Value("dum_pv_energyweek_read");
  Log 5, "at_solaredge: day " . $day;
  my $month = Value("dum_pv_energymonth_read");
  Log 5, "at_solaredge: month " . $month;
  my $year = Value("dum_pv_energyyear_read");
  Log 5, "at_solaredge: year " . $year;
  #.. die geleistete Energie größer 0 ist (was immer sein sollte, aber leider nicht immer ist) -> laufende Werte berechnen
  if ($ACE > 0) {
    fhem ("set dum_pv_energytoday " . sprintf ("%.2f",($ACE - $day)));
    fhem ("set dum_pv_energytoweek " . sprintf ("%.2f",($ACE - $week)));
    fhem ("set dum_pv_energytomonth " . sprintf ("%.2f",($ACE - $month)));
    fhem ("set dum_pv_energytoyear " . sprintf ("%.2f",($ACE - $year)));
  }
  #Log 1, "at_Solaredge: PV-Energy " . $ACE . "\n";
  #Leistung auslesen
  my $ACP = ReadingsVal("KeSolarEdge","AC-Power",0);
  my $DCP = ReadingsVal("KeSolarEdge","DC-Power",0);
  if ($DCP > 0) {
  # Verlustleistung berechnen
    fhem ("set dum_pvloss " . sprintf("%.1f", ($DCP - $ACP)));
    my $MP = Value("dum_pv_power_read");
    #Falls die größer ist als alles bis: ablegen
    if ($DCP > $MP) {
      fhem ("set dum_pv_power_read " . $DCP);
    }
  }
}

at device in FHEM

Tägliches Auswerten für spätere SVGs:

at_midnight

*23:59 {
  # Abspeichern der täglichen, wöchentlichen und monatlichen Werte 16.3.18 Loeben;
  use Time::Local;
  my ($Psec,$Pmin,$Phour,$Pmday,$Pmonth,$Pyear,$Pwday,$Pyday,$Pisdst) = localtime(time()+61);
  #Werte einlesen
  my $ace = ReadingsVal("KeSolarEdge","AC-Energy",-1);
  Log 5, "at_midnight AC-Energy" . " " . $ace;
  #Tag updaten
  # PV
  my $aceread = Value("dum_pv_energyday_read");
  Log 5, "at_midnight dum_pv_energyday_read " . $aceread;
  my $aceday = ($ace - $aceread);
  fhem ("set dum_pv_energyday_log " . sprintf("%.1f",($aceday)));
  fhem ("set dum_pv_energyday_read " . $ace);
  Log 5, "at_midnight dum_pv_energyday_read" . " " . $ace;
  my $MP = Value("dum_pv_power_read");
  fhem("set dum_pv_power_log " . $MP);
  fhem("set dum_pv_power_read 0");
  
  #Wochenwerte speichern;
  if ($Pwday == 1) {
    $aceread = Value("dum_pv_energyweek_read");
    $aceday = ($ace - $aceread);
    fhem ("set dum_pv_energyweek_log " . sprintf("%.1f",($ace - $aceread)));
    fhem ("set dum_pv_energyweek_read " . $ace);
  }  
  #Monatswerte speichern;
  if ($Pmday == 1) {
    $aceread = Value("dum_pv_energymonth_read");
    $aceday = ($ace - $aceread);
    fhem ("set dum_pv_energymonth_log " . sprintf("%.1f",($aceday)));
    fhem ("set dum_pv_energymonth_read " . $ace);
  }
  #Jahreswerte speichern;
  if ($Pyday == 1) {
    $aceread = Value("dum_pv_energyyear_read");
    $aceday = ($ace - $aceread);
    fhem ("set dum_pv_energyyear_log " . sprintf("%.1f",($aceday)));
    fhem ("set dum_pv_energyyear_read " . $ace);
  }
}

Log

Das ModbusDevice legt sich ein eigenes Log an. Um aber übersichtliche Grafiken zu bekommen werden die Daten des Dummy benötigt. Hier hilft ein Logfile

define FileLog_KePv Filelog %L/pv-%Y.log dum_pv*.*

Grafiken

Todo: Beschreibungen zu SVG hinterlegen


SunSpec (SolarEdge)

Hier nochmal eine andere Variante der Attribut-Definition für ModbusAttr. Diese Variante ist wesentlich enger an die Sunspec-Implementierung aus der SolarEdge-Dokumentation angelehnt, als die Definitionen in o.g. Beispiel-List.

attr <DEVICE-NAME> obj-h40000-len 4
attr <DEVICE-NAME> obj-h40000-reading C_SunSpec_ID
attr <DEVICE-NAME> obj-h40000-unpack (a4)
attr <DEVICE-NAME> obj-h40004-len 16
attr <DEVICE-NAME> obj-h40004-reading C_Manufacturer
attr <DEVICE-NAME> obj-h40004-unpack (a16)
attr <DEVICE-NAME> obj-h40020-len 16
attr <DEVICE-NAME> obj-h40020-reading C_Model
attr <DEVICE-NAME> obj-h40020-unpack (a16)
attr <DEVICE-NAME> obj-h40044-len 8
attr <DEVICE-NAME> obj-h40044-reading C_Version
attr <DEVICE-NAME> obj-h40044-unpack (a8)
attr <DEVICE-NAME> obj-h40052-len 16
attr <DEVICE-NAME> obj-h40052-reading C_SerialNumber
attr <DEVICE-NAME> obj-h40052-unpack (a16)
attr <DEVICE-NAME> obj-h40068-reading C_DeviceAddress
attr <DEVICE-NAME> obj-h40069-reading C_PhaseDesign
attr <DEVICE-NAME> obj-h40070-reading C_SunSpec_Length
attr <DEVICE-NAME> obj-h40071-expr $val * (10 ** ReadingsNum ('<DEVICE-NAME>' ,'I_AC_Current_SF',0))
attr <DEVICE-NAME> obj-h40071-reading I_AC_Current
attr <DEVICE-NAME> obj-h40072-expr $val * (10 ** ReadingsNum ('<DEVICE-NAME>' ,'I_AC_Current_SF',0))
attr <DEVICE-NAME> obj-h40072-reading I_AC_CurrentA
attr <DEVICE-NAME> obj-h40073-expr $val * (10 ** ReadingsNum ('<DEVICE-NAME>' ,'I_AC_Current_SF',0))
attr <DEVICE-NAME> obj-h40073-reading I_AC_CurrentB
attr <DEVICE-NAME> obj-h40074-expr $val * (10 ** ReadingsNum ('<DEVICE-NAME>' ,'I_AC_Current_SF',0))
attr <DEVICE-NAME> obj-h40074-reading I_AC_CurrentC
attr <DEVICE-NAME> obj-h40075-reading I_AC_Current_SF
attr <DEVICE-NAME> obj-h40075-unpack s>
attr <DEVICE-NAME> obj-h40076-expr $val * (10 ** ReadingsNum ('<DEVICE-NAME>' ,'I_AC_Voltage_SF',0))
attr <DEVICE-NAME> obj-h40076-reading I_AC_VoltageAB
attr <DEVICE-NAME> obj-h40077-expr $val * (10 ** ReadingsNum ('<DEVICE-NAME>' ,'I_AC_Voltage_SF',0))
attr <DEVICE-NAME> obj-h40077-reading I_AC_VoltageBC
attr <DEVICE-NAME> obj-h40078-expr $val * (10 ** ReadingsNum ('<DEVICE-NAME>' ,'I_AC_Voltage_SF',0))
attr <DEVICE-NAME> obj-h40078-reading I_AC_VoltageCA
attr <DEVICE-NAME> obj-h40079-expr $val * (10 ** ReadingsNum ('<DEVICE-NAME>' ,'I_AC_Voltage_SF',0))
attr <DEVICE-NAME> obj-h40079-reading I_AC_VoltageAN
attr <DEVICE-NAME> obj-h40080-expr $val * (10 ** ReadingsNum ('<DEVICE-NAME>' ,'I_AC_Voltage_SF',0))
attr <DEVICE-NAME> obj-h40080-reading I_AC_VoltageBN
attr <DEVICE-NAME> obj-h40081-expr $val * (10 ** ReadingsNum ('<DEVICE-NAME>' ,'I_AC_Voltage_SF',0))
attr <DEVICE-NAME> obj-h40081-reading I_AC_VoltageCN
attr <DEVICE-NAME> obj-h40082-reading I_AC_Voltage_SF
attr <DEVICE-NAME> obj-h40082-unpack s>
attr <DEVICE-NAME> obj-h40083-expr $val * (10 ** ReadingsNum ('<DEVICE-NAME>' ,'I_AC_Power_SF',0))
attr <DEVICE-NAME> obj-h40083-reading I_AC_Power
attr <DEVICE-NAME> obj-h40083-unpack s>
attr <DEVICE-NAME> obj-h40084-reading I_AC_Power_SF
attr <DEVICE-NAME> obj-h40084-unpack s>
attr <DEVICE-NAME> obj-h40085-expr $val * (10 ** ReadingsNum ('<DEVICE-NAME>' ,'I_AC_Frequency_SF',0))
attr <DEVICE-NAME> obj-h40085-reading I_AC_Frequency
attr <DEVICE-NAME> obj-h40086-reading I_AC_Frequency_SF
attr <DEVICE-NAME> obj-h40086-unpack s>
attr <DEVICE-NAME> obj-h40087-expr $val * (10 ** ReadingsNum ('<DEVICE-NAME>' ,'I_AC_VA_SF',0))
attr <DEVICE-NAME> obj-h40087-reading I_AC_VA
attr <DEVICE-NAME> obj-h40087-unpack s>
attr <DEVICE-NAME> obj-h40088-reading I_AC_VA_SF
attr <DEVICE-NAME> obj-h40088-unpack s>
attr <DEVICE-NAME> obj-h40089-expr $val * (10 ** ReadingsNum ('<DEVICE-NAME>' ,'I_AC_VAR_SF',0))
attr <DEVICE-NAME> obj-h40089-reading I_AC_VAR
attr <DEVICE-NAME> obj-h40089-unpack s>
attr <DEVICE-NAME> obj-h40090-reading I_AC_VAR_SF
attr <DEVICE-NAME> obj-h40090-unpack s>
attr <DEVICE-NAME> obj-h40091-expr $val * (10 ** ReadingsNum ('<DEVICE-NAME>' ,'I_AC_PF_SF',0))
attr <DEVICE-NAME> obj-h40091-reading I_AC_PF
attr <DEVICE-NAME> obj-h40091-unpack s>
attr <DEVICE-NAME> obj-h40092-reading I_AC_PF_SF
attr <DEVICE-NAME> obj-h40092-unpack s>
attr <DEVICE-NAME> obj-h40093-expr $val * (10 ** ReadingsNum ('<DEVICE-NAME>' ,'I_AC_Energy_WH_SF',0))
attr <DEVICE-NAME> obj-h40093-len 2
attr <DEVICE-NAME> obj-h40093-reading I_AC_Energy_WH
attr <DEVICE-NAME> obj-h40093-unpack I>
attr <DEVICE-NAME> obj-h40095-reading I_AC_Energy_WH_SF
attr <DEVICE-NAME> obj-h40096-expr $val * (10 ** ReadingsNum ('<DEVICE-NAME>' ,'I_DC_Current_SF',0))
attr <DEVICE-NAME> obj-h40096-reading I_DC_Current
attr <DEVICE-NAME> obj-h40097-reading I_DC_Current_SF
attr <DEVICE-NAME> obj-h40097-unpack s>
attr <DEVICE-NAME> obj-h40098-expr $val * (10 ** ReadingsNum ('<DEVICE-NAME>' ,'I_DC_Voltage_SF',0))
attr <DEVICE-NAME> obj-h40098-reading I_DC_Voltage
attr <DEVICE-NAME> obj-h40099-reading I_DC_Voltage_SF
attr <DEVICE-NAME> obj-h40099-unpack s>
attr <DEVICE-NAME> obj-h40100-expr $val * (10 ** ReadingsNum ('<DEVICE-NAME>' ,'I_DC_Power_SF',0))
attr <DEVICE-NAME> obj-h40100-reading I_DC_Power
attr <DEVICE-NAME> obj-h40100-unpack s>
attr <DEVICE-NAME> obj-h40101-reading I_DC_Power_SF
attr <DEVICE-NAME> obj-h40101-unpack s>
attr <DEVICE-NAME> obj-h40103-expr $val * (10 ** ReadingsNum ('<DEVICE-NAME>' ,'I_Temp_SF',0))
attr <DEVICE-NAME> obj-h40103-reading I_Temp_Sink
attr <DEVICE-NAME> obj-h40103-unpack s>
attr <DEVICE-NAME> obj-h40106-reading I_Temp_SF
attr <DEVICE-NAME> obj-h40106-unpack s>
attr <DEVICE-NAME> obj-h40107-reading I_Status
attr <DEVICE-NAME> obj-h40108-reading I_Status_Vendor
attr <DEVICE-NAME> userReadings uI_Status:I_Status.* {my $om=ReadingsNum($name,'I_Status',-1);;($om==2?'night':($om==4?'day':'off'))},\
uC_PhaseDesign:C_PhaseDesign.* {my $pd=ReadingsVal($name,'C_PhaseDesign','000');;($pd eq '101'?'single':($pd eq '102'?'split':($pd eq '103'?'3-phase':'unknown')))}

<DEVICE-NAME> ist dabei natürlich durch den realen Namen des eigenen ModbusAttr-Devices zu ersetzen.

Zusätzlich sind hier auch zwei weiter userReadings definiert, die eine textliche Umsetzung für die Parameter C_PhaseDesign und I_Status vornehmen.

Die Folgende Datei enthält die entsprechenden Anpassungen an die SolarEdge-Dokumentation, die diesen Attribut-Definitionen zugrunde liegen.

Datei:FHEM-Solaredge SunSpec ModbusAttr.pdf

Links

  1. Solaredge: Installationsanleitung
  2. Solaredge: Sunspec Protokoll