Programmierung der Mini-SPS
In Arbeit ....
Programmiert wird die Mini-SPS mit Hilfe der IDE-Vorlage "MyMiniSPS_Template_Version", die in ihrer Struktur nicht verändert werden darf. Also am besten vor der Erstellung eines eigenen Anwenderprogramms die Vorlage gleich einmal unter einem neuen Namen speichern.
Die Vorlage beinhaltet neben dem Haupt-Tab die schon auf der vorherigen Seite genannte Tabs für die Networks (siehe Bild 1). Im Haupt-Tab wird nur meine Library "MyMiniPSP" inkludiert, im setup() wird neben dem Start des Seriellen Monitors die genannte Library mit SPS.init() initialisiert und im loop() die Funktion SPS.cycle() kontinuierlich aufgerufen. Mehr ist hier für die grundsätzliche Funktionalität der Mini-SPS nicht erforderlich.
Bild 1: IDE-Vorlage "MyMiniSPS_Template_Version" mit den erforderlichen Tabs
Alle restlichen Tabs beinhalten nur, nur wie am Beispiel im Bild 2 ersichtlich, die jeweils "leere" Funktion. Hier kann der Anwender nun sein Programm erstellen. Die Funktionen und auch die Denkweise für die Erstellung einer SPS-Anweisungsliste unterscheidet sich etwas von der üblichen Arduino-Programmierung. Z.B. if-Bedingungen oder for- oder while-Schleifen sucht man in einer Anweisungsliste vergeblich. Deshalb möchte ich jetzt einige kleine Programmierbeispiele zeigen, die darstellen sollen, wie eine Anweisungsliste erstellt wird. Für alle die bereits SPS-Erfahrung haben, wird wahrscheinlich einiges bekannt sein.
Bild 2: IDE-Vorlage "MyMiniSPS_Template_Version" am Beispiel des Tab Fast_Network
Alle nachfolgenden Beispiele haben - wenn nicht anders angegeben - den bereits vorgestellten Testaufbau als Basis.
Wie bereits oben geschrieben, verändere ich die IDE-Vorlage "MyMiniSPS_Template_Version" nicht, sondern speichere die Vorlage unter einem neuen Namen "MyMiniSPS_Beispiele_Version" ab.
Beispiel 1:
Aufgabe: Wenn Taster1 (Eingang DIn1) und Taster2 (Eingang DIn2) gleichzeitig gedrückt werden, soll die LED am Ausgang DOut1 leuchten.
Logikplan:
Anweisungsliste im Network_1:
Bild 3: Anweisungsliste Beispiel 1
Das war's! Eine Zeile mit der Anweisung "AND" in der Anweisungsliste im Network_01 reicht aus, um die Aufgabe zu lösen.
Zur Erinnerung: Das Network_01 wird, wie auch die Netzwerke Network_02 bis Network_06, alle 100 ms durchlaufen. In jedem Durchlauf wird der Zustand der Eingänge eingelesen, die Verknüpfungsergebnisse gebildet und danach werden alle Ausgänge geschrieben.
Beispiel 2:
Aufgabe: Erstellung einer Torsteuerung
Bei Betätigung von Taster1 (Befehl Tor auf) beginnt ein Warnlicht (LED) zu blinken, nach 3 Sekunden fährt das Tor auf. Wenn das Tor offen ist (Rückmeldung über Taster2) blinkt das Warnlicht noch 3 Sekunden weiter.
Bei Betätigung von Taster3 (Befehl Tor zu) startet derselbe Vorgang in Zu-Richtung.
Nachfolgend eine Zusammenstellung der verwendeten Ein- bzw. Ausgänge:
- Taster1 (DIn1) = Befehl Tor AUF
- Taster2 (DIn2) = Rückmeldung Tor AUF
- Taster3 (DIn3) = Befehl Tor ZU
- Taster4 (DIn4) = Rückmeldung Tor ZU
- LED (DOut1) = Simulation Motor Richtung AUF
- LED (DOut2) = Simulation Motor Richtung ZU
- LED (DOut3) = Warnlicht
Logikplan zur Torsteuerung:
Anweisungsliste im Network:01:
void Network_1()
{//Beispiel2 Torsteuerung
//Tor oeffnen
NOT(M03, DIn3);
AND(M01, DIn1, M03);
PULSE(PULSE01, DIn3, 200);
SET(SET01, M01, PULSE01.OUT);
T_ON(TIME01, SET01.OUT, 3000);
TRANS(DOut1, TIME01.OUT);
//Tor schließen
NOT(M04, DIn4);
AND(M02, DIn2, M04);
PULSE(PULSE02, DIn4, 200);
SET(SET02, M02, PULSE02.OUT);
T_ON(TIME02, SET02.OUT, 3000);
TRANS(DOut2, TIME02.OUT);
//BlINKLICHT
OR(M05, SET01.OUT, SET02.OUT);
T_OFF(TIME03, M05, 3000);
BLINK(BLINK01, TIME03.OUT, 200);
TRANS(DOut3, BLINK01.OUT);}
Auch hier sieht man, obwohl in der Torsteuerung gleich mehrere zeitabhängige Funktionen im Eingriff sind, nämlich Impulsausgabe (pulse01 und pulse02), Ein- und Ausschaltverzögerungen (time01 - time03) und eine Blinkfunktion (blink01) ist die dafür erforderliche Anweisungsliste recht minimal ausgefallen. Wer Lust hat, kann ja zum Vergleich einen Arduino-Sketch zum Vergleich erstellen.
Leichter lesbar wird die Anweisungsliste, indem man vor dem Network z.B. für Eingänge und Ausgänge, aber auch für Merker oder logische Operatoren Namen definiert:
#define BF_AUF DIn1
#define BF_ZU DIn2
#define RM_AUF DIn3
#define RM_ZU DIn4
#define Motor_Rtg_AUF DOut1
#define Motor_Rtg_ZU DOut2
#define Blinklicht_EIN DOut3
#define AND01 M01
#define AND02 M02
#define NOT01 M03
#define NOT02 M04
#define OR01 M05
void Network_1()
{
//Beispiel Torsteuerung
//Tor oeffnen
NOT(NOT01, RM_AUF);
AND(AND01, BF_AUF, NOT01);
PULSE(PULSE01, RM_AUF, 200);
SET(SET01, AND01, PULSE01.OUT);
T_ON(TIME01, SET01.OUT, 3000);
TRANS(Motor_Rtg_AUF, TIME01.OUT);
//Tor schließen
NOT(NOT02, RM_ZU);
AND(AND02, BF_ZU, NOT02);
PULSE(PULSE02, RM_ZU, 200);
SET(SET02, AND02, PULSE02.OUT);
T_ON(TIME02, SET02.OUT, 3000);
TRANS(Motor_Rtg_ZU, TIME02.OUT);
//BlINKLICHT
OR(OR01, SET01.OUT, SET02.OUT);
T_OFF(TIME03, OR01, 3000);
BLINK(BLINK01, TIME03.OUT, 200);
TRANS(Blinklicht_EIN, BLINK01.OUT);}