Funduino Funbot

FunduinoDernière mise à jour le

Vom Zusammenbau bis zum selbstfahrenden Roboter – in elf Lektionen

Der Funbot ist ein fertiges Roboter-Kit: Alle Bauteile sitzen bereits auf einer Platine, es muss nichts verkabelt und nichts gelötet werden. Nach vier Handgriffen steht der Roboter – und die eigentliche Arbeit kann beginnen.

Diese Anleitung ist ein vollständiger Kurs. In elf aufeinander aufbauenden Lektionen gehst du von der blinkenden Leuchtdiode bis zum Roboter, der einer Linie folgt, vor Hindernissen anhält und mit Hilfe eines Lagesensors geradeaus fährt. Jede Lektion führt genau einen neuen Baustein ein – Variablen, if-Abfragen, Bibliotheken – und endet mit einem lauffähigen Sketch.

Roboterfahrzeug auf einer Platine mit Rädern, Ultraschallsensor und LEDs
Der fertig aufgebaute Funduino Funbot
Unterseite des Funbot mit montierten Motoren und Kugelrolle
Motoren und Kugelrolle an der Unterseite der Platine
1 / 2

Choisir un microcontrôleur

Les broches, le schéma électrique et le sketch des étapes de travail changent selon ta sélection. Celle-ci reste enregistrée.

Was den Funbot ausmacht

An einem fahrenden Roboter lässt sich unmittelbar ablesen, was eine Programmzeile bewirkt. Genau deshalb gehören kleine Roboterfahrzeuge zu den beliebtesten Arduino-Projekten im Unterricht.

Beim Funbot sitzen alle Bauteile bereits fest auf einer Platine. Es muss nichts verkabelt und nichts gelötet werden – nach dem Zusammenbau kann es direkt mit dem Programmieren losgehen. Das macht ihn besonders für den Informatikunterricht geeignet, wo der Schwerpunkt ohnehin auf der Software liegt.

Kompatibel ist der Funbot mit einer ganzen Reihe von Mikrocontrollern: Arduino UNO, Arduino NANO, ESP32 und Raspberry Pi Pico, jeweils samt Boards in gleicher Bauform. Programmiert werden kann klassisch mit der Arduino IDE oder visuell auf Blockbasis, etwa mit OpenRoberta.

Roboterfahrzeug auf einer Platine mit Rädern, Ultraschallsensor und LEDs
Der fertig aufgebaute Funduino Funbot

Den Funbot zusammenbauen

Der Zusammenbau besteht aus vier Handgriffen:

  • Platine vorbereiten: Brich die Ränder vorsichtig an den Sollbruchstellen heraus und leg dir die einzelnen Komponenten neben die Platine.
  • Motoren montieren: Die beiden Motoren kommen mit den weißen Halterungen an die Unterseite. Der überstehende Teil der Halterung zeigt nach außen, und auf beiden Seiten liegen jeweils die gleichen Kabelfarben.
  • Kugelrolle montieren: Sie wird mit den kurzen Nylonschrauben und den Abstandshaltern vorn an der Unterseite befestigt.
  • Komponenten ergänzen: Die übrigen Module steckst du in die dafür vorgesehenen Anschlüsse – fertig.

Achte beim Einstecken der Motoren auf die Seite: Von oben betrachtet gehört der linke Motor in den linken Stecker und der rechte in den rechten. Dreht sich später ein Rad falsch herum, ist das kein Beinbruch – dann tauschst du im Sketch einfach die beiden Richtungspins.

Unterseite des Funbot mit montierten Motoren und Kugelrolle
Motoren und Kugelrolle an der Unterseite der Platine

Stromversorgung

Zum Programmieren und Testen genügt das USB-Kabel: Alle Module lassen sich damit ansprechen. Nur für die Antriebsmotoren reicht die Leistung nicht zuverlässig aus.

Soll der Funbot frei fahren, schließt du deshalb eine externe Spannungsquelle mit 6 bis 9 Volt Gleichspannung an die DC-Buchse an. Ein Spannungswandler auf der Platine macht daraus die 5 Volt für den Mikrocontroller – eine zweite Stromquelle brauchst du also nicht.

Praktisch: Batterie und USB-Kabel dürfen gleichzeitig angeschlossen sein. Du kannst also programmieren, ohne ständig umzustecken.

Praxistipp: Es gibt wiederaufladbare 9-V-Blocks, die sich per USB-Kabel laden lassen. Das schont die Umwelt und den Geldbeutel – gerade wenn mehrere Gruppen gleichzeitig arbeiten.

Die Module des Funbot im Überblick

Diese Bauteile sitzen auf der Platine und lassen sich über den Mikrocontroller programmieren:

  • Frontscheinwerfer – zwei LEDs vorn, gemeinsam über Pin A1 geschaltet, mit 200-Ohm-Vorwiderstand
  • Zwei Taster – links an Pin A2, rechts an Pin A3, jeweils mit 10-kOhm-Pulldown
  • Lautsprecher – an Pin A0, ein passives Bauteil: der Ton muss per tone-Befehl erzeugt werden
  • Zwei N20-Antriebsmotoren – über den Motortreiber L293D angesteuert
  • Sechs WS2812B-Pixel an der Unterseite – an Pin 13, einzeln in tausenden Farben ansteuerbar
  • Ultraschallsensor RCW-0001 – arbeitet wie der bekannte HC-SR04, läuft aber mit 5V und mit 3,3V
  • Liniensensor – wird vorn waagerecht eingesteckt, meldet hell oder dunkel als digitales Signal
  • Lagesensor MPU6050 – Gyroskop und Beschleunigungssensor, über I2C angebunden

Erweitern lässt sich der Funbot mit eigenen 3D-Anbauteilen. Die Grundplatte mit ihren Bohrungen steht als STL-Datei bereit, sodass sich Träger für weitere Module – bis hin zu KI-Kameras wie der Pixycam oder der Huskylens – aufbauen lassen.

Die sechs Pixel an der Unterseite tragen die Nummern 0 bis 5 – die Zählung beginnt wie in der Programmierung üblich bei null.

Lektion 1: Die blinkenden Frontscheinwerfer

Die blinkende Leuchtdiode ist das klassische erste Programm der Mikroelektronik – und sie bringt gleich drei Grundbausteine mit.

Aufgabe: Schalte die vorderen Leuchtdioden ein, warte eine Sekunde, schalte sie wieder aus und warte erneut eine Sekunde.

  • Die Variable ganz oben merkt sich, an welchem Pin die LEDs hängen. int steht für Integer, also eine Ganzzahl. Den Namen darfst du frei wählen – er muss nur im ganzen Sketch derselbe bleiben.
  • Im Setup legt pinMode fest, dass an diesem Pin etwas ausgegeben werden soll: OUTPUT.
  • Im Loop schaltet digitalWrite die LEDs mit HIGH ein und mit LOW aus.

Ohne die beiden delay-Befehle würde das Blinken so schnell ablaufen, dass wir es nicht sehen könnten – die LEDs erschienen einfach dauerhaft an. Erst die Pausen machen den Wechsel sichtbar. Und weil der Loop sofort wieder von vorn beginnt, braucht es die zweite Pause auch nach dem Ausschalten.

Die LEDs hängen an A1 – einem analogen Pin. Trotzdem sprichst du sie mit digitalWrite an. Das ist kein Widerspruch: Analoge Pins können alles, was digitale Pins können, und zusätzlich analoge Werte einlesen.

Zum Weiterdenken: Was passiert eigentlich, wenn du die zweite Pause an den Anfang des Loop-Teils setzt?

Lektion 1: Die blinkenden Frontscheinwerfer
int modul_LED = A1;

void setup()
{
  pinMode(modul_LED, OUTPUT);
}

void loop()
{
  digitalWrite(modul_LED, HIGH);  // Scheinwerfer an
  delay(1000);                    // eine Sekunde warten
  digitalWrite(modul_LED, LOW);   // Scheinwerfer aus
  delay(1000);                    // eine Sekunde warten
}

Lektion 2: Die beiden Taster auswerten

Aufgabe: Beim Druck auf den linken Taster sollen die Scheinwerfer zwei Sekunden leuchten, beim rechten Taster vier Sekunden.

Neu sind hier drei Dinge. Erstens bekommt ein Taster im Setup ein INPUT statt eines OUTPUT – an diesem Pin soll ja etwas eingelesen werden. Zweitens liest digitalRead den Zustand des Pins aus und legt ihn in einer Variablen ab: 1 für HIGH, 0 für LOW.

Drittens kommt die if-Abfrage ins Spiel. Sie führt einen Abschnitt nur dann aus, wenn eine Bedingung erfüllt ist – genau wie im Alltag: Wenn Regen vorhergesagt ist, nimmst du einen Schirm mit. Hier lautet die Bedingung: Ist der Wert der Taster-Variablen genau 1?

In der Bedingung stehen zwei Gleichheitszeichen. Ein einzelnes = weist einer Variablen einen Wert zu; zwei == vergleichen zwei Werte miteinander. Das ist einer der häufigsten Anfängerfehler überhaupt.

Achte auf sprechende Namen: TasterL für links, TasterR für rechts. In diesem kleinen Sketch ist das noch egal – sobald du aber alle Module zusammen programmierst, entscheidet die Benennung darüber, ob du dich noch zurechtfindest.

Lektion 2: Beide Taster auswerten
int modul_TasterL = A2;
int modul_TasterR = A3;
int modul_LED = A1;

int TasterL_status = 0;
int TasterR_status = 0;

void setup()
{
  pinMode(modul_TasterL, INPUT);
  pinMode(modul_TasterR, INPUT);   // auch der rechte Taster ist ein Eingang
  pinMode(modul_LED, OUTPUT);
}

void loop()
{
  // Linker Taster: Scheinwerfer fuer 2 Sekunden
  TasterL_status = digitalRead(modul_TasterL);
  if (TasterL_status == 1)
  {
    digitalWrite(modul_LED, HIGH);
    delay(2000);
    digitalWrite(modul_LED, LOW);
  }

  // Rechter Taster: Scheinwerfer fuer 4 Sekunden
  TasterR_status = digitalRead(modul_TasterR);
  if (TasterR_status == 1)
  {
    digitalWrite(modul_LED, HIGH);
    delay(4000);
    digitalWrite(modul_LED, LOW);
  }
}

Lektion 3: Töne mit dem Lautsprecher

Aufgabe: Immer wenn der Lautsprecher einen Ton abgibt, sollen auch die Scheinwerfer leuchten. Danach folgt eine kurze Pause, dann beginnt es von vorn.

Der Lautsprecher am Pin A0 ist ein Ausgang – schließlich gibt der Mikrocontroller etwas an ihn aus. Trotzdem brauchst du für ihn kein pinMode im Setup: Der Befehl tone erledigt das von selbst.

Zwei Befehle gehören zusammen: tone startet den Ton mit einer bestimmten Tonhöhe, noTone schaltet ihn wieder ab. Beachte die Schreibweise mit großem T – die Arduino-Software unterscheidet streng zwischen Groß- und Kleinschreibung.

Der Lautsprecher auf dem Funbot ist ein passives Bauteil. Ein einfaches digitalWrite mit HIGH erzeugt deshalb keinen Ton, sondern höchstens ein Knacken – der Ton muss vom Mikrocontroller erzeugt werden.

Zum Weiterdenken: Wie müsste das Programm aussehen, wenn Licht und Ton abwechselnd statt gleichzeitig laufen sollen?

Lektion 3: Ton und Licht im Wechsel
int modul_speaker = A0;
int modul_led = A1;

void setup()
{
  pinMode(modul_led, OUTPUT);
  // Fuer den Lautsprecher ist kein pinMode noetig:
  // der tone-Befehl kuemmert sich selbst darum.
}

void loop()
{
  tone(modul_speaker, 100);        // Ton mit 100 Hertz ausgeben
  digitalWrite(modul_led, HIGH);   // Scheinwerfer an
  delay(1000);

  noTone(modul_speaker);           // Ton abschalten
  digitalWrite(modul_led, LOW);    // Scheinwerfer aus
  delay(1000);
}

Lektion 4: Die Antriebsmotoren

Die beiden N20-Motoren bekommen ihren Strom nicht vom Mikrocontroller – dessen Pins sind dafür zu schwach. Dazwischen sitzt der Motortreiber L293D, eine H-Brücke. Der Mikrocontroller schickt nur Steuersignale, die Leistung schaltet der Treiber.

Jeder Motor hat zwei Richtungseingänge. Aus ihrer Kombination ergibt sich, was der Motor tut:

  • HIGH und HIGH – der Motor steht still
  • HIGH und LOW – der Motor dreht in die eine Richtung
  • LOW und HIGH – der Motor dreht in die andere Richtung
  • LOW und LOW – der Motor steht still

Die Geschwindigkeit regelt ein dritter Pin, der Enable-Pin. Weil digitalWrite nur an und aus kennt, kommt hier analogWrite zum Einsatz: Werte zwischen 0 und 255 bestimmen, wie viel Leistung der Treiber durchlässt. Dahinter steckt die Pulsweitenmodulation, die nur an bestimmten Pins funktioniert – auf dem Funbot sind dafür passende Pins verdrahtet.

Aufgabe: Lass zunächst nur den linken Motor mit voller Leistung drehen. Erweitere den Sketch danach so, dass sich das Rad zwei Sekunden vorwärts dreht, eine Sekunde steht und sich dann zwei Sekunden rückwärts dreht.

Dreht sich ein Rad verkehrt herum, liegt das an der Bauart und ist kein Fehler. Vertausche dann im Sketch einfach die beiden Richtungspins dieses Motors – aus MotorLa HIGH und MotorLb LOW wird MotorLa LOW und MotorLb HIGH.

Skizze des Motortreibers mit den nummerierten Leitungen zu beiden Motoren
Die Verkabelung der beiden Motoren mit dem Motortreiber L293D
Lektion 4: Den linken Motor drehen lassen
int MSL = 9;        // Motor Speed Links - Enable-Pin des linken Motors
int MotorLa = 7;    // Richtungspin a
int MotorLb = 8;    // Richtungspin b

void setup()
{
  pinMode(MSL, OUTPUT);
  pinMode(MotorLa, OUTPUT);
  pinMode(MotorLb, OUTPUT);
}

void loop()
{
  analogWrite(MSL, 255);           // volle Geschwindigkeit (0 bis 255)
  digitalWrite(MotorLa, LOW);      // eine Richtung: a LOW, b HIGH
  digitalWrite(MotorLb, HIGH);
}

Lektion 5: Fahr, kleiner Roboter!

Damit der Funbot wirklich fährt, müssen sich beide Räder drehen. Der Schritt von einem zu zwei Motoren ist klein: Du ergänzt die drei Variablen für den rechten Motor – MSR für die Geschwindigkeit sowie MotorRa und MotorRb für die Richtung –, legst sie im Setup als Ausgänge fest und steuerst sie im Loop genauso an wie den linken.

Probier danach aus, was passiert, wenn du die Geschwindigkeiten unterschiedlich wählst. Schaffst du es, den Funbot im Kreis fahren zu lassen?

Lektion 5: Beide Motoren - der Funbot faehrt
int MSL = 9;        // linker Motor
int MotorLa = 7;
int MotorLb = 8;

int MSR = 6;        // rechter Motor
int MotorRa = 5;
int MotorRb = 4;

void setup()
{
  pinMode(MSL, OUTPUT);
  pinMode(MotorLa, OUTPUT);
  pinMode(MotorLb, OUTPUT);
  pinMode(MSR, OUTPUT);
  pinMode(MotorRa, OUTPUT);
  pinMode(MotorRb, OUTPUT);
}

void loop()
{
  analogWrite(MSL, 255);
  digitalWrite(MotorLa, LOW);
  digitalWrite(MotorLb, HIGH);

  analogWrite(MSR, 255);
  digitalWrite(MotorRa, LOW);
  digitalWrite(MotorRb, HIGH);
}

Lektion 6: Der Linie folgen

Jetzt bekommt der Funbot zum ersten Mal einen Sensor, der seine Fahrt steuert. Ziel: Er folgt selbstständig einer schwarzen Linie – zum Beispiel einem Streifen Isolierband auf dem Tisch.

Dazu muss er Kurven fahren können. Das geht über die Geschwindigkeit: Dreht der linke Motor schneller als der rechte, fährt der Funbot eine Rechtskurve – und umgekehrt.

Der Liniensensor liefert dieselbe Art von Signal wie ein Taster: 1 für hellen Untergrund, 0 für die dunkle Linie. Du liest ihn deshalb genauso aus wie den Taster in Lektion 2.

Neu ist die Erweiterung der if-Abfrage um else: Damit legst du fest, was passieren soll, wenn die Bedingung gerade nicht erfüllt ist. In Worten lautet das Programm: Wenn heller Untergrund erkannt wird, fahr nach rechts. Ansonsten fahr nach links. So pendelt der Funbot an der Kante der Linie entlang.

Kalibriere den Sensor, bevor du den Sketch lädst. Stell den Funbot so hin, dass der Sensor über der schwarzen Linie steht, und dreh mit einem kleinen Schraubendreher am blauen Potentiometer, bis die Status-LED am Sensor ausgeht. Dreh nicht zu weit – sonst geht sie über hellem Untergrund nicht wieder an.

Ein Zwischenschritt hilft beim Prüfen: Lass zuerst nur die Scheinwerfer leuchten, wenn die Linie erkannt wird. Erst wenn das zuverlässig klappt, kommen die Motoren dazu.

Lektion 6: Der Linie folgen
int modul_Tracking = 12;
int Tracking_status = 0;

int MSL = 9;
int MotorLa = 7;
int MotorLb = 8;

int MSR = 6;
int MotorRa = 5;
int MotorRb = 4;

void setup()
{
  pinMode(modul_Tracking, INPUT);
  pinMode(MSL, OUTPUT);
  pinMode(MotorLa, OUTPUT);
  pinMode(MotorLb, OUTPUT);
  pinMode(MSR, OUTPUT);
  pinMode(MotorRa, OUTPUT);
  pinMode(MotorRb, OUTPUT);
}

void loop()
{
  Tracking_status = digitalRead(modul_Tracking);

  if (Tracking_status == 1)
  {
    // Heller Untergrund erkannt: Rechtskurve,
    // der linke Motor dreht schnell, der rechte langsam.
    analogWrite(MSL, 255);
    digitalWrite(MotorLa, LOW);
    digitalWrite(MotorLb, HIGH);

    analogWrite(MSR, 40);
    digitalWrite(MotorRa, LOW);
    digitalWrite(MotorRb, HIGH);
  }
  else
  {
    // Dunkle Linie erkannt: Linkskurve,
    // jetzt dreht der rechte Motor schnell.
    analogWrite(MSL, 40);
    digitalWrite(MotorLa, LOW);
    digitalWrite(MotorLb, HIGH);

    analogWrite(MSR, 255);
    digitalWrite(MotorRa, LOW);
    digitalWrite(MotorRb, HIGH);
  }
}

Lektion 7: Abstand messen mit Ultraschall

Der Ultraschallsensor arbeitet wie eine Fledermaus: Er sendet Schallwellen aus und wartet darauf, dass sie von einem Gegenstand zurückgeworfen werden. Aus der Laufzeit lässt sich die Entfernung berechnen.

Zwei Pins sind daran beteiligt: Trigger startet die Messung, Echo meldet die Rückkehr der Welle. Den Trigger schaltest du dafür kurz auf LOW, dann für 10 Mikrosekunden auf HIGH und wieder zurück auf LOW.

Die Laufzeit misst der Befehl pulseIn – der vorletzte Buchstabe ist ein großes i, kein kleines L. Weil die gemessene Zeit den Hin- und den Rückweg umfasst, wird sie halbiert und dann mit der Schallgeschwindigkeit multipliziert:

Entfernung = (gemessene Zeit ÷ 2) × Schallgeschwindigkeit

Aufgabe: Miss den Abstand zu deiner Hand oder einer Wand. Liegt er unter 30 Zentimetern, sollen die Scheinwerfer aufleuchten.

Hier taucht zum ersten Mal ein neuer Datentyp auf: float. Ein int kennt nur ganze Zahlen – für die Schallgeschwindigkeit von 0,0341 Zentimetern je Mikrosekunde brauchst du Nachkommastellen. Wichtig: Im Sketch schreibst du 0.0341 mit Punkt, nicht mit Komma.

Lektion 7: Abstand messen und bei unter 30 cm leuchten
int modul_led = A1;
int modul_trigger = 10;
int modul_echo = 11;

float entfernung = 0;
float gemessene_zeit = 0;
float zeit_pro_strecke = 0;

// Schallgeschwindigkeit in Zentimetern je Mikrosekunde
float schallgeschwindigkeit = 0.0341;

void setup()
{
  pinMode(modul_led, OUTPUT);
  pinMode(modul_trigger, OUTPUT);
  pinMode(modul_echo, INPUT);
}

void loop()
{
  // Trigger kurz ausschalten, damit keine Stoersignale anliegen
  digitalWrite(modul_trigger, LOW);
  delayMicroseconds(5);

  // Messung starten: 10 Mikrosekunden HIGH
  digitalWrite(modul_trigger, HIGH);
  delayMicroseconds(10);
  digitalWrite(modul_trigger, LOW);

  // Zeit messen, bis das Echo eintrifft
  gemessene_zeit = pulseIn(modul_echo, HIGH);

  // Nur der Hinweg zaehlt, also durch zwei teilen
  zeit_pro_strecke = gemessene_zeit / 2;

  // Weg = Zeit mal Geschwindigkeit
  entfernung = zeit_pro_strecke * schallgeschwindigkeit;

  if (entfernung < 30)
  {
    digitalWrite(modul_led, HIGH);
    delay(1000);
    digitalWrite(modul_led, LOW);
  }
}

Lektion 8: Fahren und vor Hindernissen anhalten

Jetzt werden zwei Lektionen zusammengeführt: Der Funbot fährt geradeaus und misst dabei laufend den Abstand nach vorn. Taucht ein Gegenstand näher als 30 Zentimeter auf, bleibt er stehen.

Das Zusammenführen läuft immer nach demselben Muster ab: Die Variablen beider Sketche kommen nach oben, die pinMode-Zeilen beider Sketche ins Setup, und im Loop stehen erst die Motorbefehle und danach die Messung. In die if-Abfrage kommt schließlich der Code, der beide Motoren stoppt – beide Richtungspins auf LOW und die Geschwindigkeit auf 0.

Achte beim Zusammenführen darauf, wirklich beide Motoren anzusprechen. Ein häufiger Fehler ist, den Block für den linken Motor zu kopieren und dabei zu vergessen, die Variablennamen auf den rechten zu ändern – dann fährt der Funbot Kreise statt geradeaus.

Lektion 8: Fahren und vor einem Hindernis anhalten
int modul_led = A1;
int modul_trigger = 10;
int modul_echo = 11;

float entfernung = 0;
float gemessene_zeit = 0;
float zeit_pro_strecke = 0;
float schallgeschwindigkeit = 0.0341;

int MSL = 9;
int MotorLa = 7;
int MotorLb = 8;

int MSR = 6;
int MotorRa = 5;
int MotorRb = 4;

void setup()
{
  pinMode(modul_led, OUTPUT);
  pinMode(modul_trigger, OUTPUT);
  pinMode(modul_echo, INPUT);
  pinMode(MSL, OUTPUT);
  pinMode(MotorLa, OUTPUT);
  pinMode(MotorLb, OUTPUT);
  pinMode(MSR, OUTPUT);
  pinMode(MotorRa, OUTPUT);
  pinMode(MotorRb, OUTPUT);
}

void loop()
{
  // Beide Motoren vorwaerts
  analogWrite(MSR, 255);
  digitalWrite(MotorRa, LOW);
  digitalWrite(MotorRb, HIGH);

  analogWrite(MSL, 255);
  digitalWrite(MotorLa, LOW);
  digitalWrite(MotorLb, HIGH);

  // Abstand messen
  digitalWrite(modul_trigger, LOW);
  delayMicroseconds(5);
  digitalWrite(modul_trigger, HIGH);
  delayMicroseconds(10);
  digitalWrite(modul_trigger, LOW);

  gemessene_zeit = pulseIn(modul_echo, HIGH);
  zeit_pro_strecke = gemessene_zeit / 2;
  entfernung = zeit_pro_strecke * schallgeschwindigkeit;

  // Hindernis naeher als 30 cm: beide Motoren stoppen
  if (entfernung < 30)
  {
    analogWrite(MSR, 0);
    digitalWrite(MotorRa, LOW);
    digitalWrite(MotorRb, LOW);

    analogWrite(MSL, 0);
    digitalWrite(MotorLa, LOW);
    digitalWrite(MotorLb, LOW);
  }
}

Lektion 9: Die Unterbodenbeleuchtung

Die sechs WS2812B-Pixel an der Unterseite lassen sich einzeln in tausenden Farben ansteuern – und das über eine einzige Datenleitung. Im Unterricht sind sie mehr als Deko: Sie machen sichtbar, in welchem Programmabschnitt der Roboter gerade steckt. Leuchtet er grün, soll er fahren; fährt er trotzdem nicht, liegt der Fehler bei den Motoren und nicht in der Logik.

Hier kommt zum ersten Mal eine Bibliothek ins Spiel: fertiger Code, den andere geschrieben haben und den du in deinem Sketch mitbenutzt. Installiere sie über Sketch → Bibliothek einbinden → Bibliotheken verwalten und suche dort nach Adafruit NeoPixel.

Im Sketch rufst du sie mit #include auf. Danach fasst du die sechs Pixel zu einem Objekt namens BodenLED zusammen und übergibst ihm vier Angaben: Anzahl der Pixel, Datenpin, Farbraum und Frequenz.

Aufgabe: Lass die Pixel 0 und 1 rot, die Pixel 2 und 3 grün und die Pixel 4 und 5 blau leuchten. Die Farben gibst du als RGB-Werte an – Rot ist (255, 0, 0), Grün (0, 255, 0) und Blau (0, 0, 255).

setPixelColor legt nur fest, welche Farbe ein Pixel bekommen soll – sichtbar wird davon noch nichts. Erst BodenLED.show() schickt alle gesetzten Farben gemeinsam an die Pixel. Ohne diese Zeile bleibt die Unterbodenbeleuchtung dunkel.

Zum Weiterprobieren: Welche Farbe ergeben die Werte (71, 138, 132)?

Bibliotheksverwalter der Arduino IDE mit der Adafruit-NeoPixel-Bibliothek
Die Bibliothek „Adafruit NeoPixel“ im Bibliotheksverwalter
Lektion 9: Die sechs Pixel in drei Farben
#include <Adafruit_NeoPixel.h>

#define PIN 13        // Datenleitung der Pixel
#define NUMPIXELS 6   // Anzahl der Pixel auf dem Funbot

Adafruit_NeoPixel BodenLED = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

void setup()
{
  BodenLED.begin();   // Objekt starten - vergleichbar mit pinMode
}

void loop()
{
  // setPixelColor legt die Farbe fest, zeigt sie aber noch nicht an.
  BodenLED.setPixelColor(0, BodenLED.Color(255, 0, 0));   // rot
  BodenLED.setPixelColor(1, BodenLED.Color(255, 0, 0));
  BodenLED.setPixelColor(2, BodenLED.Color(0, 255, 0));   // gruen
  BodenLED.setPixelColor(3, BodenLED.Color(0, 255, 0));
  BodenLED.setPixelColor(4, BodenLED.Color(0, 0, 255));   // blau
  BodenLED.setPixelColor(5, BodenLED.Color(0, 0, 255));

  BodenLED.show();    // erst dieser Befehl schaltet die Pixel wirklich um
}

Lektion 10: Der Lagesensor MPU6050

Der MPU6050 vereint zwei Sensoren in einem Chip: ein Gyroskop, das Drehungen um die X-, Y- und Z-Achse erfasst, und einen Beschleunigungssensor. Zusammen ergeben sie die Orientierung im dreidimensionalen Raum – dieselbe Technik steckt in VR-Brillen und in der Fluglageregelung von Modellflugzeugen.

Angebunden ist er über den I2C-Bus, also über die Pins A4 und A5. Die passende Bibliothek heißt TinyMPU6050 von Gabriel Milan und wird wie die NeoPixel-Bibliothek über den Bibliotheksverwalter installiert.

Aufgabe: Lass dir den Drehwinkel um die Z-Achse im Seriellen Monitor anzeigen. Dreh den Funbot danach nach links und rechts und beobachte, wie sich der Wert verändert.

Drei Befehle aus der Bibliothek brauchst du dafür: MPU.Initialize() startet den Sensor, MPU.Calibrate() merkt sich die Ausgangslage, und MPU.Execute() holt im Loop die aktuellen Messwerte.

Stell den Funbot beim Hochladen gerade auf den Tisch und lass ihn stehen, bis im Seriellen Monitor „Kalibrierung abgeschlossen“ erscheint. Bewegst du ihn während der Kalibrierung, stimmt der Nullpunkt danach nicht.

Lektion 10: Den Winkel der Z-Achse auslesen
#include <TinyMPU6050.h>

// Objekt fuer den Sensor. (Wire) bedeutet: Kommunikation ueber I2C.
MPU6050 MPU(Wire);

void setup()
{
  MPU.Initialize();
  Serial.begin(9600);

  Serial.println("Kalibrierung beginnt, bitte warten!");
  MPU.Calibrate();
  Serial.println("Kalibrierung abgeschlossen");
}

void loop()
{
  MPU.Execute();   // aktuelle Messdaten abrufen

  Serial.print("Winkel Z-Achse = ");
  Serial.println(MPU.GetAngZ());
}

Lektion 11: Mit dem Lagesensor geradeaus fahren

Zwei Motoren laufen nie exakt gleich schnell – fertigungsbedingt zieht jedes Fahrzeug ein wenig zur Seite. Mit dem Lagesensor lässt sich das ausgleichen: Der Funbot merkt sich beim Start seine Ausgangsrichtung und steuert dagegen, sobald er davon abweicht.

Das Prinzip: Im Setup wird der Winkel der Z-Achse einmal ausgelesen und als Grundstellung gespeichert. Im Loop wird laufend gemessen, wie weit der aktuelle Winkel davon abweicht. Ist der Funbot nach links gewandert, dreht der rechte Motor langsamer – und umgekehrt.

Der Sketch führt zusammen, was du in den Lektionen zu den Motoren und zum Lagesensor gelernt hast. Er ist durchgehend kommentiert; die ausführlichen Erklärungen stehen in den beiden Lektionen davor.

Der Funbot fährt damit nicht schnurgerade, sondern in leichten Bogen um die gewünschte Richtung herum – er korrigiert ständig nach. Das ist der einfachste Fall einer Regelung. Wer mag, kann die Gegensteuerung sanfter machen, indem er den Unterschied zwischen den beiden Geschwindigkeiten verringert.

Aus demselben Prinzip lässt sich auch eine Drehung um genau 90 Grad bauen: einfach so lange drehen, bis die Abweichung 90 erreicht hat.

Lektion 11: Mit dem Lagesensor geradeaus fahren
// Zuerst werden Bibliotheken eingebunden und Variablen erstellt.

// 1. Fuer den Lagesensor
#include <TinyMPU6050.h>
MPU6050 MPU(Wire);
float Grundstellung = 0;
float Abweichung = 0;

// 2. Fuer die Motoren
int MSL = 9;
int MotorLa = 7;
int MotorLb = 8;
int MSR = 6;
int MotorRa = 5;
int MotorRb = 4;

void setup() {
  // Serielle Verbindung starten, um die Messwerte mitlesen zu koennen
  Serial.begin(9600);

  // Ein- und Ausgaenge festlegen
  pinMode(MSL, OUTPUT);
  pinMode(MotorLa, OUTPUT);
  pinMode(MotorLb, OUTPUT);
  pinMode(MSR, OUTPUT);
  pinMode(MotorRa, OUTPUT);
  pinMode(MotorRb, OUTPUT);

  // Sensor starten und kalibrieren
  MPU.Initialize();
  Serial.println("Kalibrierung beginnt, bitte warten!");
  MPU.Calibrate();
  Serial.println("Kalibrierung abgeschlossen");

  // Einmalig die Ausgangslage erfassen und merken
  MPU.Execute();
  Grundstellung = MPU.GetAngZ();
}

void loop() {
  // Aktuelle Messwerte des Lagesensors holen
  MPU.Execute();

  // Wie weit ist der Funbot von seiner Ausgangslage abgewichen?
  // Dafuer wird die Grundstellung vom aktuellen Wert abgezogen.
  Abweichung = MPU.GetAngZ() - Grundstellung;
  Serial.println(Abweichung);

  // Info: Gegen den Uhrzeigersinn nimmt der Wert zu,
  // im Uhrzeigersinn wird er kleiner und auch negativ.
  if (Abweichung >= 0) {
    // Nach links abgewichen, also leicht nach rechts gegensteuern
    analogWrite(MSL, 255);
    digitalWrite(MotorLa, LOW);
    digitalWrite(MotorLb, HIGH);

    analogWrite(MSR, 40);
    digitalWrite(MotorRa, LOW);
    digitalWrite(MotorRb, HIGH);
  }
  else {
    // Nach rechts abgewichen, also leicht nach links gegensteuern
    analogWrite(MSL, 40);
    digitalWrite(MotorLa, LOW);
    digitalWrite(MotorLb, HIGH);

    analogWrite(MSR, 255);
    digitalWrite(MotorRa, LOW);
    digitalWrite(MotorRb, HIGH);
  }
}
Évaluer le guide

Commentaires

Poser une question ou partager une expérience

Écris-nous si quelque chose ne fonctionne pas. Indique-nous ton modèle de carte et le message d’erreur.

Nous vérifions chaque commentaire avant sa publication. Ton adresse e-mail reste chez nous.