IOT2000 ohne Shield testen
Bei den ersten Schritten mit der SIMATIC IOT2000 fällt auf, dass beide Sketche sich gleichzeitig im RUN befinden können. Das kann sehr Vorteilhaft sein, wenn die Arbeitsaufteilung stimmt und bedeutet, dass die Programme sich nicht in Konkurrenz befinden dürfen. Also entweder die Pins mit der Arduino- oder der Intel® -Welt programmieren, sonst gibt es einen gemischten Salat ☺.
Absturz beim Test der PLC in Kapitel 9 festgestellt
Die Anwendung der PLC wird in Kapitel 9 vorgestellt. Hier ein Ausschnitt für das Lesen von analogen Werten.
9.2.5 Analogwerte lesen uns skalieren
Hier wurde die Funktion von SCALE aus der FUP-Programmierung verwendet und angepasst. Die
Parameter error und BIPOLAR (Bild 9.11), wurden nicht übernommen. Tritt ein
Fehler auf, z. B. bei falscher Angabe der Grenzen (HI_LIM, LO_LIM), wird der
Analogwert auf 0.0 gesetzt. Die Anwendung negativer Werte findet im
Baustein nicht statt und kann vom Leser gegebenenfalls nachgeholt werden. In
den meisten Fällen ist der negative Wert aus dem Rohwert ein Thema nach der
Skalierung, wenn das bei einem Rohwert von 0-1023 überhaupt sinnvoll ist, da
dieser nicht negativ werden kann.
Im Beispiel wurde plc.Scale
für vier Bereiche skaliert. Jeder Bereich soll einem Ausgang (A0-A3) zugeordnet werden. In Bild
9.11
sind die vier Bereiche (Punkt 1 bis Punkt 4) durch die Schieber optisch
dargestellt (diese haben keine Wirkung auf das Programm) und zeigen wie der
aktuelle Wert (AI0) von 692 sich im
dritten Bereich befindet und deswegen A2 gesetzt
ist.
9.3 Das Absturz-Problem mit C++-Klassen bei der IOT2000
Wenn sie eine Klasse nicht im loop() instanziieren (Bild 9.13),
dann darf die Klasse im Konstruktor keine Systemfunktionen aufrufen.
Wird im Konstruktor einer Klasse eine
Systemfunktion benutzt, wie z. B. Millis(),
dann hängt sich die IOT2000 nach dem Hochladen
auf (Stand Jan. 2017), wenn die Instanz der Klasse global erzeugt wird.
In Bild 9.13
ist das Beispiel der Deklaration aus den Übungen zu sehen. PLC_IOT plc(&ioSim) wird vor dem loop() deklariert. Der Konstruktor initialisiert dabei die PLC und muss unter anderem auch die
Timer zurücksetzen. In der Timerfunktion wird Millis() verwendet. Das würde zu einem Systemabsturz führen, da es Millis() anscheinend noch gar nicht gibt. Aus diesem Grunde wird die Klasse über den Konstruktor keine
Systemfunktionen aufrufen. Diese Absicherung ist im folgenden Bild
9.14
zu sehen.
Hier wird das Attribut inRun
auf false gesetzt bevor der
Konstruktor wirksam wird und somit verhindert, dass die Methode InitPLC() keine Systemfunktionen
anwendet (z. B. beim Timer). InitPLC()
wird danach inRun auf true setzen, damit z. B. Millis() für die Timer im Anwenderprogramm
verwendet werden kann.
Wenn also die Kommunikation zum Simulator
ausfällt (Checksum zählt hoch) dann
haben Sie vielleicht in einem Konstruktor eine Systemfunktion benutzt, obwohl
diese noch nicht instanziiert war und das IOT2000 kennt die Programmanwendung nicht mehr.
Nun können Sie das Problem lösen, indem Sie grundsätzlich keine globalen Deklarationen vornehmen, sondern erst
im loop() deklarieren. Das ist für die Programmierer welche z. B.
mit Singleton arbeiten nicht möglich,
denn diese sind instanziiert, bevor der loop()
beginnt. Je nach Auffassung und Begründung gehen hier die Meinungen
auseinander, aber abstürzen darf eine Hardware mit den besonderen Eigenschaften
der Industrietauglichkeit, nach meiner Meinung nicht.
Übrigens:
Bei einem Test auf dem Arduino-Board UNO mit diesem Problem, konnte kein Absturz festgestellt werden!