Die PID-Regelung wird schon lange in der Industrie verwendet, aber erst seit ein paar Jahren auch in der Arduino-Welt. Bisher gab es dazu nur wenige Bibliotheken und keine grafischen Hilfsmittel. Dieses Projekt füllt die Lücke mit einer praktischen grafischen Benutzeroberfläche (GUI), die das Experimentieren erleichtert.

Es gibt viele Mikrocontroller-Projekte, die PID-Regelungen nutzen, aber die meisten sind nicht ideal für Experimente. Erstens muss der Code jedes Mal neu kompiliert werden, wenn man einen Parameter ändert. Zweitens gibt es oft keine oder nur schlechte Visualisierung des Regelkreises – eine Zoom-Funktion fehlt häufig. Zudem sollte die Anpassung der Benutzeroberfläche einfach sein. Aus diesen Gründen wurde eine Anwendung mit HTML/JavaScript erstellt, die direkt im Internetbrowser läuft. Wenn Sie mit PID-Regelungen nicht ganz vertraut sind, schauen Sie sich den Textkasten „Wie funktioniert ein PID-Regler?“ in diesem Artikel an.
 

Nichts beschreibt das GUI-Tool besser als ein praktisches Beispiel: Wir möchten die Sollposition eines Motors schnell und sanft erreichen. Ein Motor-Encoder gibt uns dabei ständig die aktuelle Position zurück. Wer mehr über das Prinzip eines Regelkreises – bestehend aus Motor und Encoder – erfahren möchte, findet auf dieser Webseite nützliche Informationen. Auch das Elektor-Buch zu diesem Thema bietet eine gute Einführung.

Das Demo-Projekt besteht aus drei Teilen (alle Dateien können unter heruntergeladen werden): 

  • Arduino-Sketch: Berechnet die aktuelle Motorposition aus den Encodersignalen, bedient die PID-Regelung (mithilfe einer PID-Bibliothek für Arduino) und steuert den Motor mit einem externen Motortreiber. Die Motorposition wird kontinuierlich über eine serielle Schnittstelle gesendet, gleichzeitig können Befehle zur Konfiguration der PID-Parameter empfangen werden.
  • Tuning-GUI: Erstellt mit HTML, CSS und JavaScript. Die GUI läuft in jedem Browser mit nativer serieller Schnittstellen-Unterstützung (Chrome, Edge und Opera, nicht jedoch Firefox). Der Code kann mit jedem Editor einfach angepasst werden.
  • Hardware: Arduino Nano, H-Brücken-Motortreiber (L293D) und ein DC-Motor mit Encoder.

Wie funktioniert ein PID-Regler?

Ein PID-Regler ist ein Rückmelde-Regler, der in vielen Regelsystemen eingesetzt wird, um eine gewünschte Ausgangsgröße aufrechtzuerhalten, indem die Eingaben basierend auf dem Fehler zwischen gewünschtem Sollwert und dem tatsächlichen Ist-Wert angepasst werden. PID steht für proportional, integral und differential, die drei Glieder, aus denen der Regelalgorithmus besteht. Diese sollten durch drei Faktoren optimiert werden: stationärer Fehler, transiente Reaktion und Stabilität.

PID controller

Warum sind hier drei Glieder (P, I und D) notwendig? Der proportionale Anteil erhöht den Fehler um den Faktor Kp. Vielleicht denken Sie jetzt, dass ein höherer Kp-Wert eine genauere Regelung bedeutet, aber das hat seine Grenzen. Ein hoher Kp-Wert kann zu Oszillationen führen, da in unserem Fall der Motor nicht schnell genug bremsen kann und das Ziel übersteuert. Mit einem moderaten Kp-Wert wird der Sollwert nicht erreicht (dies nennt man stationären Fehler), da der Fehler klein wird, wenn der Sollwert fast erreicht ist. 

Der integrale Anteil löst das vorherige Problem, indem er alle Fehler summiert. In unserem Fall beträgt die Zykluszeit 1 ms. Das bedeutet, dass selbst die kleinsten Fehler schließlich ausgeglichen werden. Hier ist aber Vorsicht geboten, denn wenn ein System eine Grenze erreicht, kann der Integrationswert unendlich groß werden. 

Der Regelkreis kann weiter optimiert werden, indem der Ableitungsanteil genutzt wird. Hierbei wird die Veränderung des Fehlers über die Zeit betrachtet. Man kann quasi in die Zukunft sehen. Dieser Weg reagiert stark, wenn sich die regelbare Größe plötzlich vom Sollwert entfernt. Er tendiert dazu, das Überschießen und die Einschwingzeit zu reduzieren. Weitere Informationen finden Sie in diesem Buch, PID-basierte digitale Regelungstechnik mit Raspberry Pi und Arduino Uno (Elektor 2022)

Arduino-Sketch

Ein einfaches Befehlsinterface ermöglicht die Einstellung der Parameter. Dabei ist zu beachten, dass zwischen Parameter und Wert ein Leerzeichen eingefügt werden muss. Bild 1 zeigt eine Liste aller verfügbaren Befehle. Alternativ können die Parameter manuell über ein Terminalprogramm gesetzt werden, komfortabler ist jedoch die Nutzung des grafischen Tools, welches dasselbe serielle Befehlsinterface verwendet.

Available commands
Bild 1. Liste der verfügbaren Befehle.

Für die PID-Regelung wird die bewährte Arduino-Bibliothek von Brett Beauregard verwendet. Die Bibliothek PID_v2.h kann über den Bibliotheksverwalter der Arduino-IDE installiert oder von heruntergeladen werden. Eine ausführliche Beschreibung gibt es unter . Die Implementierung eines PID-Reglers ist mit dieser Bibliothek nicht kompliziert, jedoch gibt es einige Punkte zu beachten. Beispielsweise kann es vorkommen, dass die gewünschte Position nicht erreicht wird, weil der Motor mechanisch blockiert ist. In diesem Fall würde die Integralkomponente weiter steigen, was zu einer Überhöhung der nachfolgenden Positionierungen führen kann.

Eine weitere Bibliothek, EEPROM.h, ermöglicht einen einfachen Zugriff auf das EEPROM. Alle Parameter werden in einer Struktur namens Configuration gespeichert. Das erleichtert das Speichern aller Daten im EEPROM. Die maximale Geschwindigkeit wird nur über PWM eingestellt und nicht reguliert. Das Passwort ist notwendig, damit der Sketch erkennt, dass nach einem Reset oder einer Neuprogrammierung des Arduino bereits eine Konfiguration gespeichert wurde. Andernfalls werden die Standardwerte geladen.

Die Konfiguration wird durch einen Reset oder eine Neuprogrammierung des Arduino nicht überschrieben. Wenn eine neue Zielposition festgelegt wird, sendet der Sketch die Encoder-Position über den seriellen Port, bis die Zielposition erreicht ist oder 2000 Proben empfangen wurden.

Tuning-GUI

Die grafische Benutzeroberfläche ist als Webanwendung umgesetzt und läuft im Browser. Sie besteht aus vier Dateien:

  • index.html
  • pid.js
  • serial.js
  • style.css

Die Datei index.html ist verantwortlich für die Struktur. Alle Steuerelemente, Bibliotheken und Links sind ebenfalls hier integriert. Die style.css wird verwendet, um die Webseite zu gestalten, wie zum Beispiel Farbe, Schriftart, Textgröße und so weiter. Die grundlegenden Funktionen der seriellen Kommunikation befinden sich in Serial.js und die Funktionen, die mit dem Arduino kommunizieren, sind in pid.js untergebracht.

Die serielle Kommunikation ist vollständig interrupt-gesteuert, was bedeutet, dass während des Empfangs von Daten keine Informationen verloren gehen, auch wenn gleichzeitig Daten gesendet werden. Weitere Informationen finden Sie in und . Um die GUI zu starten, müssen Sie lediglich auf die Datei index.html doppelklicken. Anschließend muss der richtige Port ausgewählt werden. Dann sind alle Steuerelemente sichtbar, wie im Screenshot von Bild 2 gezeigt.

PID tuning GUI: After a COM port has been selected, all controls become visible.
Bild 2. Nachdem ein COM-Port ausgewählt wurde, werden alle Steuerungen sichtbar

Es ist wichtig, dass sich alle oben genannten Dateien im selben Ordner befinden und dass der verwendete Browser Microsoft Edge, Google Chrome oder Opera ist. Visual Studio Code wurde als Editor gewählt, da er interessante Funktionen bietet, um HTML-Seiten zu erstellen und JavaScript-Code zu schreiben. Zum Beispiel: Die Intellisense-Funktion (Codevervollständigung), automatische Strukturierung und ein lokaler Webbrowser für Test- und Entwicklungszwecke. Sie können Visual Studio Code kostenlos unter herunterladen. Allerdings kann auch jeder andere Editor verwendet werden. Das Debuggen von HTML/JavaScript-Code kann direkt im Browser erfolgen. Die Aktivierung hängt vom verwendeten Browser ab (Microsoft Edge: Ctrl+Shift+I und Google Chrome: Ctrl+Shift+J) Weitere Details finden Sie unter oder . Der Opera-Browser soll ebenfalls die serielle Schnittstelle unterstützen, aber das wurde nicht getestet.

Nachdem Sie die Werte in den Datenfeldern oder Schiebereglern geändert haben, müssen Sie den entsprechenden Send-Button drücken. Solange die Daten nicht gesendet wurden, bleibt der Button rot. Die Parametereinstellungen können auch durch Drücken von Safe Conf im EEPROM des Arduino-Controllers gespeichert werden. Eine gespeicherte Konfiguration kann durch Drücken des Buttons Load Conf abgerufen werden.

Die protokollierten Daten können im .csv-Format exportiert werden. Im Konsolenfenster werden alle seriellen Kommunikationsdaten angezeigt. In den Graphen kann mit der Maus hinein- und herausgezoomt sowie verschoben werden. Die Funktion Autoscale setzt die Grafikeinstellungen zurück. Der Umschalter Add Graph/New Graph (Bild 3) fügt die neuen Daten zu den alten hinzu oder löscht die zuvor gespeicherten Daten. Das Zeitintervall zwischen den Datenpunkten beträgt 1 ms.

PID GUI: Here “Add Graph” is selected, which means that every new position is appended to the old one. Zoom-in via mouse-wheel.
Bild 3. Hier ist Add Graph ausgewählt, was bedeutet, dass jede neue Position an die alte angehängt wird. Mit dem Mausrad hineinzoomen.

Die Grenzen der Zielposition und Parameter können in der Datei index.html geändert werden. Da index.html der Webanwendung verschiedene Verweise auf externe Bibliotheken enthält, ist eine Online-Verbindung erforderlich:

  • Chart.js (JavaScript Open-Source-Diagrammbibliothek)
  • Serial.js (vereinfacht die Nutzung von Web-Serial)

Wenn die Bibliotheken lokal installiert sind, funktioniert es auch offline.

The proportional component is set too high here. The oscillation never ends
Bild 4. Hier ist die proportionale Komponente zu hoch eingestellt. Die Oszillation hört nie auf.

So starten Sie mit der Parametereinstellung

Beginnen Sie mit Kp = 3, Ki = 0 und Kd = 0. Erhöhen Sie dann Kp, bis Sie die gewünschte Stellgröße erreichen. Ein zu hoher Wert in der proportionalen Regelung könnte zu unkontrollierbaren Oszillationen führen, wie in Bild 4 zu sehen. Danach erhöhen Sie Ki, bis Sie den Sollwert ohne (oder nahezu ohne) Überschwinger erreichen. Jetzt erhöhen Sie Kd und stoppen, bevor die Regelkreise zu oszillieren beginnen. Ein genau abgestimmtes System sollte ein Diagramm wie in Bild 5 erzeugen.

Nearly perfect result (with linear system).
Bild 5. Nahezu perfektes Ergebnis (bei linearem System).

Schaltplan

Bild 6 zeigt den Arduino Nano mit allen Verbindungen. JP1 ist für die Spannungsversorgung des Motors zuständig und JP2 ist der Anschluss für den Encoder. Die Höhe der Spannung hängt vom Motor ab und ist aufgrund der H-Bridges auf maximal 36 V begrenzt. Der Strom muss auf etwa 500 mA begrenzt werden, da sonst die H-Brücke (L293D) beschädigt werden könnte. Wenn der Motor beim Positionieren nicht stoppt, sollte die Polarität der Motoranschlüsse umgekehrt werden.

The H-bridge has two supply voltages.
Bild 6. Die H-Brücke hat zwei Versorgungsspannungen, VCC1 (Pin 16)
für die Logik und VCC2 (Pin 8) für die Motorleistung.

Encoder-Anschlüsse

Wenn Sie einen Encoder aus einem alten Tintenstrahldrucker verwenden, ist es normalerweise ganz einfach, die Pinbelegung auf der Platine zu finden. Die breiteste Verbindung ist üblicherweise Masse (oder hat ein thermisches Via), gefolgt von der Betriebsspannung, während die schmalsten die Datenleitungen sind (Bild 7). Eine andere Möglichkeit besteht darin, das Bauteil bei einem Distributor zu suchen oder einfach die Trial-and-Error-Methode anzuwenden.

PID Control article: Backside of a printer PCB (sliding carriage)
Bild 7: Rückseite einer Drucker-Platine (gleitender Wagen).

Typischer Encoder von Agilent/Avago/Broadcom

Bild 8 zeigt den Aufbau eines typischen optischen Encoders. Auf der linken Seite befindet sich eine Infrarot-LED und auf der anderen Seite gibt es zwei Infrarotempfänger. Das Band (im Fall des Schlittenwagens, sehen Sie Bild 9) und das Codierrad, das hinten am Gleichstrommotor montiert ist (Bild 10), haben winzige Streifen darauf, durch die kein Licht hindurchdringen kann. Wenn dieser Streifen oder das Rad das IR-Licht vom Sender blockiert, sehen die Empfänger es nicht.

Example of a typical optical encoder (AEDS-962x)
Bild 8. Beispiel eines typischen optischen Encoders (AEDS-962x) und die Pinbelegung auf der rechten Seite. (Quelle: Agilent AEDS-962x)
Print head assembly with belt, optical tape and optical sensor. The controller on the PCB was removed to avoid potential faults.
Bild 9. Druckkopfmontage mit Riemen, optischem Band und optischem Sensor. Der Controller auf der Platine wurde entfernt, um mögliche Fehler zu vermeiden.
PID control article:  DC-motor with encoder wheel.
Bild 10. Gleichstrommotor mit Encoder-Rad.

Probieren Sie es aus!

Die Erfahrung zeigt, dass es gar nicht so einfach ist, die optimalen Parameter für die verschiedenen Anwendungen zu finden. Die Überschwinger hängen stark vom System selbst (Dämpfung) und auch von der zurückgelegten Strecke ab. Eine Idee hierbei ist, die Parameter abhängig von der Distanz zu ändern. Für weitere Informationen sehen Sie.

Neben dem Ansteuern eines DC-Motors, wie in diesem Artikel beschrieben, können auch BLDC-Motoren betrieben werden. In diesem Fall müssen jedoch die Funktionen pwmOut(), forward() und reverse() an den jeweiligen Motorantrieb angepasst werden. Eine komplexe Bibliothek findet man unter. Diese Bibliothek ermöglicht ebenfalls eine Geschwindigkeitsregelung.


Sie haben Fragen oder Kommentare?

Wenn Sie technische Fragen oder Anmerkungen zu diesem Artikel haben, wenden Sie sich bitte an den Autor unter johannes.sturz@web.de und die Elektor-Redaktion unter redaktion@elektor.de.


Anmerkung der Redaktion: Der Artikel (240274-02) erschien in Elektor Mai/Juni 2025.

Abonnieren
Tag-Benachrichtigung zu PID Controller jetzt abonnieren!