2026-02-22 23:30:15 +01:00
2026-02-22 23:30:15 +01:00
2026-02-22 23:30:15 +01:00
2026-02-22 23:30:15 +01:00
2026-02-22 23:30:15 +01:00
2026-02-22 23:30:15 +01:00

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: hostet ESP32-AP2 (Access Point)
  • MBS2_2: verbindet sich als Client mit ESP32-AP1 und tunnelt Daten weiter

Modus MBS2_1 (AP2)

  • startet Access Point ESP32-AP2
  • empfängt UDP-Pakete auf Port 6666
  • schreibt empfangene Daten auf Serial und Serial2
  • 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 Serial entgegen 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 otherRSSI mindestens ca. 3 dBm besser 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.py als 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.py
  • robot/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.vue
  • webinterface/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 115200 Baud 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.js
  • webinterface/cotmw/serial/serial.js
  • webinterface/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 und image-Paket
  • stellt diese Daten per HTTP-API fürs Frontend bereit

API-Endpunkte (Port 6666):

  • GET /api/serial-utils/serialports
  • POST /api/serial-utils/connect mit 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 (einmal MBS2_1, einmal MBS2_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 / libcamera
  • RPi.GPIO
  • pyserial
  • Pillow
  • 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

  1. MBS1_stripped.ino auf den ESP für AP1 flashen.
  2. MBS2_stripped.ino einmal mit #define MBS2_1 auf den AP2-ESP flashen.
  3. MBS2_stripped.ino einmal mit #define MBS2_2 auf den Relay-ESP flashen.
  4. car_stripped.ino auf 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_1 und MBS2_2 per 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

  1. Webinterface öffnen.
  2. Ctrl + B / Cmd + B drücken (Serial-Menü einblenden).
  3. Den USB-Port des MBS1-ESP32 auswählen.
  4. 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
  • 115200 Baud

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_rssi und image an 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.py verwendet fest /dev/ttyACM1.
  • Es gibt keine zentrale .env-Konfiguration.
  • Das Serial-Backend hält nur das zuletzt empfangene text- und image-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.js läuft (Port 6666).
  • 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 115200 verwendet 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/ttyACM1 in robot/cam_stream.py anpassen).
  • Paketgröße kann kritisch sein: MAX_B64 in cam_stream.py beeinflusst 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.pdf
  • esp32s3_pico_uart1_rx_tx.png
  • weitere Projektdokumente (doc_esp.odt)
S
Description
No description provided
Readme 929 KiB
Languages
Vue 46.3%
Python 33.4%
C++ 11.3%
JavaScript 4.3%
CSS 4.3%
Other 0.4%