KI-gesteuerter Labyrinth-lösender Roboter mit Arduino und Bluetooth
Komponenten und Materialien
| Bauteil | Menge |
|---|---|
| Arduino Nano R3 | 1 |
| HC-06 Bluetooth Modul | 1 |
| TCRT5000 4-Kanal Infrarot-Linienverfolger-Sensormodul | 1 |
| SparkFun RedBot Sensor – Line Follower | 1 |
| ZX03 (basierend auf TCRT5000) Reflektive Infrarotsensoren (Analogausgang) | 2 |
| Android-Gerät | 1 |
| RobotGeek Continuous Rotation Servo | 2 |
| 4xAA Batteriehalter | 2 |
Apps und Online-Dienste
- Arduino IDE
- MIT App Inventor 2
Über dieses Projekt
Einführung
Dieses Tutorial baut auf meinem vorherigen Projekt auf: Line Follower Robot – PID Control – Android Setup. Sobald man einen Roboter mit Linienverfolgungsfähigkeiten hat, ist der nächste logische Schritt, ihm ein gewisses Maß an Intelligenz zu verleihen. Unser lieber „Rex, der Roboter“ wird nun versuchen, den kürzesten und schnellsten Weg aus einem „Labyrinth“ zu finden (übrigens hasst er den Minotaurus).
Zunächst: Was ist der Unterschied zwischen Maze (Irrgarten) und Labyrinth? Laut labyrinthos.net gilt im englischsprachigen Raum oft: Ein Design qualifiziert sich als Maze, wenn es Wahlmöglichkeiten im Pfad bietet. Das schließt viele moderne Installationen in Freizeitparks und Touristenattraktionen ein – auch unseren 2D-Irrgarten hier. Labyrinthe hingegen haben einen einzigen Pfad, der unweigerlich vom Eingang zum Ziel führt, wenn auch oft auf komplexesten und verschlungensten Wegen.
Die meisten Irrgärten, so komplex ihr Design auch erscheinen mag, bestehen im Wesentlichen aus einer einzigen durchgehenden Wand mit vielen Verzweigungen und Abzweigungen. Wenn die das Ziel umgebende Wand mit dem Umfang des Irrgartens am Eingang verbunden ist, lässt sich der Irrgarten immer lösen, indem man eine Hand an der Wand hält – wie viele Umwege auch immer nötig sein mögen. Diese „einfachen“ Irrgärten nennt man korrekt simply-connected oder perfect maze – also Irrgärten, die keine Schleifen enthalten.
Unser Projekt teilt sich in zwei Teile (oder „Passes“):
- Erster Pass: Der Roboter findet seinen Weg aus einem „
unbekannten perfect maze“. Egal, wo man ihn im Irrgarten platziert – er findet eine „Lösung“. - Zweiter Pass: Sobald der Roboter eine mögliche Lösung gefunden hat, optimiert er diese und findet den „
kürzesten Pfad vom Start zum Ziel“.
Das folgende Video zeigt ein Beispiel, wie Rex seinen Weg findet. Beim ersten Erkunden des Irrgartens „denkt“ der Roboter natürlich lange über die richtige Entscheidung an jeder Kreuzung nach. Er testet zahlreiche Möglichkeiten, läuft in Sackgassen und muss unnötige „U-Turns“ machen. Während dieses „1. Pass“ sammelt er Erfahrungen, macht sich „Notizen“ über die verschiedenen Kreuzungen und eliminiert schlechte Zweige. Im „2. Pass“ fährt er dann direkt und schnell zum Ziel ohne Fehler oder Zögern. In diesem Tutorial gehen wir im Detail darauf ein, wie das funktioniert:
Schritt 1: Stückliste (Bill of Materials)
Die Materialliste entspricht im Wesentlichen der des Line Follower Robot, ergänzt um 2 zusätzliche Sensoren für eine präzisere Erkennung von LINKS- und RECHTS-Kreuzungen:
Der finale Roboter ist immer noch sehr günstig (ca. 85 $):
- Gehäuse (anpassbar an deine Bedürfnisse oder verfügbare Materialien):
- 2 x Holzquadrate (80×80 mm)
- 3 x Klemmen (Binder Clips)
- 2 x Holzräder (Durchmesser: 50 mm)
- 1 x Lenkrolle (Ball Caster)
- 9 x Gummibänder
- 3M Command Bilderrahmen-Streifen
- Kunststoffhalterungen für Sensoren
- Steckbrett und Verkabelung
- 2 x Satz 4×Ni-MH-Akkus (je 5 V)
- 2 x SM-S4303R Continuous Rotation 360° Kunststoff-Servos
- Arduino Nano
- HC-06 Bluetooth Modul
- 5 x Liniensensoren (TCRT5000 4CH Modul + 1 separater Track-Sensor)
- 2 x ZX03 (basierend auf TCRT5000) Reflektive Infrarotsensoren (Analogausgang)
- 1 x LED
- 1 x Taster
Hinweis: Ich habe die unter Punkt 7 genannten Sensoren mit Analogausgang verwendet, da ich keine digitalen Sensoren wie unter Punkt 6 zur Hand hatte. Ideal wäre es, alle Sensoren gleich zu haben. Ich habe das Projekt auch mit nur den ursprünglichen 5 Sensoren getestet – es funktioniert, erfordert aber empfindlichere Einstellungen bei der Kreuzungserkennung.
Schritt 2: Änderungen am Gehäuse
Entferne das ursprüngliche Set von 5 Liniensensoren und montiere die neuen „Far LEFT“ und „Far RIGHT“ Reflektionssensoren an jedem Ende der Kunststoff-Halterungsleiste. Es ist ratsam, alle 7 Sensoren so fluchtend wie möglich auszurichten.
Schritt 3: Einbau und Test der neuen Sensoren
Das neue Array aus nun 7 Sensoren ist so montiert, dass die 5 ursprünglichen ausschließlich für die PID-Regelung (und Erkennung der „durchgehenden Linie“, dazu später mehr) zuständig sind, während die 2 neuen ausschließlich für die LINKS- und RECHTS-Kreuzungserkennung dienen.
Als kurzer Rückblick: So funktionieren die 5 ursprünglichen „digitalen“ Sensoren:
Wenn ein Sensor zentriert über der schwarzen Linie liegt, gibt nur dieser spezifische Sensor HIGH aus. Der Abstand zwischen den Sensoren sollte so berechnet sein, dass 2 Sensoren gleichzeitig die volle Breite der schwarzen Linie abdecken können – beide geben dann HIGH aus.
So funktionieren die 2 neuen „analogen“ Sensoren:
Wenn einer der Sensoren zentriert über der schwarzen Linie liegt, ist der Ausgang ein analoger Wert, typischerweise unter „100“ am Arduino ADC (0–1023). Auf helleren Oberflächen ist der Wert höher (ich habe 500–600 auf weißem Papier gemessen). Dieser Wert muss unter verschiedenen Lichtverhältnissen und Oberflächenmaterialien getestet werden, um den korrekten THRESHOLD-Schwellwert für deinen Fall zu definieren (siehe Bild).
Im Arduino-Code wird jedem Sensor ein spezifischer Name zugewiesen (der ursprüngliche Liniensensor ganz links erhält das Label „0“):
const int lineFollowSensor0 = 12; // Digitaler Eingang
const int lineFollowSensor1 = 18; // Analog Pin A4 als Digital
const int lineFollowSensor2 = 17; // Analog Pin A3 als Digital
const int lineFollowSensor3 = 16; // Analog Pin A2 als Digital
const int lineFollowSensor4 = 19; // Analog Pin A5 als Digital
const int farRightSensorPin = 0; // Analog Pin A0
const int farLeftSensorPin = 1; // Analog Pin A1
Die möglichen Ausgaben des 5-Sensor-Arrays beim Linienverfolgen:
1 1 1 1 1
0 0 0 0 0
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 den 2 neuen Sensoren ergeben sich zusätzlich:
- Far LEFT Sensor: Analogausgang größer oder kleiner als THRESHOLD
- Far RIGHT Sensor: Analogausgang größer oder kleiner als THRESHOLD
Zur Speicherung der Sensorwerte wird ein Array für die 5 digitalen Sensoren angelegt:
int LFSensor[5] = {0, 0, 0, 0, 0};
Und zwei Integer-Variablen für die 2 neuen analogen Sensoren:
int farRightSensor = 0;
int farLeftSensor = 0;
Jede Array-Position und Variable wird kontinuierlich mit den Sensorausgängen aktualisiert:
LFSensor[0] = digitalRead(lineFollowSensor0);
LFSensor[1] = digitalRead(lineFollowSensor1);
LFSensor[2] = digitalRead(lineFollowSensor2);
LFSensor[3] = digitalRead(lineFollowSensor3);
LFSensor[4] = digitalRead(lineFollowSensor4);
farRightSensor = analogRead(farRightSensorPin);
farLeftSensor = analogRead(farLeftSensorPin);
5 Sensoren ermöglichen (wie im Line Follower Projekt gezeigt) die Generierung einer „Error-Variable“, die hilft, die Position des Roboters über der Linie zu kontrollieren. Eine Variable „mode“ definiert, ob der Roboter einer Linie folgt, auf einer durchgehenden Linie ist, eine Kreuzung erreicht hat oder keine Linie erkennt.
Diese „mode“-Variable wird auch mit den „Far LEFT/RIGHT“-Sensoren verwendet. Zur Darstellung betrachten wir für die Far-Sensoren 3 Zustände:
- H (höher als THRESHOLD)
- L (kleiner als THRESHOLD)
- X (irrelevant)
Für digitale Ausgänge die üblichen 0, 1 und auch X:
H 0 X X X X L ==> mode = RIGHT_TURN; error = 0;
L X X X X 0 H ==> mode = LEFT_TURN; error = 0;
X 0 0 0 0 0 X ==> mode = NO_LINE; error = 0;
H 0 0 0 0 1 H ==> mode = FOLLOWING_LINE; error = 4;
H 0 0 0 1 1 H ==> mode = FOLLOWING_LINE; error = 3;
H 0 0 0 1 0 H ==> mode = FOLLOWING_LINE; error = 2;
H 0 0 1 1 0 H ==> mode = FOLLOWING_LINE; error = 1;
H 0 0 1 0 0 H ==> mode = FOLLOWING_LINE; error = 0;
H 0 1 1 0 0 H ==> mode = FOLLOWING_LINE; error = -1;
H 0 1 0 0 0 H ==> mode = FOLLOWING_LINE; error = -2;
H 1 1 0 0 0 H ==> mode = FOLLOWING_LINE; error = -3;
H 1 0 0 0 0 H ==> mode = FOLLOWING_LINE; error = -4;
X 1 1 1 1 1 X ==> mode = CONT_LINE; error = 0;
Die Implementierung dieser Logik in der Funktion readLFSsensors() liefert die Variablen mode und error für die Programmsteuerung. Wichtig: Teste die Sensorlogik vor dem Weiterbau. Folgende Testfunktion ist im Code enthalten:
void testSensorLogic(void) {
Serial.print(farLeftSensor);
Serial.print(" <== LEFT RIGH==> ");
Serial.print(farRightSensor);
Serial.print(" mode: ");
Serial.print(mode);
Serial.print(" error:");
Serial.println(error);
}
Schritt 4: Den Irrgarten lösen – Die Linkshand-Regel
Wie in der Einleitung besprochen, bestehen die meisten Irrgärten aus einer durchgehenden Wand mit vielen Verzweigungen. Wenn die das Ziel umgebende Wand mit dem Umfang am Eingang verbunden ist, lässt sich der Irrgarten immer lösen, indem man die linke Hand an der linken Wand hält. Diese „einfachen“ Irrgärten nennt man Simply-connected.
Nach Wikipedia lässt sich die Linkshand-Regel so beschreiben:
- Lege deine linke Hand an die Wand.
- Gehe vorwärts.
- Schließlich erreichst du das Ende. Nicht unbedingt auf dem kürzesten Weg, aber du kommst an.
Der Schlüssel ist die Erkennung der Kreuzungen und die Entscheidungsfindung basierend auf den Regeln. In unserem 2D-Irrgarten gibt es 8 Kreuzungstypen (siehe erstes Bild):
Mögliche Aktionen an Kreuzungen:
- Bei einem Kreuz: Links, Rechts oder Geradeaus
- Bei einem T: Links oder Rechts
- Bei Nur Rechts: Rechts
- Bei Nur Links: Links
- Bei Geradeaus oder Links: Links oder Geradeaus
- Bei Geradeaus oder Rechts: Rechts oder Geradeaus
- Bei Sackgasse: Zurück (U-Turn)
- Bei Ende des Irrgartens: Stopp
Anwendung der Linkshand-Regel reduziert die Optionen auf jeweils eine:
- Kreuz: Nach Links
- T: Nach Links
- Nur Rechts: Nach Rechts
- Nur Links: Nach Links
- Geradeaus oder Links: Nach Links
- Geradeaus oder Rechts: Geradeaus
- Sackgasse: Zurück (U-Turn)
- Ende: Stopp
Wenn der Roboter eine Sackgasse oder das Ende erreicht, ist die Identifikation einfach (bereits im Line Follower implementiert). Schwierig wird es bei einer „LINIE“ – das kann ein Kreuz (1) oder ein T (2) sein. Auch bei „LINKS- oder RECHTS-ABBIEGEN“ kann es sich um einfache Kurven (3, 4) oder Optionen mit Geradeaus (5, 6) handeln. Um den genauen Kreuzungstyp zu bestimmen, muss der Roboter ein „extra Stück“ fahren und prüfen, was folgt (siehe zweites Bild).
Der Ablauf lautet nun:
- Bei SACKGASSE: Zurück (U-Turn)
- Bei LINIE: Extra Stück fahren
- Linie vorhanden: Kreuz → Nach LINKS
- Keine Linie: T → Nach LINKS
- Weitere Linie: Ende des Irrgartens → STOPP
- Bei RECHTS-KURVE: Extra Stück fahren
- Linie vorhanden: Geradeaus oder Rechts → GERADEAUS
- Keine Linie: Nur Rechts → Nach RECHTS
- Bei LINKS-KURVE: Extra Stück fahren
- Linie vorhanden: Geradeaus oder Links → Nach LINKS
- Keine Linie: Nur Links → Nach LINKS
Hinweis: Bei einer „LINKS-KURVE“ kann man den Test eigentlich überspringen, da man sowieso nach links fährt. Die generische Erklärung dient nur der Klarheit. Im echten Code spare ich diesen Test. Das dritte Bild zeigt einen einfachen Test-Irrgarten auf meinem Laborboden.
Schritt 5: Implementierung des „Linkshand-an-der-Wand“-Algorithmus im Arduino-Code
Mit der erweiterten readLFSsensors()-Funktion (inkl. der 2 Extra-Sensoren) können wir die Loop-Funktion für den Algorithmus umschreiben:
void loop() {
readLFSsensors();
switch (mode) {
case NO_LINE:
motorStop();
goAndTurn(LEFT, 180);
break;
case CONT_LINE:
runExtraInch();
readLFSsensors();
if (mode == CONT_LINE) mazeEnd();
else goAndTurn(LEFT, 90); // T oder Kreuz – in beiden Fällen LINKS
break;
case RIGHT_TURN:
runExtraInch();
readLFSsensors();
if (mode == NO_LINE) goAndTurn(RIGHT, 90);
break;
case LEFT_TURN:
goAndTurn(LEFT, 90);
break;
case FOLLOWING_LINE:
followingLine();
break;
}
}
Neue Funktionen:
- followingLine() – wie beim Line Follower:
calculatePID()und Motorsteuerung permotorPIDcontrol() - runExtraInch() – fährt den Roboter ein kurzes Stück vorwärts. Die Distanz hängt von der Verzögerung ab, bevor der Motor stoppt:
void runExtraInch(void) { motorPIDcontrol(); delay(extraInch); motorStop(); } - goAndTurn(direction, angle) – wichtig, weil der Roboter nicht sofort an der Kreuzung abbiegen kann. Da es ein Differential-Roboter ist, der „um seine Achse“ dreht, muss das Radzentrum mit dem Kreuzungsmittelpunkt fluchten. Da die Sensorlinie vor der Achse liegt, muss der Roboter erst vorwärts fahren, um sie auszurichten. Die Zeitkonstante
adjGoAndTurnhängt vom Abstand Achse-Sensorlinie (d), Geschwindigkeit und Radgröße ab (siehe Bild).void goAndTurn(int direction, int degrees) { motorPIDcontrol(); delay(adjGoAndTurn); motorTurn(direction, degrees); }
An diesem Punkt löst der Roboter den Irrgarten tatsächlich! Der „Erste Pass“ ist abgeschlossen. Egal wo du im Irrgarten startest – du erreichst immer das Ende.
Schritt 6: Den Pfad speichern
Am gewählten Startpunkt trifft der Roboter 15 Kreuzungen vor dem Irrgartenende:
Links (L), Zurück (B), Links (L), Links (L), Links (L),
Zurück (B), Geradeaus (S), Zurück (B), Links (L), Links (L),
Zurück (B), Geradeaus (S), Links (L), Links (L), Ende
In jeder Kreuzung wird die getätigte Aktion in genau der Reihenfolge gespeichert. Dafür erstellen wir ein Array:
char path[100] = "";
unsigned char pathLength = 0; // Pfadlänge
int pathIndex = 0; // Index für Array-Zugriff
Am Beispiel erhalten wir:
path = [LBLLLBSBLLBSLL] und pathLength = 14
Schritt 7: Pfad vereinfachen (optimieren)
Betrachten wir die erste Gruppe: Der erste linke Zweig ist eine Sackgasse. Hätte der Roboter statt „Links-Zurück-Links“ einfach geradeaus gefahren, hätte er Zeit und Energie gespart. Die Sequenz „LBL“ entspricht also „S“. Genau so lässt sich der komplette Pfad optimieren. Wo immer ein „U-Turn“ (B) vorkommt, kann das Tripel „xBx“ auf einen einzigen Schritt reduziert werden.
Vollständige Reduktionsregeln:
- LBR = B
- LBS = R
- RBL = B
- SBL = R
- SBS = B
- LBL = S
Anwendung auf unseren Beispielpfad:
path = [LBLLLBSBLLBSLL] ==> LBL = S
path = [SLLBSBLLBSLL] ==> LBS = R
path = [SLRBLLBSLL] ==> RBL = B
path = [SLBLBSLL] ==> LBL = S
path = [SSBSLL] ==> SBS = B
path = [SBLL] ==> SBL = R
path = [RL]
Erstaunlich! Wenn der Roboter an der ersten Kreuzung RECHTS und danach LINKS nimmt, erreicht er das Ende auf dem kürzesten Pfad!
Der komplette First-Pass-Code wird in mazeSolve() konsolidiert – im Grunde die vorherige loop()-Funktion, erweitert um Speicherung und Pfadoptimierung. Am Ende des ersten Passes enthält path[] den optimierten Pfad. Neue Variable:
unsigned int status = 0; // 0 = löst, 1 = Irrgartenende erreicht
void mazeSolve(void) {
while (!status) {
readLFSsensors();
switch (mode) {
case NO_LINE:
motorStop();
goAndTurn(LEFT, 180);
recIntersection('B');
break;
case CONT_LINE:
runExtraInch();
readLFSsensors();
if (mode != CONT_LINE) {
goAndTurn(LEFT, 90);
recIntersection('L');
} else mazeEnd();
break;
case RIGHT_TURN:
runExtraInch();
readLFSsensors();
if (mode == NO_LINE) {
goAndTurn(RIGHT, 90);
recIntersection('R');
} else recIntersection('S');
break;
case LEFT_TURN:
goAndTurn(LEFT, 90);
recIntersection('L');
break;
case FOLLOWING_LINE:
followingLine();
break;
}
}
}
Neue Funktion recIntersection(direction) speichert die Kreuzung und ruft simplifyPath() auf:
void recIntersection(char direction) {
path[pathLength] = direction;
pathLength++;
simplifyPath();
}
Die simplifyPath()-Funktion stammt von Patrick McCabe (Details: patrickmccabemakes.com). Die Strategie: Bei Sequenz xBx wird der Sackgassen-Abschnitt entfernt (z. B. LBL ==> S).
void simplifyPath() {
if (pathLength < 3 || path[pathLength-2] != 'B') return;
int totalAngle = 0;
for (int i = 1; i <= 3; i++) {
switch (path[pathLength-i]) {
case 'R': totalAngle += 90; break;
case 'L': totalAngle += 270; break;
case 'B': totalAngle += 180; break;
}
}
totalAngle %= 360;
switch (totalAngle) {
case 0: path[pathLength-3] = 'S'; break;
case 90: path[pathLength-3] = 'R'; break;
case 180: path[pathLength-3] = 'B'; break;
case 270: path[pathLength-3] = 'L'; break;
}
pathLength -= 2;
}
Schritt 8: Zweiter Pass – Den Irrgarten so schnell wie möglich lösen!
Das Hauptprogramm loop() ist nun simpel:
void loop() {
ledBlink(1);
readLFSsensors();
mazeSolve(); // Erster Pass: Irrgarten lösen
ledBlink(2);
while (digitalRead(buttonPin)) { }
pathIndex = 0;
status = 0;
mazeOptimization(); // Zweiter Pass: So schnell wie möglich
ledBlink(3);
while (digitalRead(buttonPin)) { }
mode = STOPPED;
status = 0;
pathIndex = 0;
pathLength = 0;
}
Nach dem ersten Pass füttern wir den Roboter mit dem optimierten path[]-Array. Bei jeder Kreuzung entscheidet er basierend auf dem gespeicherten Pfad.
void mazeOptimization(void) {
while (!status) {
readLFSsensors();
switch (mode) {
case FOLLOWING_LINE:
followingLine();
break;
case CONT_LINE:
if (pathIndex >= pathLength) mazeEnd();
else { mazeTurn(path[pathIndex]); pathIndex++; }
break;
case LEFT_TURN:
if (pathIndex >= pathLength) mazeEnd();
else { mazeTurn(path[pathIndex]); pathIndex++; }
break;
case RIGHT_TURN:
if (pathIndex >= pathLength) mazeEnd();
else { mazeTurn(path[pathIndex]); pathIndex++; }
break;
}
}
}
Die Funktion mazeTurn(path[]) führt die Aktionen aus:
void mazeTurn(char dir) {
switch (dir) {
case 'L': goAndTurn(LEFT, 90); break; // Links abbiegen
case 'R': goAndTurn(RIGHT, 90); break; // Rechts abbiegen
case 'B': goAndTurn(RIGHT, 800); break; // Zurück (U-Turn)
case 'S': runExtraInch(); break; // Geradeaus
}
}
Der zweite Pass ist abgeschlossen! Das folgende Video zeigt das komplette Beispiel (erster und zweiter Pass). Unten der vollständige Arduino-Code dieses Tutorials:
FV6XNJWINJ45XWM.ino
F2FXS8MINJ45XX6.h
FX5MHFMINJ45XX7.ino
FT2S1WXINJ45XXA.ino
F9IC3HQINJ45XXB.ino
FU2HRXJINJ45XXV.ino
Schritt 9: Android-App zur Feinabstimmung
Die Android-App vom Line Follower Projekt kann auch hier genutzt werden (falls benötigt: App und Code unter „Line Follower Robot – PID Control – Android Setup“). Der Arduino-Code enthält bereits die Kommunikation. Wenn du die App nicht nutzen möchtest: kein Problem, der Code ist „transparent“.
Ich habe die Android-App intensiv genutzt, um Testdaten vom Roboter ans Gerät zu senden („Message Received“-Feld). Mehrere Variablen müssen präzise definiert sein, damit der Roboter den korrekten Winkel dreht. Die wichtigsten (fett markierte habe ich oft angepasst):
const int adj = 0;
float adjTurn = 8;
int adjGoAndTurn = 800;
THRESHOLD = 150;
const int power = 250;
const int iniMotorPower = 250;
int extraInch = 200;
Schritt 10: Fazit
Dies ist der zweite und letzte Teil eines komplexen Projekts, das das Potenzial eines Linienfolger-Roboters erforscht, wobei Künstliche Intelligenz (KI)-Konzepte zur Irrgartenlösung eingesetzt wurden.
Ich bin kein KI-Experte, aber basierend auf Web-Recherchen könnte das, was unser kleiner Rex tut, als KI-Anwendung gelten. Zwei Quellen:
- Wikipedia
- Universitätspapier: „Maze Solving Robot Using Freeduino and LSRB Algorithm – International Journal of Modern Engineering Research (IJMER)“
Aktualisierte Dateien findest du auf GitHub. Ich hoffe, ich konnte anderen helfen, mehr über Elektronik, Robotik, Arduino etc. zu lernen. Weitere Tutorials auf meinem Blog: MJRoBot.org
Grüße vom Süden der Welt!
Marcelo
Code-Schnipsel
Alle relevanten Code-Abschnitte sind in den Schritten oben integriert. Die vollständigen Dateien sind auf GitHub verfügbar.
Schaltpläne
z7IdLkxL1J66qOtphxqC.fzz
Herstellungsprozess
- Intelligenten Roboter mit Bridge Shield bauen – Raspberry Pi & Arduino Integration
- Gesten-gesteuerter Roboter mit Raspberry Pi
- WLAN-gesteuerter Raspberry Pi Roboter mit Python bauen – Schritt-für-Schritt
- Microsoft Kinect mit Raspberry Pi integrieren für Echtzeit-Menschenerkennung am Sonbi Roboter
- Bosch stellt KI‑gestützte Fertigungslösung auf der Hannover Messe vor
- Künstliche Intelligenz im Retail: Bewiesene Vorteile, kein Hype
- Kubernetes befähigt KI-Start-ups mit skalierbaren, containerisierten Lösungen
- KI befähigt Roboter, 90+ Objekte durch Tasten zu erkennen
- KI-gestützte Verfolgung der Entwaldung im Amazonas
- KI-gestützte Robotik: Spitzenklasse intelligenter Maschinen