From Modix to Klipper: flashing firmware, installing the host, and first config
Every Modix ships running RepRapFirmware on a Duet controller. Klipper is a different animal: the motion math runs on a cheap Raspberry Pi, and the control board just executes steps. Converting buys you input shaping, pressure advance, a modern web UI, and the tuning process we run on every machine that comes through the shop. This guide walks the full path — firmware on the control board, the host stack on the Pi, and a first config that connects to your machine.
Big warning before anything else: flashing the wrong firmware can brick a board — or worse, quietly enable a heater. Match every detail on the firmware page (MCU chip, bootloader offset, communication interface) against the board physically in your machine before flashing. If you are not sure what you have, stop and ask us.
What you need
- A Klipper-capable control board. See the next section — what works depends on your Modix generation.
- A Raspberry Pi 4 or Pi 5 with its power supply. Use the official PSU or a quality dedicated supply — do not feed the Pi from a buck converter hanging off the printer's bed/heater rail. On one of our shop machines, that exact setup let hotend-heater PWM noise corrupt the Pi's USB links until the Pi got its own supply (verified by isolation testing on 2026-11-13).
- A microSD card (32 GB is plenty; a good endurance-class card is worth it).
- Ethernet. A printer host on WiFi will eventually drop mid-print — every WiFi drop we've investigated on customer machines was the network, not the firmware. Plug in a cable.
Step 0 — Know what's in your machine
Modix's BIG-series is a cartesian moving-gantry machine — not CoreXY. The bed rides four Z ball screws and the gantry travels in Y. Any Klipper config starts with kinematics: cartesian. (We've seen more than one conversion start life with a CoreXY config copied off a forum — it will home wrong and crash the gantry.)
The stock electronics by generation (per Modix's published tech specs):
| Generation | Stock controller | Runs Klipper? |
|---|---|---|
| Gen4 (V4) | Duet 2 WiFi/Ethernet + DUEX5 (SAM4E8E) | Yes — upstream Klipper has a pin map (generic-duet2-duex.cfg), but you must compile the firmware yourself; there is no prebuilt binary in our catalog |
| GEN5 (current) | Duet 3 6HC (SAME70Q20B) | Yes — same story (generic-duet3-6hc.cfg); flashing requires the erase-jumper procedure and building from source |
| A3DP conversion kit | BTT Octopus Pro H723 main board + toolhead boards | Yes — prebuilt firmware available, see Step 1 |
What this means in practice: if your Modix still wears its stock Duet, you have two honest options:
-
Keep the Duet and build Klipper for it yourself. Klipper officially supports these boards — the pin-mapping configs live in Klipper's own
config/directory (generic-duet2-duex.cfg,generic-duet3-6hc.cfg) and each file's header gives the exact menuconfig choices and flash procedure. This is the right path if you want zero rewiring. Budget an evening: you'll need a Linux machine (or the Pi, once it's set up) to compile and flash. - Swap to a board from the prebuilt catalog. This is what we do on conversion kits: a BTT Octopus Pro (H723) main board plus toolhead boards, all of which have curated, reviewed prebuilt firmware one click away. No toolchain, no menuconfig.
Either way, the Pi host side (Steps 2–3) is identical.
Step 1 — Flash the MCU firmware
Prebuilt, CI-compiled firmware lives in Advanced3dPrinting/klipper-firmware-builder. Every binary is built straight from an official Klipper release tag from a curated, reviewed config — there is deliberately no "arbitrary menuconfig" option, because wrong firmware is the #1 way users brick a board.
Grab the right bin on the firmware download portal (or straight from the GitHub releases page):
- Pick your board, then the variant that matches your physical hardware — MCU chip, bootloader offset, and how it talks (USB, SD card, CAN). Every board page spells out which column to match.
- One trap worth repeating: the catalog warning for the Octopus family applies to conversions — an Octopus v1.1 (non-Pro) binary must not go on an Octopus Pro (or vice versa); the wrong pin mapping can enable a heater on power-up.
The per-board flash instructions are on each board's page and in every release's manifest. The three patterns you'll meet:
-
SD-card boards (most STM32F4/F446 boards): copy the
.binto a FAT32 card asfirmware.bin, power-cycle the board with the card inserted, wait ~30–60 s, then check for aFIRMWARE.CURfile on the card — that's the flash-succeeded marker. -
RP2040 boards (toolhead boards like the NiteHawk-36 in our kits): hold BOOTSEL while plugging in USB, a drive named
RPI-RP2appears, drop the.uf2on it. A board that already runs Klipper can usually be re-flashed buttonless over USB — reserve BOOTSEL for blank or dead boards. -
STM32 DFU boards: hold the BOOT button/jumper while plugging in USB, the board shows as
0483:df11, thensudo dfu-util -a 0 -d 0483:df11 --dfu-adjust=0x0800 -D <downloaded .bin>.
Never blind-flash. Before you overwrite anything, read what each board currently runs — if a board is on older firmware than your host, re-flash it; if it's already current, leave it alone:
grep -E "mcu_version|mcu_build_versions" ~/printer_data/logs/klippy.log | tail -20
Two flashing quirks we've hit on real boards, so you don't burn an afternoon:
-
STM32 G0B1 DFU entry lags a few seconds after the bootloader request — if
dfu-utilsays "No DFU capable USB device available", wait and retry rather than assuming the board is dead. - dfu-util may exit with an error right after a successful download on some boards (the device resets before the final status poll). The flash is fine — verify by unplugging/replugging and checking the board enumerates normally.
The firmware is built by automation from reviewed configs but is not hardware-tested per target — that's exactly why the board pages make you match the details manually.
Step 2 — Install the host stack on the Pi
If your machine came from us (or carries an A3DP conversion kit), use the A3DP fleet image: it ships the whole stack pre-configured — Klipper (Kalico) pinned to the fleet firmware protocol, Moonraker, Mainsail with the A3DP skin, the camera stack, the on-box MCU flasher, daily config backups, and performance tuning (no swap, klippy pinned to its own core). One image, no hand-installing.
- Download the latest
image_*.img.xz(+SHA256SUMS.txt) from the a3dp-setup-os releases page. -
Raspberry Pi Imager → choose OS → Use custom → the downloaded
.img.xz(Imager writes compressed images directly). - In Imager's OS-customization, the settings that matter:
-
Hostname — this doubles as the machine-type selector: hostnames starting
meter/a3dpmeterget the meter-IDEX kit config,rift/a3dp525get the Rift config, anything else gets a clean base config. - SSH — enable and paste your public key (the image ships with no credentials at all; if you skip this, the machine has SSH off and no way in except the UI).
- Not using Imager? Etch the image with dd/Etcher instead, then drop
a3dp-machine.conf(containingA3DP_MACHINE=meter-idex, for example) anda3dp-ssh.pub(your public key) onto the card's boot partition before first boot.
-
Hostname — this doubles as the machine-type selector: hostnames starting
- Boot. First boot takes ~2 minutes and does everything else automatically — config deployment, MCU path enumeration, service startup. Watch for the status LED, then move to Step 3.
Not an A3DP machine and don't want our image? The manual path is the standard Klipper stack — KIAUH or the upstream Klipper / Moonraker / Mainsail installers all work on PiOS Lite 64-bit. Steps 1 and 3 below apply unchanged. Two things the manual path makes you get right yourself, both learned the hard way on our fleet: the Klipper service needs the API socket flag (-a ~/printer_data/comms/klippy.sock) or Moonraker will never connect to a klippy that looks fine in the logs; and systemd-timesyncd must be running — a printer with a drifting clock breaks webcams, job history, and every log correlation you'll ever attempt.
Step 3 — First config and bring-up
On the A3DP image, the machine profile already deployed a full config at first boot, with the MCU serial paths filled in from the live USB enumeration — you don't hand-edit anything to get connected. Open http://<printer-hostname>.local/ (or the printer's IP) and you should see the Mainsail dashboard.
On a manual install (or a board swap the image doesn't have a profile for), you'll write the config yourself. The rules that keep it sane:
-
Never copy MCU paths between machines. Every
serial:line must point at this machine's boards:
Thegrep -rn "serial:" ~/printer_data/config/ ls -l /dev/serial/by-id/by-idnames encode the board's USB serial number, so identical boards get different names — that's a feature: two identical toolhead boards stay distinguishable after any re-plug. - If you're on CAN (CANbus toolheads), every
canbus_uuid:line is per-board and derived from the chip's unique ID — re-enumerate every one on every machine withpython3 ~/klipper/scripts/canbus_query.py can0. Never reuse a UUID. - Bring MCUs up one at a time: patch one
serial:line, restart Klipper, confirm that board connects in the log, move to the next. - Start from a config for your actual board family. Klipper's
config/directory has pin maps for most common boards; our meter-kit reference config lives with the fleet repos. - The temperature sections will stop Klipper with an "ADC out of range" shutdown until the hotend thermistors are actually plugged in and reading. That shutdown is the safety system working — a thermistor pulled to the rail by a missing sensor should stop the machine. Never mask it with
adc_ignore_limitsto "get past" bring-up.
Pre-print checklist (all of these before the first homing)
timedatectl # System clock synchronized: yes
curl -sI http://localhost | head -1 # HTTP 200 (Mainsail)
systemctl is-active klipper moonraker crowsnest nginx # all "active"
ls /dev/serial/by-id/ # your MCU boards, listed
Then, in order:
-
MCU firmware versions match the host. Check what each board reports against the running Klipper/Kalico version — a protocol mismatch between host and MCU is silent until it isn't. The version is in
klippy.log(themcu_versionlines) and in Moonraker's MCU status. - Motors and endstops before heaters: with heaters off, jog each axis a few mm by hand from the UI and confirm it moves the right direction; trigger each endstop manually and confirm it reads. A mirrored axis or inverted endstop is a 30-second catch now and a crashed gantry later.
- Heaters with eyes on: set the hotend to a low target and watch the temperature actually rise and stabilize; then the bed. If a temperature reading is wildly wrong (or pinned), stop — that's wiring, not tuning.
-
Camera: if you plugged one in and crowsnest reports "No usable Devices Found", the service hit its start-rate limit before the camera existed —
sudo systemctl reset-failed crowsnest(or reboot) after connecting it, and it will come up. - Only then: homing, probe calibration, PID tuning, and input shaping. That's the tuning process we run on every machine in the shop — and the reason conversions print better after it.
Remote access and support
The image ships with Tailscale installed but logged out — the customer joins their own tailnet straight from the printer UI (Dashboard → Service → REMOTE_SETUP in Mainsail), no SSH needed. For A3DP support sessions, share the printer node with us from your Tailscale admin console and we can reach the machine without ever touching your router. The support access user can be removed any time with sudo deluser a3dp-support — the machine is fully functional without it.
Everything dangerous (the MCU flasher, bed-gate controls) is deliberately LAN-only and never exposed to the internet or the tailnet.
Where things live
- Prebuilt firmware + per-board flash instructions: Advanced3dPrinting/klipper-firmware-builder — browsable catalog on the firmware download portal
-
The A3DP fleet OS image: robthide37/a3dp-setup-os — releases carry the
.img.xz+ SHA256 sums - Upstream documentation: Klipper docs · Moonraker · Mainsail
- Questions about a specific Modix conversion? That's literally our day job — contact us.
