Linienfolger-Roboter mit PID-Regelung & Android-App (MIT App Inventor)
Komponenten und Zubehör
Bauteil Anzahl Hinweis
Arduino Nano R3 1 Hauptcontroller
TCRT5000 4-Kanal IR-Liniensensor-Modul 1 4 Sensoren auf einer Platine
Einzelner TCRT5000 Sensor (5. Sensor) 1 Für 5er-Array (bessere Auflösung)
HC-06 Bluetooth-Modul 1 Serielle BT-Kommunikation
2× Continuous Rotation Servo (SM-S4303R) 2 360° Dauerlauf, Ansteuerung per µs-Puls
Android-Gerät 1 Für PID-Tuning per App
2× 4×AA NiMH-Akku-Halter (5 V je Satz) 2 Einer für Servos, einer für Arduino (Vin)
Kugelrad (Ball Caster) 1 Drittes Rad, lenkbar
Chassis: 2× Holzplatte 80×80 mm, 3× Binderclips, 2× Holzräder 50 mm, Gummibänder, 3M Command-Strips 1 Satz Low-Cost, flexibel
Breadboard, Jumper-Kabel, LED, Taster nach Bedarf
Software & Apps
Arduino IDE
MIT App Inventor 2 (App-Entwicklung per Blocks-Editor)
Projektziel
Bau eines Linienfolger-Roboters mit PID-Regelung für präzises, schnelles Spuren. Ein Android-App (via Bluetooth) ermöglicht Live-Tuning der PID-Parameter (Kp, Ki, Kd) sowie manuelle Steuerung – ideal für Wettbewerbe und Lernzwecke. Dies ist Teil 1; Teil 2 wird ein Labyrinth-Löser mit KI.
Schritt-für-Schritt Aufbau
1. Motoren (Continuous Rotation Servos)
Beide Servos (SM-S4303R) Rücken an Rücken verkleben (3M Command Strip / Doppelklebeband) → fester Block
Pulsweiten-Steuerung (µs):
1500 µs = Stopp (Neutral)
1000 µs = Vollgas Richtung A
2000 µs = Vollgas Richtung B
Dazwischen = proportional
Da Servos gespiegelt montiert sind:
Rechts: Vorwärts = 1500 → 2000 µs
Links: Vorwärts = 1500 → 1000 µs
Anschlüsse: Rechts → Pin 3, Links → Pin 5
Externe 5 V/6 V für Servos (gemeinsames GND mit Arduino!)
Nullpunkt-Abgleich: Potentiometer am Servo (gelbe Schraube) drehen bis Stillstand bei 1500 µs. Falls kein Poti: Software-Offset anpassen.
Test-Code (Nullpunkt)
#include <Servo.h>
Servo leftServo, rightServo;
void setup() {
leftServo.attach(5);
rightServo.attach(3);
leftServo.writeMicroseconds(1500);
rightServo.writeMicroseconds(1500);
}
void loop() {}
2. Chassis-Montage
Servo-Block auf untere Holzplatte (3M Strip)
Obere Platte mit 3 Binderclips auf Abstand befestigen (Höhe variabel)
Kugelrad per Binderclip hinten befestigen
Servo-Akku (5 V) zwischen Platten platzieren
Arduino Nano auf Breadboard stecken
Breadboard-GND mit Servo-Strom-GND verbinden
LED an Pin 13 (Status), Taster an Pin 9 (Start/Stopp)
3. Bluetooth HC-06 (Optional)
HC-06 TX → Arduino Pin 10 (SoftwareSerial RX)
HC-06 RX → Arduino Pin 11 (SoftwareSerial TX) – Spannungsteiler 1k/2k Ω!
VCC/GND an Arduino 5 V/GND
Bibliothek: SoftwareSerial
Roboter funktioniert auch ohne BT (Default-Parameter)
4. Liniensensoren (5× TCRT5000)
4-Kanal-Modul + 1 Einzelsensor → 5 Sensoren gesamt
Abstand so wählen, dass 2 benachbarte Sensoren die Linienbreite gleichzeitig abdecken
Beschriftung: Sensor 0 (links) → Sensor 4 (rechts)
Anschlüsse: S0=Pin12, S1=Pin18(A4), S2=Pin17(A3), S3=Pin16(A2), S4=Pin19(A5)
Potentiometer am Modul justieren: Schwarz = HIGH, Hell = LOW
2. Akku-Set (5 V) an Arduino Vin
IR-Sensor-Logik & Fehlerberechnung
Digitale Ausgabe: HIGH (1) = schwarze Linie, LOW (0) = heller Untergrund.
Mögliche Sensor-Muster (5 Bit) und zugewiesener Fehlerwert :
Sensor-Array (0–4) Fehler Bedeutung
0 0 1 0 0 0 Zentriert (Ideal)
0 0 0 0 1 +4 Weit rechts
0 0 0 1 1 +3 Rechts-außen
0 0 0 1 0 +2 Rechts
0 0 1 1 0 +1 Leicht rechts
0 1 1 0 0 -1 Leicht links
0 1 0 0 0 -2 Links
1 1 0 0 0 -3 Links-außen
1 0 0 0 0 -4 Weit links
1 1 1 1 1 STOP Querbalken / Ende
0 0 0 0 0 NO_LINE Linie verloren
Arduino-Implementierung
const int lineFollowSensor[5] = {12, 18, 17, 16, 19};
int LFSensor[5] = {0,0,0,0,0};
int error = 0;
void readLFSsensors() {
for (int i=0; i<5; i++) LFSensor[i] = digitalRead(lineFollowSensor[i]);
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;
else if (LFSensor[0]==1 && LFSensor[1]==1 && LFSensor[2]==1 && LFSensor[3]==1 && LFSensor[4]==1) mode = STOPPED;
else if (LFSensor[0]==0 && LFSensor[1]==0 && LFSensor[2]==0 && LFSensor[3]==0 && LFSensor[4]==0) mode = NO_LINE;
}
Regelung: P → PID
Proportional (P) – Basis
Basisgeschwindigkeit iniMotorPower = 250 (µs-Offset von 1500).
rightServo.writeMicroseconds(1500 + iniMotorPower - Kp * error);
leftServo.writeMicroseconds(1500 - iniMotorPower - Kp * error);
Fehler > 0 (Roboter links von Linie) → Rechter Motor langsamer, Linker schneller → Kurve rechts
Fehler < 0 → Umgekehrt
Kp = 50 funktioniert gut als Startwert
Voll-PID (Optional, für bessere Performance)
float Kp = 50, Ki = 0, Kd = 0;
float P, I, D, PIDvalue, previousError = 0;
void calculatePID() {
P = error;
I = I + error; // Integral: Summe vergangener Fehler
D = error - previousError; // Differenzial: Fehleränderung
PIDvalue = (Kp * P) + (Ki * I) + (Kd * D);
previousError = error;
}
void motorPIDcontrol() {
int leftMotorSpeed = 1500 - iniMotorPower - PIDvalue;
int rightMotorSpeed = 1500 + iniMotorPower - PIDvalue;
leftServo.writeMicroseconds(leftMotorSpeed);
rightServo.writeMicroseconds(rightMotorSpeed);
}
PID-Tuning (Manuell / Try-Error)
Kd = 0, Ki = 0. Kp erhöhen bis Roboter der Linie folgt, aber nicht oszilliert (~25–50).
Kd hinzufügen: Start mit Kp/2, Kd/2 (z. B. 25/25). Kd erhöht → weniger Überschwingen. Zu hoch → Instabilität.
Ki meist 0 bei kleinen Robotern (kein stationärer Fehler, kompliziert Tuning).
Loop-Rate (Delay in loop()) beeinflusst Reglerverhalten stark – mit anpassen.
Hauptprogramm (Loop)
#define STOPPED 0
#define FOLLOWING_LINE 1
#define NO_LINE 2
int mode = STOPPED;
int buttonPin = 9;
int iniMotorPower = 250;
void loop() {
readLFSsensors();
switch (mode) {
case STOPPED:
motorStop();
break;
case NO_LINE:
motorStop();
motorTurn(LEFT, 180); // 180° Wende
break;
case FOLLOWING_LINE:
calculatePID();
motorPIDcontrol();
break;
}
}
Android-App für PID-Tuning (MIT App Inventor 2)
App-Funktionen
Manuelle Steuerung: f,b,l,r,s → Vorwärts, Rückwärts, Links, Rechts, Stopp
PID-Slider senden: p/XXX, i/XXX, d/XXX (XXX = 0–100)
Start-Button g → Modus FOLLOWING_LINE
Hardware-Button (Pin 9) parallel nutzbar
Arduino-Seite: BT-Kommando-Verarbeitung
#include <SoftwareSerial.h>
SoftwareSerial bt(10, 11); // RX, TX
String command = "";
void checkBTcmd() {
while (bt.available()) {
char c = bt.read();
if (c == '\n') break;
command += c;
}
}
void manualCmd() {
switch (command[0]) {
case 'g': mode = FOLLOWING_LINE; break;
case 's': motorStop(); 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.substring(2).toFloat(); break;
case 'i': Ki = command.substring(2).toFloat(); break;
case 'd': Kd = command.substring(2).toFloat(); break;
}
}
void checkPIDvalues() {
// Optional: PID-Werte auf LCD anzeigen
}
void setup() {
// ... (Pin-Modes, Servo-Attach, BT.begin(9600))
while (digitalRead(buttonPin) && !mode) {
checkBTcmd();
manualCmd();
command = "";
}
checkPIDvalues();
mode = STOPPED;
}
App-Dateien
LineFollower.aia – App Inventor Projekt (bearbeitbar)
LineFollower.apk – Direkt installierbar auf Android
Fazit & Ausblick
Teil 1 abgeschlossen: Funktionierender Linienfolger mit PID, Bluetooth-Tuning, Zustandsautomat (Stopp, Linie verloren, Folgen). Nächster Schritt: Maze Solver – Roboter erkundet Labyrinth mit einfacher KI (Rechtshänder-Regel, Dead-End-Memory).
Updates & weitere Tutorials: GitHub Repo | MJRoBot.org Blog
Grüße vom Südrand der Welt! – Marcelo
Schaltplan (Fritzing)
Gesteuerter Roboter selbst bauen: Arduino, MPU-6050 & Bluetooth
Komponenten & Materialien
1 × Arduino UNO (Fahrzeug-Einheit)
1 × Arduino Nano (Fernbedienung / Transmitter)
2 × HC-05 Bluetooth Modul (eines als Master, eines als Slave)
1 × MPU-6050 (3-Achsen Gyroskop + Beschleunigungssensor)
2 × DC-Motor 12 V + Räder
1 × L293D Dual H-Bridge Motortreiber
2 × 9-V-B
Fernsteuerung eines 6-DOF Arduino-Roboterarms per Webinterface
Komponenten und Zubehör
Bauteil
Menge
Details
Arduino UNO
1
PHPoC WiFi Shield für Arduino
1
6-DOF Roboterarm
1
6 Servomotoren
Über dieses Projekt
Einsteiger-Empfehlung: Vorher Tutorials zu Arduino Motor, Servo Motor, WiFi durcharbeiten.
1. Demonstration
(Video/Demo in Originalquell
GRBL meistern: Schritt-für-Schritt Anleitung für Arduino-CNC
Einführung
Wer eine eigene CNC-Maschine baut, stößt unweigerlich auf GRBL. Dieses Tutorial erklärt: Was ist GRBL? Installation, Konfiguration, Steuerung mit Universal G-code Sender (UGS).
Was ist GRBL?
GRBL ist Open-Source-Firmware für Bewegungssteuerung von CNC-Maschinen. Auf einen Arduino (ATmega
DIY Arduino Roboterarm: Kabellos per Smartphone steuern & programmieren
Einführung
In diesem Tutorial bauen Sie einen Arduino Roboterarm mit 5 Freiheitsgraden, der kabellos per selbstentwickelter Android-App gesteuert und programmiert wird. Prozess: 3D-Druck, Elektronik, Arduino-Code, App-Entwicklung (MIT App Inventor).
Funktionsumfang der App
6 Slider für manuelle