Skip to content

About

Klipper MCU firmware for the Mellow FLY LLL Buffer Plus — autonomous in-firmware auto-feed (halls->TMC2208) + Klipper USB MCU runout. Best of standalone + Klipper.

Resources

Stars

4 stars

Watchers

3 watching

Forks

Latest commit

 

History

8 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 

Repository files navigation

Mellow FLY LLL Buffer Plus — Klipper MCU Firmware (autonomous auto-feed)

License: GPL v3 MCU Klipper

📌 Successor project — Mellow-LLL-Plus-Canonical. Same autonomous core, plus a complete Klipper host-control layer: per-lane roles, 21 G-code commands, multi-lane (one USB per board), telemetry events, a Mainsail dashboard, a prebuilt binary and a bilingual manual. This repo stays valid for a minimal, autonomous-only build.

Custom Klipper MCU firmware for the Mellow FLY LLL Buffer Plus that brings together the best of both worlds:

  • 🟢 the autonomous smart-buffer auto-feed of Mellow's standalone firmware (hall sensors drive the feed motor in firmware, real-time), and
  • 🟢 the board running as a standard Klipper USB MCU, so the filament-entrance sensor can trigger a print pause through Klipper.

Both at the same time, over a single USB cable (+ 24 V motor power) — something neither the stock standalone firmware nor the community host-macro configs can do on their own.


Why this exists

The official Mellow firmware is standalone: the buffer auto-feeds on its own but the board does not talk Klipper (no USB MCU; runout has to go through a separate signal wire).

The community Klipper integrations (river29, ss1gohan13) flash stock Klipper and re-implement the buffer with host-side g-code macros. That works, but feed bursts go through the g-code queue (latency, can lag during long G1 E moves) and they switch the active extruder, which can misdirect extrusion during a print.

This project runs the buffer state machine inside the MCU firmware as a Klipper task — zero g-code-queue latency, no active-extruder juggling, can't stall a print. The host only reads the entrance sensor on PB7.

Standalone (Mellow) Stock Klipper + host macros This firmware
Auto-feed ✅ in-firmware ⚠️ host macros (queue latency) ✅ in-firmware
Klipper MCU / USB sensor ❌ ✅ ✅
Risk of disrupting a print n/a ⚠️ ACTIVATE_EXTRUDER ✅ none
Runout → print pause signal wire USB (PB7) USB (PB7)

How it works

A small Klipper MCU task (src/buffer.c, DECL_INIT + DECL_TASK) ports the state machine of Mellow's open firmware (Fly3DTeam/Buffer) and drives the on-board TMC2208 over its single-wire UART (VACTUAL velocity mode):

HALL3 (PB4) blocked  → motor FORWARD (push filament)
HALL2 (PB3) blocked  → motor STOP
HALL1 (PB2) blocked  → motor BACK (retract)
ENDSTOP_3 (PB7) = no filament → STOP   (+ host pauses the print)

Photo-sensor convention is taken verbatim from the source: blocked = 1, clear = 0. Manual feed/retract buttons (KEY1/KEY2) and the mainboard control signals (PB5/PB6, active-low) are supported too. A 60 s continuous-feed timeout acts as a jam safety.

The only change versus the standalone is that the button "hold" is handled event-driven (non-blocking) instead of the original blocking while() loop, because blocking for seconds would break Klipper host comms. Behaviour is identical.

Pins (STM32F072CB)

Function Pin Function Pin
HALL1 PB2 KEY1 (retract) PB13
HALL2 PB3 KEY2 (feed) PB12
HALL3 PB4 FRONT signal PB5
Entrance switch PB7 BACK signal PB6
TMC EN PA6 TMC UART PB1

Installation

Done from your Klipper host (e.g. a Raspberry Pi). Commands assume ~/klipper and ~/katapult (Arksine/katapult) are cloned, the Klipper build toolchain is installed, and dfu-util is available (sudo apt install dfu-util).

Step 0 — Find your buffer & power it

Connect the buffer's USB to the host and give it 24 V on VIN (the motor needs it; the firmware configures the TMC at first boot, so 24 V must be present then).

List USB serial devices to identify the board and note your unique chip ID (you'll reuse it in printer.cfg):

ls /dev/serial/by-id/
# e.g. usb-Klipper_stm32f072xb_3C003A...3720-if00   (or a Mellow / katapult id)
#                            └──────── your XXXXXX ────────┘

Step 1 — Enter DFU mode (to install Katapult)

On the buffer board: hold BOOT, tap RESET, release RESET, then release BOOT. Confirm (needs sudo):

sudo dfu-util -l
# → Found DFU: [0483:df11] ... name="@Internal Flash  /0x08000000/064*0002Kg"

Step 2 — Back up the existing firmware (recommended)

sudo dfu-util -a 0 -d 0483:df11 -U ~/lll_backup_flash.bin       -s 0x08000000:0x20000
sudo dfu-util -a 1 -d 0483:df11 -U ~/lll_backup_optionbytes.bin            # option bytes

Step 3 — Build & flash Katapult (one-time bootloader)

Katapult lets you flash all future updates over USB without opening the case.

cd ~/katapult
make menuconfig
  • Micro-controller Architecture: STMicroelectronics STM32
  • Processor model: STM32F072
  • Clock Reference: 8 MHz crystal
  • Communication interface: USB (on PA11/PA12)
  • Application start offset: 8 KiB
  • Support bootloader entry on rapid double click of reset: OFF ⚠️ (the LLL Plus has no usable reset button; leaving this ON makes the board fail to enumerate)
make clean && make
# board still in DFU (Step 1); flash with mass-erase so no stale app remains:
sudo dfu-util -a 0 -d 0483:df11 -D out/katapult.bin -s 0x08000000:force:mass-erase:leave

Re-plug USB and confirm Katapult enumerates:

ls /dev/serial/by-id/
# → usb-katapult_stm32f072xb_XXXXXX-if00

Step 4 — Add this firmware to Klipper

cp src/buffer.c ~/klipper/src/buffer.c

Add one line to ~/klipper/src/Makefile (only compiled for the F072 buffer, never for your main board):

src-$(CONFIG_MACH_STM32F072) += buffer.c

⚠️ This line is reverted by git pull on the Klipper tree — re-add it after updating Klipper. buffer.c itself is untracked and survives.

Step 5 — Build Klipper

⚠️ make menuconfig overwrites ~/klipper/.config. If you build other MCUs (your main board, toolhead…) from this same tree, back up its config first and restore it afterwards:

cp ~/klipper/.config ~/klipper/.config.mainboard   # backup
# ...build & flash the buffer...
cp ~/klipper/.config.mainboard ~/klipper/.config    # restore later
cd ~/klipper
make menuconfig
  • Micro-controller Architecture: STMicroelectronics STM32
  • Processor model: STM32F072
  • Bootloader offset: 8 KiB bootloader (must match Katapult)
  • Clock Reference: 8 MHz crystal
  • Communication interface: USB (on PA11/PA12)
make clean && make

Step 6 — Flash Klipper over USB (via Katapult)

~/klippy-env/bin/python3 ~/katapult/scripts/flashtool.py \
  -f ~/klipper/out/klipper.bin \
  -d /dev/serial/by-id/usb-katapult_stm32f072xb_XXXXXX-if00

Use the klippy-env Python — it has pyserial (the system Python usually doesn't). After flashing, the board re-enumerates as usb-Klipper_stm32f072xb_XXXXXX-if00.

Step 7 — printer.cfg

[mcu LLL_PLUS]
serial: /dev/serial/by-id/usb-Klipper_stm32f072xb_XXXXXX-if00
restart_method: command

[filament_switch_sensor lll_entrance]
switch_pin: ^!LLL_PLUS:PB7
pause_on_runout: True

Choosing the runout behaviour (pick one):

  • Simplest — most setups: pause_on_runout: True and nothing else. On runout Klipper runs your normal PAUSE, including the park position your [gcode_macro PAUSE] / [pause_resume] already defines (the same one your slicer pause uses). Your park position lives in your PAUSE macro — pause_on_runout calls it, so you don't repeat it here.

  • Add a notification / lights / etc.: keep pause_on_runout: True and add a runout_gcode: — it runs after the pause, so use it for extra actions (not another pause):

    runout_gcode:
        M118 LLL Plus: filament runout — paused
    insert_gcode:
        M118 LLL Plus: filament reinserted
  • Fully custom routine (your own park macro, M600, unload sequence…): set pause_on_runout: False and put your macro in runout_gcode::

    pause_on_runout: False
    runout_gcode:
        MY_RUNOUT_MACRO

⚠️ Don't put a bare PAUSE in runout_gcode while pause_on_runout: True — it's a double pause. And pause_on_runout/PAUSE both rely on [pause_resume] being in your config (standard on virtually all printers).

No motor/stepper/TMC section — the firmware owns the motor; the host only reads PB7. Then FIRMWARE_RESTART.


Updating later (no case opening)

cd ~/klipper && make clean && make          # (re-add the Makefile line if a git pull removed it)
~/klippy-env/bin/python3 ~/katapult/scripts/flashtool.py \
  -f ~/klipper/out/klipper.bin \
  -d /dev/serial/by-id/usb-Klipper_stm32f072xb_XXXXXX-if00
# then FIRMWARE_RESTART

flashtool reboots the running app into Katapult over USB automatically — you can target the Klipper serial directly, no buttons.


TMC2208 register values

Derived directly from Mellow's firmware parameters (via the TMCStepper library it uses), not guessed:

Register Value Notes
GCONF 0x000001C4 spreadCycle, pdn_disable, mstep_reg_select (shaft bit set for FORWARD)
CHOPCONF 0x12020055 toff=5, vsense, 64 µsteps, intpol
IHOLD_IRUN 0x00010F07 IRUN=15, IHOLD=7 (≈ rms_current(500) @ Rsense 0.11)
PWMCONF 0xC10D0024 pwm_autoscale
VACTUAL 77575 260 rpm, 64 µsteps

Speed/current can be changed in src/buffer.c (SPEED_RPM, the register values) and re-flashed.


Known behavior — Mainsail shows MCU load ~100% (false positive)

Once this firmware is running, Mainsail's MCU Load bar for the LLL Plus may read ~100 %. This is a false positive — the MCU is not overloaded.

The autonomous auto-feed task bit-bangs the TMC2208 VACTUAL value over a software UART. Each update is a short, tightly-timed burst (~8 ms), which inflates the per-task timing standard deviation that Mainsail's load indicator is built on — even though the MCU is idle the vast majority of the time.

Measured over a full print (klippy.log / MCU stats):

Metric Value Meaning
mcu_awake ~0.03–0.06 awake only ~3–6 % of the time
mcu_task_avg ~0.4 ms tasks are short
mcu_task_stddev ~2.5 ms spikes from the bit-bang VACTUAL bursts (~8 ms) — this is what drives the "100 %" bar
send_seq vs receive_seq equal no command backlog
retransmits a few bytes over a whole print link healthy
"Timer too close" / shutdowns 0 no real overload

Conclusion: the ~100 % reading is a display artifact of the bit-bang timing jitter, not an overloaded MCU. Auto-feed, buttons and runout all keep working normally — no action needed.


Status / disclaimer

Validated on one setup (FLY LLL Buffer Plus, STM32F072CB).

Bench-tested & working:

  • Auto-feed — hall sensors driving the motor (core state machine + VACTUAL).
  • Manual hold of the feed / retract buttons (KEY1 / KEY2).
  • Runout on PB7 → print pause.

Ported faithfully from Mellow's firmware but not individually exercised here (no hardware/wiring to trigger them on this setup): mainboard signal control (PB5/PB6), the buttons' single-/double-click side-effects (EXT pin output, pause toggle), and the 60 s jam timeout.

Pins and register values are specific to this board.

⚠️ No warranty — use at your own risk. This is experimental, community firmware provided AS-IS, with NO WARRANTY of any kind (see the GPL-3.0 license — Disclaimer of Warranty §15 and Limitation of Liability §16). Flashing MCU firmware can brick the board or damage hardware. You assume all risk; the author accepts no liability for any damage, bricked board, failed/ruined print, or other loss. Back up your existing firmware first (Step 2) and make sure you understand each step before running it.

Credits

License

GPL-3.0 — derived from GPL-3.0 sources (Fly3DTeam/Buffer, Klipper).

About

Klipper MCU firmware for the Mellow FLY LLL Buffer Plus — autonomous in-firmware auto-feed (halls->TMC2208) + Klipper USB MCU runout. Best of standalone + Klipper.

Resources

Stars

4 stars

Watchers

3 watching

Forks

Releases

Packages

Contributors

Languages