#voron #voroncascade #cnc #reprapfirmware #millenniumos #scylla #firmware #vfd #h100 #modbus
# Overview
Voron Cascade is officially designed around **grblHAL + gSender** on either the BTT Scylla or Expatria FlexiHAL. This note documents the alternative path: running **RepRapFirmware (RRF) 3.6+ with MillenniumOS (MOS)** on the BTT Scylla, accessed through Duet Web Control instead of gSender.
This is a viable but unofficial path. The BTT Scylla was co-designed by BigTreeTech and Millennium Machines specifically to be a first-class RRF/MOS target for the Milo CNC mill, so the firmware story is solid. The catch is that *every prebuilt RRF/MOS config from Millennium Machines is shaped for the Milo*, not the Cascade — so the work is in adapting a Milo config to Cascade's frame, motors, spindle, and probes rather than installing anything from scratch.
# Resources
## Primary sources
- [MillenniumOS GitHub](https://github.com/MillenniumMachines/MillenniumOS) — macro library, gcode dialect, release zips
- [MillenniumOS Documentation](https://millenniummachines.github.io/docs/millennium-os/) — install + usage manual
- [MillenniumOS Installation chapter](https://millenniummachines.github.io/docs/millennium-os/manual/chapters/20_installation/) — upload, configuration wizard, post-processor
- [Millennium Machines RRF-Configs](https://github.com/MillenniumMachines/RRF-Configs) — known-good Milo configs (Scylla included) bundled with RRF firmware and MOS — *use as starting template*
- [RRF-Configs Releases page](https://github.com/MillenniumMachines/RRF-Configs/releases) — latest stable release as of 2025-11-03 is `v03.11.25-stable`
- [ArborCTL](https://github.com/MillenniumMachines/ArborCTL) — RRF daemon macro framework for RS485 VFD control (Shihlin SL3, Huanyang HY02D223B, Yalang YL620A as of 2025-10)
## RRF on STM32 (Scylla)
- [TeamGloomy STM32 RRF homepage](https://teamgloomy.github.io/) — port of RRF to STM32 boards
- [TeamGloomy BTT Scylla V1 (H723) General Info — RRF 3.5+](https://teamgloomy.github.io/btt_scylla_v1_h723_general_3_5.html)
- [TeamGloomy Scylla pin names](https://teamgloomy.github.io/btt_scylla_v1_h723_pins_3_5.html)
- [TeamGloomy Scylla CAN-FD](https://teamgloomy.github.io/btt_scylla_v1_h723_canfd_3_5.html)
- [TeamGloomy WiFi via ESP32 on Scylla](https://teamgloomy.github.io/btt_scylla_v1_h723_connected_wifi_32_3_5.html)
- [TeamGloomy supported boards](https://teamgloomy.github.io/supported_boards.html)
- [TeamGloomy RS485 adapter roundup](https://teamgloomy.github.io/adapters_rs485.html)
- [Bigtreetech Scylla V1 firmware installation — Team FDM forum thread](https://www.teamfdm.com/forums/topic/5392-bigtreetech-scylla-v1-firmware-installation/)
## RRF CNC / VFD reference
- [Duet3D: Configuring RRF for a CNC machine](https://docs.duet3d.com/User_manual/Machine_configuration/Configuration_CNC) — M453, M950 spindle, M563 tool, M669 segmentation
- [Duet3D: Connecting RS485 and Modbus RTU devices](https://docs.duet3d.com/User_manual/Connecting_hardware/RS485_Modbus) — M575, M260.1/M261.1
- [MillenniumOS forum announcement thread](https://forum.duet3d.com/topic/35335/millenniumos-a-cnc-operations-system-for-rrf-3-5)
## grblHAL / H100 VFD reference
- [grblHAL Plugins_spindle README](https://github.com/grblHAL/Plugins_spindle/blob/master/README.md) — VFD driver selection, MODVFD `$462`–`$471` settings, `$395` spindle binding
- [PrintNC wiki: VFD Control with grblHAL](https://wiki.printnc.info/en/grbl/vfd-control) — practical setup walkthrough (HY and YL620 — adapt the workflow for H100/MODVFD)
- [LinuxCNC forum: G-Penny H100 register documenting](https://www.forum.linuxcnc.org/49-basic-configuration/57333-g-penny-spindle-h100-register-settings-documenting) — `mbpoll` scan script and parameter map (38400/8E1)
- [Onefinity forum: H100 VFD setup walkthrough](https://forum.onefinitycnc.com/t/help-with-h100-vfd-setup-wiring-programming-solved/27022) — F-parameter list confirmed on a Masso, applies the same to H100 Modbus regardless of controller
- [H100 manual (Home Depot mirror)](https://images.thdstatic.com/catalog/pdfImages/b0/b008b752-3e4a-4c5c-aa62-3f425c50eff9.pdf) — register map and F-parameter list (page 79+)
- [CNCZone: Modbus address help for H100 inverter](https://www.cnczone.com/forums/spindles-vfd/473082-modbus-address-help-h100-inverter-new-post.html)
## Hardware references
- [BTT Scylla V1.0 product page (Biqu)](https://biqu.equipment/products/bigtreetech-scylla-v1-0) — STM32H723VGT6, 4× TMC2160 (60V/4.7A peak), onboard ESP32 WiFi, RS485, 8 endstops, dedicated probe + toolsetter inputs
- [BTT Scylla product page (Fabreeko)](https://www.fabreeko.com/products/bigtreetech-scylla-v1-0)
- [West3D: Maximize your Milo with the Scylla](https://west3d.com/blogs/whats-new/maximize-your-milo-with-the-scylla-control-board-from-btt) — context on the Scylla/Millennium collaboration
- [Voron Cascade GitHub](https://github.com/VoronDesign/Voron-Cascade) — CAD, manual, BOM
- [Voron Cascade product page](https://vorondesign.com/voron_cascade)
# Design
## Target stack
| Layer | Choice | Notes |
|---|---|---|
| Mainboard | BTT Scylla V1.0 | STM32H723VGT6, 4× TMC2160, onboard ESP32 WiFi, RS485, PWM spindle, probe/toolsetter inputs |
| Firmware | RepRapFirmware 3.6.x (STM32 port) | TeamGloomy build `firmware_scylla1_0_h723.bin` — H7 is the future, F4 stops at 3.6.x |
| Operations layer | MillenniumOS (MOS) latest | Probing, toolsetting, VSSC, custom gcode dialect |
| UI | Duet Web Control (DWC) | Browser-based; replaces gSender |
| Post-processor | Fusion360 `.cps` (Milo-flavored) or FreeCAD `.py` | Emits the MOS gcode dialect (M4000, G6600, M3.9, etc.) |
| Spindle control | RS485/Modbus *if* the VFD is supported by ArborCTL, else 0–10V analog via PWM→analog converter, else open-loop PWM | See Decisions below |
| VFD/spindle | Cascade default is a G-Penny 1.5 kW 24 000 RPM ER16 + a VFD | VFD model determines whether RS485 is feasible |
| Probe | XYZ touch probe (e.g. AliExpress 3D Edge Finder, ~$80–100) | MOS expects this on the dedicated probe input; deflection compensation in wizard |
| Toolsetter | Optional but recommended (Long John or equivalent) | Enables M4000/M4001 automatic tool length comp |
| E-stop | Latching safety net on Scylla | Recent MOS releases ship a config for this |
## Working volume
Cascade: **X=275, Y=220, Z=90 (110 mm total travel for tool hop)**.
This differs from the Milo "Standard" spec the prebuilt MOS configs target (X=0–335, Y=0–208, Z=0–120). Every M208 axis limit, every homing macro endstop position, and the Fusion360 `.mch` machine definition has to be re-derived for Cascade.
## Stepper / motion
Cascade uses 48 V NEMA 23s on ball screws with MGN15 rails per axis. Scylla TMC2160s are rated for 60 V at 4.7 A peak — within spec, but the per-driver thermal headroom is the question. Use M906 to set RMS current conservatively (e.g. start ≤70 % of peak) and lean on SpreadCycle, not StealthChop, for CNC. M569 `D3` (stealthChop off) is the right default for milling loads.
The Cascade is 3 axes (X, Y, Z) with a single motor each, so 3 of the Scylla's 4 driver slots are used. The 4th can drive a future rotary or a dual-Z setup. ==Confirm motor count and ball screw lead with the live Cascade BOM before computing steps/mm.==
# Decisions
## Why RRF + MOS over the default grblHAL + gSender?
- **Probing UX.** MOS's canned cycles (corner probe, bore probe, vise probe, surface) and the toolsetter integration are best-in-class in the hobby/desktop space. The grblHAL probing story is improving but is still macro-driven and less novice-friendly.
- **Shared mental model with 3D printers.** RRF, DWC, macros, and the gcode dialect map closely to Klipper/Marlin habits already in the Voron Cascade workflow.
- **Spindle/VFD control via Modbus** is first-class in RRF 3.6+ for the VFDs ArborCTL supports — closed-loop spindle speed, fault feedback, run/stop over a single 2-wire bus.
## What is being given up?
- **gSender** is grblHAL-specific. Switching to RRF means switching to Duet Web Control (DWC). DWC is a competent CNC UI but it is not a touchscreen-first machinist UI the way gSender is. ==Decide whether a Pi running a local DWC display, a pendant, or a tablet is the everyday driver.==
- **Out-of-the-box Cascade community recipes.** All Cascade-specific guides on Reddit/Discord assume grblHAL. Going RRF means treating the Cascade as a "self-built Milo-like" machine and adapting the Milo configs.
- **Some grblHAL CNC features.** grblHAL has had longer to mature on niche CNC features (canned drilling cycles, certain G-code variants). RRF covers the majority of the same ground but a few G/M codes will need user macros.
## VFD strategy
The Cascade BOM specifies the **G-Penny spindle + H100 VFD** combo with the intent to use Modbus. The H100 is a generic Chinese vector-control inverter (same hardware as the StepperOnline V70 and several other "H100" rebadges) and it speaks standard Modbus RTU — but the register map is *not* the Huanyang HY map, *not* the Shihlin SL3 map, and *not* the Yalang YL620 map. That distinction drives most of the work below. See [[#G-Penny H100 VFD]] for the full breakdown.
Short version:
- **grblHAL** does not ship a dedicated H100 driver, but the **MODVFD** generic Modbus driver covers it cleanly once you set the H100's specific registers and command words via `$462`–`$471`. This is the path most G-Penny H100 users are running.
- **RRF / MOS / ArborCTL** does not ship an H100 profile either. ArborCTL currently supports Shihlin SL3, Huanyang HY02D223B, Yalang YL620A, and (untested) Huanyang GT-2R2G-2. Adding the H100 means either writing an ArborCTL VFD profile or talking to the H100 directly with RRF's `M260.1` / `M261.1` Modbus gcodes from `daemon.g`.
Either route is viable; the grblHAL path is shorter because someone else has already written it.
Fallbacks if Modbus turns out to be a fight:
- **0–10 V analog via PWM-to-analog converter** — works with virtually any VFD, no closed loop. Use a green 6-pin terminal block PWM-to-analog board, drive from a Scylla PWM output, set the jumper to match (5 V or 24 V) the input source. Avoid the blue square opto-isolated boards (grounding flaw).
- **Open-loop PWM directly to VFD** — only if the VFD accepts a 5 V PWM input. Simplest wiring; no readback.
# G-Penny H100 VFD
The Cascade BOM specifies the G-Penny spindle paired with the H100 VFD. This section nails down what "Modbus support" actually means on this VFD across both candidate firmware stacks, since the answer is not a simple "yes."
## What the H100 actually is
The G-Penny H100 is a rebadge of a generic Chinese vector-control inverter family — the same hardware ships as the StepperOnline V70, the Huanyang H100 (different from the HY series), and several other "H100"-marked boxes. They all share the same parameter map (`F001`, `F002`, `F163`, …) and the same Modbus register layout. Knowing that "H100" and "V70" refer to the same device is essential when searching for working configs — V70 documentation applies.
Default factory comms: RS485, 9600 baud. Recommended for CNC use: **38400 baud, 8E1**. The H100 supports up to 38400 baud and 8N1 / 8E1 / 8O1 framing.
VFD-side parameter settings to enable external RS485 control:
| Param | Value | Meaning |
|---|---|---|
| `F001` | 2 | Run command source = external (Modbus) |
| `F002` | 2 | Frequency command source = external (Modbus) |
| `F163` | 1 | Modbus slave address |
| `F164` | 3 | Baud rate = 38400 |
| `F165` | 3 | Data format (8 data bits, even parity, 1 stop bit — 8E1) |
| `F169` | 0 | Communication response delay = 0 ms |
(Set `F165` to whatever matches the framing the controller will speak. Both 8N1 and 8E1 are commonly used; 8E1 is the LinuxCNC community default for this VFD.)
Key Modbus registers (H100 native addressing, decimal):
| Register | Address | Function |
|---|---|---|
| Run / Stop command | 512 (`0x0200`) | Write 1 = run forward, 2 = run reverse, 5 = stop |
| Set frequency | 513 (`0x0201`) | Write target frequency, units 0.01 Hz |
| Output frequency (readback) | 544 (`0x0220`) | Read actual running frequency, units 0.01 Hz |
| Output current | 545 (`0x0221`) | Read motor current |
| Fault code | 546 (`0x0222`) | Read fault status |
==Verify these register values against your specific H100 unit before relying on them — there are minor variations across H100 rebadges, and the LinuxCNC forum has scan scripts that walk the register space directly using `mbpoll`.==
## grblHAL with the H100 (MODVFD generic driver)
grblHAL's `Plugins_spindle` ships several VFD drivers: Huanyang HY, Huanyang GT, GS20, YL620, Modbus VFD generic, and **MODVFD**. There is *no* H100-specific driver. The MODVFD generic driver exists precisely for this case — it lets the user configure custom registers and command words for any well-behaved Modbus VFD, modeled on LinuxCNC's `vfdmod` component.
Configuration steps:
1. Build grblHAL firmware with `VFD_SPINDLE` enabled in `my_machine.h`. Either compile in just MODVFD or compile all spindles and pick at runtime.
2. In ioSender / WebUI, set the active spindle to MODVFD via `$395`.
3. Set the Modbus address via `$360` (default 1 — matches `F163=1`).
4. Set MODVFD registers and words:
```text
$461 = 6000 ; RPM to Hz factor — H100 outputs frequency × 100, motor is 2-pole, 24000 RPM @ 400 Hz
$462 = 512 ; Run/stop register (0x0200)
$463 = 513 ; Set frequency register (0x0201)
$464 = 544 ; Get frequency register (0x0220)
$465 = 1 ; Command word for CW run
$466 = 2 ; Command word for CCW run
$467 = 5 ; Command word for stop
$468 = 100 ; RPM-to-register multiplier (Hz × 100)
$469 = 60 ; RPM-to-register divider (RPM/60 = Hz)
$470 = 60 ; Register-to-RPM multiplier
$471 = 100 ; Register-to-RPM divider
```
==These values are the community starting point. Confirm against the actual H100 manual you have — a few rebadges use slightly different command words. The MODVFD/`vfdmod` ecosystem on LinuxCNC has dialed-in tables.==
5. ioSender side: set max RPM 24000, min RPM 6000 (G-Penny minimum), spindle-on delay 30 s.
6. Wire `485A`/`485B` on the Scylla to `RS+`/`RS-` on the H100. Twisted pair, ground the shield at one end.
The above is the cleanest "supported but not blessed" path on grblHAL — no source code changes, just `
-settings.
## RRF / MillenniumOS with the H100
The H100 is **not in ArborCTL's supported VFD list** as of October 2025 (Shihlin SL3, Huanyang HY02D223B, Yalang YL620A; Huanyang GT-2R2G-2 untested). Adding it means writing macros. Two approaches:
### Option A — talk to the H100 directly with RRF Modbus gcodes
RRF 3.6+ on the Scylla (via TeamGloomy's STM32 port — Scylla has RS485 built in) supports Modbus RTU through `M260.1` (write) and `M261.1` (read). This is the most direct path and doesn't depend on ArborCTL's framework being mature.
Sketch in `config.g`:
```gcode
; Enable Modbus on the Scylla's RS485 port (channel TBD per the Scylla pin table)
M575 P<chan> B38400 S7 ; mode 7 = device/Modbus
; Define the spindle as a normal PWM spindle bound to a real or virtual pin,
; so MOS sees a spindle in the object model and M3/M5 work.
M950 R0 C"<pwm_or_dummy>" L0:24000
```
Then run a daemon macro (`daemon.g` or `user-daemon.g`) that polls `spindles[0].active` and the requested RPM from the RRF object model, and translates them into Modbus writes:
```gcode
; spin up to commanded RPM
M260.1 P<chan> A1 F6 R513 B{floor(spindles[0].active * 6000 / 60 * 100 / 6000)} ; set frequency, 0.01 Hz units
M260.1 P<chan> A1 F6 R512 B1 ; run forward
; readback
M261.1 P<chan> A1 R544 B1 F3 V"hz"
echo "Spindle actual: " ^ (var.hz[0] / 100 * 60) ^ " RPM"
```
This is what ArborCTL does internally for the VFDs it supports — except you write the H100 transform yourself rather than picking from a menu.
### Option B — write an H100 profile for ArborCTL
ArborCTL is open source (GPL-3.0) and macro-based, with VFD profiles stored under `macro/` in the repo. The structure is roughly: read the spindle state from the object model, write the appropriate Modbus packets per VFD, read back status. Adding an H100 profile means copying the closest existing profile (Shihlin SL3 is probably the cleanest reference) and swapping the register addresses and command words for the H100 values above.
Upside: integrates cleanly into the MOS daemon framework, gets feedback and fault handling for free, contributable upstream.
Downside: more upfront work and ArborCTL is alpha and changing — a profile written today may need to follow framework changes.
==Decision: start with Option A (direct `M260.1`/`M261.1` macros) for the first cuts. If it works reliably, promote to Option B and submit upstream as the H100 profile.==
## Cross-stack summary
| Capability | grblHAL | RRF + MOS |
|---|---|---|
| H100 has a dedicated driver | No | No |
| Generic Modbus path | **Yes — MODVFD via `$462`–`$471`** | Yes — raw `M260.1`/`M261.1` |
| Framework profile (purpose-built) | Not needed; MODVFD is the framework | Possible via custom ArborCTL profile |
| Closed-loop RPM feedback | Yes | Yes |
| Fault feedback / e-stop on VFD trip | Yes | Yes (read fault register) |
| Effort to reach working spindle | ~Low (set 10 `
-settings) | ~Medium (write the daemon macro) |
| Effort to be "production-ready" | Low | Medium (until an ArborCTL profile exists) |
The H100 is *supported* by both stacks, but only because both stacks have a generic Modbus pathway. Neither vendor ships a turnkey driver. The grblHAL MODVFD path is the smaller pile of work — and that is the right reading for "the default Cascade path uses grblHAL."
# Configuration
## What gets customized vs. carried over
The Millennium Machines `milo-v1.5-ldo-scylla-mos-...zip` (or similar) is the **starting template**, not the final config. The following pieces are Cascade-specific and need to be rewritten:
- `sys/config.g` — `M208` axis limits, `M92` steps/mm, `M906` motor currents, `M566/M203/M201` jerk/feed/accel, machine name. Keep the MOS bootstrap line at the bottom: `M98 P"mos.g"`.
- `sys/homex.g`, `sys/homey.g`, `sys/homez.g` — direction, endstop pin (`xstop`, `ystop`, `zstop` or `*max` variants per the Scylla pin table), back-off distances. Cascade homing may differ from Milo (e.g. Z homes to top, away from spoilboard).
- `sys/touchprobe.g.example` → `touchprobe.g` — `M558 K0 P5 C"probe"` or `C"!ystopmax"` depending on probe wiring and polarity.
- `sys/toolsetter.g.example` (if present) → `toolsetter.g` — `M558 K1 P8 C"xstopmax"` or whichever pin the toolsetter lands on. ==Confirm Scylla pin label conventions against the TeamGloomy Scylla pin table.==
- Spindle declaration — `M950 R0 C"<pwm_pin>" L<min_rpm>:<max_rpm>` for PWM, or RS485 + ArborCTL daemon for Modbus.
- `M453` to put RRF in CNC mode.
- `M669 S0.2 T0.2` (or similar) to enable move segmentation so probing and feed-hold can interrupt long moves.
- `M563` tool definitions — **remove** if MOS is managing tools (MOS uses `M4000`/`M4001`); keep simple `M563 P0 R0` only if not using MOS for tool management.
- Fusion360 machine definition `.mch` — build one for X=0–275, Y=0–220, Z=0–90 from the Milo `.mch` as a template.
## Example skeleton (illustrative, not copy-paste-ready)
```gcode
; Cascade CNC config.g (skeleton)
G90 ; absolute moves
G21 ; millimetres
M453 ; CNC mode
; --- Network ---
M550 P"VoronCascade"
M552 S1
M587 S"<ssid>" P"<pass>" ; one-time, then remove
; --- Drives (TMC2160 on Scylla, slots 0-3) ---
M569 P0 S1 D3 ; X, spreadCycle
M569 P1 S1 D3 ; Y
M569 P2 S1 D3 ; Z
M584 X0 Y1 Z2
M92 X<steps/mm> Y<steps/mm> Z<steps/mm> ; derived from motor + screw lead
M906 X<mA> Y<mA> Z<mA> I40 ; conservative idle current
M203 X8000 Y8000 Z3000 ; max feed mm/min
M201 X1000 Y1000 Z500 ; accel mm/s^2
M566 X600 Y600 Z200 ; instantaneous speed change
; --- Limits ---
M208 X0:275 Y0:220 Z-90:0 ; Z negative because tool moves down from home
; --- Endstops ---
M574 X1 S1 P"xstop"
M574 Y1 S1 P"ystop"
M574 Z2 S1 P"zstop" ; or pin per the Scylla pin table
; --- Probes ---
M558 K0 P5 C"probe" H2 A10 S0.01 T1200 F300:50 ; touch probe (filtered)
M558 K1 P8 C"xstopmax" H10 A10 S0.01 T1200 F300:60 ; toolsetter (unfiltered)
; --- Spindle ---
M950 R0 C"spindle_pwm" L0:24000 ; PWM spindle
; OR (RS485 ArborCTL) replace with:
; M575 P<chan> B<baud> S7 ; enable Modbus
; M98 P"arborctl.g" ; load daemon
M669 S0.2 T0.2 ; move segmentation
; --- Movement segmentation, CNC misc ---
M564 H0 ; allow moves before homing? (typically no for CNC; left at default)
; --- MillenniumOS bootstrap (must be last) ---
M98 P"mos.g"
```
== This skeleton is a placeholder — every `<...>` value needs filling in once the Cascade BOM revision being built is confirmed (motors, ball screw lead, VFD model, probe wiring). ==
# Pitfalls
These are the things most likely to trip the build.
1. **Prebuilt configs are for the Milo, not the Cascade.** The `RRF-Configs` releases will boot and run on the Scylla, but the M208 limits, homing positions, and Fusion360 `.mch` machine definition will all be wrong. Treat the prebuilt zip as a *template*, never as a final config.
2. **Cascade defaults to grblHAL + gSender.** Almost every Cascade-specific tutorial, wiring diagram, and Discord answer assumes that stack. Going RRF means cross-referencing two ecosystems (Millennium Machines for firmware, Voron for the frame) and reconciling them by hand.
3. **VFD compatibility for RS485 is narrow.** ArborCTL supports a small list of VFDs (Shihlin SL3, Huanyang HY02D223B, Yalang YL620A, Huanyang GT-2R2G-2 untested). Pick the VFD with this list in hand, or accept analog/PWM control.
4. **TMC2160 driver thermals at NEMA 23 currents.** 4.7 A peak is the chip rating; sustained current under milling load is materially less. Start conservative on M906 and monitor driver temperature; the integrated heatsink helps but airflow into the electronics bay still matters.
5. **MOS expects probe and toolsetter to be defined as Z-Probes** (`M558 K0`, `M558 K1`). The Cascade doesn't ship with these — they have to be sourced separately. Without a toolsetter, MOS still works with guided manual tool length probing, but the workflow is slower.
6. **Touch probe deflection** on cheap "3D edge finder" probes is typically 0.2–0.4 mm. MOS compensates for this in its config wizard, but the user needs to actually run the deflection calibration step. ==Don't skip the wizard's deflection measurement.==
7. **Touch probe filtering (P5 vs P8).** P5 is filtered (debounced), P8 is unfiltered. MOS recommends K0 P5 for the touch probe, K1 P8 for the toolsetter. Only *one* probe can be P5 — collision is possible if other features want filtered probing.
8. **CNC mode parenthesis behaviour.** In RRF CNC mode (`M453`), `( )` are gcode comments. This breaks meta-gcode if you accidentally use `if (cond)` style — wrap subexpressions in `{ }` instead.
9. **MOS OutOfMemory warnings in the README** refer to STM32F4 boards. Scylla is STM32H723 (a big H7), so this should not bite — but it's a reminder that MOS is memory-heavy and global variables in user macros should be kept minimal.
10. **MOS post-processor is Milo-flavored.** The Fusion360 `.cps` and `.mch` files emit Milo gcode (M4000, G6600, M3.9). They will work on the Cascade, but the `.mch` will misreport travel limits unless customized for X=275, Y=220, Z=90.
11. **No `M563` after MOS is installed** unless MOS is explicitly *not* managing tools. Leftover `M563 P0...` lines from the Milo template will conflict with `M4000`/`M4001`.
12. **Cancel-on-messagebox bug** (documented in the MOS README): clicking Cancel on a probing messagebox *outside* a print may continue motion. Always test probing routines with the spindle off and on soft material first.
13. **WiFi on first boot takes 5–10 minutes** while the Scylla flashes its WiFi module. If the `Milo` (or renamed) AP doesn't appear, the most common fix is checking the SD card to see whether `firmware.bin` got renamed to `FLY.CUR` — if not, the flash didn't happen.
14. **DWC ≠ gSender.** DWC is excellent for setup and one-off jobs, but if the user expects an always-on touch-friendly job runner like gSender, plan for a Pi or tablet running the DWC frontend, or a CNC pendant via USB-HID.
15. **STM32F4 deprecation.** TeamGloomy has stated that RRF v3.7+ will be STM32H7-only. Scylla is H7, so this is upside, not downside — but it does mean documentation that mentions F4 timing or F4 PWM behaviour does not apply.
# Implementation plan
Roughly sequential — each step should be confirmed before moving on.
## Phase 1: Inventory and decisions
1. ==Confirm Cascade revision and BOM as built== — motor model, ball screw lead, endstop type and polarity, intended VFD, intended spindle.
2. VFD is **fixed as the G-Penny H100** per the Cascade BOM. Plan for Modbus RTU at 38400 baud / 8E1; expect to either configure grblHAL's MODVFD generic driver (path of least resistance) or write a custom RRF `daemon.g` macro (Option A in [[#G-Penny H100 VFD]]).
3. Source a touch probe (XYZ edge finder) and decide on toolsetter (Long John or equivalent). Document part numbers in [[Voron Cascade BOM]].
4. Decide on the DWC frontend strategy: Pi + touchscreen, tablet, browser, or pendant. ==Affects the Universal Electronics Box layout — coordinate with [[Electronics]].==
## Phase 2: Firmware bring-up (bench, no spindle wired)
5. Format SD card: FAT16 if ≤4 GB, FAT32 if 4–32 GB, class 4 or faster.
6. From the [RRF-Configs releases](https://github.com/MillenniumMachines/RRF-Configs/releases), download the most recent Scylla-based bundle (currently `v03.11.25-stable`) including MOS.
7. Extract the zip to the SD card *root* — no nested folder.
8. Insert the SD card into the Scylla, power on, wait 5–10 minutes for first-boot flash.
9. Connect to the `Milo` AP (`password: millenniummachines`), open `http://192.168.40.1`.
10. Rename machine in `config.g` (`M550 P"VoronCascade"`), set WiFi credentials with `M587`, rename `network.g.example` → `network.g`, reboot, confirm DHCP works.
## Phase 3: Adapt the Milo config to the Cascade
11. Replace `M208` limits with Cascade values (X 0–275, Y 0–220, Z −90:0).
12. Compute and set `M92` steps/mm for each axis based on motor steps, microstepping (typically x16), and ball screw lead.
13. Set `M906` motor currents conservatively (start ~60–70 % of nameplate RMS), `D3` SpreadCycle in `M569`.
14. Adjust `M203`/`M201`/`M566` based on motor/screw combo; start conservative (~6000 mm/min rapids).
15. Edit `homex.g`/`homey.g`/`homez.g` for Cascade endstop locations and directions. Confirm endstop polarity (`!` prefix on pin name if NC).
16. Bench-test motion: jog each axis 10 mm, home each axis, confirm soft limits. ==Do this with no spindle, no probe, no work attached.==
## Phase 4: Probes and toolsetter
17. Wire the touch probe to the dedicated probe input. Edit `touchprobe.g` (`M558 K0 P5 C"probe"`).
18. Wire the toolsetter (if used) to its input. Edit `toolsetter.g` (`M558 K1 P8 C"xstopmax"` or whichever pin per [TeamGloomy Scylla pin names](https://teamgloomy.github.io/btt_scylla_v1_h723_pins_3_5.html)).
19. Restart, run `G8000` to start the MOS configuration wizard. Walk through deflection calibration, datum tool, toolsetter offset.
## Phase 5: Spindle / VFD
20. Mount and wire the VFD per its manual. Confirm phase rotation by spinning the spindle off-machine first.
21. If RS485 (H100, the BOM path):
- Wire Scylla `485_A`/`485_B` → H100 `RS+`/`RS−`. Twisted pair, shield grounded at the Scylla end.
- Set the H100 parameters per [[#G-Penny H100 VFD]]: `F001=2`, `F002=2`, `F163=1`, `F164=3`, `F165=3`, `F169=0`.
- Configure `M575 P<chan> B38400 S7` on the Scylla channel that the RS485 transceiver lives on.
- Pick a path:
- **Option A** (recommended for first cuts): write a `daemon.g` macro that maps `spindles[0].active` to `M260.1`/`M261.1` transactions against H100 registers 512 / 513 / 544.
- **Option B** (longer term): fork [ArborCTL](https://github.com/MillenniumMachines/ArborCTL), copy the Shihlin SL3 profile as a template, swap in H100 registers, contribute upstream.
- If on grblHAL instead: skip the above, set `$395` to MODVFD, configure `$461`/`$462`–`$471` per [[#grblHAL with the H100 MODVFD generic driver|grblHAL with the H100]].
22. If 0–10 V analog:
- Wire a green 6-pin PWM-to-analog converter; jumper to 5 V or 24 V based on the source.
- Configure `M950 R0 C"<pwm_pin>" L0:24000`.
23. If open-loop PWM:
- Wire spindle PWM output directly to VFD frequency input.
- Configure `M950 R0 C"<pwm_pin>" L0:24000`.
24. Test `M3 S6000` → `M5`. Confirm direction, then ramp to nominal RPM.
## Phase 6: Post-processor and first cuts
25. Install the Fusion360 `.cps` post-processor from the MOS release.
26. Duplicate the Milo `.mch` machine definition, edit X/Y/Z travel to Cascade values, re-link to the post.
27. Generate a "cut air" toolpath, run through DWC, watch the probe / tool change steps.
28. Cut MDF or hardwood as a first real job to validate steps/mm, squareness, and spindle behaviour.
## Phase 7: Hardening
29. Wire the latching safety net e-stop per the recent RRF-Configs Scylla examples.
30. Set up pendant / tablet / DWC display per the Phase 1 decision.
31. Document the working `config.g`, `network.g`, `touchprobe.g`, `toolsetter.g`, `homex/y/z.g` in this folder (or back them up to a git repo).
# TODO
- ~~Lock in the VFD model with ArborCTL compatibility in mind~~ — fixed by the Cascade BOM as G-Penny + H100; ArborCTL has no H100 profile so the work lives in a custom daemon macro (see [[#G-Penny H100 VFD]])
- ==Confirm Cascade endstop wiring conventions (min/max, NO/NC) vs. Scylla pin labels==
- ==Source touch probe and decide on toolsetter==
- ==Pick DWC frontend strategy (Pi+touchscreen vs. tablet vs. pendant)==
- ==Compute steps/mm for the Cascade's specific NEMA23 + ball screw combo==
- ==Build Cascade-specific Fusion360 `.mch` machine definition (X=275, Y=220, Z=90)==
- ==Decide whether to fork/clone `RRF-Configs` to maintain a Cascade variant in version control==
- ==H100: verify register addresses (512/513/544) and command words against the actual H100 manual that ships with the Cascade BOM — there are minor variations across rebadges==
- ==H100: pick Option A vs Option B for RRF integration (raw `M260.1`/`M261.1` daemon vs. custom ArborCTL profile)==
- ==H100: decide 8N1 vs 8E1 framing (LinuxCNC community uses 8E1; pick one and stick with it across VFD and controller)==
# Build Log
## 2026-05-26
- Initial research and draft of this note: surveyed MillenniumOS, BTT Scylla (STM32H723), TeamGloomy's RRF STM32 port, Voron Cascade defaults
- Identified the core mismatch: every Millennium prebuilt config targets Milo dimensions (335×208×120), Cascade is 275×220×90 — work is in adapting a Milo config, not from scratch
- Confirmed Scylla is supported by RRF 3.5+ via TeamGloomy (`firmware_scylla1_0_h723.bin`) and that STM32H7 is on the supported path past v3.7
- Confirmed RS485/Modbus VFD support is in RRF 3.6+ (Duet 3 mainboards officially; Scylla via TeamGloomy port has built-in RS485)
- Follow-up question: G-Penny H100 VFD compatibility
- Confirmed H100 = StepperOnline V70 = generic Chinese vector inverter family with standard Modbus RTU
- Default comms: 38400 baud / 8E1; VFD-side params: `F001=2, F002=2, F163=1, F164=3, F165=3, F169=0`
- Key registers: 512 (run/stop), 513 (set frequency), 544 (output frequency readback)
- **grblHAL has no native H100 driver but covers it cleanly via the MODVFD generic driver** (`$462`–`$471`)
- **ArborCTL has no H100 profile** (supported: Shihlin SL3, Huanyang HY02D223B, Yalang YL620A). RRF still talks to it via raw `M260.1`/`M261.1` from `daemon.g`, or via a custom ArborCTL profile
- Added [[#G-Penny H100 VFD]] section with both stacks' config paths, cross-stack capability table, and Decision: Option A (raw Modbus macros) first, Option B (ArborCTL profile) later
- Resolved the "lock in the VFD" TODO; added three H100-specific follow-ups
# References
- [[Electronics]] — Cascade electrical / PSU plan
- [[Voron Cascade BOM]] — running parts list
- [[LLM Note Spec]] — note structure spec