Line Patrol Robot – PID-Steuerung – Android-Einstellungen

Line Patrol Robot – PID-Steuerung – Android-Einstellungen

Original

Der Zweck dieses Projekts besteht darin, einen linienfolgenden Roboter mit PID-Steuerung zu bauen. Wir werden auch ein Android-Gerät verwenden, um die wichtigsten Steuerparameter für eine bessere und schnellere Abstimmung einfach einzustellen. Das im Projekt verwendete Lenkgetriebe kann auch durch MG996 ersetzt werden. Die Einführung des Lenkgetriebes wie MG996 finden Sie hier

Dieses Projekt ist das erste eines komplexen zweiteiligen Projekts, bei dem es mein Ziel ist, das Potenzial von linienfolgenden Robotern zu erkunden. In Teil 2: Maze Solver Robot, Using Artificial Intelligence with Arduino wird der Roboter Labyrinthe mithilfe einfacher Techniken der künstlichen Intelligenz erkunden und lösen.

Schritt 1: Stückliste

Die Liste der benötigten Materialien ist ziemlich einfach:

  • Körper (kann je nach Bedarf angepasst werden):
    • 2 Holzwürfel (80X80mm)
    • 3 Ordner
    • 2 Holzräder (Durchmesser: 50 mm)
    • 1 Rolle
    • 9 Gummibänder
    • 3M-Streifen
    • Kunststoffstecker zur Sensorbefestigung
    • Steckbrett und Verkabelung
  • 2 Sätze Batterien (je 5 V)
  • 2 x SM-S4303R kontinuierlich drehbarer 360-Grad-Servo
  • Arduino Nano
  • HC-06 Bluetooth-Modul
  • 5 Linienverfolgungssensoren (TCRT5000 4-Kanal-Infrarot-Tracking-Tracking-Sensormodul + 1 unabhängiger Spursensor)
  • 1 LED
  • 1 Knopf

Schritt 2: Richten Sie den Motor ein

Fügen Sie hier eine Bildbeschreibung ein

Fügen Sie hier eine Bildbeschreibung ein
Fügen Sie hier eine Bildbeschreibung ein

Fügen Sie hier eine Bildbeschreibung ein
Es wurden 2 Servos mit kontinuierlicher Rotation (SM-S4303R) verwendet. Sie werden zu einem einzigen festen Block „zusammengeklebt“. Diese Servos arbeiten mit einer bestimmten Geschwindigkeit, die durch die Breite der Impulse definiert wird, die ihre Dateneingänge empfangen. Bei diesem Servo liegt die Impulsbreite zwischen 1,0 ms (1.000 Mikrosekunden) und 2,0 ms (2.000 Mikrosekunden). Andere Servos verwenden möglicherweise andere Impulsbreiten.

Überprüfen Sie die Detailinformationen:

  • Der 1,5-ms-Impuls bringt das Servo in die neutrale Position oder „Stopp“.
  • Ein Impuls von 1,0 ms befiehlt dem Servo, mit voller Geschwindigkeit (~70 U/min) in eine Richtung zu fahren
  • Der Vollgeschwindigkeitsimpuls in die entgegengesetzte Richtung beträgt 2,0 ms.
  • Impulse zwischen 1,0 und 1,5 ms oder 1,5 ms und 2,0 ms erzeugen eine proportionale Geschwindigkeit.

Die beiden Servos sind physisch miteinander verbunden. Folgen Sie der oben dargestellten Schaltung, um sie mit Strom zu versorgen (extern 5 V oder 6 V) und versorgen Sie sie mit dem Signal vom Arduino:

  • Linkes Servo: Arduino Pin 5
  • Rechter Servo: Arduino Pin 3

Sobald alles angeschlossen ist, muss als Erstes ein 1,5-ms-Impuls gesendet werden, um zu überprüfen, ob der Motor „gestoppt“ ist (nicht läuft). Wenn nicht, müssen die Servos bis zum Anschlag eingestellt werden (achten Sie auf den gelben Bolzen unter den Servos). HINWEIS: Wenn Ihr Servo nicht über diese physikalische Einstellung verfügt, versuchen Sie, den Parameter „1500“ Mikrosekunden innerhalb der Funktion zu ändern (nach oben oder unten), bis Sie einen vollständigen Stopp erhalten.

Der folgende Arduino-Code erledigt die Aufgabe:

#include <Servo.h> // Servo library 
Servo leftServo;
Servo rightServo;

Void setup()
{
  leftServo.attach(5);
  rightServo.attach(3);
  leftServo.writeMicroseconds(1500);
  rightServo.writeMicroseconds(1500);
}

void loop()
{
}

Schritt 3: Montieren Sie Gehäuse und Motor für den Bewegungstest

Fügen Sie hier eine Bildbeschreibung ein
Fügen Sie hier eine Bildbeschreibung ein
Fügen Sie hier eine Bildbeschreibung ein
Fügen Sie hier eine Bildbeschreibung ein
Fügen Sie hier eine Bildbeschreibung ein
Fügen Sie hier eine Bildbeschreibung ein
Fügen Sie hier eine Bildbeschreibung ein

  1. Befestigen Sie die beiden Servos mit 3M-Streifen an einem der quadratischen Holzstücke.
  2. Befestigen Sie das zweite Holzquadrat mit Klemmklammern am oberen Holz. Passen Sie die Länge der Plattform an Ihre Bedürfnisse an.
  3. Befestigen Sie die Kugelrollen mit Klemmklammern.
  4. Die Stromversorgung der Motoren erfolgt über einen der 5-V-Akkus. Dieser Batteriesatz wird zwischen dem Steckbrett und dem Gehäuserahmen montiert.
  5. Verbinden Sie den verwendeten Akku mit dem Servo: Die linke Seite ist für die Stromversorgung des Servos vorgesehen
  6. Verbinden Sie den Arduino Nano mit dem Steckbrett
  7. Verbinden Sie den GND des Netzteils mit dem Arduino GND.
  8. Servos an Arduino anschließen: links ==> Pin 5; rechts ==> Pin 3
  9. Verbinden Sie die LED mit dem Arduino-Pin 13
  10. Verbinden Sie den Knopf mit Arduino Pin 9

Beachten Sie, dass aufgrund der Montage der Servos (umgekehrt) folgende Geschwindigkeitsbereiche gelten:

  • Vorwärtsgeschwindigkeit des rechten Servos von 1.500us (Stopp) bis 2.000us (volle Geschwindigkeit)
  • Die Vorwärtsgeschwindigkeit des linken Servos wurde von 1.500us (Stopp) auf 1.000us (volle Geschwindigkeit) erhöht.

Zu Signal- und Testzwecken ist an Pin 13 eine externe LED angebracht.

An Pin 9 ist außerdem ein Taster angeschlossen. Diese Schaltfläche ist für Testzwecke und die Inbetriebnahme des Roboters nützlich.

Zum Beispiel:

while(digitalRead(buttonPin)) 
{ 
}
motorTurn (LEFT, 500);
motorTurn (RIGHT, 500);

Beachten Sie, dass die 500 Zeilen, die dem Roboter befehlen, nach links abzubiegen, 2 Millisekunden zu warten und dann nach rechts abzubiegen, erst erfolgen, nachdem Sie die Taste gedrückt haben (buttonPin = 0). Bis dahin stoppt das Programm in einer Endlosschleife.

Der folgende Code kann als Grundlage für einen vollständigen Motortest (vorwärts, rückwärts, Punkt, links abbiegen, rechts abbiegen) verwendet werden. Bei Bedarf müssen Sie die Verzögerung für den gewünschten Drehwinkel entsprechend dem Motor anpassen (außerdem sollten manchmal die linken und rechten Impulswerte leicht unterschiedlich sein, um die mangelnde Motorbalance auszugleichen).

Anhang

Motor_Test.ino herunterladen

Schritt 4: Bluetooth-Modul (optional)

Fügen Sie hier eine Bildbeschreibung ein
Fügen Sie hier eine Bildbeschreibung ein

Das Bluetooth-Modul HC-06 sollte wie abgebildet auf dem Steckbrett montiert werden. Es wird die Arduino-Bibliothek SoftSerial verwendet.

Nachfolgend die HC-06-Pin-Anschlüsse:

  • TX an Arduino Pin 10 (Rx)
  • RX -Pin an Arduino -Pin 11 (Tx)
  • VCC/GND – Arduino 5V/GND

Der Roboter funktioniert mit oder ohne Bluetooth. Der Code ist so aufgebaut, dass der Bot die Standardparameter verwendet, wenn Sie BT nicht aktivieren. Wenn Sie also den HC-06-Mod nicht installieren möchten, machen Sie sich keine Sorgen, der Code funktioniert trotzdem einwandfrei. Im letzten Teil dieses Tutorials werde ich untersuchen, wie man eine Android-App zum Senden von Daten verwendet, um Roboterparameter besser abzustimmen und/oder den Roboter im manuellen Modus zu bewegen. Wenn zum Beispiel jemand mehr Rennen mit linienfolgenden Bots erkunden möchte, würde ich die Verwendung von Bluetooth und der App als optionale Option belassen.

Schritt 5: Hinzufügen von Linienverfolgungssensoren

Fügen Sie hier eine Bildbeschreibung ein
Fügen Sie hier eine Bildbeschreibung ein
Fügen Sie hier eine Bildbeschreibung ein
Fügen Sie hier eine Bildbeschreibung ein
Fügen Sie hier eine Bildbeschreibung ein

Fügen Sie hier eine Bildbeschreibung ein
Fügen Sie hier eine Bildbeschreibung ein
Fügen Sie hier eine Bildbeschreibung ein
Fügen Sie hier eine Bildbeschreibung ein
Fügen Sie hier eine Bildbeschreibung ein

  1. Befestigen Sie die 5 Sensoren wie auf dem Foto gezeigt am Kunststoffstreifen
  2. Es wird empfohlen, den Sensor zum Testen zu kennzeichnen. Sensornamen von „0“ (weiter links) bis „4“ (weiter rechts)
  3. Legen Sie die Kabel unter den Rahmen und befestigen Sie sie mit dem Gummiband (nicht zu verwechseln mit den Rädern oder Rollen).
  4. Verbinden Sie die Kabel wie gezeigt mit den Arduino-Pins:
    • Sensor0 = 12
    • Sensor 1 = 18
    • Sensor 2 = 17
    • Sensor 3 = 16
    • Sensor 4 = 19
  5. Ein zweiter Satz 5-V-Batterien und verbinden Sie ihn mit dem Arduino Vin.

In meinem Fall verwende ich ein Modul, das 4 Sensoren + 1 zusätzlichen Sensor integriert. All dies ist kompatibel. Der Einfachheit halber habe ich im Diagramm fünf separate, miteinander verbundene Sensoren eingefügt. Das Endergebnis ist für beide Konfigurationen das gleiche.

Schritt 6: IR-Sensorlogik

Fügen Sie hier eine Bildbeschreibung ein

Der Infrarotsensor besteht aus einer einzelnen Infrarot-LED und einer Infrarot-Fotodiode. Infrarotlicht von der LED beleuchtet die Oberfläche und wird zur Infrarot-Fotodiode zurückreflektiert. Die Fotodiode erzeugt dann eine Ausgangsspannung proportional zum Reflexionsgrad der Oberfläche (höhere Werte für „helle Oberflächen“ und niedrigere Werte für „schwarze/dunkle Oberflächen“).
Fügen Sie hier eine Bildbeschreibung ein

Der integrierte Schaltkreis auf dem Sensormodul erzeugt als Ausgang ein einfaches digitales Signal (high: dunkel; low: hell). Ein am Modul montiertes Potentiometer (siehe Bild) stellt die richtige Lichtstärke ein, die als „dunkel“ oder „hell“ angezeigt wird. Die Funktionsweise besteht darin, dass es an seinem Ausgang einen hohen digitalen Pegel („1“) erzeugt, wenn die reflektierte Lichtfarbe schwarz/dunkel ist, und einen niedrigen Pegel („0“) für eine andere hellere Farbe.
Fügen Sie hier eine Bildbeschreibung ein
Ich habe hier ein integriertes Modul mit 4 Sensoren und ein zusätzliches Modul mit einem einzigartigen Sensor (andere Form, aber gleiche Logik) verwendet. Wie unten erläutert, besteht die Kombination aus einer Reihe von 5 Sensoren, die meiner Meinung nach eine schöne und reibungslose Steuerung ermöglichen.
Fügen Sie hier eine Bildbeschreibung ein
Fügen Sie hier eine Bildbeschreibung ein
Das 5-Sensor-Array ist so montiert, dass, wenn nur ein Sensor relativ zur schwarzen Linie zentriert ist, nur dieser Sensor HIGH erzeugt. Andererseits sollte der Abstand zwischen den Sensoren so berechnet werden, dass beide Sensoren gleichzeitig die gesamte Breite der schwarzen Linie abdecken können, wodurch ebenfalls hohe Pegel auf beiden Sensoren erzeugt werden (siehe Abbildung oben).

Mögliche Sensorarray-Ausgaben beim Verfolgen einer Linie sind:

  • 0 0 0 0 1
  • 0 0 0 1 1
  • 0 0 0 1 0
  • 0 0 1 1 0
  • 0 0 1 0 0
  • 0 1 1 0 0
  • 0 1 0 0 0
  • 1 1 0 0 0
  • 1 0 0 0 0

Mit 5 Sensoren kann eine „Fehlervariable“ generiert werden, die dabei hilft, die Position des Roboters auf der Produktionslinie zu steuern, wie im Bild unten gezeigt.

Denken wir darüber nach, der beste Zustand ist, wenn der Roboter zentriert ist und die Linie knapp unter dem „mittleren Sensor“ (Sensor 2) liegt. Die Ausgabe des Arrays wird sein: 0 0 1 0 0, in diesem Fall ist „error“ „null“. Wenn der Roboter anfängt, nach links zu fahren (die Linie „scheint sich nach rechts zu bewegen“), muss der Fehler mit zunehmendem positiven Signal zunehmen. Wenn der Roboter anfängt, sich nach rechts zu bewegen (die „Linie“ scheint sich nach links zu bewegen“), muss der Fehler in gleicher Weise zunehmen, jedoch jetzt mit einem negativen Signal.

Die mit dem Sensorzustand verbundene Fehlervariable ist:

  • 0 0 0 0 1 ==> Fehler = 4
  • 0 0 0 1 1 ==> Fehler = 3
  • 0 0 0 1 0 ==> Fehler = 2
  • 0 0 1 1 0 ==> Fehler = 1
  • 0 0 1 0 0 ==> Fehler = 0
  • 0 1 1 0 0 ==> Fehler = -1
  • 0 1 0 0 0 ==> Fehler = -2
  • 1 1 0 0 0 ==> Fehler = -3
  • 1 0 0 0 0 ==> Fehler = -4

Betrachtet man den Arduino-Code, wird jeder Sensor mit einem bestimmten Namen definiert (der Zeile links nach dem Sensor wird die Bezeichnung „0“ zugewiesen):

const int lineFollowSensor0 = 12;
const int lineFollowSensor1 = 18;
const int lineFollowSensor2 = 17;
const int lineFollowSensor3 = 16;
const int lineFollowSensor4 = 19;

Um den Wert jedes Sensors zu speichern, wird eine Array-Variable erstellt:

int LFSensor[5]={0, 0, 0, 0, 0};

Jede Position des Arrays wird kontinuierlich mit der Ausgabe jedes Sensors aktualisiert:

LFSensor[0] = digitalRead(lineFollowSensor0);
LFSensor[1] = digitalRead(lineFollowSensor1);
LFSensor[2] = digitalRead(lineFollowSensor2);
LFSensor[3] = digitalRead(lineFollowSensor3);
LFSensor[4] = digitalRead(lineFollowSensor4);

Mit dem Wert jedes Sensors muss eine Logik implementiert werden, um die Fehlervariable zu generieren:

if((LFSensor[0]== 0 )&&(LFSensor[1]== 0 )&&(LFSensor[2]== 0 )&&(LFSensor[3]== 0 )&&(LFSensor[4]== 1 )) error = 4;

else if((LFSensor[0]== 0 )&&(LFSensor[1]== 0 )&&(LFSensor[2]== 0 )&&(LFSensor[3]== 1 )&&(LFSensor[4]== 1 )) error = 3; 

else if((LFSensor[0]== 0 )&&(LFSensor[1]== 0 )&&(LFSensor[2]== 0 )&&(LFSensor[3]== 1 )&&(LFSensor[4]== 0 )) error = 2;

else if((LFSensor[0]== 0 )&&(LFSensor[1]== 0 )&&(LFSensor[2]== 1 )&&(LFSensor[3]== 1 )&&(LFSensor[4]== 0 )) error = 1;

else if((LFSensor[0]== 0 )&&(LFSensor[1]== 0 )&&(LFSensor[2]== 1 )&&(LFSensor[3]== 0 )&&(LFSensor[4]== 0 )) error = 0;

else if((LFSensor[0]== 0 )&&(LFSensor[1]== 1 )&&(LFSensor[2]== 1 )&&(LFSensor[3]== 0 )&&(LFSensor[4]== 0 )) error =- 1;

else if((LFSensor[0]== 0 )&&(LFSensor[1]== 1 )&&(LFSensor[2]== 0 )&&(LFSensor[3]== 0 )&&(LFSensor[4]== 0 )) error = -2;

else if((LFSensor[0]== 1 )&&(LFSensor[1]== 1 )&&(LFSensor[2]== 0 )&&(LFSensor[3]== 0 )&&(LFSensor[4]== 0 )) error = -3;

else if((LFSensor[0]== 1 )&&(LFSensor[1]== 0 )&&(LFSensor[2]== 0 )&&(LFSensor[3]== 0 )&&(LFSensor[4]== 0 )) error = -4;

Schritt 7: Steuerrichtung (Proportionalsteuerung – P)

Fügen Sie hier eine Bildbeschreibung ein

Zu diesem Zeitpunkt ist unser Roboter zusammengebaut und läuft. Sie sollten einige grundlegende Tests am Motor durchführen, den Ausgang des Sensors ablesen und ihn mit einem Kabel testen. Was fehlt, ist das eigentliche „Gehirn“, der erste Schritt zur „künstlichen Intelligenz“. Wir werden eine Steuerlogik implementieren, die garantiert, dass der Roboter der Linie folgt.

Einfache Proportionalsteuerung:

Unter der Annahme, dass der Roboter auf einer Linie läuft, lautet die Ausgabe des Sensorarrays: 0 01 0 0. Der entsprechende Fehler ist „0“. In diesem Fall sollten beide Motoren mit konstanter Geschwindigkeit vorwärts laufen.

Zum Beispiel:

Definieren Sie Variablen: iniMotorSpeed = 250;Stellen Sie 1,250usdie Impulse dar, die das linke Servo empfängt, und 1,750usdie Impulse, die das rechte Servo empfängt. Mit diesen Parametern bewegt sich der Roboter mit halber Geschwindigkeit vorwärts. Denken Sie daran, dass die Impulslänge für die Vorwärtsgeschwindigkeit des rechten Servos von 1,500us(Stopp) bis 2,000us(volle Geschwindigkeit) und die des linken Servos von 1,500us(Stopp) bis 1,000us(volle Geschwindigkeit) reicht.

rightServo.writeMicroseconds(1500 + iniMotorPower);
leftServo.writeMicroseconds(1500 - iniMotorPower);

Angenommen, der Roboter fährt nach links (wie „LINE fährt nach rechts“) und deckt Sensor 3 ab. Die Array-Ausgabe lautet: 0 0 1 1 0, error = 1. In diesem Fall müssen Sie den Roboter nach rechts drehen. Dazu muss man die Geschwindigkeit des rechten Servos reduzieren, also die Länge der Impulse verkürzen. Außerdem muss die Geschwindigkeit des linken Servos erhöht werden, was bedeutet, dass die Länge der Impulse des linken Servos verringert wird. Dazu müssen wir die Motorsteuerungsfunktion ändern:

rightServo.writeMicroseconds(1500 + iniMotorPower - error); ==> Positive error: decrease velocity
leftServo.writeMicroseconds(1500 - iniMotorPower - error); ==> Positive error: increase velocity

Die obige Logik ist korrekt und es ist leicht zu verstehen, dass das Addieren oder Subtrahieren von „1“ Mikrosekunde zur Impulslänge nicht in Echtzeit zu der gewünschten Korrektur führt. Intuitiv sollten die zu addierenden oder zu subtrahierenden Zahlen größer sein, beispielsweise 50, 100 usw. Um dies zu erhalten, muss der „Fehler“ mit einer Konstante multipliziert werden (nennen wir ihn „K“). Sobald die Wirkung dieser Konstante proportional zum Fehler ist, nennen wir sie „Proportionalitätskonstante: Kp“ .

Die motorische Funktion wird sein:

int Kp = 50;
rightServo.writeMicroseconds(1500 + iniMotorPower - Kp*error);
leftServo.writeMicroseconds(1500 - iniMotorPower - Kp*error);

Wir können wiederherstellen, was mit dem Motor passieren würde, wie im Bild unten gezeigt:

  • Sensoranordnung: 0 0 1 0 0 ==> error = 0 ==> 右伺服脉冲长度 = 1,750us ==> 左舵机脉冲长度 = 1,250us(beide Motorgeschwindigkeiten sind gleich)
  • Sensorarray: 0 0 1 1 0 ==> error = 1 ==> 右舵机脉冲长度 = 1,700us(较慢)==> 左舵机脉冲长度 = 1,200us(schneller)

Wenn die Situation umgekehrt wäre und der Roboter nach rechts gefahren würde, wäre der Fehler „negativ“ und die Geschwindigkeit des Servos sollte sich ändern:

  • Sensoranordnung: 0 0 1 0 0 ==>error = 0 ==> 右伺服脉冲长度 = 1,750us ==> 左舵机脉冲长度 = 1,250us(beide Motorgeschwindigkeiten sind gleich)
  • Sensorarray: 0 1 1 0 0 ==> error = -1 ==> 右舵机脉冲长度 = 1,800us(更快)==> 左舵机脉冲长度 = 1,300us(langsamer)

An diesem Punkt ist klar, dass der Roboter zur Seite getrieben wird, je größer der Fehler, desto schneller muss er in die Mitte zurückkehren. Die Reaktionsgeschwindigkeit des Roboters auf den Fehler ist proportional dazu. Dies wird als „Proportionalsteuerung“ bezeichnet, die „P“-Komponente der komplexeren Steuerung PDI (Proportional, Derivative, Integral).

Schritt 8: PID-Steuerung (optional)

Fügen Sie hier eine Bildbeschreibung ein

Fügen Sie hier eine Bildbeschreibung ein

Fügen Sie hier eine Bildbeschreibung ein

Wenn Sie diesen Teil überspringen möchten, ist das auch kein Problem. Sie können weiterhin die im letzten Schritt erläuterte Proportionalsteuerung verwenden oder mit etwas Köpfchen ein komplexeres Steuerungssystem in Ihren Roboter implementieren. Machen wir weiter!

PID (Proportional, Derivativ und Integral) ist eines der gebräuchlichsten Regelungsschemata. Die meisten industriellen Regelkreise nutzen irgendeine Form der PID-Regelung. Es gibt viele Möglichkeiten, einen PID-Regelkreis abzustimmen, einschließlich der in diesem Beispiel verwendeten manuellen Technik.

Stellen Sie sich PID als eine einfache Feder vor. Eine Feder hat eine ursprüngliche Länge und neigt dazu, bei Störungen durch Ausdehnung oder Kontraktion in kürzester Zeit auf ihre ursprüngliche Länge zurückzukehren. In ähnlicher Weise verfügt ein PID-Algorithmus in einem System über einen festgelegten Wert für eine bestimmte zu steuernde physikalische Größe, einen sogenannten „Sollwert“, und wenn sich dieser aus irgendeinem Grund ändert, steuert das System die anderen notwendigen Funktionen darin, um den gewünschten Wert zu erreichen in kürzester Zeit. Zeit, um zum ursprünglichen Sollwert zurückzukehren. PID-Regler werden überall dort eingesetzt, wo eine physikalische Größe geregelt und einem vorgegebenen Wert angeglichen werden muss. Zum Beispiel Tempomaten, Robotik, Thermostate, Spannungsregler usw.

Wie funktionieren PIDs?

Das System berechnet den „Fehler“ oder die „Abweichung“ einer physikalischen Größe von einem Sollwert, indem es ihren aktuellen Wert mit einem Sensor misst. Um wieder zum Sollwert zu gelangen, sollte dieser „Fehler“ minimiert werden und im Idealfall gleich Null sein. Außerdem sollte dieser Vorgang so schnell wie möglich erfolgen. Idealerweise sollte das System mit einer Hysterese von Null auf Änderungen seines Sollwerts reagieren.

Weitere Informationen finden Sie in vielen Büchern und auf Websites, unter anderem hier :

PID implementieren

  1. Fehlerelement (e):

Dies entspricht der Differenz zwischen dem Sollwert und dem aktuellen Wert der Regelgröße.

error = set_point – current_value(in unserem Fall wird die Fehlervariable von der Position des Roboters auf der Linie übernommen)

  1. Proportionaler Term (P):

Dieses Element ist proportional zum Fehler.

P = Fehler

Dieser Wert ist für das Ausmaß der Änderung der physikalischen Größe verantwortlich, die zum Erreichen des Sollwerts erforderlich ist. Der Proportionalanteil bestimmt die Anstiegszeit oder Geschwindigkeit des Regelkreises, um den Sollwert zu erreichen.

  1. Integraler Artikel (I):

Dieser Term ist die Summe aller vorherigen Fehlerwerte.

I = I + Fehler

Dieser Wert ist für die schnelle Reaktion des Systems auf Sollwertänderungen verantwortlich. Der Integralterm wird verwendet, um den stationären Fehler zu eliminieren, der durch den Proportionalterm erforderlich ist. Im Allgemeinen werden Integralterme für kleine Roboter nicht verwendet, da uns der stationäre Fehler egal ist und dies die „Schleifenabstimmung“ erschweren würde.

  1. Differential- oder Ableitungsterm (D):

Dieser Term ist die Differenz zwischen dem momentanen Fehler des Sollwerts und dem Fehler zum vorherigen Zeitpunkt.

D = Fehler – previousError

Dieser Wert ist dafür verantwortlich, dass sich die Änderungsrate der physikalischen Größe verlangsamt, wenn sie sich dem Sollwert nähert. Ableitungen werden verwendet, um ein Überschwingen oder den Grad der „Übersteuerung“ des Systems zu reduzieren.

Gleichung:

PIDvalue = (Kp*P) + (Ki*I) + (Kd*D)

In:

  • Kp ist eine Konstante, mit der das Ausmaß der Änderung variiert wird , die zum Erreichen des Sollwerts erforderlich ist .
  • Ki ist eine Konstante , mit der die Geschwindigkeit variiert wird, mit der sich eine physikalische Größe ändert, um einen Sollwert zu erreichen .
  • Kd ist eine Konstante, mit der die Stabilität des Systems variiert wird .

Eine Möglichkeit, die Schleife zu optimieren, besteht darin, die vorläufige Fehlermethode auszuprobieren :

  1. Setzen Sie die Kd-Variable auf 0 und passen Sie zunächst den Kp-Term individuell an. In unserem Fall ist Kp = 25 ein guter Ausgangspunkt. Am Ende haben wir es verwendet Kp=50und es hat mit meinem Roboter gut funktioniert.
  2. Erhöhen Sie diesen Wert, wenn der Roboter zu langsam reagiert.
  3. Verringern Sie diesen Wert, wenn der Roboter schnell reagiert und instabil wird.
  4. Sobald der Roboter angemessen reagiert, optimieren Sie den Ableitungsteil ( Kd ) des Regelkreises. Stellen Sie zunächst die Kp- und Kd-Werte jeweils auf $\frac{1}{2}$ des Kp-Werts ein. Wenn der Roboter beispielsweise angemessen mit Kp = 50 reagiert, stellen Sie für den Start Kp = 25 und Kd = 25 ein. Erhöhen Sie die Kd-Verstärkung (Ableitung), um das Überschwingen zu reduzieren und das Überschwingen zu reduzieren, wenn der Roboter instabil wird.

Ein weiterer zu berücksichtigender Teil ist die tatsächliche Sample-/Loop-Rate . Eine Beschleunigung oder Verlangsamung dieses Parameters kann die Leistung des Roboters erheblich beeinträchtigen. Dies wird durch die Anweisung im Code delayfestgelegt . Dies ist ein heuristischer Ansatz, bei dem mit Fehlern versucht wird, die besten Ergebnisse zu erzielen.

Realisieren Sie basierend auf der obigen Methode die PID-Funktion:

void calculatePID()
{
  P = error;
  I = I + error;
  D = error-previousError;
  PIDvalue = (Kp*P) + (Ki*I) + (Kd*D);
  previousError = error;
}

Die im letzten Schritt verwendete einfache Kp-Konstante wird durch diesen vollständigeren PID-Wert ersetzt:

void motorPIDcontrol()
{
  int leftMotorSpeed = 1500 - iniMotorPower - PIDvalue;
  int rightMotorSpeed = 1500 + iniMotorPower - PIDvalue;
  
  leftServo.writeMicroseconds(leftMotorSpeed);
  rightServo.writeMicroseconds(rightMotorSpeed);
}

Beachten Sie jedoch, dass bei Kd und Ki = 0 der PID-Wert nur verwendet wirdKp*error

Schritt 9: Endgültiger Code

Fügen Sie hier eine Bildbeschreibung ein

Fügen Sie hier eine Bildbeschreibung ein

In diesem Schritt kann der Roboter einer konstanten Schleife folgen und diese ohne Anhalten abschließen.

Das Schleifenprogramm wird sein:

void loop ()
{
  readLFSsensors(); // read sensors, storage values at Sensor Array and calculate "error"
  calculatePID(); 
  motorPIDcontrol();
}

Für eine vollständigere und praktischere Bedienung müssen jedoch mindestens einige grundlegende Befehle für die Drahtbewegung hinzugefügt werden. Lassen Sie uns eine neue Variable einführen: „mode“. Wir werden 3 Zustände für diese Variable definieren:

Modell:

- #define STOPPED  0
- #define FOLLOWING_LINE 1
- #define NO_LINE 2

Wenn alle Sensoren eine schwarze Linie finden, lautet die Ausgabe des Sensorarrays: 1 1 1 1 1. In diesem Fall können wir den Modus als „STOPPED“ definieren und der Roboter sollte einen „Vollstopp“ durchführen.

if((LFSensor[0]== 1 )&&(LFSensor[1]== 1 )&&(LFSensor[2]== 1 )&&(LFSensor[3]== 1 )&&(LFSensor[4]== 1 )) 
{ 
  mode = STOPPED;
}

Andere häufige Situationen für einen linienfolgenden Roboter sind, wenn er eine „drahtlose“ oder Sensor-Array-Ausgabe findet als: 0 0 0 0 0. In diesem Fall können wir es so programmieren, dass es sich um 180 Grad oder in einem kleinen Winkel zurückdreht, bis es eine Linie findet und wieder zu den normalen Linienbedingungen zurückkehrt.

else if((LFSensor[0]== 0 )&&(LFSensor[1]== 0 )&&(LFSensor[2]== 0 )&&(LFSensor[3]== 0 )&&(LFSensor[4]== 0 )) 
{ 
  mode = NO_LINE;
}

Das Ganze loop()wird sein:

void loop() 
{
  readLFSsensors();
  switch (mode)
  {
    case STOPPED:
       motorStop();
       break;
    case NO_LINE:
       motorStop();
       motorTurn(LEFT, 180);
       break;
    case FOLLOWING_LINE:
       calculatePID();
       motorPIDcontrol();
       break;
  }
}

Der eigentliche endgültige Code wird einige zusätzliche Logik, einige Variablen, die initialisiert werden müssen, usw. enthalten. In der obigen Erklärung habe ich sie der Einfachheit halber weggelassen, aber beim Betrachten des endgültigen Codes sollte alles klar sein.

Schritt 10: Optimieren der PID-Regelung mit der Android-App

Fügen Sie hier eine Bildbeschreibung ein
Fügen Sie hier eine Bildbeschreibung ein
Fügen Sie hier eine Bildbeschreibung ein

Im vorangehenden Code finden Sie die folgenden Definitionen der mit der PID-Steuerung verwendeten Konstanten in „robotDefines.h“:

float Kp=50;
float Ki=0;
float Kd=0;

Wie im vorherigen Schritt erwähnt, ist die Verwendung der „Versuch-und-Irrtum“-Methode die beste Möglichkeit, die richtigen Konstanten für die Verwendung mit einem PID-Regler zu definieren. Der Nachteil besteht darin, dass jedes Mal, wenn das Programm geändert werden muss, das Programm neu kompiliert werden muss. Eine Möglichkeit, den Vorgang zu beschleunigen, besteht darin, die Android-App zum Senden von Konstanten während der „**Setup-Phase“ zu verwenden.

Ich habe speziell dafür eine Android-Anwendung entwickelt. Zusamenfassend:

  • Traditionelle manuelle Befehle:
    • FW, BW, Left, Right and Stop, wird die Bewerbung jeweils an die BT-Module „f“, „b“, „l“, „r“ und „s“ gesendet.
  • Enthält außerdem 3 Schieberegler, einen für jede PID-Konstante:
    • Kp: „p/XXX“
    • Ki: „i/XXX“
    • Kd: „d/XXX“
      • Dabei ist „XXX“ eine Zahl zwischen 0 und 100.
  • Fügen Sie einen zusätzlichen Knopf hinzu, der genau dem entspricht, der am Arduino Pin9 angeschlossen ist. Sie können eines davon verwenden.

Unten finden Sie die .aia-Datei zum Ändern auf ***MIT AppInventor*** und die .apk-Datei zur direkten Installation auf Ihrem Android-Gerät.

Anhang

MJRoBot_Line_Follower_PID_Control.aia

Laden Sie MJRoBot_Line_Follower_PID_Control.apk herunter

herunterladen

Schritt 11: Ändern Sie den Code für die PID-Fernabstimmung

Dabei void setup()führen wir eine Schleife ein, in der Sie die PID-Parameter an den Roboter senden können, bevor Sie das Auto ans Netz bringen:

  while (digitalRead(buttonPin) && !mode)
  {  
    checkBTcmd();  // verify if a comand is received from BT remote control
    manualCmd ();    
    command = "";  
  }
  checkPIDvalues();
  mode = STOPPED;

Der manuelle Befehl wäre:

void manualCmd()
{
  switch (command[0])
  {
    case 'g':
      mode = FOLLOWING_LINE;
      break;
    
    case 's': 
      motorStop(); //turn off both motors
      break;

    case 'f':  
      motorForward();  
      break;

    case 'r':     
      motorTurn(RIGHT, 30);
      motorStop();
      
      break;

   case 'l': 
      motorTurn(LEFT, 30);
      motorStop();
      break;
    
    case 'b':  
      motorBackward();
      break;
      
    case 'p':
      Kp = command[2];
      break;
    
    case 'i':
      Ki = command[2];
      break; 
    
    case 'd':
      Kd = command[2];
      break;
  }
}

Hier ist der endgültige Code, einschließlich der PID-Einrichtung über Android:

Anhang

generalFunctions.ino

herunterladen

motorFuntions.ino

herunterladen

robotDefines.h

herunterladen

sensorFuntions.ino

herunterladen

smart_MJRoBot_Line_Follower_PID.ino

herunterladen

Schritt 12: Fazit

Dies ist das erste eines komplexen Projekts, das das Potenzial von linienfolgenden Robotern untersucht. Im nächsten Teil werde ich basierend auf diesem Projekt in Maze Solving Robot einen Labyrinth-Lösungsroboter entwickeln .

Update-Dateien für dieses Projekt finden Sie auf GITHUB: https://github.com/Mjrovai/MJRoBot-Line-Follower

Weitere Tutorials finden Sie im Blog: MJRoBot.org

Supongo que te gusta

Origin blog.csdn.net/acktomas/article/details/130009184
Recomendado
Clasificación