Hey! Sie scheinen aus United States zu kommen, möchten Sie auf die Englisch Webseite wechseln?
Switch to Englisch site
Skip to main content

Eine Ampel mit Structured Text und einem RevPi Core 3 steuern

Rev-pi-traffic-lights_6c34ec164c742d5ec27dfa3a3035e7060206633b.jpg

Ein Structured-Text-Programm (SPS) zur Steuerung einer Ampel mit dem RevPi Core 3.

Nachdem ich den RevPi Core 3 und das DIO, wie in einem früheren Post beschrieben, auf einer DIN-Hutschiene montiert und in Betrieb genommen hatte, war ich nun voller Tatendrang und wollte gerne etwas Nützliches damit anstellen. Um die Machbarkeit nachzuweisen, nahm ich mir vor, eine einfache Ampelanlage zu simulieren.

Structured Text (ST)

Es gibt drei Hauptsprachen für SPS-Steuerungsprogramme: Structured Text Language (ST), Ladder Logic und Function Block Diagram (FBD). Die beiden letzteren haben, wie schon ihre Namen nahelegen, eine grafischere Oberfläche, sind jedoch nicht ganz so flexibel wie Structured Text. Außerdem unterstützt die im Lieferumfang des RevPi enthaltene kostenlose Version von logi.CAD 3 nur ST, was mir die Entscheidung abnahm.

Structured Text ist zwar eine standardisierte Sprache nach Industriestandard IEC 61131-3 und der Kern der Sprache bleibt immer gleich, doch jeder SPS-Anbieter hat eigene Varianten und Ergänzungen. Ich habe im Internet ein nützliches Einführungs-Tutorial für die ersten Schritte gefunden. Für alle, die mit Computersprachen vertraut sind: ST ist von PASCAL abgeleitet und erinnert mich an das BASIC, mit dem ich in grauer Vorzeit auf meinem ZX80 Ping-Pong-Spiele programmiert habe.

logi.CAD 3

LogiCAD-PiProgram_b300a7ac9dfe7aee0989ee4e56f1b155b2db7b77.png

Nicht nur die Sprache, sondern auch die Software hatte ich noch nie verwendet. Das logi.CAD 3-Glossar hat mir zur Klärung einiger Begriffe und als Nachschlagewerk sehr geholfen. Insbesondere habe ich mir Folgendes notiert:

  • Objekte – Im Projekt-Explorer von logi.CAD 3 befinden sich die Objekte in Ordnern und sind ihnen untergeordnet. Sie sind mit Dateien in einem Dateisystem vergleichbar.
  • Projekte – Ein Projekt ist ein spezieller Ordnertyp im Projekt-Explorer von logi.CAD 3. Standardmäßig ist das Projekt das Stammverzeichnis im Projekt-Explorer.


Alles zusammen wird als Anwendung bezeichnet und umfasst nicht nur die STL-Datei mit dem von Ihnen geschriebenen Code, sondern auch eine Konfigurationsdatei, globale Variablen und eine spezifische Bibliothek für die von Ihnen verwendete SPS.

Ein paar Mal musste ich feststellen, dass logi.CAD 3 die Anwendung nicht erstellen konnte, obwohl gemeldet wurde, dass die Syntax und alles andere OK war. In diesen Fällen war es hilfreich, das Projekt durch Anklicken der Option „Clean“ (Bereinigen) im Projektmenü zu „bereinigen“ und Logi.CAD 3 die Arbeit machen zu lassen. Danach wurde die Anwendung erfolgreich erstellt und geladen.

Blinkende Lichter

Ich hatte eine einfache Anwendung entwickelt, bei der ein einziges Licht blinkte. Sie beruhte auf dem Beispiel in der Kurzanleitung des RevPi, das ich im vorherigen Blogbeitrag verwendet habe.

PROGRAM RevolutionPiCounterProgram
	VAR
		value 	: BOOL;  
	END_VAR
		
	VAR_EXTERNAL	
		Red_1 : BOOL;
		Amber_2 : BOOL;
		Green_3 : BOOL;
	END_VAR
		
	IF value THEN
		Red_1 := False;
		value := False;
	ELSE
		Red_1 := True; 
		value := True;
	END_IF;
	
END_PROGRAM

In diesem Beispiel blinkt die LED ständig. Dies liegt daran, dass SPS-Anwendungen automatisch wiederholt werden. „End_Program“ bedeutet eigentlich „Zurück zum Anfang und nochmal von vorn“.

Im Tutorial wird das so formuliert: „Wenn die SPS END_PROGRAM erreicht, beginnt der Scan-Zyklus der SPS erneut und das Programm wird wiederholt“:

Verkehrsampel

Rev-pi-traffic-lights2_af54ffec2d5bf3bf5b8520c79aef064f818568a8.jpg

Nun musste ich herausfinden, wie ich erreichen konnte, dass die LEDs in der Reihenfolge einer normalen Ampel blinkten: Rot, Rot und Gelb, Grün, Gelb und dann wieder Rot.

Man kann die Geschwindigkeit ändern, mit der das Licht blinkt, indem man einen Wert in der Konfigurationsdatei bearbeitet. Dadurch ändert sich jedoch die Geschwindigkeit des gesamten Scanzyklus. Das ist primitiv: Es macht einfach die gesamte Anwendung langsamer. Ich wollte die Geschwindigkeit für jede Leuchte einzeln ändern können. Es zeigte sich, dass diese Aufgabe schwieriger war als ursprünglich erwartet.

Die TON-Funktion (Zeitgeberverzögerung) sorgte für die gewünschte Verzögerung, aber mein Code hatte einfach nicht die Wirkung, die ich wollte. Ich konnte eine LED für eine bestimmte Zeit aufleuchten und dann wieder ausgehen lassen, aber dann leuchtete sie kein zweites Mal auf, oder sie blinkte, aber ich konnte nicht festlegen, wie lange sie ausgeschaltet blieb. Ich drehte mich im Kreis und dachte schon, ich hätte mich übernommen – da stieß ich auf der Suche nach Hilfe im Internet auf einen hilfreichen Beitrag im Codesys-Forum, in dem die CASE-Anweisung erwähnt wurde. Codesys ist eine Alternative zu logi.CAD und ich stellte fest, dass es einige Unterschiede in der verwendeten ST-Syntax gibt, aber ich konnte mir eines der Beispiele zunutze machen.

Ich hatte auch im Online-Tutorial etwas über die CASE-Anweisung gelesen, aber erst als ich das Beispiel sah, erkannte ich plötzlich, wie ich sie in der Praxis anwenden konnte.

Dies ist der Code, der dabei am Ende herauskam:

PROGRAM RevolutionPiProgram

	VAR  
	wait : TON; 
	count : INT;
	END_VAR
		
	VAR_EXTERNAL	
		Red_1 : BOOL;
		Amber_2 : BOOL;
		Green_3 : BOOL;
	END_VAR
		
CASE count OF
	0: //init
		count := count + 1;

	1: // Red
   
		Red_1 := True;
		Amber_2 := False;
     	Green_3 := False;
     
		wait(IN:=TRUE, PT:=T#5s);
		
		IF wait.Q THEN
			wait(IN:=FALSE);
			count := count + 1;
		END_IF;

  	 2: // Red and Amber
   		
   		Red_1 := True;
    	Amber_2 := True;
    	Green_3 := False;
     
     	wait(IN:=TRUE, PT:=T#5s);
	
		IF wait.Q THEN
			wait(IN:=FALSE);
			count := count + 1;
		END_IF;

   	3:  // Green

		Red_1 := False;
		Amber_2 := False;
		Green_3 := True;
     
     	wait(IN:=TRUE, PT:=T#5s);
     		
     	IF wait.Q THEN
     		wait(IN:=FALSE);
     		count := count + 1;
     	END_IF;
      
  	 4: // Amber
   
   		Red_1 	:= False;
   		Amber_2 := True;
   		Green_3 := False;
   		
   		wait(IN:=TRUE, PT:=T#5s);
   		
   		IF wait.Q THEN
   			wait(IN:=FALSE);
   			count := count + 1;
   		END_IF;
   		
		ELSE
		count := 0;

END_CASE;

END_PROGRAM


CASE wird verwendet, um eine Anweisung dann auszuführen, wenn ein bestimmter Ganzzahlwert auftritt. In diesem Beispiel wird eine Integer-Variable „count“ erstellt, deren Wert sich bei jedem SPS-Scan um 1 erhöht, bis CASE zum letzten Mal durchlaufen und durch ELSE wieder auf Null gesetzt wird. TON sorgt dafür, dass jede Anweisung 5 Sekunden lang ausgeführt wird. Dies lässt sich ändern, indem man den Wert „5s“ in der folgenden Zeile bearbeitet:

wait(IN:=TRUE, PT:=T#5s);

Bei Bedarf kann jeder Lichtsequenz eine andere Zeitdauer zugewiesen werden (ich habe sie für das Video hier unten alle auf 2 Sekunden gesetzt). Der Code lässt sich auch problemlos erweitern, um weitere Lichter hinzuzufügen.

Fazit

Die Auseinandersetzung mit einer (für mich) neuen Computersprache und unbekannten Software ist immer eine Herausforderung, aber ich bin mit der eleganten Lösung zufrieden, die ich schließlich gefunden habe. Die Ampel, die dabei herausgekommen ist, mag vielleicht nicht im engeren Sinne „straßentauglich“ sein, aber ich habe eine Vorstellung, wie sie sich mit geringem Aufwand so weiterentwickeln lässt, dass sie bei einmaligen Ereignissen wie z. B. Landwirtschaftsmessen oder ähnlichen Anlässen einfache Verkehrssteuerungsaufgaben übernehmen kann.

I have a background in the arts, environmental conservation and IT support. In my spare time I do a bit of DJing and I like making things.