Robot Telemetry System

Distributed environmental monitoring — ESP32 Bluetooth sensor nodes, Raspberry Pi hardware bridge, MQTT telemetry pipeline, and a Next.js control frontend.

Live data from https://iot.optospintronics.org · loading…

System Architecture

ESP32 Sensor Nodes

Each ESP32 samples its sensor every 10 s and stores up to 500 records in a circular buffer. Batches of 25 records are sent over Bluetooth Classic (RFCOMM) with random startup jitter, a 5 s ACK timeout, and exponential retry backoff. Records are only removed after the Pi sends the ACK byte (0x06).

Raspberry Pi — Hardware Bridge

A JDY-31 Bluetooth UART module on GPIO 14/15 (hardware UART — Pi onboard Bluetooth disabled) receives sensor batches. The Pi validates JSON, sends ACK immediately, then publishes each record to MQTT over TLS with QoS-1. A Pololu A-Star on USB handles motor commands. The Pi Camera streams MJPEG via picamera2.

MQTT · Node-RED · Database

Records are published to robot/sensors/<SENSOR_ID> with QoS-1. Node-RED subscribes with a wildcard, routes each payload to the correct sensor table, and exposes HTTP APIs consumed by both the control frontend and this website.

PC Control Frontend

A Next.js app with four pages: Controller (joystick + live camera), Sensors (Bluetooth trigger — timed Start or continuous Listen — with per-sensor cards and live data badge), Data Browser (full history with chart/table toggle), and Settings (Pi IP/port, network scan).

Live Sensor Data

Click a card to view its history chart · auto-refreshes every 30 s

BME680

active

Temperature · Humidity · Pressure · Gas Resistance

No data received yet.

click to view chart

LTR390

active

Ambient Light (Lux) · UV Index

No data received yet.

click to view chart

SCD41

active

CO₂ · Temperature · Humidity

No data received yet.

click to view chart

DHT11

active

Temperature · Humidity

No data received yet.

click to view chart

SGP41

active

VOC index · NOx index (air quality)

No data received yet.

click to view chart

Implementation Notes

Reliable Bluetooth Transfer

  • ACK sent before MQTT publish — stays within the 5 s ESP32 timeout
  • JDY-31 status lines stripped from the UART buffer before JSON parsing
  • Pi onboard Bluetooth disabled (dtoverlay=disable-bt) to free ttyAMA0
  • Frontend auto-retries on 409 (stale listener): stop → wait → restart
  • Listener skips bad records and continues — thread never killed on a single failure

Sensors Page

  • Start: timed Bluetooth window (60 s, auto-extends on each receipt)
  • Listen: continuous mode — port stays open indefinitely
  • "Latest" badge flashes green on the card that most recently received data
  • Sensor history refreshes from Node-RED on every new Bluetooth batch

Controller Page

  • Arrow joystick fixed left — sends /motors/<left>,<right> commands
  • MJPEG camera feed fixed right — streams directly from /stream.mjpg
  • Motor speeds −400 to +400; differential drive direction mapping
  • Connection auto-polled every 5 s; controls disabled when Pi unreachable

MQTT Reliability

  • loop_start() called before publish, wait_for_publish() per message
  • Without loop(), TLS closes before QoS-1 PUBACK — messages silently dropped
  • Each record published individually so partial batches are never lost