TIA Schiebe- und Rotationsbefehle Anwendungsbeispiele

Xedos

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

Mache momentan meine Weiterbildung zur SPS-Fachkraft und wegen den Prüfungen sollen wir in der Theorie lernen, wie Schiebe und Rotationsbefehle funktionieren.
Ansicht die Funktion dahinter habe ich verstanden, aber auf die Frage wofür man das mal gebrauchen könnte, konnte mir der Kursleiter auch keine Antwort geben.
Habt ihr Anwendungsbeispiele wo ihr das schonmal gebraucht habt ?

Mit freundlichen Grüßen

Xedos
 
Habt ihr Anwendungsbeispiele wo ihr das schonmal gebraucht habt ?
z.B. Zahlenformate zwischen INT und BCD, Hex, Char, String effizient umwandeln, Zahlen in Ziffern zerlegen, Ziffern in Zahlen tauschen, Lauflichter, IO/NIO-Schieberegister, ...

Programmbeispiele
BCD-Wandlung ohne BCDF-Fehler

AWL: Nibbles in einem Byte tauschen

spontan: durch Ziffern-Zerlegung bei der INT-nach-ASCII-Wandlung, anstatt String Funktionen.
(...)
Ich habe mal 2 SCL-Varianten und eine AWL-Variante programmiert und die Codegrößen verglichen:
Code:
Vergleich Codegröße SCL original Programm mit Stringfunktionen, SCL besser, SCL optimiert, AWL
Größe der String-FC I_STRNG + LEN + RIGHT + CONCAT = 966 Bytes

SCL orig. #1 + tmp : 752 Bytes + Code der 4 String-FC 966 Bytes
SCL ohne String-FC : 472 Bytes
SCL optimiert DINT : 464 Bytes
AWL FB (by PN/DP)  : 104 Bytes
(...)
Code:
//AWL FB : i in ID-String 'W1_nnnn' wandeln
//Pointer auf den OUT-Parameter ID in der Instanz
      TAR2                              //FB-Multiinstanzoffset aus AR2
      UD    DW#16#FFFFFF                //Bereichskennung (DB) ausblenden
      L     P##ID                       //Adresse ID in der Instanz
      +D                                // Adresse ID im IDB
      LAR1                              //Pointer auf den OUT-Parameter ID

      L     W#16#807                    //maxLen 8 + IstLen 7
      T     DIW [AR1,P#0.0]             //String-Header initialisieren

//Prefix-Zeichen 'W1_' in String eintragen
      L     'W1_0'
      T     DID [AR1,P#2.0]

//INT 4 Ziffern nach ASCII
      L     #i                          //INT 0..9999, z.B. 1234
      DTB                               //00_00_12_34 (BCD)
      SLD   4                           //00_01_23_40
      SRW   4                           //00_01_02_34
      SLD   12                          //10 23_40_00
      SRW   4                           //10_23_04_00
      SRD   4                           //01_02_30_40
      SRW   4                           //01_02_03_04 (Hex)
      L     '0000'
      OD                                //in ASCII-Chars '1234' wandeln
      T     DID [AR1,P#5.0]             //'1234' in String eintragen
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Beispiel:
Du hast einen Rundtakttisch mit mehreren Stationen.
Jede Station Station bearbeitet das Teil hat eine am Ende eine Fertigmeldung und eine Teil-iO-Meldung.
Hier kann man zum Beispiel die Schiebebefehle anwenden.

Anderes Beispiel:
Rechnen mit Schiebeoperationen. Die Schiebeoperationen sind schneller als die Rechenoperationen.
So kannst eu eine einfache Integer-Multiplikation wie x4 auch durch ein SHL(2) ersetzen.

Anderes Beispiel:
Schrittketten kann man auch mit Schiebebefehlen realisieren.
Anstelle von einer Schritt-Nummer kann man auch z.B. ein Bit in einem Word weiterschieben.
Zusammen mit den Slice-Zugriffen in TIA gibt das recht einfache und schnelle Schrittketten.

Anderes Beispiel:
Formatwandlungen bei BCD- und ASCII-Codes oder Checksummen-Funktionen.

Also Möglichkeiten und Anwendungen gibt's da recht viele.
Besonders wenn es schnell und / oder effizient sein muß, haben die Funktionen Vorteile.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Trauriges Zeichen 😒 Frag ihn mal (nach dem Abschluß), ob er schon jemals ne Maschine oder Anlage programmiert hat :)
Hey,

an sich ist er sehr jung hat aber viel Ahnung von programmieren, er hat halt in SCL mit dem sowohl er als auch ich programmiere, andere Alternativen gefunden um die selben Funktionen auszuführen. Man sagt ja immer viele Wege führen nach Rom und er arbeitet anschließend nicht gerne mit den Schiebe- und Rotationsbefehlen.

Mit freundlichen Grüßen

Xedos
 
Man sagt ja immer viele Wege führen nach Rom und er arbeitet anschließend nicht gerne mit den Schiebe- und Rotationsbefehlen.
Mit SCL (für SPS) kann man (wie mit VB/VBS für andere Anwendungen) schnell gut verstehbaren Code produzieren.

Wenn es aber wirklich effizient sein muss (oder früher unbedingt sein musste), dann greift man (wo sinnvoll) auf Algorithmen mit Schiebe- und Rotationsbefehlen zurück. Das erfordert zwar beim Programmieren mehr nachdenken und testen und dauert länger, dafür rennt der Code dann aber meistens viel schneller als mit simplen/Standard-Algorithmen. z.B. für Checksummen, Verschlüsselung, Videoverarbeitung, ...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Noch ein Beispiel:
Bei Analogeingangskarten sind die rechten zwei Bits manchmal Diagnosebits und die restlichen Bits der eigentliche Analogwerte. Um das "sauber" zu trennen, muss man sinnvollerweise schieben.
 
Um das "sauber" zu trennen, muss man sinnvollerweise schieben.
Achtung: bei Analogwerten muss man das Rechtsschieben (meistens) unter Beachtung des Vorzeichens machen. Deshalb besser mit Ganzzahl-Division machen oder darauf achten, dass vorzeichenrichtiges Schieben verwendet wird. Nach IEC 1131-3 gibt es allerdings kein vorzeichenrichtiges Rechtsschieben (SHR) - es werden immer Nullen eingeschoben.
 
Noch ein Beispiel:
Bei Analogeingangskarten sind die rechten zwei Bits manchmal Diagnosebits und die restlichen Bits der eigentliche Analogwerte. Um das "sauber" zu trennen, muss man sinnvollerweise schieben.
Hast Du da nen konkretes Beispiel? So wie ich das kenne, sind zwar manchmal die 2 niedrigsten Bits Diagnose (bei Analogwerten mit einer Auflösung von weniger als 14bit), aber den "Analogwert" selber musst Du nicht verschieben, der passt trotzdem (mit Ungenauigkeit in den letzten Bits) Da liest man üblicherweise die 2 Bits aus und löscht sie ab. Was bei S7-1500 mit Slice ganz gut geht... Wortvariable.%X0 Wortvariable.%X1
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ob und wie man die 2 Statusbits entfernt, ist wohl eher eine Geschmacksfrage.
Lässt man die Statusbits einfach drin, behält man eine Ungenauigkeit von weniger als ein LSB des ADU.
Man kann die Statusbits auch einfach ausmaskieren und behält den Analogwert x..32764 mit Schrittweite 4
oder man schiebt die Statusbits raus durch vorzeichenrichtiges rechtsschieben und erhält einen Analogwert x..8191 mit Schrittweite 1

z.B. ADU 14 Bit mit 2 Statusbits in Bit 0 und Bit 1
Code:
Analogwert16 := AnalogRohwert AND 16#FFFC;   // (-32768..)0..32764 mit Schrittweite 4
Analogwert14 := AnalogRohwert / 4;   // (-8192..)0..8191 mit Schrittweite 1
 
Ich habe da auch noch zwei Snippets zu Beispielen mit Schiebebefehlen.
Muss ich hoffentlich nicht näher erklären?

Code:
// DB-Nr. ermitteln
   L     P##DB_ANLAGEN; // BLOCK_DB
   TAR2  ;
   SLD   8; // Bereichskennung eliminieren
   SRD   8;
   +D    ;
   LAR1  ;
   L     W [AR1,P#0.0]; // DB_NR
   T     #DB_NR;

Code:
VAR_TEMP
  MY_ANY                            : ANY;
  X AT MY_ANY:
    STRUCT
      ID                            : BYTE;
      TYP                           : BYTE;
      ANZAHL_TYP                    : INT;
      DB_NR                         : WORD;
      ZEIGER                        : DWORD;
    END_STRUCT;
  BYTE_ADRESSE                      : INT;
END_VAR

// prüfen ob ANY-Pointer im Bereich "DB"
IF SHR(IN:=X.ZEIGER, N:=24) <> 2#10000100 ...    // kein DB

// Byte-Adresse auslesen
BYTE_ADRESSE := WORD_TO_INT(DWORD_TO_WORD(SHR(IN:=X.ZEIGER, N:=3)) AND 16#FFFF);
 
Ich habe da auch noch zwei Snippets zu Beispielen mit Schiebebefehlen.
Muss ich hoffentlich nicht näher erklären?

Code:
// DB-Nr. ermitteln
   L     P##DB_ANLAGEN; // BLOCK_DB
   TAR2  ;
   SLD   8; // Bereichskennung eliminieren
   SRD   8;
   +D    ;
   LAR1  ;
   L     W [AR1,P#0.0]; // DB_NR
   T     #DB_NR;

Code:
VAR_TEMP
  MY_ANY                            : ANY;
  X AT MY_ANY:
    STRUCT
      ID                            : BYTE;
      TYP                           : BYTE;
      ANZAHL_TYP                    : INT;
      DB_NR                         : WORD;
      ZEIGER                        : DWORD;
    END_STRUCT;
  BYTE_ADRESSE                      : INT;
END_VAR

// prüfen ob ANY-Pointer im Bereich "DB"
IF SHR(IN:=X.ZEIGER, N:=24) <> 2#10000100 ...    // kein DB

// Byte-Adresse auslesen
BYTE_ADRESSE := WORD_TO_INT(DWORD_TO_WORD(SHR(IN:=X.ZEIGER, N:=3)) AND 16#FFFF);
ja, für Pointer allgemein kenn ich diese Schieberei. Aber Pointer versuch ich in TIA komplett zu vermeiden...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
ja, für Pointer allgemein kenn ich diese Schieberei. Aber Pointer versuch ich in TIA komplett zu vermeiden...
Rubrik TIA - hatte ich glatt übersehen. Meine Beispiele stammen natürlich aus längst vergangenen Zeiten. Dann halt nur der Vollständigkeit halber.
 
... oder wenn man zum Speicherplatz/größe sparen mehrere (kleine) Zahlenwerte in ein Byte oder Word packt, dann geht das Packen und Entpacken am verständlichsten mit Schiebebefehlen.
z.B.
- S7-Verbindung: TSAP = Rack und Steckplatz des Verbindungspartners
- S7-DATE_AND_TIME-Format: Byte7 enthält die niederwertigste Ziffer der Millisekunden und den Wochentag
- Befehlswords, Statuswords, Konfigwords mancher Profibus-/Profinet-Geräte, z.B. Waagen, FU ...
 
- häufige Aufgabe: zählen, wie viele Bits oder welche Bits in einem ..Word gesetzt sind
- ein bestimmtes Bit in einem Word setzen/rücksetzen, dessen Position als Zahlenwert vorgegeben wird
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ob und wie man die 2 Statusbits entfernt, ist wohl eher eine Geschmacksfrage.
Lässt man die Statusbits einfach drin, behält man eine Ungenauigkeit von weniger als ein LSB des ADU.
Man kann die Statusbits auch einfach ausmaskieren und behält den Analogwert x..32764 mit Schrittweite 4
oder man schiebt die Statusbits raus durch vorzeichenrichtiges rechtsschieben und erhält einen Analogwert x..8191 mit Schrittweite 1

z.B. ADU 14 Bit mit 2 Statusbits in Bit 0 und Bit 1
Code:
Analogwert16 := AnalogRohwert AND 16#FFFC;   // (-32768..)0..32764 mit Schrittweite 4
Analogwert14 := AnalogRohwert / 4;   // (-8192..)0..8191 mit Schrittweite 1
Ja, genau, eher Geschmacksfrage. Aber wenn man die drin lässt, denkt jeder "Halbexperte", der die Rohwerte der Analogkarte sieht (und nicht die Programmierung kennt), dass die Auflösung "stufenlos", also ohne Schrittweite 4, von 0 bis 16383 geht, also 14-Bit-Auflösung ist, und das ist eben irreführend. Die Auflösung ist i.d.R. nur 12-Bit, also 0...4096 ! Da wir die "Rohwerte" bei der Justage mit anzeigen, will ich da keine falschen Erwartungen wecken.
 
Zurück
Oben