TIA Redundante CPU auf Prime/Backup abfragen.

BalmungD

Level-2
Beiträge
36
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi ich habe hier 2x 1515R-2 PN CPUs die als Redundanz laufen.

Ich möchte gerne überwachen ob beide CPUs laufen und einen Alarm Generieren falls eine Ausfällt. Dafür ist mit der OB72 (CPU_RedundancyError) in den Sinn gekommen, Problem das der auch wirklich nur Aufgerufen wird wenn es mal einen Synchronisierten RUN beider CPUs gab.
Laufen also beide CPUs mal in Sync. RUN und eine Fällt aus habe ich den Aufruf und kann mir hier den Alarm setzen. Das Problem nach einem Stromausfall wenn dann nur eine der beiden CPUs dann wieder Startet erkennt er nicht das eine der beiden CPUs nicht mit gestartet ist und er denkt alles ist in Ordnung und setzt somit keinen neuen Alarm.

Jemand eine Idee mit welchem System FB man dies auslesen kann?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi Danke das werde ich mir mal anschauen ich bin aber selbst noch auf eine sehr Alte Dokumentation gefunden über den OB72 der sogar auf aktuellen CPUs noch Funktioniert.

Nur nach einem Neustarten/Stromausfall muss die Zeit Verzögerung recht hoch eingestellt werden da die CPUs relativ lange brauchen um sich zu Synchronisieren und in der Zeit eine schon läuft.
Dafür kann im OB72 das Fault_ID genutzt werden.

Variable Datentyp Beschreibung
OB72_EV_CLASS BYTE Ereignisklasse und Kennungen: · B#16#78: gehendes Ereignis· B#16#73, B#16#75, B#16#79: kommendes Ereignis
OB72_FLT_ID BYTE Fehlercode (mögliche Werte: B#16#01, B#16#02, B#16#03, B#16#20, B#16#21, B#16#22, B#16#23, B#16#31, B#16#33, B#16#34, B#16#40, B#16#41, B#16#42, B#16#43, B#16#44, B#16#50, B#16#51, B#16#52, B#16#53, B#16#54, B#16#55, B#16#56, B#16#C1, B#16#C2)
OB72_PRIORITY BYTE Prioritätsklasse; parametrierbar über STEP 7 (Hardwarekonfiguration)
OB72_OB_NUMBR BYTE OB-Nummer (72)
OB72_RESERVED_1 WORD Nur für Fehlercode B#16#03: · high byte: Kennung für den Inhalt von OB72_INFO_2 und OB72_INFO_3- 0: OB72_INFO-2 und OB72_INFO_3 sind ohne Bedeutung- B#16#C4: Der Eintritt in den redundanten Betrieb nach Fehlersuchbetrieb erfolgte mit Master-Reserve-Umschaltung (falls OB72_INFO_3=W#16#0001) bzw. ohne Master-Reserve-Umschaltung (falls OB72_INFO_3=W#16#0002). OB72_INFO_2 ist reserviert.- B#16#CD: OB72_INFO_2 und OB72_INFO_3 enthalten die tatsächliche Sperrzeit für Prioritätsklassen > 15· low byte: reserviert
OB72_INFO_1 WORD Nur für Fehlercode B#16#C2:· high byte: Kennung für die überschrittene Überwachungszeit:- 1: Zykluszeitverlängerung- 2: Peripherietotzeit- 3: Kommunikationsverzögerung· low byte: aktueller Aufdatversuch
OB72_INFO_2 WORD Nur für Fehlercode B#16#03 und OB72_RESERVED_1=B#16#CD: high word der tatsächlichen Sperrzeit für Prioritätsklassen > 15 in ms
OB72_INFO_3 WORD Nur für Fehlercode B#16#03:· OB72_RESERVED_1=B#16#C4:- W#16#0001: Eintritt in den redundanten Betrieb nach Fehlersuchbetrieb erfolgte mit Master-Reserve-Umschaltung- W#16#0002: Eintritt in den redundanten Betrieb nach Fehlersuchbetrieb erfolgte ohne Master-Reserve-Umschaltung· OB72_RESERVED_1=B#16#CD: low word der tatsächlichen Sperrzeit für Prioritätsklassen > 15 in ms
OB72_DATE_TIME DATE_AND_TIME Datum und Uhrzeit, zu denen der OB angefordert wurde
Die folgende Tabelle zeigt, welches Ereignis den Start des OB 72 verursacht hat.


OB72_EV_CLASS OB72_FLT_ID Startereignis des OB 72
B#16#73 B#16#01 Redundanzverlust (1v2) durch Ausfall einer CPU
B#16#73 B#16#02 Redundanzverlust (1v2) durch STOP der Reserve, der vom Anwender ausgelöst wurde
B#16#73 B#16#03 H-System (1v2) in den redundanten Betrieb gegangen
B#16#73 B#16#20 Fehler bei RAM-Vergleich
B#16#73 B#16#21 Fehler beim Vergleich von Prozessabbild-Ausgangswert
B#16#73 B#16#22 Fehler beim Vergleich von Merkern, Zeiten oder Zählern
B#16#73 B#16#23 Unterschiedliche Betriebssystemdaten erkannt
B#16#73 B#16#31 Reserve-Master-Umschaltung wegen Masterausfall
B#16#73 B#16#33 Reserve-Master-Umschaltung im Rahmen einer Anlagenänderung im laufenden Betrieb
B#16#73 B#16#34 Reserve-Master-Umschaltung wegen Verbindungsstörung am Synchronisationsmodul
B#16#73 B#16#40 Synchronisationsfehler im Anwenderprogramm durch abgelaufene Wartezeit
B#16#73 B#16#41 Synchronisationsfehler im Anwenderprogramm durch Warten an unterschiedlichen Synchronisationspunkten
B#16#73 B#16#42 Synchronisationsfehler im Betriebssystem durch Warten an unterschiedlichen Synchronisationspunkten
B#16#73 B#16#43 Synchronisationsfehler im Betriebssystem durch abgelaufene Wartezeit
B#16#73 B#16#44 Synchronisationsfehler im Betriebssystem durch falsche Daten
B#16#79 B#16#50 Fehlendes SYNC-Modul
B#16#79 B#16#51 Änderung am Synchronisationsmodul ohne NETZEIN
B#16#79/B#16#78 B#16#52 SYNC-Modul gezogen/gesteckt
B#16#79 B#16#53 Änderung am Synchronisationsmodul ohne Urlöschen
B#16#79 B#16#54 SYNC-Modul: Doppelvergabe einer Baugruppenträgernummer
B#16#79/B#16#78 B#16#55 SYNC-Modul-Fehler/beseitigt
B#16#79 B#16#56 Unzulässige Baugruppenträgernummer auf SYNC-Modul eingestellt
B#16#73 B#16#C1 Abbruch des Aufdatvorgangs
B#16#73 B#16#C2 Abbruch des Aufdatvorgangs wegen Überschreiten einer Überwachungszeit beim n-ten Versuch (1 <= n <= maximal mögliche Anzahl der Aufdatversuche nach Abbruch wegen Zeitüberschreitung)
 
Grundsätzlich verzichte ich lieber auf den OB und mach das direkt im Anwenderprogramm.
Ich habe da auch schon was gemacht. Da könnte man gut drauf aufsetzen.
Code:
TYPE "st_H_Systemkopf"
VERSION : 0.1
   STRUCT
      Primary : Bool;
      Secondary : Bool;
      nonRedundancy : Bool;
      SyncCableFail : Bool;   // Synchronisationsleitung fehlerhaft
      Maintenance : Bool;   // Wartung nötig (Diagnosebuffer)
      Error : Bool;   // Systemfehler (Diagnosebuffer)
      Mode : Int;   // 0 Unbekannt, 1 Stop, 2 Anlauf, 3 Run, 4 Run-Syncup
   END_STRUCT;

END_TYPE

FUNCTION_BLOCK "FB_H_System"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_INPUT
      LADDR_HSystem : HW_ANY;   // HSystem HW Adresse ""Local1~RHSystem""
      LADDR_Head1 : HW_ANY;   // Kopf1 HW Adresse "Local1~HCPUredCtrl"
      LADDR_Head2 : HW_ANY;   // Kopf1 HW Adresse "Local2~HCPUredCtrl"
      LADDR_Head1_Common : HW_ANY;   // Kopf1 HW Adresse "Local1~Common"
      LADDR_Head2_Common : HW_ANY;   // Kopf1 HW Adresse "Local2~Common"
   END_VAR

   VAR_OUTPUT
      SystemOperatingState : Int;   // 0 Unbekannt, 1 Stop, 2 Anlauf, 3 Run-Solo, 4 Syncup, 5 Run-Redundant
      Kopf1 : "st_H_Systemkopf";
      Kopf2 : "st_H_Systemkopf";
   END_VAR

   VAR
      DIS_HSystem {InstructionName := 'DIS'; LibVersion := '1.0'; ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'; S7_SetPoint := 'False'} : DIS;
      DIS_Head1 {InstructionName := 'DIS'; LibVersion := '1.0'} : DIS;
      DIS_Head2 {InstructionName := 'DIS'; LibVersion := '1.0'} : DIS;
      DNN {InstructionName := 'DNN'; LibVersion := '1.0'; ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'; S7_SetPoint := 'False'} : DNN;
      Mode { S7_SetPoint := 'True'} : Byte;
      Takt {InstructionName := 'TON_TIME'; LibVersion := '1.0'} : TON_TIME;
      Output {InstructionName := 'R_TRIG'; LibVersion := '1.0'} : R_TRIG;
      stTakt : Struct
         q : Bool;
         in : Bool;
      END_STRUCT;
      PrimaryID : Int;
   END_VAR

   VAR_TEMP
      Status : Int;
      Busy : Bool;
      RetVal : Int;
      subordinateState : UInt;
      CNT_DIAG_temp : UInt;
      MRP_proof_Off : Bool;
      Modi : DWord;
      CPU1ERRLED : Int;   // Error LED
      CPU1MAINLED : Int;   // Wartungs LED
      CPU2ERRLED : Int;   // Error LED
      CPU2MAINLED : Int;   // Wartungs LED
   END_VAR

   VAR CONSTANT
      Syncup_sperren : Byte := 3;
      Syncup_MRP_freigeben : Byte := 4;
      Syncup_anfordern : Byte := 7;
      Syncup_anfrage_gesperrt : Byte := 10;
      MRP_proof_deact : Byte := 14;
      "RUN-Redundant" : UInt := 40;
      "RUN-Solo" : UInt := 37;
   END_VAR


BEGIN
    // ========================================================================================
    // Titel:           FB_H_System
    // Version:         0.0.7
    //
    // Datum:           1.Nov.2024
    // Autor:           VoR
    // Beschreibung:    Der Baustein wertet den aktuellen zustand des H_Systems aus. wenn
    //                  das System wegen aufgebrochenem MRP Ring nicht synchronisiert, wird die
    //                  MRP-Prüfung deaktiviert und das System in den Run-Redundant Modus überführt.
    //                  die MRP-Prüfung wird wieder aktiviert sobald der Ring geschlossen wurde.
    //                  Der aktuelle Betriebszustand wird am SystemOpteratingState ausgegeben
    //                  Der Zustand der beiden Systemköpfe am Ausgang Kopf1 bzw. Kopf2.
    //                  das aussetzen der MRP Prüfung bedingt Firmware >=3.0 der S7-1500 H_Steuerungen
    //                 
    // ========================================================================================
   
   
    #Output(CLK := (#Mode <> 0) AND NOT #stTakt.q);
   
    #Takt(IN := #stTakt.in,
          PT := T#500ms,
          Q => #stTakt.q);
   
    #stTakt.in := NOT #stTakt.q AND (#Mode <> 0);
   
   
    #Status := RH_CTRL(REQ := #Output.Q,
                       Mode := #Mode,
                       Busy => #Busy);
   
    //Get diag state of R/H system.
    #RetVal := GET_DIAG(MODE := 2, LADDR := #LADDR_HSystem, CNT_DIAG => #CNT_DIAG_temp, DIAG := #DNN);
    #subordinateState := #DNN.SubordinateState;
    #MRP_proof_Off := #DNN.SubordinateIOState.%X15; // MRP prüfung für Sync-Up deaktiviert.
   
   
    //Get system operating state
    #RetVal := GET_DIAG(MODE := 1, LADDR := #LADDR_HSystem, CNT_DIAG => #CNT_DIAG_temp, DIAG := #DIS_HSystem);
   
    CASE #DIS_HSystem.OperatingState OF
        #"RUN-Solo":
            IF NOT #MRP_proof_Off AND (#subordinateState <> 0) THEN
                #Mode := #MRP_proof_deact;
            ELSE
                #Mode := #Syncup_anfordern;
            END_IF;
        #"RUN-Redundant":
            IF #MRP_proof_Off THEN
                #Mode := #Syncup_MRP_freigeben;
            ELSIF (NOT #Mode = 0) THEN
                #Mode := 0;
            END_IF;
    END_CASE;
   
    // Zustand an HMI
    CASE #DIS_HSystem.OperatingState OF
        33: // Stop
            #SystemOperatingState := 1;
        35: // Anlauf
            #SystemOperatingState := 2;
        37: // Run-Solo
            #SystemOperatingState := 3;
        38: // Syncup
            #SystemOperatingState := 4;
        40: // Run-Redundant
            #SystemOperatingState := 5;
        ELSE
            #SystemOperatingState := 0;
    END_CASE;
   
    #PrimaryID := RH_GetPrimaryID();
   
    REGION Zustand #Kopf1
        #RetVal := GET_DIAG(MODE := 1, LADDR := #LADDR_Head1, CNT_DIAG => #CNT_DIAG_temp, DIAG := #DIS_Head1);
        #CPU1MAINLED := LED(LADDR := #LADDR_Head1_Common, LED := 3);
        #CPU1ERRLED := LED(LADDR := #LADDR_Head1_Common, LED := 2);
        #Kopf1.Primary := #PrimaryID = 1;
        #Kopf1.Secondary := #PrimaryID = 2;
        #Kopf1.nonRedundancy := #DIS_HSystem.OperatingState <> #"RUN-Redundant";
        #Kopf1.SyncCableFail := #DIS_Head1.OwnState = 3;
        #Kopf1.Maintenance := #CPU1MAINLED > 1;
        #Kopf1.Error := #CPU1ERRLED > 1;
        CASE #DIS_Head1.OperatingState OF
            1..4: // Stop
                #Kopf1.Mode := 1;
            6: // Anlauf
                #Kopf1.Mode := 2;
            8, 9: // Run
                #Kopf1.Mode := 3;
            21, 22: // Run-Syncup
                #Kopf1.Mode := 4;
            ELSE
                #Kopf1.Mode := 0;
        END_CASE;
    END_REGION
   
    REGION Zustand #Kopf2
        #RetVal := GET_DIAG(MODE := 1, LADDR := #LADDR_Head2, CNT_DIAG => #CNT_DIAG_temp, DIAG := #DIS_Head2);
        #CPU2MAINLED := LED(LADDR := #LADDR_Head2_Common, LED := 3);
        #CPU2ERRLED := LED(LADDR := #LADDR_Head2_Common, LED := 2);
        #Kopf2.Primary := #PrimaryID = 2;
        #Kopf2.Secondary := #PrimaryID = 1;
        #Kopf2.nonRedundancy := #DIS_HSystem.OperatingState <> #"RUN-Redundant";
        #Kopf2.SyncCableFail := #DIS_Head2.OwnState = 3;
        #Kopf2.Maintenance := #CPU2MAINLED > 1;
        #Kopf2.Error := #CPU2ERRLED > 1;
        CASE #DIS_Head2.OperatingState OF
            1..4: // Stop
                #Kopf2.Mode := 1;
            6: // Anlauf
                #Kopf2.Mode := 2;
            8, 9: // Run
                #Kopf2.Mode := 3;
            21, 22: // Run-Syncup
                #Kopf2.Mode := 4;
            ELSE
                #Kopf2.Mode := 0;
        END_CASE;
    END_REGION
   
END_FUNCTION_BLOCK

DATA_BLOCK "H_System_DB"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
NON_RETAIN
"FB_H_System"

BEGIN

END_DATA_BLOCK

DATA_BLOCK "H_systemzustand"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
NON_RETAIN
   VAR
      systemzustand : Int;
      Kopf1 { S7_SetPoint := 'False'} : "st_H_Systemkopf";
      Kopf2 : "st_H_Systemkopf";
   END_VAR


BEGIN

END_DATA_BLOCK

ORGANIZATION_BLOCK "Main_H_System"
TITLE = "Main Program Sweep (Cycle)"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1

BEGIN
    "H_System_DB"(LADDR_HSystem := "Local1~RHSystem",
                  LADDR_Head1 := "Local1~HCPUredCtrl",
                  LADDR_Head2 := "Local2~HCPUredCtrl",
                  LADDR_Head1_Common := "Local1~Common",
                  LADDR_Head2_Common := "Local2~Common",
                  SystemOperatingState => "H_systemzustand".systemzustand,
                  Kopf1 => "H_systemzustand".Kopf1,
                  Kopf2 => "H_systemzustand".Kopf2);
END_ORGANIZATION_BLOCK

Das liefert dir schon fertig was du brauchst im DB H_Systemzustand
Das habe ich für eine H CPU geschrieben, funktioniert aber grundsätzlich auf einer R auch. musst du halt noch ein paar Anpassungen vornehmen z.B. für die Synccable überwachung.
 
Zurück
Oben