TIA For-Schleife 32 Bitweise

exclis066

Level-2
Beiträge
28
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Moin Zusammen,

ich habe 64 Bit Struct oder Array (32 Bit Fehler+32Bit Meldungen).
Der Code, den ich unten geschrieben habe, überprüft alle Bits.
Wie kann ich erreichen, dass nur die Fehlerbits geprüft werden?


DB:
Variable Array[0..63] of Bool
Variable_1 Array[0..63] of Bool
Variable_2 Array[0..63] of Bool
Variable_3 Array[0..63] of Bool
Variable_4 Array[0..63] of Bool
Variable_5 Array[0..63] of Bool
Variable_6 Array[0..63] of Bool

Code:
#i := 0;
#Byte := 0;
#Bit := 0;


FOR #i := #IN1 TO #IN2 BY 1 DO
    
    #ErrorNumber := 0;
    #Byte := #i / 8; // Bytenummer berechnen
    #Bit := #i MOD 8; // Bitnummer berechnen
    
        #fehlerTrue := WORD_TO_BLOCK_DB(#DBNr).DX(#Byte, #Bit);
        
        IF #fehlerTrue THEN
            #ErrorNumber := #i + #Fehlerbereiche;
            RETURN;
        END_IF;
      
    
END_FOR;



Hat Jemand eine andere Idee?

VG
Excliss
 
Moin exclis066,

was meinst du mit "überprüfen"?
Wieso 64 Bit struct ODER Array?

Wie sind die Fehler/Meldungen angeordnet?
0-31 = Fehler; 32-63 = Meldung
oder alternierend (Fehler, Meldung, Fehler, Meldung, Fehler, ...)?

Wenn Du noch dabei bist, zu überlegen, wie Du die Variablen aufbaust, wären zwei Arrays
Fehler[0..31] und Meldung[0..31] nicht chic?


Du versuchst "nach alter Schule" absolut auf Adressen zuzugreifen. Tu Dir einen Gefallen und mach es symbolisch.

Mal ein Beispiel (kommt halt auf Deine Anwendung an):
Code:
varError := false;
FOR i := 0 TO 31
    IF "DB".Fehler[#i] THEN
        varError := true;
    END_IF;
END_FOR;

VG

MFreiberger
 
die Fehler/Meldungen sind (0-31 = Fehler; 32-63 = Meldung) angeordnet, und die sind fest, also entweder 64 Bit Struct oder Array[0..63] of Bool.
Und ich muss absolut auf Adressen zugreifen.
VG
Excliss
 
Moin exclis066,

also handelt es sich um ein struct und nicht um ein Array...
Du könntest Dir die Struct 'E-stop' in ein Array[0..31] of Bool umkopieren und dann das Array durchsuchen.

Das umkopieren könntest Du z.B. mit serialize (macht aus einer Struktur, einem Array, einem UDt,... ein ArrayOfByte) und deserialize (macht aus einem ArrayOfByte eine Struktur, Array...) die Struktur in ein Array[0..31] of Bool überführen.
Ach, geht ja auch nicht. die 32 Fehlerbit sind ja nur eine Teilstruktur... Wobei... Du könntest die ganze Struktur serialisieren und dann nur ein Teil des ByteArrays in ein Array[0..31] of Bool überführen.

Andere Frage: Warum ist 'E-stop' überhaupt als struct und nicht als Array[0..n] of Bool angelegt? Ich ahne, dass die einzelnen Bits ein Symbol erhalten sollen, das den Fehler beschreibt. Eine Alternative wäre, den Kommentar passend anzupassen (kann man nämlich für jedes Array-Element separat).

Warum enthält die Struktur FehlerBits und Meldebits? Es kann hilfreich sein, zwei Unterstrukturen (Fehler / Meldungen) anzulegen.

Man könnte (da es 32 Bit sind), wenn es eine eigene Struktur wäre, auch GATHER nutzen. Also die einzelnen Bits der Struktur in ein DWORD ablegen.

Code:
#error := 0;
#maske := 16#1;

FOR #i := 0 TO 31 DO
    IF
        (#dwordFehler AND #maske) = 2**#i
    THEN
        #error := #i;
        exit;
    END_IF;
    #maske := SHL(IN := #maske, N := 1);
END_FOR;

Jetzt eine Frage: funktioniert Dein Code und Du suchst nur eine einfachere Variante oder funktioniert Dein Code nicht und Du suchst den Fehler?

VG

MFreiberger
 
Das ist doch von einer Sinumerik, oder?

Ohne genau zu Wissen was du vorhast und ob das überhaupt Sinn gibt.
Denke ich das du das gebrauchen kannst (ungetestet):

Code:
[CODE]#offset:=554;

FOR #Bereich := 0 TO ? DO
    FOR #ByteNummer := 0 TO 31 DO
        FOR #BitNummer := 0 TO 7 DO
           
            #ErrorNumber := 0;
            #Byte := offset+#ByteNummer+#Bereich*64; // Bytenummer berechnen
            #Bit := #BitNummer; // Bitnummer berechnen
   
            #fehlerTrue := WORD_TO_BLOCK_DB(#DBNr).DX(#Byte, #Bit);
       
            IF #fehlerTrue THEN
                RETURN;
            END_IF;
     
        END_FOR;
    END_FOR;
END_FOR;


Und Aufpassen bei der Fehlernummer Berechnung. Da sind Lücken drin (nicht fortlaufend) z.B.
nach Alarm 700463 kommt 700500.

1668607442829.png
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Vielen Dank für eure Antworten.
Hi MFreiberger, mein Code läuft aber die Aufgabe fordert mehr :) muss noch einiges gemacht werden.
Ja Tschoke, das ist Sinumerik 840d sl Steuerung und hier geht's um die db2 und Ich werde deine Code mal ausprobieren.

Meine Aufgabe ist 500000er Kanalbereich, 600000er Achsbereiche und 700000er Anwenderbereiche erste aktive Alarmnummer über die gesetzte Bit ermitteln.
Die Lücken sind unterschiedlich, es macht die Aufgabe schwer.
 

Anhänge

  • 840dsl_Alarme PLC.pdf
    162,5 KB · Aufrufe: 22
Zuviel Werbung?
-> Hier kostenlos registrieren
Ist das wichtig?

Du kanns bei der Lösung unterschützen.
Ja ich denke schon , wenn es einen Übungsaufgabe ist würde ich mich mal grundsätzlich mit der Hilfe zurückhalten.
Es ist ja nicht immer einer verfügbar , der einem die Arbeit macht.

mich würde halt nur interessieren was ich mit der Info anfangen kann, an einer realen Maschine.
könnte ja sein das ich das gut finde und was draus mache
 
Hi Tschoke,
ich habe deinen Code getestet.
ich habe nur diese Zeile angepasst und hat funktioniert.
#Byte := offset+#ByteNummer+#Bereich*64; // Bytenummer berechnen

jetzt bin ich bei der Fehlernummer auswerten dran.


Code:
//for the db2 active error search
#i := 0; // i nullsetzen
#Byte := 0; // Bytenummer nullsetzen
#Bit := 0; // Bitnummer nullsetzen
#Bereich := 0;


FOR #Bereich := 0 TO 250 DO
    FOR #ByteNummer := 0 TO 31 DO
        FOR #BitNummer := 0 TO 7 DO
            
            #ErrorNumber := 0;
            #Byte := #offset + #Bereich /8; // Bytenummer berechnen
            #Bit := #BitNummer; // Bitnummer berechnen
            
            #fehlerTrue := WORD_TO_BLOCK_DB(#DBNr).DX(#Byte, #Bit);
            
            IF #fehlerTrue THEN
                #ErrorNumber := #Bereich + #Fehlerbereiche;
                RETURN;
            END_IF;
            
        END_FOR;
    END_FOR;
END_FOR;
 
ich habe deinen Code getestet.
ich habe nur diese Zeile angepasst und hat funktioniert.
Also den Code den du gepostet hast, kann nicht funktionieren.

Code:
#Bereich := 0 TO 250 DO
Es gibt doch keine 250 Bereiche. Mit Bereich meinte ich: 1Bereich=32FM+32BM

- Variable #offset wird nie einen Wert zugewiesen. Müsste auf den Offset des ersten Bereich (554) gesetzt werden.

Code:
#Byte := #offset + #Bereich /8;
Warum geteilt durch 8? Gibt keinen Sinn.
Hab mich oben vertan. Hab aus versehen den BitOffset bei den Bytes verwendet.
Versuchs mal so:

Code:
#offset:=554;

FOR #Bereich := 0 TO ? DO
    FOR #ByteNummer := 0 TO 3 DO
        FOR #BitNummer := 0 TO 7 DO
          
            #ErrorNumber := 0;
            #Byte := offset+#ByteNummer+#Bereich*8; // Bytenummer berechnen
            #Bit := #BitNummer; // Bitnummer berechnen
  
            #fehlerTrue := WORD_TO_BLOCK_DB(#DBNr).DX(#Byte, #Bit);
      
            IF #fehlerTrue THEN
                RETURN;
            END_IF;
    
        END_FOR;
    END_FOR;
END_FOR;
 
Zuviel Werbung?
-> Hier kostenlos registrieren
ich denke, ich muss wieder auf Fussmethode wechseln. Ich werde eine Array of Dint definieren. Ich werde Alle Fehlernummer eintragen.

Fehlernummer:=Array [#Bereich]; könnte Problem lösen.
 
ich habe das Problem gelöst. anbei die Lösung.



Code:
  VAR_INPUT
      startByte : Int;
      endeByte : Int;
      DBNr : Int;
      Offset : Int;
   END_VAR

   VAR_OUTPUT
      ErrorNumber : DInt;
   END_VAR

   VAR_TEMP
      i : Int;
      Byte : Int;
      Bit : Int;
      j : Int;
      fehlerTrue : Bool;
      A : Int;
      E : Int;
   END_VAR

BEGIN
    
    
    #j := 0; // i nullsetzen
    #Byte := 0; // Bytenummer nullsetzen
    #Bit := 0; // Bitnummer nullsetzen
    #A:=#startByte*8;
    #E :=#endeByte*8;
    
    
    FOR #i := #A TO #E BY 1 DO
        
        #ErrorNumber := 0;
        #Byte := #i / 8; // Bytenummer berechnen
        #Bit := #i MOD 8; // Bitnummer berechnen
        #j := #i - #Offset;
        
        #fehlerTrue := WORD_TO_BLOCK_DB(#DBNr).DX(#Byte, #Bit);
            
        IF #fehlerTrue THEN
                #ErrorNumber := "testDB".Fehlernum[#j];
                RETURN;
        END_IF;
        
    END_FOR;
 
Zurück
Oben