TIA Mehre Bits aus Datenbaustein auf TRUE abfragen

REMARC_C

Level-1
Beiträge
10
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Leute,
ich möchte mehrere Bits aus einem Datenbaustein abfragen um damit einen Alarm Ausgang zu generieren.
Die schnellste Lösung wäre natürlich das folgender Maßen zu machen:
"Out_X.X := DB10.DBX_X.X OR DB10.DBX_X.Y" .... usw. das ganze dann noch 46 weitere Male. Das ist aber für mich keine ganz so elegante Lösung.

Meine Frage ist gibt es noch bessere? Vllt mit einer Schleife? Ich habe mal 2 Bilder angehängt damit ihr meinen DB und meinen FC sehen könnt.

Gruß
 

Anhänge

  • FC.PNG
    FC.PNG
    5,1 KB · Aufrufe: 30
  • DB10.jpg
    DB10.jpg
    82,8 KB · Aufrufe: 44
Ist es denn entscheidend, ob irgendein Bit im gesamten DB gesetzt ist?
Oder möchtest Du feiner unterteilen und mit einer Schleife in den deklarierten ARRAYS abfragen?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich will nur bestimmte Bits abfragen:
1.) DB10.DBX1.1
2.) DB10.DBX9.1
3.) DB10.DBX17.1
4.) DB10.DBX25.1
...
...
48.) DB10.DBX377.1
 

Anhänge

  • FC3.PNG
    FC3.PNG
    8,8 KB · Aufrufe: 24
Zuletzt bearbeitet:
Die schnellste und für jede beliebige Bitanordnung machbare Lösung wäre das Lesen der betreffenden DB-WORDs oder -DWORDs und ausmaskieren der Bits (geht nicht mit "optimierten" DB):
Code:
Out_X := (%DB10.DBW2 AND W#16#5555 OR %DB10.DBW4 AND W#16#FFFF OR ... ) <> 0;
Ohne Kommentar ist so ein Bits-Ausmaskieren kaum verständlich, und wie bei jeder unsymbolischen direkten Speicher-Adressierung passt sich der Code natürlich nicht automatisch an, wenn in dem Speicherbereich Bits verschoben werden.

Wenn es eine Schleife sein soll:
- Eine Schleife kann man nur auf zusammenhängende oder regelmäßig strukturierte Daten anwenden, oder man muß aufwendig das Überspringen von Elementen programmieren. Hängen Deine Bits regelmäßig zusammen?
- In einer Schleife Elemente indiziert symbolisch ansprechen kann man nur Elemente von Arrays. Liegen Deine Bits in einem Array?
- In einer Schleife Adressen ansprechen kann man nur von Elementen die eine Adresse haben. Haben Deine Bits eine Adresse? ("optimierte" DB gehen nicht)
- Wie indirektes Adressieren von Speicheradressen gemacht werden muß hängt von der verwendeten CPU ab - welche CPU verwendest Du? Bei S7-1500 mußt Du PEEK verwenden.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Die hängen regelmäßig zusammen. Der DB ist folgendermaßen aufgebaut:
Byte 0 und 1 ist ein ARRAY, Bitmeldungen vom Antrieb
Byte 2 und 3 ist ein Word, hier schreibe ich die Bits rein... ist ne Funktion für meinen KTP
Byte 4-7 ist ein Realwert, Wickeldurchmesser...

Beginnend bei Adresse 1.1 will ich in jedem weiteren 8. Byte dieses Bit lesen... demnach also 1.1; 9.1; 17.1 usw.
 
Wer setzt die Bits? Könnte der Baustein nicht einen IN_OUT-Bool haben, der beim Setzen eines Bits auch das IN_OUT-Bit als Sammelmeldung setzt? Dann hast Du nach Durchlauf aller Bits auch gleich das Sammelbit.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
In dem Bild ist mal dargestellt wie das ganze aussieht. Ich generiere die Störung in dem FB und schreibe sie dann anschließend in den DB. Quasi für jeden Antrieb einzeln.
FB.jpg
 
Ich will nur bestimmte Bits abfragen:
1.) DB10.DBX1.1
2.) DB10.DBX9.1
3.) DB10.DBX17.1
4.) DB10.DBX25.1
...
...
48.) DB10.DBX377.1
Code:
[COLOR="#008000"]// xBit : BOOL[/COLOR]
[COLOR="#008000"]// Adr  : DINT[/COLOR]

#xBit := 0;
FOR #Adr := 1 TO 377 BY 8 DO  [COLOR="#008000"]//#Adr: 1, 9, 17, 25 ... 377[/COLOR]
    IF PEEK_BOOL(area := B#16#84, dbNumber := 10,        [COLOR="#008000"]//DB10[/COLOR]
                     byteOffset := #Adr, bitOffset := 1) [COLOR="#008000"]//DBX[#Adr].1[/COLOR]
    THEN
        #xBit := 1;  [COLOR="#008000"]//1-Bit gefunden![/COLOR]
        EXIT;        [COLOR="#008000"]//ein 1-Bit gefunden reicht[/COLOR]
    END_IF;
END_FOR;

Harald
 
Ich generiere die Störung in dem FB und schreibe sie dann anschließend in den DB. Quasi für jeden Antrieb einzeln.
Anhang anzeigen 40667
Du könntest dem FB1 einen IN_OUT "IO_SF_FU_FAULT" geben:
Code:
IF "intern_FU_FAULT" THEN
    "IO_SF_FU_FAULT" := 1;
END_IF;
Dann vor allen FB1-Aufrufen eine Bool-Variable "Sammelfehler" auf 0 setzen, dann bei allen FB1-Aufrufen "IO_SF_FU_FAULT" mit der Bool-Variable "Sammelfehler" beschalten. Nach Durchlauf aller FB1-Instanzen liegt gleichzeitig der Sammelfehler vor.

Harald
 
Code:
[COLOR=#008000]// xBit : BOOL[/COLOR]
[COLOR=#008000]// Adr  : DINT[/COLOR]

#xBit := 0;
FOR #Adr := 1 TO 377 BY 8 DO  [COLOR=#008000]//#Adr: 1, 9, 17, 25 ... 377[/COLOR]
    IF PEEK_BOOL(area := B#16#84, dbNumber := 10,        [COLOR=#008000]//DB10[/COLOR]
                     byteOffset := #Adr, bitOffset := 1) [COLOR=#008000]//DBX[#Adr].1[/COLOR]
    THEN
        #xBit := 1;  [COLOR=#008000]//1-Bit gefunden![/COLOR]
        EXIT;        [COLOR=#008000]//ein 1-Bit gefunden reicht[/COLOR]
    END_IF;
END_FOR;

Harald

Also mit dem ersten byte funktionert es schonmal. Aber nicht mit dem zweiten also Adresse DB10.DBX9.1

hier mein Programmauschnitt dazu:

//Störung Spule oder Fadenriss
#xBit := 0;
FOR #xAdr := 1 TO 377 BY 8 DO //#Adr: 1, 9, 17, 25 ... 377
IF PEEK_BOOL(area := B#16#84, dbNumber := 10, //DB10
byteOffset := 1, bitOffset := 1)//DBX[#Adr].1
THEN
#xBit := 1;
EXIT;
END_IF;
END_FOR;

IF #xBit = TRUE THEN
"FWA_INP_A600.2" := TRUE;
END_IF;
IF #xBit = FALSE THEN
"FWA_INP_A600.2" := FALSE;
END_IF;
 
Schon gut. Habe meinen Fehler hatte bei "byteOffset := 1" stehen. Jetzt rennt es. Vielen Dank für deine Hilfe!!!!!:cool::cool::cool:
 
Zuviel Werbung?
-> Hier kostenlos registrieren
IF #xBit = TRUE THEN
"FWA_INP_A600.2" := TRUE;
END_IF;
IF #xBit = FALSE THEN
"FWA_INP_A600.2" := FALSE;
END_IF;
Wenn schon Logikverknüpfungen in SCL dann bitte nicht so ein furchtbares Gestammel.. ;)
Deine IF..THEN..Orgie schreibt man professionell so:
Code:
"FWA_INP_A600.2" := #xBit;

Harald
 
Zurück
Oben