Das hier ist die Projektseite von einer SPS (in Kleinformat) für die STM32F4 CPU
Damit kann man eine STM32F4-CPU (z.B. vom Discovery-Board) als SPS benutzen.
Die Anpass-Schaltungen für die IO-Pins müssen natürlich extern gemacht werden.
Im Projektfile ist ein TXT-File mit einer kleinen Anleitung und 4 Demo SPS-Programme enthalten. Zum programmieren der SPS kann ein beliebiges Terminal Programm benutzt werden (am einfachsten ist es aber mit meinem UART-Terminal , ab der Version 1.5 gibt es eine Registerkarte für die SPS)
Um ein SPS-Programm dauerhaft im Flash zu speichern, muss es per FileConverter in ein C-File gewandelt werden (ein Beispiel-File ist enthalten)
Version :
V: 1.00 (vom 26.02.2014)
Anleitung :
STM32F4_SPS_V100 (hier eine kurze Anleitung als Text-File)
Beispiele :
AWL_Lauflicht (hier ein “Lauflicht” für das Discovery mit 4 LEDs)
AWL_Monoflop (hier ein “Monoflop” von 1sec für das Discovery mit einer LED)
AWL_Blinklicht (hier ein “Blinklicht” mit 2 LEDs und zwei Timern)
AWL_Analog (hier ein Demo der ADC-Funktion mit 4 LEDs und einem AD-Eingang)
Beschreibung :
Die SPS auf der CPU enthält einen Parser für AWL-Textfiles der einen Bytecode erzeugt und einen Interpreter der diesen in einer Endlosloop ausführt.
(Bis per UART “SPS_STOP” empfangen wird)
Im Flash gespeichert ist schon ein Minimal-Beispiel damit nach dem einschalten der CPU schon was passiert. Mit dem Beispiel kann über den User-Button die grüne LED eingeschaltet werden. Das AWL-Programm dazu sieht so aus :
Beispiel-AWL :
// SPS-Demo 01 [UB 2014] // LED per Taster schalten VAR_INPUT Taster_1 AT PA0 // User-Button END_VAR VAR_OUTPUT LED_GN AT PD12 // Gruene LED END_VAR AWL_START U Taster_1 // Taster einlesen = LED_GN // an LED ausgeben END_AWL
AWL-Befehle :
Die AWL-Befehle sind an die Siemens Step-5 / Step-7 angelehnt.
Kommentare beginnen mit “//” der Parser überspringt dann den Rest der Zeile.
Im Moment werden 36 Befehle unterstützt :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | U : UND UN : UND-NICHT (NAND) O : ODER ON : ODER-NICHT (NOR) X : XOR XN : XNOR U( : UND mit Verzweigung O( : ODER mit Verzweigung X( : XOR mit Verzweigung ) : Ende einer Verzweigung = : Zuweisung R : Reset S : Set NOT : invertiert das VKE SET : setzt das VKE CLR : loescht das VKE FN : trigger auf Flanke negativ FP : trigger auf Flanke positiv == I : Vergleich auf Gleichheit <>I : Vergleich auf Ungleich >I : Vergleich auf Groesser >=I : Vergleich auf GroesserGleich <=I : Vergleich auf KleinerGleich +I : Akku2 + Akku1 -I : Akku2 - Akku1 *I : Akku2 * Akku1 /I : Akku2 / Akku1 L : Load (Konstante oder Variable) in Akku T : Transfer Akku in Variable ZV : Zähler (einen Schritt vorwärts) ZR : Zähler (einen Schritt rückwärts) SI : Timer (Impuls) SV : Timer (Verlängerter Impuls) SE : Timer (Einschaltverzögerung) SS : Timer (Speichernde Einschaltverzögerung) SA : Timer (Ausschaltverzögerung) |
Digital IN/OUT :
Die physikalischen Ein-Ausgänge müssen zu beginn der AWL deklariert werden.
Als GPIO kann theoretisch jeder Pin der CPU benutzt werden PA0 bis PG15
(Rx+Tx sollten frei bleiben !!)
1 2 3 4 5 6 7 | VAR_INPUT Taster1 AT PA0 // Digital Eingang an PA0 END_VAR VAR_OUTPUT LED1 AT PD12 // Digital Ausgang an PD12 END_VAR |
Analog IN :
Analoge Eingänge müssen auch zu Begin der AWL deklariert werden.
(Vorsicht, nicht jeder Pin der CPU ist ein Analog-Eingang)
1 2 3 | VAR_ADC
POTI AT PA1 // Analog-Eingang an PA1
END_VAR |
Merker und Bausteine :
Merker und Bausteine müssen (wie die I/O zu beginn der AWL deklariert werden.
Im Moment werden 4 Typen unterstützt
1 2 3 4 5 6 | VAR Merker1 : BOOL // Variable vom Typ boolean Zahl1 : WORD // 16bit Variable IC1 : COUNTER // 16bit Zähler (2 Modes) IC2 : TIMER // 16bit Timer (5 Modes) END_VAR |
UART :
Zur Verbindung mit dem PC ist eine UART aktiviert
(Tx=PC10, Rx=PC11 mit 115200 Baud 8N1)
Mit einem Terminal-Programm kann ein AWL-File zur SPS gesendet werden
(diese muss zuvor per “SPS_STOP” angehalten werden)
Ich habe mein Terminal-Programm so geändert, das man in der Registerkarte “SPS” direkt ein AWL-File eingeben und per UART zur SPS senden kann.
(zum unterbrechen einer laufenden SPS gibt es einen Button)
Parser :
Wenn der Parser einen Fehler erkennt, liefert er eine Fehlernummer, die Zeilen-Nummer mit dem Fehler und das Token das den Fehler erzeugt hat.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #define AWL_ERR_NO_ERROR 0x00 // alles OK #define AWL_ERR_FILESIZE_0 0x01 // File hat 0 Bytes #define AWL_ERR_NO_ASCII 0x02 // Unerlaubtes Zeichen #define AWL_ERR_TOKEN_LEN 0x03 // Token zu lang #define AWL_ERR_UNKNOWN_TOKEN 0x04 // Token unbekannt #define AWL_ERR_UNKNWON_PORTPIN 0x05 // Portpin unbekannt #define AWL_ERR_UNKNWON_VARTYP 0x06 // Variablentyp unbekannt #define AWL_ERR_AT_MISSING 0x07 // "AT" fehlt #define AWL_ERR_DP_MISSING 0x08 // ":" fehlt #define AWL_ERR_VAR_OUT_MISSING 0x09 // keinen OUT-Pin deklariert #define AWL_ERR_START_MISSING 0x0A // "AWL_START" fehlt #define AWL_ERR_UNKNOWN_VARIABLE 0x0B // unbekannte Variable #define AWL_ERR_FLAG_ERROR 0x0C // Flag error #define AWL_ERR_FILESIZE_MAX 0x0D // File zu gross #define AWL_ERR_OPCODE_MAX 0x0E // max anzahl Opcodes erreicht #define AWL_ERR_VAR_IN_MAX 0x0F // max anzahl VAR_IN erreicht #define AWL_ERR_VAR_OUT_MAX 0x10 // max anzahl VAR_OUT erreicht #define AWL_ERR_VAR_MEM_MAX 0x11 // max anzahl VAR erreicht #define AWL_ERR_VAR_ADC_MAX 0x12 // max anzahl VAR_ADC erreicht #define AWL_ERR_STACK_OVF 0x13 // Stack ueberlauf #define AWL_ERR_STACK_UNF 0x14 // Stack unterlauf #define AWL_ERR_STACK_UNEQUAL 0x15 // Stack != 0 #define AWL_ERR_WRONG_VARTYP 0x16 // unerlaubter Variablentyp |
Interpreter :
Der Interpreter läuft in einer Endlosloop (mit 1ms Zycluszeit) bis er mit einem UART Befehl “SPS_STOP” angehalten wird oder ein Laufzeitfehler auftaucht.
1 2 3 4 5 6 7 8 | #define SPS_ERR_NO_ERROR 0x00 // alles OK #define SPS_ERR_UNKNOWN_OPCODE 0x01 // unbekannter Opcode #define SPS_ERR_STACK_OVF 0x02 // Stack ueberlauf #define SPS_ERR_STACK_UNF 0x03 // Stack unterlauf #define SPS_ERR_UNKNOWN_LIST 0x04 // unbekannte Liste #define SPS_ERR_UNKNOWN_TYP 0x05 // unbekannter Typ #define SPS_ERR_UNKNOWN_PORTPIN 0x06 // Portpin unbekannt #define SPS_ERR_HI_CYCLUS_TIME 0x07 // zu hohe cyclus Zeit |
Hinweis :
Der Parser und Interpreter können nicht alle Fehler abfangen, also mit etwas “bedacht” an das erstellen der AWL gehen
Begrenzungen :
Diese Begrenzungen sind aktiviert :
AWL darf nur aus Ascii-Zeichen (und CarriageReturn, Linefeed) bestehen
Max Länge eines Token : 20 Zeichen
Max Länge eines AWL-Files : 5000 Zeichen
Max Anzahl VAR_INPUT : 20
Max Anzahl VAR_OUTPUT : 20
Max Anzahl VAR_ADC : 16
Max Anzahl VAR : 50
Max Anzahl an Opcodes : 500
Max Stacktiefe bei Verzweigung : 10
Downloads :
Hier der komplette CooCox-Projektordner zum download :
Das PC-Terminal findet ihr hier (unter UART-Terminal) :
Echt cooles Projekt, wenn ich mal wieder Zeit haben sollte werde ich damit mal meinen Sägeautomaten umrüsten. Den hatte ich vor Jahren mit einer billig SPS programmiert und kürzlich erst einen Programmfehler entdeckt den ich aber mangels nicht mehr vorhandenen Software nicht mehr ändern kann.
Hi ich hab eine SPS auf Basis des STM32F427 entwickelt und suche
eigentlich jetzt eine AWL / FUP Software die auf meine Hardware
angepasst werden könnte.
Die Hardware wurde sogar CE zertifiziert.
9 E/A (8 relais ausgänge + 1 NPN 0,5V), CAN, Ethernet, Profibus, RS485,
RS232 alles isoliert, ein Display.
Vielleicht könnten wir ja da eine Synergie bilden?