TIA PLC-Name und IP vom Programm aus vergeben

Smazze

Level-2
Beiträge
23
Reaktionspunkte
2
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

ich habe 5 Steuerungen (CPU 1516-F PN, TIA V19) die alle gleich programmiert werden sollen bis auf den PLC-Namen und die IP-Adresse.
Somit möchte ich nur eine HW-Config haben mit einer PLC die ich mit kleinen Anpassungen in jede Steuerung lade.
Gibt es eine Möglichkeit über das SPS-Programm dynamisch auf die Daten PLCName und IP zuzugreifen?

Sowas wie.

Steuerungsnummer =1 //Muss angepasst werden

Wenn Steuerungsnummer = 1 dann
PLCName := PLC_1
IP := 192.168.0.1
wenn Steuerungsnummer = 2 dann
PLCName :=PLC_2
IP :=192.168.0.2
....

oder eine Art config Datei oderso?

Ich möchte nur an einer Stelle ändern und nicht an 4..


Vielen Dank im Vorfeld!!
Smazze
 
Hier:
1748600120966.png

Und dann:
Option "IP address is set directly at the device":
  • Assign online
  • Assignment by user program (instruction IP_CONFIG for S7-300/400, T_CONFIG for S7-1200/1500)
  • Assign via CPU display (S7-1500)
  • Higher-level IO controller makes assignment (only with I-devices)

Persönlich wurde ich es nur machen für eine zweiten Schnittstelle welche mit eine anderen Netzwerk verbunden werden muss.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Das ist im Grunde kein Problem. Die von Jesper gezeigten Einstellungen in der Hardware-Konfiguration sind allerdings Voraussetzunng. Ich kann die Details am WE posten, da ich ein entsprechendes Projekt habe, wo ich zwei identische Anlagen parallel entwickeln musste. Damit ich sicher war, dass in beiden der gleiche Code läuft, habe ich einen DB erstellt, der lediglich die Nr. der Anlage als Konstante enthält. Die Steuerung überprüft anhand der Nummer, ob die eigene IP/ der eigene Name stimmt und ändert diesen im Bedarfsfall sofort.

Aber: Wenn Du da einen Fehler machst und die beiden Steuerungen im gleichen Subnetz laufen, hast Du den Salat (IP-Konflikt= Chaos). Ich werde nach Abschluss des Projekts zwei getrennte Versionen erstellen, aber für die bisherige Entwicklung war es eine große Hilfe.
 
Schritt 1 besteht im Auslesen der aktuellen IP. (Falls benötigt)
Dieser FB ist mir irgendwie zugeflogen, ich denke hier im Forum:

Code:
FUNCTION_BLOCK "FB_Get_Parameter_Network_Interface"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_INPUT
      REQ : Bool;
      HW_ID : HW_IO;
   END_VAR

   VAR_OUTPUT
      IPParam : Struct
         IPAddress : Array[0..3] of USInt;
         SubnetMask : Array[0..3] of USInt;
         StandardGateway : Array[0..3] of USInt;
         MACAddress : Array[0..5] of Byte;
         PNName : String;
      END_STRUCT;
      Busy : Bool;
      Valid : Bool;
      Error : Bool;
      Status : DWord;
      LEN : UInt;
   END_VAR

   VAR
      Data_Record : Struct
         BlockType : UInt;
         BlockLength : UInt;
         BlockVersionHigh : USInt;
         BlockVersionLow : USInt;
         Data : Array[0..301] of Byte;
      END_STRUCT;
      Get_Data {InstructionName := 'RDREC'; LibVersion := '1.0'} : RDREC;
   END_VAR

   VAR_TEMP
      name_length : USInt;
      i : Int;
      SiemensSpecialPadding : Int;
   END_VAR


BEGIN
    #Get_Data(REQ := #REQ,
              ID := #HW_ID,
              INDEX := 16#8080,
              MLEN := 0,
              VALID => #Valid,
              BUSY => #Busy,
              ERROR => #Error,
              STATUS => #Status,
              LEN => #LEN,
              RECORD := #Data_Record);
    IF #Get_Data.VALID THEN
        #name_length := BYTE_TO_USINT(#Data_Record.Data[0]);
        Chars_TO_Strg(Chars := #Data_Record.Data,
                      pChars := 1,
                      Cnt := #name_length,
                      Strg => #IPParam.PNName);
       
        IF ((#name_length + 3) MOD 4) <> 0 THEN
            // "PADDING"
            // get to next DoubleWord
            #SiemensSpecialPadding := #name_length + 5 - ((#name_length + 3) MOD 4);
        ELSE
            #SiemensSpecialPadding := #name_length + 1;
        END_IF;
       
        MOVE_BLK(IN := #Data_Record.Data[#SiemensSpecialPadding],
                 COUNT := 6,
                 OUT => #IPParam.MACAddress[0]);
       
        // between MAC and IP are two bytes for padding again
        FOR #i := 0 TO 3 DO
            #IPParam.IPAddress[#i] := BYTE_TO_USINT(#Data_Record.Data[#SiemensSpecialPadding + 8 + #i]);
            #IPParam.SubnetMask[#i] := BYTE_TO_USINT(#Data_Record.Data[#SiemensSpecialPadding + 12 + #i]);
            #IPParam.StandardGateway[#i] := BYTE_TO_USINT(#Data_Record.Data[#SiemensSpecialPadding + 16 + #i]);
        END_FOR;
    END_IF;
END_FUNCTION_BLOCK
 
Zuletzt bearbeitet:
Im zweiten Schritt wird bei Bedarf eine neue IP und eine neuer Name geschrieben:

Code:
FUNCTION_BLOCK "IP lesen und korrigieren"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR
      Taktgeber {InstructionName := 'TON_TIME'; LibVersion := '1.0'; S7_SetPoint := 'False'} : TON_TIME;
      Takt { S7_SetPoint := 'True'} : Bool;
      "IP auslesen CPU" : "FB_Get_Parameter_Network_Interface";
      "neue IP in CPU schreiben" {InstructionName := 'T_CONFIG'; LibVersion := '1.0'} : T_CONFIG;
      "IP auslesen CP 1543-1" : "FB_Get_Parameter_Network_Interface";
      "neue IP in CP 1543-1 schreiben" {InstructionName := 'T_CONFIG'; LibVersion := '1.0'} : T_CONFIG;
   END_VAR

   VAR_TEMP
      et : Time;
      "gewandeltes Array 1" : Array[0..3] of USInt;
      "gewandeltes Array 2" : Array[0..3] of USInt;
   END_VAR


BEGIN
            // IP-Adresse der CPU auslesen und bei Bedarf korrigieren
            // Die Überprüfung soll vorerst einmal pro Minute laufen.
            #Taktgeber(IN := NOT #Takt,
                       PT := "Par"."Taktfrequenz IP-Check",
                       Q => #Takt,
                       ET => #et);
            
            // Zuerst die IP der CPU auslesen ...
            #"IP auslesen CPU"(REQ := #Takt,
                               HW_ID := "Local~CPU",
                               IPParam => "Mon".Steuerung."SPS-Hardware"."Ethernet-Schnittstelle CPU lesen".IPParam,
                               Busy => "Mon".Steuerung."SPS-Hardware"."Ethernet-Schnittstelle CPU lesen".Busy,
                               Valid => "Mon".Steuerung."SPS-Hardware"."Ethernet-Schnittstelle CPU lesen".Valid,
                               Error => "Mon".Steuerung."SPS-Hardware"."Ethernet-Schnittstelle CPU lesen".Error,
                               Status => "Mon".Steuerung."SPS-Hardware"."Ethernet-Schnittstelle CPU lesen".Status,
                               LEN => "Mon".Steuerung."SPS-Hardware"."Ethernet-Schnittstelle CPU lesen".LEN);
            
            "IP Byte zu USint"(Eingang:="Mon"."akt. Parameter".Bauwerk.SPS."Ip-Adresse CPU".Adresse.InterfaceAddress.ADDR,
                               Ausgang=>#"gewandeltes Array 1");
            IF "Mon".Steuerung."SPS-Hardware"."Ethernet-Schnittstelle CPU lesen".Valid
            THEN
                IF "Mon".Steuerung."SPS-Hardware"."Ethernet-Schnittstelle CPU lesen".IPParam.IPAddress <>
                    #"gewandeltes Array 1"
                    OR "Test-DB"."IP-Adressen"."IP-Adressen CPU erneuern"
                THEN
                    #"neue IP in CPU schreiben".Req := TRUE;
                END_IF;
            END_IF;
            
            // .. und bei Abweichung neu schreiben:
            #"neue IP in CPU schreiben"
            (Interface := "Local~CPU",
             Conf_Data := "Mon"."akt. Parameter".Bauwerk.SPS."Ip-Adresse CPU",
             Done => "Mon".Steuerung."SPS-Hardware"."Ethernet-Schnittstelle CPU schreiben".Done,
             Busy => "Mon".Steuerung."SPS-Hardware"."Ethernet-Schnittstelle CPU schreiben".Busy,
             Error => "Mon".Steuerung."SPS-Hardware"."Ethernet-Schnittstelle CPU schreiben".Error);
            
            IF #"neue IP in CPU schreiben".Done
                OR #"neue IP in CPU schreiben".Error
            THEN
                "Mon".Steuerung."SPS-Hardware"."Ethernet-Schnittstelle CPU schreiben".Status :=
                #"neue IP in CPU schreiben".Status;
                "Mon".Steuerung."SPS-Hardware"."Ethernet-Schnittstelle CPU schreiben".Error_Loc :=
                #"neue IP in CPU schreiben".Err_Loc;
                #"neue IP in CPU schreiben".Req := FALSE;
            END_IF;
            
            
            // Danach die IP-Adresse des CP 1543-1 auslesen ...
            #"IP auslesen CP 1543-1"(REQ := #Takt,
                                     HW_ID := "Local~CP_1543-1~CP",
                                     IPParam => "Mon".Steuerung."SPS-Hardware"."Ethernet-Schnittstelle CP 1543-1 lesen".IPParam,
                                     Busy => "Mon".Steuerung."SPS-Hardware"."Ethernet-Schnittstelle CP 1543-1 lesen".Busy,
                                     Valid => "Mon".Steuerung."SPS-Hardware"."Ethernet-Schnittstelle CP 1543-1 lesen".Valid,
                                     Error => "Mon".Steuerung."SPS-Hardware"."Ethernet-Schnittstelle CP 1543-1 lesen".Error,
                                     Status => "Mon".Steuerung."SPS-Hardware"."Ethernet-Schnittstelle CP 1543-1 lesen".Status,
                                     LEN => "Mon".Steuerung."SPS-Hardware"."Ethernet-Schnittstelle CP 1543-1 lesen".LEN);
            "IP Byte zu USint"(Eingang:="Mon"."akt. Parameter".Bauwerk.SPS."Ip-Adresse CP 1543-1".Adresse.InterfaceAddress.ADDR,
                               Ausgang=>#"gewandeltes Array 2");
            
            
            IF #Takt
                & NOT #"neue IP in CPU schreiben".Busy
                & "Mon".Steuerung."SPS-Hardware"."Ethernet-Schnittstelle CPU lesen".IPParam.IPAddress =
                #"gewandeltes Array 1"
            THEN
                IF "Mon".Steuerung."SPS-Hardware"."Ethernet-Schnittstelle CP 1543-1 lesen".IPParam.IPAddress <>
                    #"gewandeltes Array 2"
                    OR "Test-DB"."IP-Adressen"."IP-Adressen CP erneuern"
                THEN
                    #"neue IP in CP 1543-1 schreiben".Req := TRUE;
                END_IF;
                
                // ... und in den CP schreiben
            END_IF;
            #"neue IP in CP 1543-1 schreiben"
            (Interface := "Local~CP_1543-1~CP",
             Conf_Data := "Mon"."akt. Parameter".Bauwerk.SPS."Ip-Adresse CP 1543-1",
             Done => "Mon".Steuerung."SPS-Hardware"."Ethernet-Schnittstelle CP 1543-1 schreiben".Done,
             Busy => "Mon".Steuerung."SPS-Hardware"."Ethernet-Schnittstelle CP 1543-1 schreiben".Busy,
             Error => "Mon".Steuerung."SPS-Hardware"."Ethernet-Schnittstelle CP 1543-1 schreiben".Error);
            
            IF #"neue IP in CP 1543-1 schreiben".Done
                OR #"neue IP in CP 1543-1 schreiben".Error
            THEN
                "Mon".Steuerung."SPS-Hardware"."Ethernet-Schnittstelle CP 1543-1 schreiben".Status :=
                #"neue IP in CP 1543-1 schreiben".Status;
                "Mon".Steuerung."SPS-Hardware"."Ethernet-Schnittstelle CP 1543-1 schreiben".Error_Loc :=
                #"neue IP in CP 1543-1 schreiben".Err_Loc;
                #"neue IP in CP 1543-1 schreiben".Req := FALSE;
            END_IF;
END_FUNCTION_BLOCK
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Damit die IP-Adressen, die als Bytes rauskommen, lesbar sind:
Code:
FUNCTION "IP Byte zu USint" : Void
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_INPUT
      Eingang : Array[0..3] of Byte;
   END_VAR

   VAR_OUTPUT
      Ausgang : Array[0..3] of USInt;
   END_VAR

   VAR_TEMP
      i : Int;
   END_VAR


BEGIN
    FOR #i:= 0 TO 3 DO
        #Ausgang[#i] := BYTE_TO_USINT(#Eingang[#i]);
    END_FOR;
END_FUNCTION

Bitte erspart mir Eure Kommentare zu meiner Art, Variablen zu benennen. Ich habe es nicht mehr nötig, mich umzustellen.
 
Zurück
Oben