2-Rad Sprachgesteuerter Roboter mit Arduino & BitVoicer Server bauen
Komponenten und Zubehör
| Arduino UNO | 1 |
| Pololu Dual MC33926 Motortreiber-Shield | 1 |
| SparkFun XBee Shield | 1 |
| Microchip RN171VX WiFi-Modul | 1 |
| SparkFun Elektret-Mikrofon Breakout (verstärkt) | 1 |
| 2WD Roboter-Chassis | 1 |
| LM1117 (TO-220) 3,3V Spannungsregler | 1 |
| Kondensator 10 µF | 1 |
| LED (diverse) | 4 |
| Widerstand 330 Ω | 4 |
| AA-Batterien (1,5 V) | 4 |
| 9V-Blockbatterie | 1 |
| 9V auf Hohlstecker Adapter | 1 |
| Steckbrücken / Draht | 17 / 1 |
| Schrauben & flexible Kunststoffklemme | 1 |
Benötigte Werkzeuge
- Lötkolben
- Zange
- Schraubendreher
Apps und Online-Dienste
- BitVoicer Server 1.0 (Lizenz erforderlich, ca. 8,90 $)
Über dieses Projekt
Dieses Tutorial zeigt den Bau eines 2WD sprachgesteuerten Roboters. Der Ansatz lässt sich auf Schritt- und Servomotoren übertragen – Referenz für jedes sprachgesteuerte Roboterprojekt mit mechanischer Bewegung.
Komponentenübersicht (ca. 150 $ gesamt): Arduino UNO (~25 $), Pololu Shield (~30 $), XBee Shield (~15 $), RN171VX WiFi (~35 $), Mikrofon (~8 $), BitVoicer Server (~9 $), Chassis (~16 $), Regler/Kondensator/LEDs/Widerstände/Batterien/Kabel (~10 $).
Signalfluss: Sprache → Bewegung
- Schallwellen → SparkFun Elektret-Breakout (Verstärkung)
- Verstärktes Signal → Arduino ADC (Digitalisierung, Pufferung)
- Audiosamples → RN171VX WiFi → BitVoicer Server (Streaming)
- BitVoicer Server: Spracherkennung
- Erkannter Text → vordefinierte Befehle → Arduino (TCP/IP)
- Arduino: Befehl dekodieren → Motoren, Dauer, Geschwindigkeit festlegen
- Pololu Shield → Motoren mit Spannung/Strom versorgen
Schritt 1: Komponenten kennenlernen
Arduino UNO R3 – Herzstück. Andere Boards möglich (z. B. DUE für Sprachantworten).
Pololu Dual MC33926 Shield – Steuert 5–28 V DC-Motoren, bis 3 A kontinuierlich. Hervorragende Dokumentation & Arduino-Library: setSpeeds(links, rechts) mit Vorzeichen für Richtung. Belegte Pins: D4,7,8,9,10,12; A0,A1; GND; 5V. Wichtig: Nur D9,D10 als PWM, Timer 2 (UNO) nicht von BVSMic (BitSophia) genutzt.
Microchip RN171VX WiFi – Serielle Steuerung, XBee-Formfaktor → passt auf SparkFun XBee Shield.
Problem & Lösung: Während WiFi sendet, tritt starkes Rauschen im Audio-ADC auf (Peak-Strom bis 240 mA stört Referenzspannung oder Antenne strahlt auf freiliegende Pins). Lösung: 3,3 V-Regler (LM1117) + 10 µF Elko auf XBee-Shield gelötet → saubere Referenz für ADC & Mikrofon. Vorher: Stille-Pegel 35/100 im Server-Monitor.
Status-LEDs auf XBee-Shield (v.l.n.r.):
- BitVoicer Server läuft / Verbindung aktiv
- Datendurchleitung aktiv
- Spracherkennungs-Engine zugewiesen
- Aktivierungswort erkannt (leuchtet nur während Aktivierungszeitraum)
Mikrofon: Analog, passende Versorgungsspannung, ≥100× Verstärkung (typisch Elektret).
2WD-Chassis: Günstiges eBay-Set: Acryl-Plattform, 2 Räder, 360°-Lenkrad, 2 Getriebemotoren (1:48), 4×AA-Halter, Encoderscheiben, Schrauben.
Schritt 2: Montage
Alle Komponenten gemäß Bildern auf Chassis montieren. Mikrofon auf Drahtbügel, Filzstreifen am Lenkrad & Schwamm an Mikrofonkabel gegen Fahrgeräusche – verbessert Spracherkennung.
Alternative: LEDs & Regler auf kleinem Steckbrett statt Auflöten.
Schritt 3: WiFi-Modul einrichten
RN171VX vollständig per Serial steuerbar: $$$ → Command Mode, Befehle senden, exit → Data Mode.
Code „WiFi Module Setup“ (unten) konfiguriert Modul für Heimnetz. Drei Stellen mit „XXXXXX“ anpassen:
set wlan ssid XXXXXX→ Netzwerkname (SSID)set wlan phrase XXXXXX→ Passwortset ip address XXXXXX→ Gewünschte statische IP
Bei anderer Authentifizierung als WPA2-PSK: set wlan auth anpassen (Doku beachten).
Wichtig: SparkFun Shield Schalter
- DLINE: Code-Upload per USB
- UART: Serielle Kommunikation mit WiFi-Modul
Beide nutzen gleichen Serial-Port am ATmega. Falsche Stellung → Upload-Fehler.
Upload-Prozedur:
- Schalter auf DLINE
- Code in Arduino IDE hochladen
- Sofort nach Upload (5 s Delay im Code) Schalter auf UART stellen
- Modul-LEDs blinken während Konfiguration (~25 s) anders
- Modul per
ping [IP]testen
Schritt 4: Roboterbewegungen planen
Zwei DC-Motoren ermöglichen komplexe Bewegungen. Tutorial beschränkt sich auf ~30 Basisbewegungen + Kombinationen. Keine Drehgeber/Ultraschall → keine Hochpräzision, aber ausreichend für Navigation.
Geschwindigkeit kalibrieren: Maßband parallel, beide Motoren 1–2 s laufen, Strecke messen. Bei mir: 13,7 cm/s bei 62,5 % Maxspeed (250/400, Pololu-Lib). 1 m → 7299 ms. Andere Strecken: Dreisatz. Kurven: ein Rad schneller / gegenläufig. Trigonometrie für Radwege nötig. Quellen: CirclePath, Two-wheeled robot motion.
Geometrische Figuren (Quadrat, Dreieck, Kreis) im Video am Ende: Kombinationen von Basisbewegungen, definiert in BitVoicer Voice Schema (nicht im Arduino-Code).
Schritt 5: Arduino-Code hochladen
Sketch „Robot Source Code“ (BVS_Demo3.ino) hochladen. Schalter auf DLINE! Vorher Libraries installieren: BitVoicer Server & Pololu Motor Driver (ZIP-Import).
Code-Highlights:
- Konstanten: Motorspeeds (STOP=0, SLOW=100, NORMAL=250, FAST=400), Richtungen (FRONT=-1, BACK=1), 40 Befehls-Codes (Byte).
- Steuerungsvariablen:
motorSpeed(aktuell),cmdDuration(ms),cmdStartTime,cmdRunning,lastFwdCmd(für „Come Back“). - WiFi-Verbindung:
Connect()/Disconnect()versetzen Modul in Command Mode, öffnen/schließen TCP-Verbindung zu Server (IP 192.168.0.11:4194). Im Loop: Reconnect bei Timeout. - RunCommand(byte cmd): Switch-Case setzt Motorgeschwindigkeiten & Dauer per
ms.setSpeeds(). Zeiten in ms aus Schritt 4.cmdRunning=true,cmdStartTime=millis().
Schritt 6: BitVoicer Server einrichten
Gerät anlegen: „Mixed Device“ namens ArduinoUnoWiFi. Communication: TCP/IP, IP des WiFi-Moduls (Schritt 3). Cues: Start/End of Activated Period aktivieren, Int16 SendData (1/0) an Gerät → LED für Aktivierungswort.
Voice Schema bauen: Sätze → Befehle (Byte-Werte aus Konstanten). Viele Satzvarianten pro Befehl möglich (z. B. „move forward one meter“ + „go forward one meter“ → gleicher Befehl). Komplexe Befehle (z. B. „do a square“) senden Befehlssequenzen mit Delays. Unbegrenzt viele Sätze möglich (hier >80).
Tipps: Default-Befehl in Optionen setzen; Befehle per Copy-Paste duplizieren.
Solution Objects zum Import: Device.sof, VoiceSchema.sof
Schritt 7: Fazit
AA-Batterien einlegen, 9V an Arduino → Roboter lebt! Nach Einschalten: WiFi-Modul verbindet, TCP-Verbindung steht (Modul-LED dauerhaft), 3 von 4 Status-LEDs leuchten → Spracherkennung bereit.
Spracherkennung sehr gut (nicht 100 %), Bewegungspräzision verbesserungswürdig. Lösung: Drehgeber an Encoderscheiben (Chassis liegt bei) für streckengesteuerte Bewegung + Ultraschall für Hindernisvermeidung. Vielleicht später – bis dahin: Viel Spaß beim Nachbauen!
Code
WiFi Module Setup (Arduino)
void setup() {
Serial.begin(115200);
pinMode(13, OUTPUT);
delay(5000);
Serial.print("$$$"); delay(1000);
Serial.println("set wlan auth 4"); delay(1000);
Serial.println("set wlan phrase XXXXXX"); delay(1000);
Serial.println("set wlan ssid XXXXXX"); delay(1000);
Serial.println("set wlan channel 0"); delay(1000);
Serial.println("set wlan join 1"); delay(1000);
Serial.println("set wlan tx 0"); delay(1000);
Serial.println("set ip dhcp 0"); delay(1000);
Serial.println("set ip address XXXXXX"); delay(1000);
Serial.println("set comm remote 0"); delay(1000);
Serial.println("set comm close 0"); delay(1000);
Serial.println("set comm open 0"); delay(1000);
Serial.println("set comm size 500"); delay(1000);
Serial.println("set comm time 50"); delay(1000);
Serial.println("set uart baud 115200"); delay(1000);
Serial.println("set uart flow 0"); delay(1000);
Serial.println("save"); delay(1000);
Serial.println("exit"); delay(1000);
digitalWrite(13, LOW);
}
void loop() { }
Robot Source Code (Arduino)
#include <BVSP.h>
#include <BVSMic.h>
#include <DualMC33926MotorShield.h>
#define BVS_RUNNING 2
#define BVS_SRE 5
#define BVS_DATA_FWD 3
#define BVS_ACT_PERIOD 6
#define BVSM_AUDIO_INPUT 3
const unsigned long STATUS_REQUEST_INTERVAL = 2000;
const unsigned long STATUS_REQUEST_TIMEOUT = 1000;
const int MIC_BUFFER_SIZE = 64;
BVSP bvsp = BVSP();
BVSMic bvsm = BVSMic();
DualMC33926MotorShield ms = DualMC33926MotorShield();
byte micBuffer[MIC_BUFFER_SIZE];
boolean connected = false;
const int SPEED_STOP = 0;
const int SPEED_SLOW = 100;
const int SPEED_NORMAL = 250;
const int SPEED_FAST = 400;
const int DIRECTION_FRONT = -1;
const int DIRECTION_BACK = 1;
int motorSpeed = SPEED_NORMAL;
unsigned long cmdDuration = 0;
unsigned long cmdStartTime = 0;
bool cmdRunning = false;
byte lastFwdCmd = 0;
// Befehls-Codes (0-39)...
const byte CMD_STOP = 0;
const byte CMD_MOVE_FORWARD = 1;
// ... (CMD_MOVE_FORWARD_1_CM bis CMD_TURN_RIGHT_45_BACKWARD = 39)
void setup() {
Serial.begin(115200);
pinMode(BVS_RUNNING, OUTPUT);
pinMode(BVS_SRE, OUTPUT);
pinMode(BVS_DATA_FWD, OUTPUT);
pinMode(BVS_ACT_PERIOD, OUTPUT);
AllLEDsOff();
bvsp.begin(Serial, STATUS_REQUEST_TIMEOUT, STATUS_REQUEST_INTERVAL);
bvsp.frameReceived = BVSP_frameReceived;
bvsm.begin();
ms.init();
}
void loop() {
if (!connected) { Connect(Serial); connected = true; bvsp.reset(); }
bvsp.keepAlive();
bvsp.receive();
digitalWrite(BVS_RUNNING, bvsp.isBVSRunning());
digitalWrite(BVS_DATA_FWD, bvsp.isDataFwdRunning());
if (bvsp.isSREAvailable()) {
digitalWrite(BVS_SRE, HIGH);
if (!bvsm.isRecording) { bvsm.setAudioInput(BVSM_AUDIO_INPUT, EXTERNAL); bvsm.startRecording(); }
if (bvsm.available) {
if (bvsp.inboundMode == FRAMED_MODE) bvsp.setInboundMode(STREAM_MODE);
int bytesRead = bvsm.read(micBuffer, MIC_BUFFER_SIZE);
bvsp.sendStream(micBuffer, bytesRead);
}
} else {
digitalWrite(BVS_SRE, LOW);
digitalWrite(BVS_ACT_PERIOD, LOW);
if (bvsm.isRecording) bvsm.stopRecording();
}
if (bvsp.hasStatusTimedOut()) {
if (bvsm.isRecording) bvsm.stopRecording();
Disconnect(Serial); AllLEDsOff(); connected = false;
}
if (cmdRunning && millis() - cmdStartTime >= cmdDuration) RunCommand(CMD_STOP);
}
void BVSP_frameReceived(byte dataType, int payloadSize) {
switch (dataType) {
case DATA_TYPE_BYTE: RunCommand(bvsp.getReceivedByte()); break;
case DATA_TYPE_INT16: digitalWrite(BVS_ACT_PERIOD, bvsp.getReceivedInt16()); break;
}
}
void RunCommand(byte cmd) {
switch (cmd) {
case CMD_STOP: ms.setSpeeds(SPEED_STOP, SPEED_STOP); cmdRunning = false; return;
case CMD_MOVE_FORWARD: lastFwdCmd = cmd; ms.setSpeeds(motorSpeed * DIRECTION_FRONT, motorSpeed * DIRECTION_FRONT); cmdDuration = 60000; break;
case CMD_MOVE_FORWARD_1_CM: lastFwdCmd = cmd; ms.setSpeeds(motorSpeed * DIRECTION_FRONT, motorSpeed * DIRECTION_FRONT); cmdDuration = 23; break;
// ... alle 40 Cases mit ms.setSpeeds() & cmdDuration ...
case CMD_COME_BACK: RunCommand(lastFwdCmd); return;
case CMD_SET_SPEED_SLOW: motorSpeed = SPEED_SLOW; return;
case CMD_SET_SPEED_NORMAL: motorSpeed = SPEED_NORMAL; return;
case CMD_SET_SPEED_FAST: motorSpeed = SPEED_FAST; return;
}
cmdStartTime = millis(); cmdRunning = true;
}
void Connect(HardwareSerial &serialPort) {
serialPort.print("$$$"); delay(500);
serialPort.println("open 192.168.0.11 4194"); delay(1000);
serialPort.println("exit"); delay(500);
}
void Disconnect(HardwareSerial &serialPort) {
serialPort.print("$$$"); delay(500);
serialPort.println("close"); delay(1000);
serialPort.println("exit"); delay(500);
}
void AllLEDsOff() {
digitalWrite(BVS_RUNNING, LOW);
digitalWrite(BVS_SRE, LOW);
digitalWrite(BVS_DATA_FWD, LOW);
digitalWrite(BVS_ACT_PERIOD, LOW);
}
Schaltplan
Herstellungsprozess
- Bluetooth-gesteuerter Raspberry Pi Roboter mit Audio-Feedback bauen
- Internet-gesteuerter Video-Streaming-Roboter mit Arduino & Raspberry Pi bauen
- RFID-Anwesenheitssystem mit Arduino & Python – Daten direkt in phpMyAdmin (XAMPP) speichern
- Interaktives Gyroskop-LED-Display mit NeoPixel-Ring & Arduino
- Android-gesteuertes Roboterfahrzeug mit Raspberry Pi Motor Shield
- Servogesteuerter Hindernisvermeidungs-Roboter: Bauen mit Arduino & HC-SR04
- Roomba Create 2 per Arduino & Android steuern – Schritt-für-Schritt
- Arduino-basierter 6-DoF Roboterarm mit Nunchuk-Steuerung
- Sprachgesteuerter Roboter mit Arduino Nano bauen
- Sprachgesteuerte Haushaltsgeräte: Bluetooth-Steuerung mit Google Assistant