Selsyn Gauge MQTT Controller
MQTT-based gauge controller for ESP32 / MicroPython. Drives a VID28/BKA30D/X25 stepper gauge and integrates with Home Assistant via MQTT.
Files
| File | Description |
|---|
boot.py | WiFi connect + OTA trigger |
ota.py | Gitea API poller for OTA updates |
ota_config.json | OTA config (create from ota_config.example.json) |
ota_config.example.json | OTA config template |
gaugemqttcontinuous.py | Main MQTT controller |
gauge_vid6008.py | Stepper driver for VID28/BKA30D/X25 gauges |
main.py | Entry point, calls ota.mark_ok() on success |
config.json | Application config (create from config.example.json) |
config.example.json | Template with all options |
Deployment
# First time: upload via USB
ampy --port /dev/ttyUSB0 put boot.py
ampy --port /dev/ttyUSB0 put ota.py
ampy --port /dev/ttyUSB0 put ota_config.json
ampy --port /dev/ttyUSB0 put main.py
ampy --port /dev/ttyUSB0 put gaugemqttcontinuous.py
ampy --port /dev/ttyUSB0 put gauge_vid6008.py
ampy --port /dev/ttyUSB0 put config.json
# Monitor serial output
minicom -D /dev/ttyUSB0 -b 115200
MQTT Topics
All topics are prefixed with mqtt_prefix:
| Topic | Direction | Description |
|---|
/set | ← | Target value from HA |
/state | → | Current value |
/status | → | online/offline |
/zero | ← | Trigger zero calibration |
/led/red/set | ← | ON/OFF |
/led/red/state | → | ON/OFF |
/led/green/set | ← | ON/OFF |
/led/green/state | → | ON/OFF |
/led/backlight/set | ← | {"state": "ON"/"OFF", "color": {"r","g","b"}, "brightness": 0-255} |
/led/backlight/state | → | Current backlight state |
Configuration
Copy config.example.json to config.json and ota_config.example.json to ota_config.json and edit:
WiFi
WiFi credentials are in ota_config.json (shared with OTA settings), not config.json.
MQTT
| Key | Default | Description |
|---|
mqtt_broker | — | Broker IP/hostname |
mqtt_port | 1883 | Broker port |
mqtt_user | — | MQTT username |
mqtt_password | — | MQTT password |
mqtt_client_id | — | Unique client ID |
mqtt_prefix | — | Topic prefix for all MQTT messages |
Gauge
| Key | Default | Description |
|---|
gauge_pins | [12, 13] | GPIO pins (4phase: IN1-4, stepdir: DIR, STEP) |
gauge_mode | stepdir | Driver mode: stepdir (DIR+STEP) or 4phase (full-wave) |
gauge_min | 0 | Minimum value |
gauge_max | 7300 | Maximum value |
gauge_pulse | 4 | Pulse width in milliseconds |
gauge_half_step | false | Use 8-phase half-step mode (1200 steps, smoother) |
smooth_step_ms | 50 | Smooth movement interval |
idle_release_ms | 3000 | Release coils after idle (ms) |
rezero_interval_ms | 3600000 | Auto-rezero interval (ms, default 1hr) |
OTA
| Key | Default | Description |
|---|
gitea_base | — | Gitea server URL (no trailing slash) |
repo_owner | — | Repository owner |
repo_name | — | Repository name |
repo_folder | — | Folder inside repo to sync |
repo_branch | main | Branch to track |
api_token | — | API token for private repos |
wifi_ssid | — | WiFi network name |
wifi_password | — | WiFi password |
LEDs
| Key | Default | Description |
|---|
led_red_pin | 33 | Red LED GPIO pin |
led_green_pin | 32 | Green LED GPIO pin |
led_bl_pin | 23 | RGB backlight (WS2812/NeoPixel) GPIO pin |
Home Assistant Discovery
| Key | Default | Description |
|---|
device_name | “Selsyn 1” | Device name in HA |
device_model | “Chernobyl Selsyn-inspired gauge” | Device model |
device_manufacturer | “AdeBaumann” | Device manufacturer |
device_area | “Control Panels” | Suggested area in HA |
gauge_entity_name | “Selsyn 1 Power” | Gauge entity name |
gauge_unit | “W” | Unit of measurement for gauge |
red_led_entity_name | “Selsyn 1 Red LED” | Red LED entity name |
green_led_entity_name | “Selsyn 1 Green LED” | Green LED entity name |
backlight_entity_name | “Selsyn 1 Backlight” | Backlight entity name |
backlight_unit | “%” | Unit for backlight |
Timing
| Key | Default | Description |
|---|
heartbeat_ms | 10000 | State publish interval (ms) |
OTA Updates
On each boot, boot.py connects WiFi and runs ota.update(). The updater:
- If last boot was good and commit unchanged → skip file check entirely
- Otherwise, compares file SHA1 hashes with local manifest
- Downloads changed/missing files to
.tmp, then renames into place - On success, saves manifest with commit SHA;
main.py writes OK flag
Manifest
Create ota_manifest.txt in your repo root to specify which files to sync:
boot.py # specific file
main.py # another file
*.py # wildcard (matches anywhere)
selsyn/ # entire directory (trailing slash)