Forum: Mikrocontroller und Digitale Elektronik Arduino PLC-ähnlicher Scheduler (ESP32)


von PLCler (Gast)


Lesenswert?

Hallo,

ich benötige für eine Anwendung einen PLC/Ähnliche Programmabarbeitung.
Im Endeffekt will ich mit einer festen Zykluszeit alle Eingänge lesen, 
dann Berechnungen durchführen und als letztes alle Ausgänge schreiben.

Input --> Calculate --> Output

Ihr ahnt es schon: Es geht um etwas zeitkritisches ;).
Bzw. eine Berechnung, die eine feste Zykluszeit erfordert.
Das Ganze soll auf einem ESP32 mit Arduino laufen.

Gibt es sowas schon? (Beispielprojekt?)
Oder gibt es irgendwo Infos wie man sowas am besten implementiert? 
(Artikel, Blog usw.?)

Ein Umsetzung mit RTOS-Funktionen ist aus meiner Sicht nicht notwendig.
Die drei Abschnitte müssen ja komplett durchlaufen und dürfen nicht 
unterbrochen werden. Es muss eher geprüft werden ob es zu einer 
Zeitüberschreitung kommt.

Vielen Dank für konstruktive Antworten.

von Adam P. (adamap)


Lesenswert?

PLCler schrieb:
> Ihr ahnt es schon: Es geht um etwas zeitkritisches ;)

Prinzipiell würde das schon gehen,
aber bei Arduino und loop() wäre ich vorsichtig, da der von Arduino 
verwendete Timer deine loop() unterbricht.

Was ist bei dir zeitkritisch?
Die Verarbeitungszeit wird ja wohl fix sein.

von Cyblord -. (cyblord)


Lesenswert?

PLCler schrieb:
> Input --> Calculate --> Output
>
> Ihr ahnt es schon: Es geht um etwas zeitkritisches ;).

Du musst ja nur sicherstellen dass keiner dieser 3 Schritte länger 
braucht als deine minimal zulässige Zykluszeit.
Dann lässt du diese Routinen über einen Timerinterrupt aufrufen um eine 
gleichmäßige Zeitbasis zu haben.
Und du lässt die Finger von Arduino weil du da nie weißt was dir wie 
reinquatschen kann.

von J. S. (jojos)


Lesenswert?

um welche Zykluszeit geht es denn? Im Millisekundenbereich kann man doch 
durchaus das FreeRTOS benutzen, das ist ja eingebaut.
Dann haben die meisten ESP32 2 Cores, wovon einer für die eigene App 
frei ist. Damit sollte Wifi auch nicht stören, oder wird das 
abgeschaltet?
Und auch Arduino stört nicht wenn die Task eine höhere Prio bekommt als 
das main. Für das EVA sehe ich auch keine 3 Aufgaben, das kann ja eine 
Sequenz sein die nicht aufgeteilt werden muss.

: Bearbeitet durch User
von PLCler (Gast)


Lesenswert?

Danke für die Antworten.

Cyblord -. schrieb:
> Du musst ja nur sicherstellen dass keiner dieser 3 Schritte länger
> braucht als deine minimal zulässige Zykluszeit.
> Dann lässt du diese Routinen über einen Timerinterrupt aufrufen um eine
> gleichmäßige Zeitbasis zu haben.
Das ist tatsächlich eine Idee. Ich habe noch zu sehr im Kopf verankert 
keine langen Programmabschnitte in ISRs zu legen.
Dann muss ich mir aber noch überlegen wie ich abfange, dass sich zwei 
ISR-Aufrufe überschneiden weil die Berechnung zu lange dauert.
Das ist zwar nicht gewünscht aber zur Laufzeit möglich. Eine Warnung und 
kein kompletter Absturz wäre wünschenswert.

J. S. schrieb:
> um welche Zykluszeit geht es denn? Im Millisekundenbereich kann man doch
> durchaus das FreeRTOS benutzen, das ist ja eingebaut.
> Dann haben die meisten ESP32 2 Cores, wovon einer für die eigene App
> frei ist. Damit sollte Wifi auch nicht stören, oder wird das
> abgeschaltet?
> Und auch Arduino stört nicht wenn die Task eine höhere Prio bekommt als
> das main. Für das EVA sehe ich auch keine 3 Aufgaben, das kann ja eine
> Sequenz sein die nicht aufgeteilt werden muss.
Bezüglich dem FreeRTOS habe ich immer die Bedenken, dass ein Task ja 
unterbrochen werden kann. Das will ich ja nicht.
Kann man abfragen ob ein Task unterbrochen wurde? Dann wäre es ja 
möglich eine Warnung auszugeben.

von PLCler (Gast)


Lesenswert?

Bezüglich der Zykluszeit wäre kleiner gleich 20ms das Ziel. Das hängt 
aber eher von der Kommunikation nach außen ab, also die "Ein- und 
Ausgänge". Die Verarbeitung dazwischen ist bei 240Mhz eher unkritisch.

von Adam P. (adamap)


Lesenswert?

PLCler schrieb:
> Ich habe noch zu sehr im Kopf verankert
> keine langen Programmabschnitte in ISRs zu legen.

Das solltest du weiterhin so handhaben.

PLCler schrieb:
> Bezüglich der Zykluszeit wäre kleiner gleich 20ms das Ziel

Das ist ja mehr als eine menge Zeit.

von J. S. (jojos)


Lesenswert?

PLCler schrieb:
> Bezüglich dem FreeRTOS habe ich immer die Bedenken, dass ein Task ja
> unterbrochen werden kann. Das will ich ja nicht.

Wenn es nur eine Task auf dem Core gibt, dann wird auch nicht 
unterbrochen, ausser von Interrupts. Und bei mehreren Task gibt es 
Prioritäten, wichtiges bekommt eben eine hohe Prio.

Sollen keine Werte verloren gehen, schreibt man die in der IO Taksk mit 
der hohen Prio in eine Queue. Die Verarbeitung läuft in einer anderen 
Task und holt in einer while Schleife die Daten aus der Queue. Sind 
keine Daten da, wartet diese Task und kostet keine Zeit. Das 
funktioniert solange die Queue nicht überrant wird, aber da kann man 
Fehler beim schreiben detektieren.

Und einen 240 MHz Xtensa Kern muss man erstmal überlastet bekommen.

von J. S. (jojos)


Lesenswert?

PLCler schrieb:
> Ich habe noch zu sehr im Kopf verankert
> keine langen Programmabschnitte in ISRs zu legen.

und es gibt Funktionen die nicht in einer ISR ausgeführt werden möchten. 
Da ist die Entkopplung durch Threads auch besser.

von PLCler (Gast)


Lesenswert?

J. S. schrieb:
> Wenn es nur eine Task auf dem Core gibt, dann wird auch nicht
> unterbrochen, ausser von Interrupts. Und bei mehreren Task gibt es
> Prioritäten, wichtiges bekommt eben eine hohe Prio.

Dann habe ich da etwas nicht ganz verstanden. Ich dachte immer dass beim 
FreeRTOS mit Round-Robin mit 1ms Taktung die Tasks immer 1ms ausgeführt 
und dann pausiert werden. Und wieder weiter ausgeführt werden sobald sie 
wieder dran sind.

Ich Dachte dass dann sowas herauskommt:
(Task1_T1 entspricht Task1 Teil1)
    1ms      1ms       1ms       1ms   
Task1_T1  Task2_T1  Task1_T2  Task2_T2 
                                       

von J. S. (jojos)


Lesenswert?

ein Task im RTOS wird gestartet und läuft solange du willst. Nicht 
zyklisch, das muss man selber implementieren. Wenn eine Aufgabe in 0,1 
ms erledigt ist, dann kann man sich schlafen legen. Vorher rechnet man 
den nächsten Aktivierungszeitpunkt aus und wartet dann bis man geweckt 
wird.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

PLCler schrieb:
> ich benötige für eine Anwendung einen PLC/Ähnliche Programmabarbeitung.
> Im Endeffekt will ich mit einer festen Zykluszeit alle Eingänge lesen
Genau das passiert bei einer "normalen" SPS nicht. Da wird die 
"Mainloop" immer so schnell wie möglich durchlaufen und damit die 
Zustandsautomaten (aka. Merkerketten) so schnell wie möglich bedient.

Nur "besondere" Eingänge werden per Interrupt abgeholt und bearbeitet 
oder der Mainloop zur Verfügung gestellt.

PLCler schrieb:
> Bezüglich dem FreeRTOS habe ich immer die Bedenken, dass ein Task ja
> unterbrochen werden kann. Das will ich ja nicht.
Wieso nicht? Weil deine Programme so ausgelegt sind, dass immer ein 
kompletter Block durchlaufen werden muss?

Diese ganze "getaktete" Denkweise kommt nur daher, dass sich Menschen 
(und vor allem die programmierenden Menschen) mit "schnellstmöglich" so 
unheimlich schwertun.

Adam P. schrieb:
> PLCler schrieb:
>> Bezüglich der Zykluszeit wäre kleiner gleich 20ms das Ziel
> Das ist ja mehr als eine menge Zeit.
Du hast noch nie eine richtig ausgelastete SPS gesehen...

Adam P. schrieb:
> Die Verarbeitungszeit wird ja wohl fix sein.
Nein, eben das ist niemals der Fall. Denn je nach Zustand der Automaten 
muss ja etwas anderes getan werden. Und "andere Arbeit" dauert eben auch 
unterschiedlich lange.

: Bearbeitet durch Moderator
von Cyblord -. (cyblord)


Lesenswert?

Adam P. schrieb:
> PLCler schrieb:
>> Ich habe noch zu sehr im Kopf verankert
>> keine langen Programmabschnitte in ISRs zu legen.
>
> Das solltest du weiterhin so handhaben.

Immer Zielorientiert bleiben und nicht dogmatisch.

Wenn ein SPS-like Ablauf geplant ist, der sonst durch gar keine anderen 
Interrupts unterbrochen werden kann, spricht nichts dagegen die 
Hauptschleife in einem Timerinterrupt ablaufen zu lassen.
Hier will man ja gar nicht, dass evt. ein anderer Interrupt unterbricht 
und man dann vielleicht die Zykluszeit reißt.

Ansonsten kann man auch einfach die Hauptschleife in der main ansiedeln 
und per Timer Interrupt lediglich ein Flag umschalten wonach die 
Hauptschleife dann einen weiteren Zyklus fährt.

von Stefan F. (Gast)


Lesenswert?

Das letzte Beispiel auf 
http://stefanfrings.de/multithreading_arduino/index.html#exakte zeigt, 
wie man einen klassischen Zustandsautomaten in regelmäßigen festen 
Intervallen ausführt.

Ich würde die Intervalle allerdings variabel halten, solange dazu kein 
wichtiger Grund besteht. Die main Loop kann ja unabhängig davon einen 
Check enthalten, ob ein Task (oder alle zusammen) seine erlaubte Zeit 
überschritten hat und das dann irgendwie melden.

von J. S. (jojos)


Lesenswert?

die Task Aktivierung muss man in FreeRTOS auch nicht mehr selber 
berechnen, das macht vTaskDelayUntil()
https://www.freertos.org/vtaskdelayuntil.html

Wenn das ganze EVA dann in einem Task stattfindet, dann jittert die 
Ausgabe nur um die Varianz der Berechnungszeit. Wenn die Berechnung 
länger als die Zykluszeit dauert, dann würde der Task nach der Ausgabe 
sofort wieder weiterlaufen, was man aber auch abfangen kann.

: Bearbeitet durch User
von Adam P. (adamap)


Lesenswert?

Lothar M. schrieb:
> Adam P. schrieb:
>> PLCler schrieb:
>>> Bezüglich der Zykluszeit wäre kleiner gleich 20ms das Ziel
>> Das ist ja mehr als eine menge Zeit.
> Du hast noch nie eine richtig ausgelastete SPS gesehen...

Doch habe ich.

Lothar M. schrieb:
> Adam P. schrieb:
>> Die Verarbeitungszeit wird ja wohl fix sein.
> Nein, eben das ist niemals der Fall. Denn je nach Zustand der Automaten
> muss ja etwas anderes getan werden. Und "andere Arbeit" dauert eben auch
> unterschiedlich lange.

Jedoch sprach er von ein paar Eingänge lesen.
Habe da nichts von SPS gelesen.

Und sein Vorhaben aus seinem User Namen zu schliessen, naja.

Also wenn es mehr als ein paar I/O sind, dann gebe ich dir natürlich 
recht.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Adam P. schrieb:
> Habe da nichts von SPS gelesen.
PLC ist das englische Wort für SPS:
https://de.wikipedia.org/wiki/Speicherprogrammierbare_Steuerung

> Und sein Vorhaben aus seinem User Namen zu schliessen, naja.
Überschrift? Achtes Wort im ersten Post?

: Bearbeitet durch Moderator
von Adam P. (adamap)


Lesenswert?

Lothar M. schrieb:
> PLC ist das englische Wort für SPS.

Ja, aber er erwähnte "ähnlich" und "nur" ein paar I/O.
Schien mir jetzt nicht so Rechenintensiv, dass man es wie ein SPS OS 
handhaben müsste.

Dazu kam noch "Arduino".

Wie dem aus sei ;)
Wenn es so ist, dann sollte man erstmal drüber nachdenken welche 
Algorithmen man für Berechnung etc. laufen lassen möchte.
Dann worst case Szenario simulieren, dann hätte man zumindest ein 
Anhaltspunkt für die Laufzeit.

: Bearbeitet durch User
von Adam P. (adamap)


Lesenswert?

Lothar M. schrieb:
>> Und sein Vorhaben aus seinem User Namen zu schliessen, naja.
> Überschrift? Achtes Wort im ersten Post?

ja ;) du hast mich.

war vorhin noch auf Arbeit im Code vertieft und irgendwie hab ich es 
überlesen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.