TIA Software UART am Digitalout einer S7-1200 ?

Zuviel Werbung?
-> Hier kostenlos registrieren
Ich habe mal einen kurzen Sonntagstest gemacht um zu prüfen wie schnell und genau sich mit dem Verfahren Signale auswerten lassen. Zum Einsatz kommt eine 1214C DC/DC/Rly mit Firmware 2.2.
Ein Rechtecksignal habe ich auf E0.0 aufgelegt, in der Hardwarekonfiguration ist die kleinstmögliche Filterzeit von 0,2 ms eingestellt.

Testprogramm:
Code:
#n_cycles_lo := 0;
#n_cycles_hi := 0;
#n_edges := 0;

#T_SampleTimeout(IN := false,
                 PT := t#1s);
#T_SampleTimeout(IN := true,
                 PT := t#1s);

WHILE (#T_SampleTimeout.Q = false AND #n_edges < 2) DO
    #RxD_eb := "RxD_eb":P;
    #RxD := #RxD_eb.%X0;
    IF (#RxD AND NOT #RxD_old) THEN
        #n_edges := #n_edges + 1;
    END_IF;
    IF #n_edges >= 1 THEN
        IF (#RxD) THEN
            #n_cycles_hi := #n_cycles_hi + 1;
        ELSE
            #n_cycles_lo := #n_cycles_lo + 1;
        END_IF;
    END_IF;
    #RxD_old := #RxD;
END_WHILE;
// Ergebnisse für Anzeige am HMI
#n_cycles_lo_hmi := #n_cycles_lo;
#n_cycles_hi_hmi := #n_cycles_hi;

Ich habe mir die Zählwerte im DB über eine HMI-Simulation angesehen. Ergebnisse:

Bei 2ms High-Signal auf E0.0 schwankt der Zähler #n_cycles_hi zwischen 12 und 28.
Bei 4ms High-Signal auf E0.0 schwankt der Zähler #n_cycles_hi zwischen 40 und 58.

Bei 4ms ist das Signal gelegentlich für mehrere Sekunden stabil bei 58, dann gibt es für ein paar Sekunden starke Schwankungen und wird dann wieder stabil.

Außer die neuen CPUs sind wesentlich schneller als meine hier, dann sind die anvisierten 9600 bit/s wohl nicht möglich. Auch wenn du nur senden willst, denn das Prinzip bleibt ja gleich.
 
Hallo Thomas,
das Problem bei deinen Test ist vlt die alte Hardware, ab V4.0 lassen sich Filterzeiten
von 0,1 Microsekunden einstellen, da kannst du unter Umständen etwas ganz anderes erreichen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Verzögerungszeiten der Eingänge sind nicht relevant, weil bei der Aufgabe gar keine Eingänge abgefragt werden.

Hier mal meine Sonntags-Überlegungen zu der sehr interessanten Aufgabe, also mein Konzept in Pseudocode:
Code:
**********************************************************
OB1-Task:
**********************************************************
IF SendRequest AND Bytecounter = 0 THEN Bytecounter := 1; //Telegrammausgabe starten

**********************************************************
Weckalarm (z.B. OB30) alle 2ms 
**********************************************************
IF Bytecounter <= 0 THEN RETURN;  //nichts zu senden
IF Bytecounter > messageLen THEN  //Telegrammausgabe fertig
  Bytecounter := 0;
  RETURN;
END_IF;

//Systemzeitgeber/Startzeit abfragen
curr_RUNTIME := RUNTIME(); //ns?

//Bitschalt-Zeitpunkte berechnen:
T0 := curr_RUNTIME - 2 ns + 104167 nS; //Zeitpunkt Bit .0 nach Startbit
T1 := T0 + 104167 nS //Zeitpunkt Bit .1 nach Bit .0
T2 := T1 + 104167 nS
T3 := T2 + 104167 nS
T4 := T3 + 104167 nS
T5 := T4 + 104167 nS
T6 := T5 + 104167 nS
T7 := T6 + 104167 nS //Zeitpunkt Bit .7 nach Bit .6
T8 := T7 + 104167 nS //Zeitpunkt Stopbit nach Bit .7
//(wenn T8 < curr_RUNTIME dann kommt ein Zeitgeber-Überlauf! --> korrigieren!)

//Zeichen aus dem Sendetelegramm
Byte:=message[Bytecounter];

//das Byte bitweise seriell ausgeben
OUT:P := 1;           //Startbit (0) ausgeben
WHILE RUNTIME() < T0; //Bitzeit warten
OUT:P := NOT Byte.0;  //Bit .0 LSB ausgeben
WHILE RUNTIME() < T1; //Bitzeit warten
OUT:P := NOT Byte.1;  //Bit .1 ausgeben
WHILE RUNTIME() < T2;
OUT:P := NOT Byte.2;  //Bit .2 ausgeben
WHILE RUNTIME() < T3;
OUT:P := NOT Byte.3;  //Bit .3 ausgeben
WHILE RUNTIME() < T4;
OUT:P := NOT Byte.4;  //Bit .4 ausgeben
WHILE RUNTIME() < T5;
OUT:P := NOT Byte.5;  //Bit .5 ausgeben
WHILE RUNTIME() < T6;
OUT:P := NOT Byte.6;  //Bit .6 ausgeben
WHILE RUNTIME() < T7;
OUT:P := NOT Byte.7;  //Bit .7 MSB ausgeben
WHILE RUNTIME() < T8;
OUT:P := 0;           //Stopbit (1) ausgeben, Länge Stopbit + Idle wird ca. 1ms

//fertig, 1 Byte serielle Ausgabe komplett, hat knapp 1ms gedauert
//auf nächstes Byte des Telegramms weiterstellen
Bytecounter := Bytecounter + 1;

//das nächste Byte wird im nächsten Weckalarm-Aufruf ausgegeben (ca 1ms nach hier)

Laut technischen Daten der S7-1200 schalten die für PWM nutzbaren Ausgänge Aa.0 bis Aa.3 schneller, vermutlich ist es besser, diese Ausgänge zu benutzen.

Gut ist, daß in dem Schnittstellen-Protokoll zum Sensor eine BCC enthalten ist, so daß der Sensor Fehler bei der Bitserialisierung erkennen kann.


PS: Welche Auflösung hat eigentlich RUNTIME()? Und warum mußte sich Siemens für die S7-1200 sowas umständliches einfallen lassen, statt einfach nur den Zählerstand des Systemtimers (TIME_TCK) zu liefern?

Harald
 
Ich bin gespannt ob das funktioniert. Bei 9600 bit/s dürfte das scharf an der Grenze des möglichen liegen. Bei meiner Auswertung dauert ein Schleifendurchlauf max. 167µs. Der Code bei der Ausgabe ist etwas kürzer, aber bei Runtime() muss je nach Firmware Version der CPU noch ein Überlauf abgefangen werden.
Irgendwo funkt bei der Ausführung noch das Betriebssystem dazwischen, ansonsten würde ich bei meiner Auswertung nicht so große Sprünge sehen. Das fällt bei der Ausgabe über die Zeit zwar nicht so ins Gewicht, aber das Programm muss ja nur für 50µs unterbrochen werden, und schon funktioniert es nicht mehr.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Sag mal Harald was hat es mit den Baustein 'Runtime' auf sich,
im Handbuch von 2014 kann ich den nicht finden. Kann die 1200er
das überhaupt?
Hat mich grad auch gewundert, da er in der Bibliothek auch nicht vorhanden ist. Ich kann den Baustein aber im Programm einfügen.
 
Sag mal Harald was hat es mit den Baustein 'Runtime' auf sich,
im Handbuch von 2014 kann ich den nicht finden. Kann die 1200er
das überhaupt?
Es kann sein, daß es RUNTIME() für die S7-1200 erst seit Ende 2014 gibt. Im S7-1200 Systemhandbuch 2015 ist RUNTIME drinne.

Wie können Sie bei der S7-1200/S7-1500 die Gesamtzykluszeit eines Programms messen?

Nachtrag:
In der Programmiersprachen-Vergleichsliste wird RUNTIME mindestens seit Ende 2014 für die S7-1200 dokumentiert.
Übrigens steht da auf "Seite 3"
Nutzen Sie zur Laufzeitmessung einzelner Anweisungen einen OB Priorität >15. Dadurch verfälscht „online beobachten“ die Laufzeit nicht. Weitere Informationen finden Sie in der Online-Hilfe zu SIMATIC STEP 7. Geben Sie in der Suche
„RUNTIME“ ein.

Harald
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Funktioniert auch bei meiner steinalten CPU mit FW2.2, habs grad reingeladen.
Die Messwerte schwanken bei meiner Erfassung eines Rechtecksignals mit 4ms Hi/lo teilweise um +/- 1 Millisekunde, das ist nicht wirklich brauchbar. Ich weiß aber nicht woran das liegt.
 
Ich bin gespannt ob das funktioniert. Bei 9600 bit/s dürfte das scharf an der Grenze des möglichen liegen.
Ja, da bin ich auch gespannt. Wenn ich eine aktuelle S7-1200 zum rumspielen hätte würde ich es am liebsten sofort ausprobieren. Theoretisch könnte es gerade so funktionieren.

Meine Hoffnung basiert auch darauf, daß ein Weckalarm eine so hohe Priorität hat, daß er nicht oder äußerst selten unterbrochen wird.
Siemens gibt sogar indirekt einen Hinweis, daß OB mit Priorität > 15 wohl nicht durch Kommunikation unterbrochen werden. Welche Prio hat ein Weckalarm? Ist die womöglich sogar einstellbar???

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich habe mein Testprogramm mal in einen Weckalarm OB mit 100 ms Aufrufzyklus verschoben, vorher hatte ich ihn im OB1. Das läuft dann auf jeden Fall wesentlich stabiler.
Bei Rechteck mit 2ms High bekomme ich jetzt konstant zwischen 21..23 Durchläufe. Ich habe aber noch eine Zeitmessung einprogrammiert, und die erfasst zwischen 1,8 und 2,1 ms. Bei längeren Zeiten habe ich nicht so große absolute Schwankungen.

Also scheint wohl die Kommunikation den SPS Zyklus zu unterbrechen. Darum hatte ich mir die Werte vorher auch über ein HMI anzeigen lassen, um nicht die CPU durch das Online-Beobachten zu belasten. Das macht aber keinen Unterschied.
Um definitiv feststellen zu können dass es an der Kommunikation liegt, müsste ich einen Messzyklus ohne Kommunikation starten und dann nachher ablesen. Hab ich aber jetzt keine Lust zu...
 
Ich habe mir die Daten mal kurz ohne Beobachtung durch PG oder HMI in ein Array kopiert.
Wenn das Programm im OB1 Zyklus läuft, habe ich trotzdem zwischendurch immer kleine Ausreißer nach oben. Wenn es im Zeitinterrupt OB30 im 100ms Zyklus läuft, konnte ich das nicht so feststellen. Es scheint zumindest, dass dann auch andere Unterbrechungen verhindert werden, oder es fällt dort bisher nur nicht auf, weil im konstant laufenden OB1 die Wahrscheinlichkeit einer Unterbrechung größer ist.
 
Ich bin ja zu tief beeindruckt, welche Herzblut Programmierer ihr seid.:p
Euch ist aber schon noch bewusst dass ich nur mal gefragt hatte ob das gehen könnte?
Und nicht erwartet habe: „Macht mir das mal“

Großen Dank an euch alle !

Ich finde es schön dass es immer noch Leute gibt, die sich mit einer Problemstellung wirklich auseinandersetzen und nicht gleich sagen „Geht nicht“
DANKE!!


Bei meiner CPU handelt es sich um eine CPU 1215C DC/DC/DC V4.1
Welche Prio hat ein Weckalarm? Ist die womöglich sogar einstellbar???
Priorität ist einstellbar: „Der Wert muss zwischen 2 und 24 liegen“
 
Hallo,
ich habe Antwort vom Hersteller:
Nach dessen Aussage, geht es nicht ohne die A232 Box.
Ich habe eine bestellt zum Testen.
Ich kann das noch nicht glauben, da die Box zu wenig kostet um viel Technik zu enthalten.
Dazu erzähle ich dann mehr wenn ich die Box habe.


Zwei Probleme habe ich im Moment bei dem Nachvollziehen von dem SLC Programm von PN/DP
1. Wie bekomme ich beim Baustein Cyclic Interrupt das „Optimierter Bausteinzugriff“ ausgeschaltet? (der Hacken ist grau und lässt sich nicht abwählen)
2. Wie greife ich auf den aktuellen Zählerstand der Runtime Datentype-> LReal direkt zu um sie in einer WHILE Schleife zu verwenden?

Wenn ich Runtime() so einsetzte:

"DB_1".curr_RUNTIME := RUNTIME("DB_1".Tag_Memory)

Dann steht in { "DB_1".curr_RUNTIME} die Zeit seit dem letzten Aufruf von Runtime()

und im {DB_1".Tag_Memory} der gespeicherte Zeit (also eigendlich die aktuelle) für die nächste Abfrage.

Ständig Runtime() aufzurufen um {DB_1".Tag_Memory} aktualisiert zu bekommen ist einem
Kontinuierlichen Ablauf sicher nicht förderlich .
Ich bin mit SLC noch nicht so vertraut, da die meisten meiner Kunden es mir nicht gestatten oder ungern sehen. Das Prinzip von PN/DP Konzept in Pseudocode habe ich aber verstanden.
Da ist nix mit Bit Gewackel am Ausgang _innerhalb_ eines Zyklus.
Zumindest wackelt bei mir schon mal was ….. wenn auch noch nicht so wies soll ;-)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Nunja, um das was du vorhast zu realisieren, muss genau andere programmiert werden wie eine SPS normalerweise programmiert wird.
Üblicherweise wird ein Ausgang nur einmal pro Zyklus zugewiesen, und vor allem nicht in einem Zyklus innerhalb einer Schleife auf irgendwas gewartet. Aber das geht hier nicht anders.

Pack am besten die komplette Auswertung in einen eigenen FB, und diesen rufst du dann im entsprechenden Interrupt auf. Ohne irgendwelche Global-DBs.
 
Für heute bin ich erstmal zufrieden …..
1 Byte (10bit) schwanken noch zwischen 1,03 – 1,06 ms
Noch keine Erklärung habe ich warum Bit.6 länger ist.
 

Anhänge

  • 1Byte__10Bit.jpg
    1Byte__10Bit.jpg
    506,7 KB · Aufrufe: 42
Zurück
Oben