15 KiB
Handover Mobile Base Station
Dieses Repository ist eine vollständige Kopie eines fertigen Uni-Projekts zur Demonstration eines WLAN-Handover-Szenarios mit:
- einem mobilen Fahrzeug/Roboter (AlphaBot2 + Raspberry Pi + ESP32),
- mehreren ESP32-basierten Basisstationen,
- einem Webinterface zur Live-Visualisierung von Verbindungsdaten und Kamerabildern.
Das Projekt kombiniert Robotik, Embedded-Firmware, serielle Kommunikation, UDP-Weiterleitung und ein Web-Dashboard.
Projektziel
Ziel ist es, ein mobiles System zu bauen, das sich zwischen zwei WLAN-Basisstationen bewegt und dabei:
- kontinuierlich Verbindungsdaten (RSSI, verbundene Basisstation, alternative Basisstation) überträgt,
- bei besserem Signal automatisch einen Handover ausführt,
- Kamerabilder vom Fahrzeug streamt,
- alle Daten in einem Webinterface visualisiert.
Repository-Struktur
HandoverMobileBaseStation/
├── doc_vault/ # Hardware-Doku, Datenblätter, Pinout-Grafiken
├── esp_firmware/ # Arduino-ESP32-Firmware (MBS1, MBS2, Fahrzeug)
│ ├── MBS1_stripped/
│ ├── MBS2_stripped/
│ └── car_stripped/
├── robot/ # Raspberry Pi / AlphaBot2 Python-Skripte
│ ├── AlphaBot2.py
│ ├── TRSensors.py
│ ├── line_follow.py
│ ├── pid_line_follow1.py
│ ├── IRremote.py
│ ├── cam_stream.py
│ └── ReadMe.md # Teil-Doku zum Robotik-Teil
└── webinterface/
└── cotmw/ # Vue 3 + Vite Frontend + Node Serial-Bridge
├── src/
└── serial/
Gesamtarchitektur (vereinfacht)
[Raspberry Pi am Roboter]
├─ Kamera -> cam_stream.py -> JSON (image) über USB-Serial (115200)
└─ AlphaBot2 / IR / Line-Follow (lokal auf Pi)
|
v
[ESP32 im Fahrzeug: car_stripped]
- sendet Telemetrie + Kamera-JSON per UDP (Port 6666)
- wechselt zwischen AP1/AP2 je nach RSSI
|
+---------+---------+
| |
v v
[MBS1 / AP1] [MBS2 / AP2]
| |
| (direkt) | (über MBS2_1 -> UART -> MBS2_2 -> AP1)
+---------+---------+
|
v
[ESP32 MBS1 per USB an PC]
|
v
[Node Serial Backend :6666]
|
v
[Vue Webinterface (Vite)]
Hinweis zu MBS2: Im Code ist die zweite Basisstation in zwei Rollen aufgeteilt (MBS2_1 und MBS2_2). Dafür werden in der vollständigen Kette typischerweise zwei ESP32 mit derselben Sketch-Datei (aber unterschiedlichen #define-Modi) verwendet.
Komponenten im Detail
1) esp_firmware/ (ESP32 / Arduino)
MBS1_stripped (AP1 + UDP -> USB-Serial Bridge)
Datei: esp_firmware/MBS1_stripped/MBS1_stripped.ino
Funktion:
- startet einen Access Point
ESP32-AP1, - hört auf UDP Port
6666, - schreibt empfangene UDP-Pakete auf
Serial(USB, 115200 Baud), - dient als zentrale Einspeisung ins Webinterface (über den PC-USB-Port).
Wichtige Parameter (im Code):
- SSID:
ESP32-AP1 - Passwort:
PASS0000 - AP-IP:
192.168.178.1 - UDP-Port:
6666 - Baudrate:
115200
MBS2_stripped (zweite Basisstation / Relay, zwei Modi)
Datei: esp_firmware/MBS2_stripped/MBS2_stripped.ino
Die Sketch enthält zwei Rollen, die über #define ausgewählt werden:
MBS2_1: hostetESP32-AP2(Access Point)MBS2_2: verbindet sich als Client mitESP32-AP1und tunnelt Daten weiter
Modus MBS2_1 (AP2)
- startet Access Point
ESP32-AP2 - empfängt UDP-Pakete auf Port
6666 - schreibt empfangene Daten auf
SerialundSerial2 - kann damit Daten an eine zweite ESP32-Instanz weitergeben
Modus MBS2_2 (Relay zu AP1)
- verbindet sich mit
ESP32-AP1 - liest Daten von
Serial2 - sendet diese Daten per UDP an AP1 (
192.168.178.1:6666)
UART-Verbindung in MBS2_stripped
Serial2 ist auf folgende Pins gelegt:
- RX: GPIO
18 - TX: GPIO
17
Siehe auch doc_vault/esp32s3_pico_uart1_rx_tx.png.
car_stripped (Fahrzeug-ESP / Handover-Client)
Datei: esp_firmware/car_stripped/car_stripped.ino
Funktion:
- scannt verfügbare Netze (
ESP32-AP1,ESP32-AP2) - verbindet sich initial mit der stärkeren Basisstation
- sendet Statusdaten regelmäßig per UDP an das Gateway (
UDP_PORT 6666) - nimmt Kameradaten/JSON von
Serialentgegen und leitet sie per UDP weiter - führt automatischen Netzwechsel aus, wenn das andere Netz deutlich stärker ist
Handover-Logik (aus Code):
- Wechsel, wenn
otherRSSImindestens ca.3 dBmbesser ist als aktuelles RSSI.
Gesendete Statusdaten (JSON, newline-terminiert):
{"type":"text","IP":"192.168.178.x","Base Station":"ESP32-AP1","RSSI":"-56","Other Network":"ESP32-AP2","Other RSSI":"-68"}
Kameradaten (vom Raspberry Pi kommend) werden als JSON-Pakete weitergeleitet:
{"type":"image","data":"<base64-jpeg>"}
2) robot/ (Raspberry Pi + AlphaBot2)
Dieser Teil läuft auf dem Raspberry Pi auf dem Fahrzeug/Roboter.
cam_stream.py (Kamera -> ESP über Serial)
Datei: robot/cam_stream.py
Funktion:
- liest Frames von einer Pi-Kamera (
Picamera2), - konvertiert zu Graustufen,
- komprimiert/verkürzt JPEGs so, dass Base64-Daten klein bleiben (im Code
MAX_B64 = 1200), - sendet die Daten als JSON (
type=image) über Serial an den Fahrzeug-ESP, - versucht bei Serial-Abbruch automatisch die Verbindung neu aufzubauen.
Wichtige Details:
- serielle Schnittstelle ist aktuell hartkodiert auf
/dev/ttyACM1 - Baudrate:
115200 - Ausgabeformat ist newline-terminiertes JSON (wichtig für den Parser im Backend)
line_follow.py (regelbasierter Linienfolger)
Datei: robot/line_follow.py
Funktion:
- automatische Sensor-Kalibrierung (
TRSensor) - Erkennung schwarzer/weißer Linie
- einfache Korrekturlogik für Spurhaltung
- zusätzliche Erkennung stärkerer Kurven (90°-ähnliche Abbiegungen)
pid_line_follow1.py (PID-Linienfolger)
Datei: robot/pid_line_follow1.py
Funktion:
- PID-Regelung für glatteres Folgen der Linie
- Suchroutine bei Linienverlust
- konfigurierbare Parameter (
Kp,Ki,Kd, Geschwindigkeit, Timeouts)
IRremote.py (Fernsteuerung + Start/Stopp von PID-Line-Follow)
Datei: robot/IRremote.py
Funktion:
- liest IR-Signale über GPIO
- steuert den AlphaBot2 manuell (vor/zurück/links/rechts/stop)
- passt PWM-Geschwindigkeit an
- startet
pid_line_follow1.pyals separaten Prozess per Tastendruck - stoppt den PID-Line-Follow-Prozess erneut per Tastendruck
Hinweis:
- Die konkreten Tasten-Codes sind auf die verwendete Fernbedienung abgestimmt (NEC-artige IR-Codes im Skript).
AlphaBot2.py und TRSensors.py
Dateien:
robot/AlphaBot2.pyrobot/TRSensors.py
Funktion:
- Hardware-Abstraktion für Motoransteuerung (PWM, Fahrtrichtung)
- Ansteuerung und Kalibrierung des 5-Kanal-TR-Linienfolgesensors
Vorhandene Teil-Doku
Datei: robot/ReadMe.md
Enthält zusätzliche Projektnotizen zu:
- Kamera-Streaming
- Line Follow (Entwicklungsideen)
- Fernbedienungssteuerung
- systemd/Daemon-Setup auf dem Raspberry Pi
3) webinterface/cotmw/ (Vue 3 + Vite + Serial Backend)
Das Webinterface besteht aus zwei Teilen:
- einem Vue-Frontend (
webinterface/cotmw) - einem Node/Express-Backend für den Zugriff auf lokale Serial-Ports (
webinterface/cotmw/serial)
Frontend (Vue 3 + Vite)
Wichtige Dateien:
webinterface/cotmw/src/App.vuewebinterface/cotmw/src/components/*webinterface/cotmw/vite.config.js
Funktionen im UI:
- HUD mit Live-Werten:
- IP
- aktuelle Basisstation
- RSSI
- alternative Basisstation + RSSI
- Polling-Zähler
- Kamera-Widget (drag & drop)
- RSSI-Plot (aktuelle vs. alternative Basisstation)
- Topologie/Locations-Visualisierung (inkl. Handover-Animation)
- optionale Weiterleitung der Daten an externes System (
External.vue)
Verstecktes Serial-Menü
Der Serial-Connector ist absichtlich versteckt und wird per Tastenkombination eingeblendet:
Ctrl + B(Windows/Linux)Cmd + B(macOS)
Danach kann im UI:
- ein lokaler Serial-Port ausgewählt werden
- die Verbindung mit
115200Baud aufgebaut werden - der eingehende Datenstrom eingesehen werden
Das Frontend pollt anschließend standardmäßig alle 200 ms den Backend-Endpunkt /api/serial-utils/latest.
Backend (Node + Express + serialport)
Wichtige Dateien:
webinterface/cotmw/serial/server.jswebinterface/cotmw/serial/serial.jswebinterface/cotmw/serial/routes/serialUtils.js
Funktion:
- listet lokale Serial-Ports
- verbindet sich mit ausgewähltem Port
- liest eingehende Zeilen (newline-basiert)
- speichert das zuletzt empfangene
text-Paket undimage-Paket - stellt diese Daten per HTTP-API fürs Frontend bereit
API-Endpunkte (Port 6666):
GET /api/serial-utils/serialportsPOST /api/serial-utils/connectmit Body{ "path": "/dev/tty..." }GET /api/serial-utils/latest
Vite Proxy
In webinterface/cotmw/vite.config.js ist im Dev-Server ein Proxy konfiguriert:
/api->http://localhost:6666
Dadurch kann das Frontend lokal ohne CORS-Probleme auf das Serial-Backend zugreifen.
Hardware-Übersicht (praktisch)
Je nach Aufbau werden typischerweise benötigt:
- 1x AlphaBot2 (oder kompatibles Chassis mit Motorsteuerung)
- 1x Raspberry Pi (z. B. Pi 4) auf dem Fahrzeug
- 1x Pi-Kamera (Picamera2-kompatibel)
- 1x TR-Linienfolgesensor (5-Kanal)
- 1x IR-Empfänger + passende Fernbedienung
- 1x ESP32 auf dem Fahrzeug (
car_stripped) - 1x ESP32 für
MBS1_stripped - 2x ESP32 für
MBS2_stripped(einmalMBS2_1, einmalMBS2_2) bei vollem AP2-Relay-Aufbau - 1x PC/Laptop für Webinterface + Node-Backend
Software-Voraussetzungen
PC / Laptop (Webinterface + Serial Backend)
- Node.js (empfohlen: aktuelle LTS-Version)
- npm
- Zugriff auf den USB-Serial-Port des MBS1-ESP32 (Linux: ggf. Gruppe
dialout)
Raspberry Pi (Robot / Kamera)
- Raspberry Pi OS
- Python 3
Picamera2/libcameraRPi.GPIOpyserialPillow- optional/je nach Skript-Imports:
Flask,opencv-python
In robot/cam_stream.py sind bereits Beispiel-Schritte für die Kamera-Umgebung notiert (APT + venv).
ESP32-Entwicklung
- Arduino IDE mit ESP32-Boardpaket oder PlatformIO
- passende Board-Konfiguration für die verwendeten ESP32-Module
Setup und Inbetriebnahme
A) ESP32-Firmware flashen
MBS1_stripped.inoauf den ESP für AP1 flashen.MBS2_stripped.inoeinmal mit#define MBS2_1auf den AP2-ESP flashen.MBS2_stripped.inoeinmal mit#define MBS2_2auf den Relay-ESP flashen.car_stripped.inoauf den Fahrzeug-ESP flashen.
Hinweise:
- SSIDs/Passwort sind im Code hartkodiert (
ESP32-AP1,ESP32-AP2,PASS0000). - UDP-Port ist durchgehend
6666. - Baudrate ist durchgehend
115200.
B) Verkabelung / Verbindungen herstellen
Mindestens notwendig:
- Fahrzeug-ESP per USB/Serial mit Raspberry Pi verbinden (für Kamera-/JSON-Übergabe)
- MBS1-ESP per USB/Serial mit PC/Laptop verbinden (für Webinterface-Datenquelle)
Für den vollen AP2-Relay-Aufbau zusätzlich:
MBS2_1undMBS2_2per UART (Serial2) verbinden (Pins siehe Firmware /doc_vault)
C) Serial-Backend starten (PC)
cd webinterface/cotmw/serial
npm install
node server.js
Das Backend läuft anschließend auf http://localhost:6666.
D) Frontend starten (PC)
cd webinterface/cotmw
npm install
npm run dev
Danach im Browser die von Vite ausgegebene URL öffnen (typisch http://localhost:5173).
E) Serial-Port im Webinterface verbinden
- Webinterface öffnen.
Ctrl + B/Cmd + Bdrücken (Serial-Menü einblenden).- Den USB-Port des MBS1-ESP32 auswählen.
Connect (Baud: 115200)klicken.
Wenn Daten ankommen, sollten Telemetrie und Kamerabild im Dashboard erscheinen.
F) Robotik-/Kamera-Skripte auf dem Raspberry Pi starten
Beispiele:
Kamerastream zum Fahrzeug-ESP
cd robot
python3 cam_stream.py
IR-Fernsteuerung + PID-Line-Follow-Start/Stopp
cd robot
python3 IRremote.py
Direkter Start des PID-Line-Followers
cd robot
python3 pid_line_follow1.py
Direkter Start des regelbasierten Line-Followers
cd robot
python3 line_follow.py
Kommunikationsformate und Schnittstellen
Serial (Pi -> Fahrzeug-ESP)
Format:
- newline-terminiertes JSON
115200Baud
Beispiel:
{"type":"image","data":"<base64-jpeg>"}\n
UDP (Fahrzeug-ESP -> Basisstationen)
- Port:
6666 - Payload: JSON-Strings (Text-Status und Kamera-Frames)
HTTP (Web-Frontend -> Serial-Backend)
Basis-API (über Vite-Proxy als /api/...):
/api/serial-utils/serialports/api/serial-utils/connect/api/serial-utils/latest
Optional: Externe Datenweiterleitung (im Webinterface)
Komponente: webinterface/cotmw/src/components/External.vue
Funktion:
- sendet Änderungen von
rssi,other_rssiundimagean einen externen HTTP-Endpunkt - Ziel-URL:
http://<ip>:<port>/api/send - Authentifizierung via Header
x-api-key
Standardwerte im UI:
- IP:
138.68.114.176 - Port:
3000
Bekannte Einschränkungen / technische Schulden
- Viele Parameter sind hartkodiert (SSID, Passwort, Ports, Serial-Pfade, IPs).
cam_stream.pyverwendet fest/dev/ttyACM1.- Es gibt keine zentrale
.env-Konfiguration. - Das Serial-Backend hält nur das zuletzt empfangene
text- undimage-Paket im Speicher. - Fehlerbehandlung und Logging sind für Demo/Prototyping ausgelegt, nicht für Produktion.
- Das Vue-Frontend enthält bewusst versteckte UI-Elemente (Serial-Menü per Shortcut).
- Die
webinterface/cotmw/package.json-Scripts sind eher Frontend-orientiert; der Serial-Server wird separat gestartet.
Troubleshooting
Keine Daten im Webinterface
- Prüfen, ob
webinterface/cotmw/serial/server.jsläuft (Port6666). - Prüfen, ob im Browser das Serial-Menü geöffnet und ein Port verbunden wurde (
Ctrl/Cmd + B). - Prüfen, ob der richtige USB-Port des MBS1-ESP32 gewählt wurde.
- Prüfen, ob Baudrate
115200verwendet wird. - Prüfen, ob tatsächlich newline-terminierte JSON-Pakete gesendet werden.
Kamera erscheint nicht / instabil
- Kamerazugriff auf dem Raspberry Pi prüfen (
libcamera,Picamera2). - Serielle Verbindung zum Fahrzeug-ESP prüfen (
/dev/ttyACM1inrobot/cam_stream.pyanpassen). - Paketgröße kann kritisch sein:
MAX_B64incam_stream.pybeeinflusst Bildqualität und Übertragbarkeit.
ESP verbindet sich nicht mit Basisstationen
- SSID/Passwort im ESP-Code prüfen (
ESP32-AP1,ESP32-AP2,PASS0000). - Sicherstellen, dass beide Access Points gestartet sind.
- Versorgungsspannung und Antennen/Position prüfen (RSSI).
Rechteprobleme bei Serial/GPIO (Linux)
- Benutzer in passende Gruppen aufnehmen (z. B.
dialout, ggf. GPIO-spezifisch je Setup). - Skripte testweise mit ausreichenden Rechten starten.
Hinweise zur Weiterentwicklung
Sinnvolle nächste Schritte für eine robustere Version:
- zentrale Konfiguration (
.env/ Config-Dateien) für SSIDs, Ports, Serial-Geräte - strukturiertere Paketprotokolle (Sequenznummern, Timestamps, Checks)
- besserer Image-Transport (Chunking statt einzelner kurzer Base64-Payloads)
- Telemetrie-Logging / Replay im Backend
- sauberer Start per
docker-compose(Web + Serial-API, sofern Host-Serial durchgereicht) - automatische Geräteerkennung und Health-Checks
Zusatzmaterial im Repository
doc_vault/ enthält u. a.:
esp32s3_pico_1_datasheet.pdfesp32s3_pico_uart1_rx_tx.png- weitere Projektdokumente (
doc_esp.odt)