-> Hier kostenlos registrieren
Hallo zusammen,
erst einmal möchte ich Danke sagen an @Blockmove, der mit einem kleinen Denkanstoß dafür sorgte, dass ich mir mal schnell Gedanken machte über meine Solaranlage. Man muss dazu sagen, dass dieses Projekt erst ging, nachdem ich meinen Solar-log 500 über die Firmware 2.8.1 Build 49 gezogen hatte, aktuell Firmware 3.6.0 Build 99. Dadurch hatte ich Zugriff auf Modbus TCP. Ich habe die Bausteine nur mit der S7-1500 gemacht, bei anderen Steuerungen müssen eben Anpassungen gemacht werden.
Funktionsbaustein für den Solar-log um über Modbus TCP an die Daten zu kommen:
	
	
	
		
Und da ich dann auch im FB für den Solar-log die UNIX Zeit in DTL umwandeln musste und nirgends ein Baustein gerade Griffbereit hatte, griff ich auf Wikipedia zu und formte den Code in einen SCL Baustein um und falls den Jemand mal in Zukunft braucht dann kann er sich auch hier verweilen:
	
	
	
		
Gruß
Jürgen
	
		
			
		
		
	
				
			erst einmal möchte ich Danke sagen an @Blockmove, der mit einem kleinen Denkanstoß dafür sorgte, dass ich mir mal schnell Gedanken machte über meine Solaranlage. Man muss dazu sagen, dass dieses Projekt erst ging, nachdem ich meinen Solar-log 500 über die Firmware 2.8.1 Build 49 gezogen hatte, aktuell Firmware 3.6.0 Build 99. Dadurch hatte ich Zugriff auf Modbus TCP. Ich habe die Bausteine nur mit der S7-1500 gemacht, bei anderen Steuerungen müssen eben Anpassungen gemacht werden.
Funktionsbaustein für den Solar-log um über Modbus TCP an die Daten zu kommen:
		Code:
	
	FUNCTION_BLOCK "Solarlog"
TITLE = Solarlog500
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : Juergen
VERSION : 0.1
   VAR_INPUT 
      Modbus_REQ : Bool;   // Activates the requested transmission if TRUE
      Modbus_Disconnect : Bool;   // Initiates a disconnect operation
      Modbus_Mode : USInt;   // Specifies the type of request: read, write or diagnostic
      Modbus_Data_Addr : UDInt;   // Specifies the starting address of the data to be accessed in the Modbus client
      Modbus_Data_LEN : UInt;   // Specifies the number of bits or words to be accessed
      Modbus_InterfaceId : UInt;   // HW-identifier of IE-interface submodule
      Modbus_ID : CONN_OUC;   // connection reference / identifier
      Modbus_ConnectionType : Byte;   // type of connection: 11=TCP/IP, 19=UDP (17=TCP/IP)
      Modbus_ActiveEstablished : Bool;   // active/passive connection establishment
      Modbus_RemotePort : UInt;   // remote UDP/TCP port number
      "TCPIP_V4_Addr[1]" : Byte;   // Remote IP Addr 1 (IPv4)
      "TCPIP_V4_Addr[2]" : Byte;   // Remote IP Addr 2 (IPv4)
      "TCPIP_V4_Addr[3]" : Byte;   // Remote IP Addr 3 (IPv4)
      "TCPIP_V4_Addr[4]" : Byte;   // Remote IP Addr 4 (IPv4)
   END_VAR
   VAR_OUTPUT 
      Modbus_Done : Bool;   // Instruction finished without error
      Modbus_Busy : Bool;   // Modbus transaction in progress
      Modbus_Error : Bool;   // Instruction finished with error
      Modbus_Status : Word;   // Detailed error information
      "lastUpdateTime_Unix-Format" : UDInt;   // Unixtime, wann das letzte Registerupdate erfolgt ist. 0=noch keine Live-Daten (Einheit = Sec)
      "lastUpdate_DT-Format" {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL;   // DT-Format, wann das letzte Registerupdate erfolgt ist. 0=noch keine Live-Daten (Einheit = DT-Format)
      Pac : UDInt;   // Gesamte Leistung Pac von allen Wechselrichtern und Zählern im Wechselrichtermodus (Einheit = W)
      Pdc : UDInt;   // Gesamte Leistung Pdc von allen Wechselrichtern (Einheit = W)
      Uac : UInt;   // Durchschnittliche Spannung Uac aller Wechselrichter (Einheit = V)
      Udc : UInt;   // Durchschnittliche Spannung Udc aller Wechselrichter (Einheit = V)
      "Daily yield" : UDInt;   // Summierter Tagesertrag aller Wechselrichter (Einheit = Wh)
      "Yesterday yield" : UDInt;   // Summierter gestriger Tagesertrag aller Wechselrichter (Einheit = Wh)
      "Monthly yield" : UDInt;   // Summierter Monatsertrag aller Wechselrichter (Einheit = Wh)
      "Yearly yield" : UDInt;   // Summierter Jahresertrag aller Wechselrichter (Einheit = Wh)
      "Total yield" : UDInt;   // Gesamtertrag aller Wechselrichter (Einheit = Wh)
      "Pac consumption" : UDInt;   // momentaner Gesamtverbrauch Pac aller Verbrauchszähler (Einheit = W)
      "Daily yield consumption" : UDInt;   // Summierter Tages-Verbrauch aller Verbrauchszähler (Einheit = Wh)
      "Yesterday yield consumption" : UDInt;   // Summierter Verbrauch des gestrigen Tages; alle Verbrauchszähler (Einheit = Wh)
      "Monthly yield consumption" : UDInt;   // Summierter Verbrauch des Monats; alle Verbrauchszähler (Einheit = Wh)
      "Yearly yield consumption" : UDInt;   // Summierter Verbrauch des Jahres; alle Verbrauchszähler (Einheit = Wh)
      "Total yield consumption" : UDInt;   // Summierter Gesamtverbrauch; alle Verbrauchszähler (Einheit = Wh)
      TotalPower : UDInt;   // Installierte Generatorleistung (Einheit = Wh/Wp)
   END_VAR
   VAR 
      MB_CLIENT_Instance {InstructionName := 'MB_CLIENT'; LibVersion := '5.2'} : MB_CLIENT;
      Modbus_Connection {InstructionName := 'TCON_IP_v4'; LibVersion := '1.0'} : TCON_IP_v4 := (64, 1, (), true, ([()]), 502, ());
      RAW_DATA { S7_SetPoint := 'True'} : Array[0..31] of UInt;
   END_VAR
   VAR_TEMP 
      Sekunden_Pro_Tag : UDInt;
      Tage_im_Gemeinjahr : UDInt;
      Tage_in_4_Jahren : UDInt;
      Tage_in_100_Jahren : UDInt;
      Tage_in_400_Jahren : UDInt;
      TagN_AD_1970_01_01 : UDInt;
      TagN : UDInt;
      Sekunden_seit_Mitternacht : UDInt;
      temp : UDInt;
      tJahr : UDInt;
      tMonat : UDInt;
      tTag : UDInt;
      tStunde : UDInt;
      tMinute : UDInt;
      tSekunde : UDInt;
   END_VAR
BEGIN
    // Initialisierung
        
        //ModBus-Parameter
        #Modbus_Connection.InterfaceId := #Modbus_InterfaceId;
        #Modbus_Connection.ID := #Modbus_ID;
        #Modbus_Connection.ConnectionType := #Modbus_ConnectionType;
        #Modbus_Connection.ActiveEstablished := #Modbus_ActiveEstablished;
        
        //TCPIP_Adresse initialisieren
        #Modbus_Connection.RemoteAddress.ADDR[1] := #"TCPIP_V4_Addr[1]";
        #Modbus_Connection.RemoteAddress.ADDR[2] := #"TCPIP_V4_Addr[2]";
        #Modbus_Connection.RemoteAddress.ADDR[3] := #"TCPIP_V4_Addr[3]";
        #Modbus_Connection.RemoteAddress.ADDR[4] := #"TCPIP_V4_Addr[4]";
        
    
    //ModBus-Daten lesen
    #MB_CLIENT_Instance(REQ:=#Modbus_REQ,
                        DISCONNECT:=#Modbus_Disconnect,
                        MB_MODE:=#Modbus_Mode,
                        MB_DATA_ADDR:=#Modbus_Data_Addr,
                        MB_DATA_LEN:=#Modbus_Data_LEN,
                        DONE=>#Modbus_Done,
                        BUSY=>#Modbus_Busy,
                        ERROR=>#Modbus_Error,
                        STATUS=>#Modbus_Status,
                        MB_DATA_PTR:=#RAW_DATA,
                        CONNECT:=#Modbus_Connection);
    
    //--------------------- Solarlog RAW-Daten richtig einordnen ---------------------
    //
    
        //Unix-Zeitstempel einlesen (Einheit = Sec)
        
        #"lastUpdateTime_Unix-Format".%W0 := #RAW_DATA[0];
        #"lastUpdateTime_Unix-Format".%W1 := #RAW_DATA[1];
        
        //Gesamtleistung Pac aller Wechselrichter einlesen (Einheit = W)
        
        #Pac.%W0 := #RAW_DATA[2];
        #Pac.%W1 := #RAW_DATA[3];
        
        //Gesamtleistung Pdc aller Wechselrichter einlesen (Einheit = W)
        
        #Pdc.%W0 := #RAW_DATA[4];
        #Pdc.%W1 := #RAW_DATA[5];
        
        //Durchschnittliche Spannung Uac aller Wechselrichter einlesen (Einheit = V)
        
        #Uac := #RAW_DATA[6];
        
        //Durchschnittliche Spannung Udc aller Wechselrichter einlesen (Einheit = V)
        
        #Udc := #RAW_DATA[7];
        
        
        //Summierter Tagesertrag aller Wechselrichter einlesen (Einheit = Wh)
        
        #"Daily yield".%W0 := #RAW_DATA[8];
        #"Daily yield".%W1 := #RAW_DATA[9];
        
        //Summierter gestriger Tagesertrag aller Wechselrichter einlesen (Einheit = Wh)
        
        #"Yesterday yield".%W0 := #RAW_DATA[10];
        #"Yesterday yield".%W1 := #RAW_DATA[11];
        
        //Summierter Monatsertrag aller Wechselrichter einlesen (Einheit = Wh)
        
        #"Monthly yield".%W0 := #RAW_DATA[12];
        #"Monthly yield".%W1 := #RAW_DATA[13];
        
        //Summierter Jahresertrag aller Wechselrichter einlesen (Einheit = Wh)
        
        #"Yearly yield".%W0 := #RAW_DATA[14];
        #"Yearly yield".%W1 := #RAW_DATA[15];
        
        //Gesamtertrag aller Wechselrichter einlesen (Einheit = Wh)
        
        #"Total yield".%W0 := #RAW_DATA[16];
        #"Total yield".%W1 := #RAW_DATA[17];
        
        //Momentaner Gesamtverbrauch Pac aller Verbrauchszaehler einlesen (Einheit = W)
        
        #"Pac consumption".%W0 := #RAW_DATA[18];
        #"Pac consumption".%W1 := #RAW_DATA[19];
        
        //summierter Tagesverbrauch aller Verbrauchszaehler einlesen (Einheit = Wh)
        
        #"Daily yield consumption".%W0 := #RAW_DATA[20];
        #"Daily yield consumption".%W1 := #RAW_DATA[21];
        
        //summierter gestriger Tagesverbrauch aller Verbrauchszaehler einlesen (Einheit = Wh)
        
        #"Yesterday yield consumption".%W0 := #RAW_DATA[22];
        #"Yesterday yield consumption".%W1 := #RAW_DATA[23];
        
        //summierter Monatsverbrauch aller Verbrauchszaehler einlesen (Einheit = Wh)
        
        #"Monthly yield consumption".%W0 := #RAW_DATA[24];
        #"Monthly yield consumption".%W1 := #RAW_DATA[25];
        
        //summierter Jahresverbrauch aller Verbrauchszaehler einlesen (Einheit = Wh)
        
        #"Yearly yield consumption".%W0 := #RAW_DATA[26];
        #"Yearly yield consumption".%W1 := #RAW_DATA[27];
        
        //summierter Gesamtverbrauch aller Verbrauchszaehler einlesen (Einheit = Wh)
        
        #"Total yield consumption".%W0 := #RAW_DATA[28];
        #"Total yield consumption".%W1 := #RAW_DATA[29];
        
        //installierte Generatorleistung einlesen (Einheit = Wh/Wp)
        
        #TotalPower.%W0 := #RAW_DATA[30];
        #TotalPower.%W1 := #RAW_DATA[31];
        
    
    
    
    //Unix-Zeitstempel in DT-Format wandeln
    //
    //Initialisierung
    
    #Sekunden_Pro_Tag := 86400; // 24h * 60m * 60s
    #Tage_im_Gemeinjahr := 365; //kein Schaltjahr
    #Tage_in_4_Jahren := #Tage_im_Gemeinjahr * 4 + 1; // 4 * 365 +1
    #Tage_in_100_Jahren := #Tage_im_Gemeinjahr * 100 + 25 - 1; // 100 * 365 + 25 - 1
    #Tage_in_400_Jahren := #Tage_im_Gemeinjahr * 400 + 100 - 4 + 1; // 400 * 365 + 100 - 4 + 1
    #TagN_AD_1970_01_01 := 719468; //Tagnummer bezogen auf den 1. Maerz des Jahres "Null"
    
    //------------------------------------------------------------------------------------------------------
    
    #TagN := #TagN_AD_1970_01_01 + #"lastUpdateTime_Unix-Format" / #Sekunden_Pro_Tag;
    #Sekunden_seit_Mitternacht := #"lastUpdateTime_Unix-Format" MOD #Sekunden_Pro_Tag;
    
    //Schaltjahrregel des Gregorianischen Kalenders
    //Jedes durch 100 teilbare Jahr ist kein Schaltjahr, es sei denn, es ist durch 400 teilbar
    
    #temp := 4 * (#TagN + #Tage_in_100_Jahren + 1) / #Tage_in_400_Jahren - 1;
    #tJahr := 100 * #temp;
    #TagN -= #Tage_in_100_Jahren * #temp + #temp / 4;
    
    //Schaltjahrregel des Julianischen Kalenders
    //Jedes durch 4 teilbare Jahr ist ein Schaltjahr
    
    #temp := 4 * (#TagN + #Tage_im_Gemeinjahr + 1) / #Tage_in_4_Jahren - 1;
    #tJahr += #temp;
    #TagN -= #Tage_im_Gemeinjahr * #temp + #temp / 4;
    
    //TagN enthaelt jetzt nur noch die Tage des errechneten Jahres bezogen auf den 1. Maerz
    
    #tMonat := (5 * #TagN + 2) / 153;
    #tTag := #TagN - (#tMonat * 153 + 2) / 5 + 1;
    //153 = 31 + 30 + 31 + 30 + 31 Tage fuer die 5 Monate von Maerz bis Juli
    //153 = 31 + 30 + 31 + 30 + 31 Tage fuer die 5 Monate von August bis Dezember
    //      31 + 28                Tage fuer Januer und Februar (siehe unten)
    //+2: Justierung der Rundung
    //+1: Der erste Tag im Monat ist 1 (und nicht 0)
    
    #tMonat += 3; // vom Jahr, das am 1. Maerz beginnt auf unser normales Jahr umrechnen
    IF (#tMonat > 12) THEN
        //Monate 13 und 14 entsprechen 1 (Januar) und 2 (Februar) des naechsten Jahres
        #tMonat -= 12;
        #tJahr += #tJahr;
    END_IF;
    
    #tStunde := #Sekunden_seit_Mitternacht / 3600;
    #tMinute := #Sekunden_seit_Mitternacht MOD 3600 / 60;
    #tSekunde := #Sekunden_seit_Mitternacht MOD 60;
    
    //DTL zusammenbauen
    
    #"lastUpdate_DT-Format".YEAR := UDINT_TO_UINT(#tJahr);
    #"lastUpdate_DT-Format".MONTH := UDINT_TO_USINT(#tMonat);
    #"lastUpdate_DT-Format".DAY := UDINT_TO_USINT(#tTag);
    #"lastUpdate_DT-Format".HOUR := UDINT_TO_USINT(#tStunde);
    #"lastUpdate_DT-Format".MINUTE := UDINT_TO_USINT(#tMinute);
    #"lastUpdate_DT-Format".SECOND := UDINT_TO_USINT(#tSekunde);
    
END_FUNCTION_BLOCKUnd da ich dann auch im FB für den Solar-log die UNIX Zeit in DTL umwandeln musste und nirgends ein Baustein gerade Griffbereit hatte, griff ich auf Wikipedia zu und formte den Code in einen SCL Baustein um und falls den Jemand mal in Zukunft braucht dann kann er sich auch hier verweilen:
		Code:
	
	FUNCTION "Unixzeit_Nach_DTL" : Void
TITLE = Unixzeit_Nach_DTL
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : Juergen
VERSION : 0.1
   VAR_INPUT 
      Unixtime : UDInt;
   END_VAR
   VAR_OUTPUT 
      Datum_Uhrzeit {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL;
   END_VAR
   VAR_TEMP 
      Sekunden_Pro_Tag : UDInt;
      Tage_im_Gemeinjahr : UDInt;
      Tage_in_4_Jahren : UDInt;
      Tage_in_100_Jahren : UDInt;
      Tage_in_400_Jahren : UDInt;
      TagN_AD_1970_01_01 : UDInt;
      TagN : UDInt;
      Sekunden_seit_Mitternacht : UDInt;
      temp : UDInt;
      tJahr : UDInt;
      tMonat : UDInt;
      tTag : UDInt;
      tStunde : UDInt;
      tMinute : UDInt;
      tSekunde : UDInt;
   END_VAR
BEGIN
    //Initialisierung
    
    #Sekunden_Pro_Tag := 86400; // 24h * 60m * 60s
    #Tage_im_Gemeinjahr := 365; //kein Schaltjahr
    #Tage_in_4_Jahren := #Tage_im_Gemeinjahr * 4 +1; // 4 * 365 +1
    #Tage_in_100_Jahren := #Tage_im_Gemeinjahr * 100 + 25 - 1; // 100 * 365 + 25 - 1
    #Tage_in_400_Jahren := #Tage_im_Gemeinjahr * 400 + 100 - 4 + 1; // 400 * 365 + 100 - 4 + 1
    #TagN_AD_1970_01_01 := 719468; //Tagnummer bezogen auf den 1. Maerz des Jahres "Null"
    
    //------------------------------------------------------------------------------------------------------
    
    #TagN := #TagN_AD_1970_01_01 + #Unixtime / #Sekunden_Pro_Tag;
    #Sekunden_seit_Mitternacht := #Unixtime MOD #Sekunden_Pro_Tag;
    
    //Schaltjahrregel des Gregorianischen Kalenders
    //Jedes durch 100 teilbare Jahr ist kein Schaltjahr, es sei denn, es ist durch 400 teilbar
    
    #temp := 4 * (#TagN + #Tage_in_100_Jahren + 1) / #Tage_in_400_Jahren - 1;
    #tJahr := 100 * #temp;
    #TagN -= #Tage_in_100_Jahren * #temp + #temp / 4;
    
    //Schaltjahrregel des Julianischen Kalenders
    //Jedes durch 4 teilbare Jahr ist ein Schaltjahr
    
    #temp := 4 * (#TagN + #Tage_im_Gemeinjahr + 1) / #Tage_in_4_Jahren - 1;
    #tJahr += #temp;
    #TagN -= #Tage_im_Gemeinjahr * #temp + #temp / 4;
    
    //TagN enthaelt jetzt nur noch die Tage des errechneten Jahres bezogen auf den 1. Maerz
    
    #tMonat := (5 * #TagN + 2) / 153;
    #tTag := #TagN - (#tMonat * 153 + 2) / 5 + 1;
    //153 = 31 + 30 + 31 + 30 + 31 Tage fuer die 5 Monate von Maerz bis Juli
    //153 = 31 + 30 + 31 + 30 + 31 Tage fuer die 5 Monate von August bis Dezember
    //      31 + 28                Tage fuer Januer und Februar (siehe unten)
    //+2: Justierung der Rundung
    //+1: Der erste Tag im Monat ist 1 (und nicht 0)
    
    #tMonat += 3; // vom Jahr, das am 1. Maerz beginnt auf unser normales Jahr umrechnen
    IF (#tMonat>12) THEN
        //Monate 13 und 14 entsprechen 1 (Januar) und 2 (Februar) des naechsten Jahres
        #tMonat -= 12;
        #tJahr += #tJahr;
    END_IF;
    
    #tStunde := #Sekunden_seit_Mitternacht / 3600;
    #tMinute := #Sekunden_seit_Mitternacht MOD 3600 / 60;
    #tSekunde := #Sekunden_seit_Mitternacht MOD 60;
    
    //Date and Time zusammenbauen
    
    #Datum_Uhrzeit.YEAR := UDINT_TO_UINT(#tJahr);
    #Datum_Uhrzeit.MONTH := UDINT_TO_USINT(#tMonat);
    #Datum_Uhrzeit.DAY := UDINT_TO_USINT(#tTag);
    #Datum_Uhrzeit.HOUR := UDINT_TO_USINT(#tStunde);
    #Datum_Uhrzeit.MINUTE := UDINT_TO_USINT(#tMinute);
    #Datum_Uhrzeit.SECOND := UDINT_TO_USINT(#tSekunde);
    
    
    
END_FUNCTIONGruß
Jürgen
 
	 
  
  
 
		
 
 
		 
  
 