The architecture, the RS-485 line protocol that replaced Modbus, how settings are split between the board and the host, and the firmware-update flow.
drDRO is a three-part system connected by one serial wire:
The Kivy UI and all display / motion logic. Owns the serial link and the unit-dependent ratio maths.
STM32F411: reads scales, drives the servo, keeps persistent settings, and runs a dual-bank IAP bootloader.
The bootable Arch Linux ARM SD image that runs the host app on a Raspberry Pi.
The host talks to the board over a single half-duplex RS-485 bus at 115200 baud with auto-direction transceivers — one device, no addressing. A 30 Hz poll loop reads live state; UI actions and firmware transfers are serialised on the same wire through an async command queue so nothing interleaves.
Instead of Modbus registers, the firmware speaks a compact, CLI-friendly text protocol. Access is by named variable, not register address.
# Request: command [args] [*HH]\n (*HH = optional XOR-8 checksum)
get servo.max
# Response: key=value lines, a crc line, then a blank line
servo.max=3000.0
crc=1B
\r, \n or \r\n are all accepted; a lone \n repeats the last command.crc=HH line (XOR-8 of the body) and a blank line; an error=… line means failure.scales.pos=12345,988,0,42.sta set get settings save
load bank rollback version
help update reset
The 30 Hz hot loop uses a single sta round-trip (scale positions & speeds,
servo position / speed / target / mode); it benchmarks well over 100 Hz, leaving headroom to interleave other requests.
The variables the host reads and writes by name (mapped to firmware fields):
| Variable | Type | N | R/W | Meaning |
|---|---|---|---|---|
scales.pos | i32 | 4 | RW | Scale positions |
scales.speed | i32 | 4 | RO | Scale speeds |
scales.num / scales.den | i32 | 4 | RW | Sync ratio numerator / denominator |
scales.sync | u16 | 4 | RW | Per-scale sync enable |
scales.filt | u16 | 4 | RW | Encoder input filter (0–15) |
servo.max | f32 | 1 | RW | Max speed (steps/s) — flash-stored |
servo.acc | f32 | 1 | RW | Acceleration — flash-stored |
servo.jog | f32 | 1 | RW | Jog speed (live) |
servo.idx | f32 | 1 | RW | Indexing feedrate cap |
servo.mode | u16 | 1 | RW | 0=off, 1=sync/index, 2=jog |
servo.pos / servo.speed | — | 1 | RO | Live servo position / speed |
servo.tgt | i32 | 1 | RW | Steps-to-go (write = start indexed move) |
diag.cycles / diag.interval | u32 | 1 | RO | Loop diagnostics |
Values that change rarely (only on a mechanical change) live in the board's flash and are the source of truth; frequently-changing and host-only values stay on the host.
servo.max, servo.acc — read on connect, set+save on change.scales.filt — encoder filter, re-applied on connect.save.scales.num/den) — unit-dependent, pushed live, never saved to flash.On connect the app reads the board's persisted values and syncs the UI to them, rather than re-pushing config every reconnect. Machine profiles snapshot both sides together.
Firmware is flashed over the same RS-485 wire via the board's bootloader — no ST-Link required.
The app sends update; the board jumps to the bootloader and greets with bootloader=ready.
info reports the active / loaded banks and their validity; the updater targets the inactive one.
flash <bank> streams the firmware .bin over YMODEM (1024-byte STX blocks, CRC-16, EOT handshake) with a live progress bar.
bank <bank> marks it active (persisted), then boot copies it to Exec and jumps in. rollback reverses it.
The dual-bank design means a bad flash never bricks the board — the previous bank is always intact and selectable.
| Path | What |
|---|---|
config.ini (repo root) | Serial port, baud, mode, scale count, display colour. |
~/.config/drdro-software/ | Per-instance YAML for axes, inputs, servo, ELS, formats. |
~/.config/drdro-software/profiles/ | Saved machine profiles. |
/opt/drdro/app (appliance) | The installed app + its .venv on the Pi image. |
/var/log/drdro/ (appliance) | App / Kivy logs on the Pi image. |
drDRO is RCP with the driver layer swapped. If you're migrating:
config.ini drops the address key.~/.config/drdro-software/ (RCP YAML isn't auto-migrated; copy it over).