Step 7 RS232 einlesen und CHAR-Bytes als INT umrechnen

Benited

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

ich bin seit einigen Wochen an einem Projekt mit serieller Schnittstelle.
Ich lese und schreibe Daten von/an einen Motorregler (Plettenberg).
Das Senden klappt einwandfrei bis auf vernachlässigbare Kleinigkeiten.
Das Empfangen bereitet mir größere Probleme.

In einer Funktion FC1, welche ich im OB1 aufrufe, habe ich dies erledigt.
Code:
CALL  SFB   61 , DB61      
       EN_R  :=
       R     :=FALSE
       LADDR :=W#16#0
       NDR   :=#ndr
       ERROR :=
       STATUS:=
       RD_1  :=P#DB1.DBX0.0 BYTE 75
       LEN   :=#Len


Receive-Beispiel:
S=5.000V,A=5.000V,PWM= 0,U= 25.7V,I= 0.5A,RPM= 0,con= 24°C,mot= 24°C

(diese Zeile wird fortlaufend im Leerlauf ca. jede Sekunde und im Betrieb ca. 5 mal in der Sekunde neu gesendet.)
75 CHAR + Carriage Return '$R' + Line Feed '$L' = 77 CHAR/BYTEs


Wie man sieht schreibe ich diese emfangenen CHAR's in den DB1.
Dieser besteht nur einem ARRAY[0..76] of CHAR.
Die Länge der empfangenen Daten (#Len) sind 77.

Da ich beim Senden eines CHAR's z.B. einem 's' für serielle Ansteuerung das erste BYTE (hier in dem Fall ein 'S') überschrieben wird,
verschieben sich anschließend alle BYTE's um eine Zeile nach unten im DB1.

Zuerst wollte ich die Länge #Len variabel einstellen lassen um das Verschieben zu kompensieren, allerdings ist das nach meinem SPS Wissenstand zu kompliziert.
Also habe ich die Idee gehabt, eine SCL Quelle zu erstellen, die nach einem bestimmten CHAR sucht. Da es ein CHAR sein sollte, der nur einmal im ARRAY auftaucht, habe ich den Line Feed '$L' verwendet. Das große 'S' ist keine Möglichkeit, da dies überschrieben wird, beim Senden eines CHAR's (siehe oben).

SCL-Quelle:
Code:
FUNCTION FC200 : VOID
CONST
    ANZ := 76;                    // Größe des Arrays
END_CONST
    
VAR_INPUT
    data : ARRAY[0..76] OF CHAR;  // zu durchsuchendes Array
    ptrn : CHAR;                  // zu suchender CHAR
END_VAR


VAR_OUTPUT
    pos : INT;                    // Position, wenn nicht gefunden dann -1
END_VAR


VAR_TEMP
    i : INT;
END_VAR   
   
BEGIN
    pos := -1;
    FOR i := 0 TO ANZ DO
        IF data[i] = ptrn THEN
            pos := i;
            EXIT;
        END_IF;
    END_FOR;
END_FUNCTION

Diese Funktion sollte mir eine INT Dezimalzahl ausgeben, in welchem DB1 DBB der '$l' CHAR steht.
Klappt auch soweit, außer dass mir manchmal eine -1 ausgegeben wird, da der Line Feed nicht gefunden wird. Allerdings wird auch manchmal ein Wert >76 ausgegeben.
z.B. 6987, 6148, ... (habe ich im Fehlerspeicher der SPS entdeckt, als ich mithilfe eines ANY-Pointers ein DBB aufrufen wollte. Geht allerdings nur bis 76!
Fehler:
2018-10-15 15_06_56-Fotos.png
Hat jemand eine Idee wie ich nur Werte zwischen 0...76 ausgeben lassen kann?
Oder weiß jemand wie man dies auf einem anderen Weg lösen kann (Allerdings habe ich nur den Antrieb mit serieller Schnittstelle, ein anderer würde nicht in Frage kommen;))?



Danke für jeden, der mir helfen kann


Beni
 
Zuletzt bearbeitet:
Moin,
so ganz verstanden habe ich dein Problem noch nicht. Aber der Reihe nach. Warum gibst du bei deinem Empfangsbereich 75 Bytes Länge an, wenn du eigentlich laut deinem Text 77 Byte empfangen möchtest?
Code:
CALL  SFB   61 , DB61      
       EN_R  :=
       R     :=FALSE
       LADDR :=W#16#0
       NDR   :=#ndr
       ERROR :=
       STATUS:=
       RD_1  :=P#DB1.DBX0.0 BYTE [COLOR=#ff0000]75 <- Warum?[/COLOR]
       LEN   :=#Len
 
Dann weiter im Text. Werte am besten mal das Error-Bit (ist nur einen Zyklus da) und das Statuswort aus. Ich vermute nämlich, dass dein Empfangen nicht richtig funktioniert.
Wie aktivierst du den SFB61 eigentlich, wenn der Eingang EN_R nicht beschaltet ist?
Und Lässt du deine Suchfunktion auch erst loslaufen, wenn der SFB fertig (NDR) gemeldet hat?
 
Der SFB61 hatte ich zuerst über einen Merker aktiviert, aber er empfängt auch ohne dass der EN_R beschalten ist.
Und nein, daran hab ich noch nicht gedacht, mit dem NDR zu arbeiten.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Der Baustein SFB61 arbeitet azyklisch und macht sehr wahrscheinlich in vielen deiner SPS-Zyklen nix. Erst in dem Moment in dem dein FU seine Daten gesendet hat und auf deiner Seite das NDR-Bit kommt, sind die Daten konsistent übertragen und in deinem DB "gültig". Dann darfst du auch erst deine Suchfunktion lossuchen lassen.
 
Hab mal die Suche und anschließende Auswertung mit NDR aktiviert. Muss der EN_R währenddessen auf FALSE sein? Klappt nämlich auch so, nur dauert die Auswertung ca 2 Sekunden, was aber in meinem Fall egal ist.
 
Muss der EN_R währenddessen auf FALSE sein?
Das weis ich leider nicht - ich würde aber behaupten der darf true bleiben.

Klappt nämlich auch so, nur dauert die Auswertung ca 2 Sekunden, was aber in meinem Fall egal ist.
Welche Auswertung dauert 2 Sekunden? Dauert es zwei Sekunden bis der SFB61 NDR meldet (das wäre ja normal - liegt ja an dem Sendeintervall deines Kommunikationspartners) oder dauert deine Suchfunktion 2 Sekunden??? <- das wäre eher nicht normal ;)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Welche Auswertung dauert 2 Sekunden? Dauert es zwei Sekunden bis der SFB61 NDR meldet (das wäre ja normal - liegt ja an dem Sendeintervall deines Kommunikationspartners) oder dauert deine Suchfunktion 2 Sekunden??? <- das wäre eher nicht normal ;)

Bevor ich meine Suche durch NDR gestartet habe, dauerte es ca 1 Sekunde, bis sich der Inhalt meiner MWs geändert hat.
In den MWs stehen als INT Werte meine BYTE Adressen für die 4 Drehzahlbytes.
Jetzt dauerts ca 2 Sekunden bis sich der Wert ändert.

Aber ich habe jetzt noch ein Problem. Nach ein paar Sekunden ohne irgend ein Übertragen von BYTEs geht die SPS in "Stop" mit dem Fehler: Bereichslängenfehler beim Lesen.
Meine Variable aus der SCL Quelle gibt den INT Wert "9236" aus. Und durch die Auswertung versucht meine SPS z.B. DB1.DBB9236 zu adressieren, was nicht vorhanden ist.
Wie kann ich den SCL Ausgang "pos" auf einen Wert im Bereich 0...76 begrenzen? Habe ich das nicht hiermit gemacht?
Code:
VAR_INPUT
    data : ARRAY[COLOR=#ff0000][0..76][/COLOR] OF CHAR;  // zu durchsuchendes Array
    ptrn : CHAR;                  // zu suchender CHAR
END_VAR
 
Bevor ich meine Suche durch NDR gestartet habe, dauerte es ca 1 Sekunde, bis sich der Inhalt meiner MWs geändert hat.
In den MWs stehen als INT Werte meine BYTE Adressen für die 4 Drehzahlbytes.
Jetzt dauerts ca 2 Sekunden bis sich der Wert ändert.
Wie gesagt, der SFB arbeit azyklisch, kann also durchaus einen Moment brauchen bis er neue Daten bekommen hat. Das liegt natürlich auch an deinem Verbindungspartner. Wenn dieser erst nach 2 Sekunden neue Daten sendet, dann kannst du auch nicht schneller empfangen ;)

Aber ich habe jetzt noch ein Problem. Nach ein paar Sekunden ohne irgend ein Übertragen von BYTEs geht die SPS in "Stop" mit dem Fehler: Bereichslängenfehler beim Lesen.
Meine Variable aus der SCL Quelle gibt den INT Wert "9236" aus. Und durch die Auswertung versucht meine SPS z.B. DB1.DBB9236 zu adressieren, was nicht vorhanden ist.
Wie kann ich den SCL Ausgang "pos" auf einen Wert im Bereich 0...76 begrenzen? Habe ich das nicht hiermit gemacht?
Code:
VAR_INPUT
    data : ARRAY[COLOR=#ff0000][0..76][/COLOR] OF CHAR;  // zu durchsuchendes Array
    ptrn : CHAR;                  // zu suchender CHAR
END_VAR
Deine Array-Grenzen begrenzen zwar den von dir reservierten Datenbereich, aber zugreifen kann eine Funktion natürlich auch in einen nicht mehr reservierten Bereich. Das muss deine For-Schleife verhindern. Außerdem sollte deine Suchfunktion doch überhaupt nicht arbeiten, wenn eh keine neue Daten zu Verfügung stehen? Wenn das NDR-Bit des SFB länger als einen Zyklus ansteht, dann solltest du deine Suchfunktion nur bei positiver Flanke des NDR-Bits einmalig aufrufen und deine Schleife natürlich nur von 0 bis 76 laufen lassen.
 
Deine Array-Grenzen begrenzen zwar den von dir reservierten Datenbereich, aber zugreifen kann eine Funktion natürlich auch in einen nicht mehr reservierten Bereich. Das muss deine For-Schleife verhindern. Außerdem sollte deine Suchfunktion doch überhaupt nicht arbeiten, wenn eh keine neue Daten zu Verfügung stehen? Wenn das NDR-Bit des SFB länger als einen Zyklus ansteht, dann solltest du deine Suchfunktion nur bei positiver Flanke des NDR-Bits einmalig aufrufen und deine Schleife natürlich nur von 0 bis 76 laufen lassen.

In das mit der For-Schleife muss ich mich zwar erst einlesen (habe nur den SCL Baustein nach einer Vorlage aus dem Forum geschrieben:-?), sollte aber hoffentlich kein Problem sein.


Mir ist gerade aufgefallen, das ich meine Ausgabe vom FC200 (Suchfunktion) pos auf das MW100 lege.
Allerdings liegen im MB100 meine Taktmerker :ROFLMAO: (ich Idiot).
Sollte also funktionieren wenn ich den Fehler behebe.
 
Zurück
Oben