Match the file-preprocessor behaviour for live operator input. When a
Z-down jog or MDI line would push (A-Z) above the safe band, append
the matching A delta to the same line so the planner runs Z and A
together. Same direction-aware refusal: only error when the operator
explicitly asks A to move *up* (delta > 0) past the bound, or when
the required A would violate A's soft minimum.
Implementation:
* ExternalAxis.coordinate_mdi rewrites a multi-line MDI burst,
tracking G90/G91 modal across lines (jogs always emit
M70/G91/G0/M72; standard MDI defaults to G90). Z and A targets
are computed in machine coords using offset_z and offset_a so
the work-coord A token we emit is consistent with the operator's
frame.
* The 'A0' the jog UI emits for axes that aren't moving is treated
as 'no A intent' (G91 delta of zero) and freely overridden.
* Hooked into Mach.mdi after the existing ATC rewrite. On
ExternalAxisError the burst is dropped with a user message; the
planner check downstream still fires as defense in depth.
* Planner.__encode also catches ExternalAxisError now (vs
bricking on uncaught) - logs to the operator messages list and
halts the cycle cleanly so subsequent jogs work.
* check_coupling itself is now improvement-aware: only refuses
moves that worsen an existing violation. Pure XY jogs and
Z-up/A-down recovery moves pass even when (A-Z) is currently
above the bound.
Tested locally with synthetic MDI: small Z jog within band, Z jog
across the boundary (auto-injects A delta), G90 MDI G0 Z-50
(appends A106), explicit A-lift while Z deep (refuses), pure XY
jog (unchanged), G91 A-down (unchanged), G90 G0 A0 with
offset_a=134 (refuses as lift to home).
OneFinity CNC Controller Firmware (W-axis fork)
This is the OneFinity / Buildbotics bbctrl firmware with a virtual W axis driven by an auxcnc ESP32 over USB serial. See docs/AUX_W_AXIS.md for the design and config.
Layout
src/avr/ AVR firmware (motion controller, AtxMega)
src/boot/ AVR bootloader
src/bbserial/ Linux kernel module for the bbserial driver
src/py/bbctrl/ Python control daemon (Tornado + websockets)
src/js/ Vue.js UI (legacy)
src/svelte-components/ Newer Svelte UI for dialogs and settings
src/pug/ Pug templates compiled into build/http/index.html
src/resources/ Static assets and config templates
scripts/ Install / update / RPi build helpers
docs/ Architecture, dev setup, W-axis docs
Build & flash (quick path, macOS or Linux)
The full build (make) requires avr-gcc, but the controller and UI
only depend on the Python + web parts. If you're shipping a UI/Python
change you don't need the AVR toolchain.
Prerequisites
- Node.js (any recent LTS) with npm
- Python 3 with setuptools
npm installonce at the project root (this is wired into thenode_modulesMake target, but on a fresh checkout it's clearer to do it explicitly)
npm install
(cd src/svelte-components && npm install)
macOS gotcha: esbuild platform pin
The Pi build leaves node_modules/esbuild pinned to
linux-arm64, which won't run on Darwin. If npm run build inside
src/svelte-components complains about esbuild, reinstall it for the
host:
cd src/svelte-components
rm -rf node_modules/esbuild
npm install esbuild@0.14.49 --no-save
(Use the version that matches package-lock.json.)
Build the web UI + Python sdist
# Build the Svelte components
(cd src/svelte-components && npm run build)
# Render pug templates and copy assets into build/http
make all # AVR step will fail without avr-gcc; safe to ignore
# if you didn't change anything under src/avr or src/boot
# Package
./setup.py sdist
ls dist/bbctrl-*.tar.bz2
make pkg is the canonical target but it tries to build AVR first. On
hosts without avr-gcc, run the steps above directly.
If bbctrl-*.tar.bz2 is missing src/bbserial/bbserial.ko, copy the
prebuilt .ko from a previous official release into src/bbserial/
before running setup.py sdist (the install script on the controller
just installs the existing module if a newer one isn't shipped).
Flash to a controller
curl -X PUT -H "Content-Type: multipart/form-data" \
-F "firmware=@dist/bbctrl-1.6.7.tar.bz2" \
-F "password=onefinity" \
http://onefinity.local/api/firmware/update
…or use the Make target:
make update HOST=onefinity.local PASSWORD=onefinity
The controller stops bbctrl, untars the package, runs
scripts/install.sh, and brings the service back up. Total downtime
is ~30-45s. Watch progress at http://<host>/ (you'll get 404s while
bbctrl restarts, then the new UI).
Verify the flash
curl -s http://onefinity.local/ | grep -c "OneFinity"
curl -s http://onefinity.local/api/aux/status # if W axis is enabled
Build & flash (full path, Debian/Linux)
For AVR + GPlan rebuilds, see docs/development.md.
That path uses qemu + chroot to cross-compile gplan for ARM and needs
the gcc-avr / avr-libc toolchain.
W axis (auxcnc)
This fork adds a virtual W axis. See docs/AUX_W_AXIS.md for:
- G-code surface (
G28 W0,G1 W25, etc.) - The G-code preprocessor and hook architecture
- aux.json keys
- REST API (
/api/aux/*) - UI surface (jog row in Control, settings panel in Settings)
- Edge cases (ESP reboot mid-job, limit closed at home start, …)