Omnidirektionaler Roboter für sicheres Personentracking
Bauteile und Zubehör
| L298N Dual-Schrittmotortreiber (bis 2 A) | 2 |
| LM2596 DC-DC Step-Down-Regler (12 V → 5 V) | 1 |
| LiPo-Akku-Alarm (Unterspannungswarner) | 1 |
| 24 U/min DC 12 V Getriebemotor (4 mm Welle) | 3 |
| Arduino Nano R3 (Motorsteuerung) | 1 |
| Microsoft LifeCam HD-3000 (Gesichtserkennung) | 1 |
| Jumper-Kabel (diverse) | 10 |
| Creator Ci20 (Hauptprozessor, OpenCV) | 1 |
| 11,1 V 3S LiPo-Akku | 1 |
Benötigte Werkzeuge
- 3D-Drucker
- Lötkolben
Apps und Online-Dienste
- OpenCV (Gesichtserkennung)
Über das Projekt
Ursprüngliche Idee
Für den „Hackster Terminate the Competition“-Wettbewerb: Ein Roboter, der Menschen sucht – aber nicht wie im Terminator tötet, sondern Gutes tut. Dieser omnidirektionale Roboter findet Sie, erkennt Ihr Gesicht, fährt auf Sie zu und komplimentiert Sie!
Ziel: Alles aus kaufbaren Modulen (eBay) zusammensteckbar, Gehäuse 3D-druckbar (selbst oder via 3D Hubs).
Funktionsweise

Vier Hauptbereiche:
- Stromversorgung: LiPo → LM2596 → 5 V Rail, LiPo-Alarm.
- Ci20: Gesichtserkennung per OpenCV, sendet Steuerbefehle seriell an Arduino.
- Arduino Nano: setzt Befehle in Motortreiber-Signale um (3× L298N für 3 Omni-Räder).
- Mechanik: 3D-gedrucktes Chassis, Omni-Räder.
Stromversorgung

Dem Schaltplan folgen – keine blauen Rauchzeichen!
Arduino an L298N anschließen
Anleitung: Instructables L298N Tutorial.
3D-Druck des Gehäuses
Designziele: cool aussehen, Ci20 präsentieren. Alle Teile (Deckel, Boden, Räder) druckbar. STL-Dateien unten. M4-Schrauben für Motorbefestigung.

Ci20: OpenCV Gesichtserkennung
- OpenCV installieren: Schritt-für-Schritt-Tutorial (Link im Original).
- Code kompilieren & ausführen:
Binärdatei:g++ -I/usr/local/include/opencv -I/usr/local/include/opencv2 -L/usr/local/lib/ -g -o binary main.cpp \ -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_ml -lopencv_video \ -lopencv_features2d -lopencv_calib3d -lopencv_objdetect -lopencv_contrib \ -lopencv_legacy -lopencv_stitchingFaceTracking(Quelle:main.cpp/FaceTracking.cpp).

Ci20 & Arduino zusammenführen
Arduino mit untenstehendem Sketch flashen, per USB an Ci20 anschließen, FaceTracker starten, Webcam einstecken. Erkennt das Gesicht in der Bildmitte, fährt der Roboter vorwärts.
Fertig? Herausforderungen
- Lautsprecher & Sounddateien hinzufügen: Bei großem Gesicht im Bild Kompliment abspielen.
- Suchmodus: Kein Gesicht 1–2 Min → Roboter dreht sich auf der Stelle (Befehl
R XXan Arduino, XX = Drehzeit ms).
Code
Arduino Sketch – Main
Empfängt Fahrbefehle (X, Y, Rotation) von Ci20 per Serial, steuert 3 Motoren omnidirektional.
// Motor 1
int dir1PinA = 3, dir2PinA = 2, speedPinA = 9;
// Motor 2
int dir1PinB = 4, dir2PinB = 5, speedPinB = 8;
// Motor 3
int dir1PinC = 6, dir2PinC = 7, speedPinC = 10;
int x = 0, y = 0, dominantUltrasonic = 0;
bool moveMotor = false; int startTime = 0;
void setup() {
Serial.begin(9600);
pinMode(dir1PinA, OUTPUT); pinMode(dir2PinA, OUTPUT); pinMode(speedPinA, OUTPUT);
pinMode(dir1PinB, OUTPUT); pinMode(dir2PinB, OUTPUT); pinMode(speedPinB, OUTPUT);
pinMode(dir1PinC, OUTPUT); pinMode(dir2PinC, OUTPUT); pinMode(speedPinC, OUTPUT);
startTime = millis();
}
String rpiString;
void loop() {
readDataFromRPi();
delay(30);
}
void readDataFromRPi() {
while (Serial.available()) {
delay(3);
if (Serial.available() > 0) {
char c = Serial.read();
rpiString += c;
if (c == 'n') break;
}
}
if (rpiString.length() > 0) {
Serial.println(rpiString);
String isRotate = getValue(rpiString, ' ', 0);
String xval = getValue(rpiString, ' ', 1);
String yval = getValue(rpiString, ' ', 2);
x = xval.toInt(); y = yval.toInt();
startTime = millis();
if (isRotate == "r") rotate(x);
else driveInDirection(x, y);
rpiString = "";
}
}
String getValue(String data, char separator, int index) {
int found = 0; int strIndex[] = {0, -1}; int maxIndex = data.length() - 1;
for (int i = 0; i <= maxIndex && found <= index; i++) {
if (data.charAt(i) == separator || i == maxIndex) {
found++; strIndex[0] = strIndex[1] + 1;
strIndex[1] = (i == maxIndex) ? i + 1 : i;
}
}
return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}
Arduino Sketch – MotorControl
Berechnet Radgeschwindigkeiten für omnidirektionale Fahrt (3 Räder, 120° versetzt).
void driveInDirection(float newX, float newY) {
delay(20);
float x = newX, y = newY;
float theta = atan2(y, x);
float mag = sqrt(x*x + y*y);
float vx = mag * cos(theta), vy = mag * sin(theta);
float w1 = -vx;
float w2 = 0.5 * vx - sqrt(3)/2 * vy;
float w3 = 0.5 * vx + sqrt(3)/2 * vy;
float wSet[] = {w1, w2, w3};
float largest = 0;
for (int i=0;i<3;i++) if (abs(wSet[i]) > largest) largest = abs(wSet[i]);
float speedCoef = 147.0 / largest;
w1 *= speedCoef; w2 *= speedCoef; w3 *= speedCoef;
if (x==0 && y==0) { w1=w2=w3=0; }
w1 = constrain(w1, -150, 150);
w2 = constrain(w2, -150, 150);
w3 = constrain(w3, -150, 150);
bool w1_ccw = w1 < 0, w2_ccw = w2 < 0, w3_ccw = w3 < 0;
byte w1_speed = map(abs(w1), 0, 150, 0, 255);
byte w2_speed = map(abs(w2), 0, 150, 0, 255);
byte w3_speed = map(abs(w3), 0, 150, 0, 255);
analogWrite(speedPinA, w1_speed); analogWrite(speedPinB, w2_speed); analogWrite(speedPinC, w3_speed);
digitalWrite(dir1PinA, !w1_ccw); digitalWrite(dir2PinA, w1_ccw);
digitalWrite(dir1PinB, !w2_ccw); digitalWrite(dir2PinB, w2_ccw);
digitalWrite(dir1PinC, w3_ccw); digitalWrite(dir2PinC, !w3_ccw);
}
void rotate(float ms) {
float w1=255, w2=255, w3=255;
bool w1_ccw = w1<0, w2_ccw = w2<0, w3_ccw = w3<0;
byte w1_speed = map(abs(w1),0,150,0,255);
byte w2_speed = map(abs(w2),0,150,0,255);
byte w3_speed = map(abs(w3),0,150,0,255);
analogWrite(speedPinA, w1_speed); analogWrite(speedPinB, w2_speed); analogWrite(speedPinC, w3_speed);
digitalWrite(dir1PinA, !w1_ccw); digitalWrite(dir2PinA, w1_ccw);
digitalWrite(dir1PinB, !w2_ccw); digitalWrite(dir2PinB, w2_ccw);
digitalWrite(dir1PinC, w3_ccw); digitalWrite(dir2PinC, !w3_ccw);
delay(ms);
analogWrite(speedPinA,0); analogWrite(speedPinB,0); analogWrite(speedPinC,0);
}
FaceTracking C++ für Ci20
Nutzt OpenCV Haar-Cascade für Gesichtserkennung, sendet Steuerbefehle per Serial (/dev/ttyUSB0, 9600 Baud) an Arduino.
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include
#include
#include
#include
#include
using namespace std; using namespace cv;
CascadeClassifier face_cascade;
String window_name = "Face Detection";
int sendSerial(char* message) {
int fd = open("/dev/ttyUSB0", O_RDWR);
if (fd == -1) { perror("dev/ttyUSB0"); return 1; }
struct termios tios; tcgetattr(fd, &tios);
tios.c_iflag = IGNBRK | IGNPAR; tios.c_oflag = 0; tios.c_lflag = 0;
cfsetspeed(&tios, B9600); tcsetattr(fd, TCSAFLUSH, &tios);
usleep(1000); write(fd, message, strlen(message)); return 0;
}
void detectFaces(Mat frame) {
vector faces; Mat frame_gray;
cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
equalizeHist(frame_gray, frame_gray);
face_cascade.detectMultiScale(frame_gray, faces, 1.1, 3, 0|CASCADE_SCALE_IMAGE, Size(30,30));
for (size_t i=0; i frame.cols/3 && center.x < frame.cols/3*2) sendSerial("F 50 50");
else sendSerial("0 0 ");
}
imshow(window_name, frame);
}
int main() {
sendSerial("0 0 ");
VideoCapture cap(0);
cap.set(CV_CAP_PROP_FRAME_WIDTH, 480);
cap.set(CV_CAP_PROP_FRAME_HEIGHT, 240);
Mat frame;
if (!face_cascade.load("haarcascade_frontalface_default.xml")) { cout << "classifier"; return -1; }
while (cap.read(frame)) {
detectFaces(frame);
if (waitKey(30) >= 0) break;
}
return 0;
}
Benutzerdefinierte Teile & Gehäuse
- Bodenplatte: Fasst alle Bauteile, Deckel montierbar.
- Deckel: Präsentiert den Ci20.
- Omni-Räder: Eigenes Design (Thingiverse-Remix), Halbrad mit Motorwellenaufnahme.
Schaltplan

Details siehe Story-Abschnitt.
Herstellungsprozess
- Fortgeschrittenes Tischtennisball-Tracking mit Raspberry Pi und OpenCV
- Raspoulette: Solar-betriebenes autonomes Hühnerklappen-System Prototyp
- DIY Wall-E-inspirierter Raspberry Pi CD-Box-Roboter
- Rolling Alarm Robot: Intelligentes, mobiles Wecksystem mit Raspberry Pi und Google Kalender
- Sprachgesteuerter Computer-Vision-Roboter auf Windows 10 IoT Core bauen
- ROS Roboter: Terminal-gesteuerte Navigation auf Raspberry Pi
- Simple Pi Robot: 2-WD Autonomer Rover mit Raspberry Pi bauen
- Smartes Indoor-Navigations-Roboter-Kit für Arduino-Projekte
- Linearmotoren verstehen: Von elektrischer Energie zur präzisen Linearbewegung
- Getränkeroboter: Technologie, Automatisierung und Rolle in der Getränkeindustrie