Tag Archives: Klipper

MissChanger Klipper Configuration

Posted 29 September 2025

I have decided to make the Klipper-related changes for my MissChanger adventure into its own post, so readers won’t have to wade through all my other non-klipper related blatherings.

The current project status is:

  • My single SB configuration with single-extruder config file 250830_OrigToolhead_printer.cfg & 250920_Original_stealthburner_leds.cfg working fine.
  • Currently using my new SB (due to original SB’s neopixel intermittency) with original SB’s NH BCB (due to new SB,s PCB failure). This combo works fine

Next step is to reload 250928_MC_T0_printer.cfg, 250922_T0-Nitehawk-Revo-LDO_Ex.cfg and 250922_T0_stealthburner_leds.cfg. this config file set loaded and started up fine.

Now it is time to go through Vim’s ‘Calibration’ (Section 4 in the TOC) instructions to see if I can get prints to work

02 October 2025 Update:

The first part of the ‘Calibration’ section is intended to shake the toolhead around on the Tap & Change mount to make sure it will slide onto and off the mount during tool changes.

Ran ‘G28’ (Home All) and confirmed the toolhead Z position of +10mm at the center of the bed.

Set the heated bed temp to 60C. According to Vin, this is to get the chamber temp up to 40C or so before starting the ‘shake & bake’ routine.

Tried to run ‘SHAPER_CALIBRATE’ but got a ‘Unknown Command’ error. Researched this a bit, and decided to skip this step for the moment.

So, I moved on to Section 4.1 – Park Position Calibrate.

First, I mounted the docking hardware I had previously constructed. This in itself required a bit of work to get everything assembled and mounted.

Then I ran the Home-All & QGL and STOP_TOOL_PROBE_CRASH_DETECTION.

I temporarily replaced the ‘100’ with ‘0.1’ in the toolhead movement options for X/Y movement. Then I used these movement options to optimize the ‘X’ position of the toolhead in front of the leftmost dock, as shown.

This process turned out to be a LOT more complicated than I thought, due to the irregular shape of the stealthburner toolhead. Not only did the X position have to be correct, but the dock module rotation around the 10mm rod mattered as well. Eventually I got what I think is a good lineup at X = 68.7.

After getting the X value down, and getting a good dock module orientation, I tried some dock/undock movements as shown in the following short video:

Tool 0 Dock/Undock testing

The above test was performed by moving the toolhead laterally to the optimum X position (68.7), and forward to just in front of the dock (Y ~ 110). Then I commanded a 50mm Y travel to fully engage the toolhead in the dock without forcing the docking collar up the locking ramp, followed by backing the toolhead out 50mm & repeating the process.

At this point I have one toolhead docking station calibrated with the leftmost docking station.

As a side note, my replacement NH USB PC and replacement RGB LED string came in today, so I have two working toolheads again. My original (Red) SB is now labelled as ‘T1’ and my second (Gray) SB is now labelled as ‘T0’. the USB serial ID’s are”

The next step is to create a second toolhead-specific config with its companion stealthburner_leds.cfg. Since the two stealthburners are identical save for their USB IDSs, this should be relatively easy.

I copied 250922_T0-Nitehawk-Revo-LDO_Ex.cfg to 251002_T1-Nitehawk-Revo-LDO_Ex.cfg, replaced the T0 USB ID with the new T1 USB ID, replaced include 250922_T0_stealthburner_leds.cfg with include 251002_T1_stealthburner_leds.cfg, and changed all 20 instances of ‘nhk0:’ with ‘nhk1:’.

I copied 250922_T0_stealthburner_leds.cfg to 251002_T1_stealthburner_leds.cfg and changed ‘nhk0:gpio7’ to ‘nhk1:gpio7’

Then I saved 250928_MC_T0_printer.cfg to 251002_MC_T1_printer.cfg and (on line 826) changed include ./250922_T0-Nitehawk-Revo-LDO_Ex.cfg to include ./251002_T1-Nitehawk-Revo-LDO_Ex.cfg.

Then using SCP in a Windows command window, I loaded all the above to the raspberry, changing the name of 251002_MC_T1_printer.cfg to just printer.cfg.

I disconnected the USB/Power connector onT0 and restarted restarted the printer. Got ‘mcu nhk0’ Unable to connect.

03 October 2025 Update:

I was a bit ahead of myself with getting the second toolhead up and running. For one thing, I discovered the problem I was having with not being able to successfully do a firmware restart instead having to cycle power was a known problem with the LDO USB adaptor board, and the fix was to physically remove two resistor chips from the PCB. I did this for both the USB adaptor boards.

Then I realized I hadn’t really completed the ‘park position calibrate’ step – I had just done the X position step, so I reverted the firmware to the T0 configuration and started over with this procedure. This time I wound up with X = 69.7 (probably due to some lateral movement of the entire docking bar).

05 October 2025 Update:

Finally got all the way through the dock park calibrate step for T0, and was able to run several successful TEST_DOCK cycles

08 October 2025 Update:

The last couple of days have been marked by one disaster after another. First, I have been unable to get the neopixel string on my new(er) Stealthburner to work, even though I would have sworn on a stack of bibles that it was working fine a few days ago. Second, I tried to ‘unload filament’, forgetting that that particular macro (and a few others I suspect) move the toolhead to the front of the printer, where it promptly collided with the docking assembly, and third, I tried a test print with my new(er) toolhead forgetting that I needed to recalibrate the z-axis offset, so my extruder tip was dragging along the print bed while I frantically banged on the fine-tuning Z+ button. I thought I was doing OK until I watched in horror as the entire conical tip of the extruder fell onto the print bed, along with a huge glop of molten filament! YIKES!!!

Neopixel LED Woes:

By swapping the front shell of my known-good original toolhead with the one from my new(er) toolhead, I was able to determine that the neopixel problem followed the front shell – so not a NH PCB, umbilical or USB adaptor problem. I removed the neopixel strings from both shells and swapped just the neopixel string – and the problem followed the suspect string. Visual inspection of the string was hampered by the fact that whoever assembled the string used all black wires for the intra-pixel connections, and then glopped what looks like black RTV on the connections.

While I did find and repair a broken connection, the string still didn’t work. At this point I decided to get a replacement string on order, so I jumped up on Amazon and ordered this:

When it arrived, I plugged it into my new(er) toolhead (thankfully without going to the trouble of installing all the LEDs) whereupon I discovered that it didn’t work either! I did the same thing with my original shell – no joy there either. Now I feel like I’m in an episode of “The Twilight Zone” (for those of you old enough to have watched them); I have three strings, one of which is brand-new, but only my original toolhead string actually works! After sleeping on this, I decided to set up a test jig to test all the strings independently of the printer. I grabbed an ancient Arduino UNO and a 3-pin 2.0mm male JST plug from my parts bin, downloaded Adafruit’s wonderful NeoPixel library and used their ‘strandtest.ino’ example program to drive the string under test. After getting through all the normal stupid programmer issues, I was able to validate the test jig against my known-good neopixel string – Yay! Then I tested the suspect string from my new(er) toolhead – yep still bad – and then the brand-new string from Amazon – bad. I was really shocked that the new string was bad, as it looked perfect physically, and since the pixels are wired in parallel, I would certainly have expected at least one to work. So, I went looking on Amazon for reviews and found one that said the blue (data) and black (ground) wires were reversed in the connector – yikes! I reversed the pins, and voila` the string lit up – YAY!!

Re-pinned Amazon Neopixel string

Now I have two working strings and one that’s still dead. Maybe it has the same mis-wiring issue? I grabbed my trusty Hanmatek DOS1102 digital O’Scope (a must-have for a well-equipped lab) and used it on my brand-new working string to verify that each pixel chip on the brand-new string had good, solid data (see trace-grab below).

However, when I looked at the ‘bad’ string, I can see the proper waveform on the ‘DO’ solder pad on the ‘input’ side of the first pixel, but not on the ‘output’ side (I didn’t realize until just now that there was an ‘input’ and ‘output’ side – I thought the data line was just like the +V and GND – straight passthrough). So, I bypassed the first pixel by physically connecting the ‘output’ wire to the ‘input’ pad and sure ’nuff, the remaining two pixels lit right up!

‘Bad’ neopixel string test with first pixel bypassed

I installed the new Neopixel string into my ‘T0’ toolhead (with the gray shell). Now that I have my nifty Arduino test program, I was able to test the string at each stage of the installation process to make sure all the required wire contortions didn’t fatally pinch a wire or break a solder connection. Here it is after the string was fully installed (and yes, I did check that the front-facing LED was working too).

Toolhead T0 shell with Neopixel string installed

If you happen to have an Arduino-compatible board (Ardiono, Sparkfun, Teensy, etc) you can easily build the same test jig. I have provided the Arduino code below:

Filament Load/Unload macros – and others?

When I tried to do a filament unload, the toolhead promptly drove itself right into the dock – oops! It was at this point that I realized I really didn’t know what I was doing, and had to get A LOT smarter. The filament unload macro (and surely many others) uses print bed size information from printer.cfg. gcode_macro UNLOAD_FILAMENT calls a macro called ‘FRONT’ to move the toolhead to the front center of the print bed, as shown below:

As can be seen in the above code, the line “G1 X{x_center} Y10 F7800” uses the variable ‘x_center’, but goes to Y = 10, which is why it drives into the dock. This macro should really use something like “Y{printer.position_max – 10}, where ‘printer.position_max’ changes depending on whether or not the dock is present (i.e. on the value of the ‘variable_dock’ variable in ‘gcode_macro _home’)

11 October 2025 Update:

The above issue ran me down a rabbit hole from which I have just emerged – dirty but victorious. Although this crash problem could have been fixed easily by just changing ‘Y10’ to ‘Y110’, I was worried about other places where ‘magic numbers’ might be lurking. And then this got me thinking about all those places in the code where ‘printer.toolhead.axis_maximum.y’ is used, as this value doesn’t currently get changed when CONFIG_TOGGLE is executed.

So, I posed this problem to Grok as follows:

I have the MissChanger toolchanger mod installed. This mod uses a macro called CONFIG_TOGGLE to modify some printer.cfg parameters to account for the approximately 130mm at the front of the build plate occluded by the toolhead docking assembly, The python function ‘klipper-toolchanger/klipper/extras/config_switch.py’ manages this by replacing a section of printer.cfg with either the contents of ‘printer_data/config/config/config_no_dock.cfg’ or ‘printer_data/config/config/config_wt_dock.cfg’ I have attached copies of ‘printer.cfg’, ‘config_wt_dock.cfg’ and ‘config_no_dock.cfg’. It looks like the switch code should modify the printer object’s minimum_y value (derived from the stepper_y section’s position_max) instead of ( or maybe in addition to) the ‘variable_xh’ value in printer.cfg, as the printer object’s values are used everywhere in the code. What do you think?

Amazingly, Grok not only agreed with the idea in principal, but went on to digest the files I had provided and then produce a complete step-by-step procedure for implementing the idea, including complete ‘config_switch files. Grok even analyzed ‘klipper-toolchanger/klipper/extras/config_switch.py’ and figured out that the [stepper_y] and [tmc5160 stepper_y] sections would have to be moved below the ‘;< # Section Variable marker’ line in printer.cfg so that ‘config_switch.py’ could modify the ‘position_min:’ value appropriately. And Grok did the whole thing in just a few minutes! To say that I was blown away by this would be to hugely understate the impact this had on me – wow!

Armed with Grok’s step-by-step plan, I was able (after more ‘running around in circles’ than I care to admit) come up with a complete working set of files to support ‘with_dock’ and ‘without_dock’ configuration switching.

At this point I can switch from the ‘dock module installed’ to the ‘dock module removed’ condition freely. It remains to be seen whether I can now build on that to get to a fully functional dual-toolhead system.

16 October 2025 Update:

I was away for a while, but I’m back now. I read through my notes above, and starting from there will try to make a bit more progress. After getting the ‘config_toggle’ to work, I’m going to try to get the current toolhead (gray shell) working to the point of doing a test print. DON’T FORGET TO MAKE SURE THE ‘CONFIG_TOGGLE’ state matches the actual physical state (docking assembly present or not)!

Note: If you get the error “failed to detect active tool” after a head-banging episode, it is probably because the power was cycled with the toolhead resting on the print bed with the z_axis sensor in the ‘triggered’ state – apparently this prevents the toolhead from being ‘active’. Manually raise the gantry sufficiently to UNtrigger the sensor (blue LED changes to RED). Don’t worry about keeping the gantry level as this will be done later.

In the ‘Dock Installed’ configuraion, I got the Home_all to work, but the gantry-level failed with an ‘out of bounds’ error. This was due to the config_wt_dock.cfg file having ‘110’ as the min Y, but ‘position_min’ in [stepper_y] was set to 130 – oops. I fixed this by setting both numbers to 120 and did ‘Save&Restart’. Then I did *two* ‘CONFIG_TOGGLES’ and re-checked. OOPS! no change to ‘printer.cfg’ – how can this be?

I went back into config_wt_dock.cfg and saw that the numbers had not changed – so what happenec? Checked config_no_dock.cfg and those numbers are OK (25 for min quad level move in Y, position_min = 0 in [stepper_y]).

Did ONE Config_Toggle, and I see the value changed to the ‘no_dock’ values. Did a second one, and now the values are ‘110’ and ‘130’ again, even though I changed them to 120 & 120 in config_wt_dock.cfg. No, they are still 110 & 130 in config_wt_dock.cfg. I edited them again, verified that they were still correct after a save, then did a Save & Restart and checked again. This time they are correct. Oooh, I have a headache! I did a CONFIG_TOGGLE and verified the ‘no_dock’ numbers were correct, but when I did another CONFIG_TOGGLE, not only were the ‘wt_dock’ numbers wrong in printer.cfg, they were also wrong in /config/config_wt_dock.cfg! Something is editing (or reverting?) the wt_dock file

OK, the problem was that CONFIG_TOGGLE calls CONFIG_SAVE before anything else, and CONFIG_SAVE, writes the dock-related contents of printer.cfg to ‘config_wt_dock’ or ‘config_no_dock’ depending on the value (True or False) of the ‘variable_dock:’ parameter. Now fixed.

So now HOME_ALL and QUAD_GANTRY_LEVEL both worked as expected in the ‘with dock’ configuration. So now doing the ‘Calibrate reference z-offset’ step. *should* use the value ‘130’ (min_y = 120 + 10 = 130). YES! It did – and I’m getting a successful print – YAY!

The first test print required a ‘fine-tune’ adjustment of +0.350 to get the right amount of ‘squish’. When the print completed, I accepted the change, and this modified the z-offset to -2.000 (was -1.650). The second test print was OK without any fine-tuning.

I would like to have the toolhead go to Z = 225 after the print has finished but, if possible, do this only for the ‘with_dock’ configuration. I modified printer.cfg to put the entire PRINT_END macro just below the ‘variables’ marker, and then changed the finish z-axis position to 225. Then I ran a test print and this worked – the toolhead climbed to 225, pulling the dock assembly with it so I could easily access the finished print. Then I did a ‘SAVE_CONFIG_MODE’ from the console to write the new printer.cfg contents to the ‘config_wt_dock.cfg’ file. I checked this file and verified that the PRINT_END macro had indeed been saved to it. Then I switched to the ‘no-dock’ configuration, again moved the PRINT_END macro below the variable marker, changed the ending z position to Z25, and ran SAVE_CONFIG_MODE to write it out to ‘config_no_dock’.

Then I did a ‘test print, to verify that the PRINT_END macro works as intended in this config.

18 October 2025 Update:

I couldn’t get the TEST_DOCK operation to work. I kept getting ‘move out of bounds’ errors even though I had executed the STOP_TOOL_PROBE_CRASH_DETECTION macro. This worked before, so I was more than a little bit confused. When I asked Grok about this, he maintained that the STOP_TOOL_PROBE_CRASH_DETECTION has only a ‘local’ (whatever that means) effect – the hardware bounds listed in the config file are still checked and honored. Just now it came to me that I caused this problem when I modified the configuration toggle mechanism to dynamically modify the ‘position_min’ variable in [stepper_y]

I thought I was being very clever, but apparently not clever enough for klipper!

19 October 2025 Update:

When I asked Grok about this issue, it gave me a pretty detailed explanation why the previous ‘clever idea’ didn’t (and won’t) work. Here is Grok’s response:

To address your issue with position_min blocking docking operations while still leveraging printer.toolhead.axis_minimum.y (and similar) for general macro consistency, the core challenge is that position_min enforces a hard, system-wide limit on all moves—it’s static after startup and can’t be dynamically toggled or selectively bypassed for specific macros without workarounds. Based on Klipper’s documentation and community discussions, there are no built-in ways to change it at runtime or ignore it per-macro safely. However, here’s a viable strategy that balances your goals, with options from safe (recommended) to more advanced/risky.Recommended Approach: Use Soft Limits with Full Hardware RangeRevert position_min to 0 in both toggle files (config_no_dock.cfg and config_wt_dock.cfg) to allow full Y-axis access at the hardware level—this ensures docking macros can always succeed without errors, even mid-print. Then, enforce an “effective” minimum Y (your occlusion value, e.g., 130) as a soft limit via macro variables and conditionals. This propagates dynamically without magic numbers by referencing a single variable, while still using the printer object’s actual axis_minimum.y (now always 0) as a base.

Step 1: Update Toggle Files for Full Range

  • In both config_no_dock.cfg and config_wt_dock.cfg, set [stepper_y] position_min: 0 (keep other values like position_max: 310).
  • This makes printer.toolhead.axis_minimum.y always 0 after restart, avoiding any hard bounds errors during docking.

Step 2: Define an Effective Min Y Variable. Add or update a global variable in your toggle files (e.g., in [gcode_macro _static_variable] or a new [gcode_macro _limits]). Use variable_dock to set an “effective_min_y”:

[gcode_macro _limits]
variable_effective_min_y: {% if printer["gcode_macro _home"].dock %} 130.0 {% else %} printer.toolhead.axis_minimum.y {% endif %}  # Your occlusion value; use 110 if that's exact
gcode:  # Empty, just for variables
  • Place this in the swappable section of both toggle files (after the marker).
  • Now, printer[“_limits”].effective_min_y acts as your dynamic, dock-aware min Y—it’s 130 when docked (soft-enforcing occlusion for print ops) and 0 otherwise.
  • After toggling/restarting, this propagates to all macros without hardcoding 130 everywhere.

Step 3: Update Macros to Use the Effective MinReplace direct references to printer.toolhead.axis_minimum.y or hard Y values with {printer[“_limits”].effective_min_y} (or add offsets as needed). Examples:

  • Prime Line (e.g., in PRINT_START or a prime macro):
  • {% set prime_y = printer["_limits"].effective_min_y + 5 %} # Safe offset from effective min
  • G1 X{printer.toolhead.axis_maximum.x / 2} Y{prime_y} F7800 # Prime at front if no dock, or just above occlusion if docked
  • Parking (e.g., in PAUSE or M600):G1 X{printer.toolhead.axis_maximum.x / 2} Y{printer["_limits"].effective_min_y + 5} F6000 # Parks safely above effective min
  • Other Macros: For any that position near front (e.g., nozzle clean, unload), use similar: Y{printer[“_limits”].effective_min_y + offset}.
  • Keep [bed_mesh] and [quad_gantry_level] toggling as-is—they already use high min Y (e.g., 110) when docked to avoid probing occluded areas.

Benefits and Trade-offs

  • Keeps Using Printer Object: You still reference printer.toolhead.axis_minimum.y as a base (it’s now reliably 0), but layer the effective value on top for dock awareness—no magic numbers scattered around.
  • Docking Succeeds: Full range allows low-Y moves without errors.
  • Safety: Soft limits prevent accidental print/probe in occluded areas via macros, but won’t block invalid custom G-code (e.g., manual G0 Y10 would still work—add warnings if needed).
  • No Restart Mid-Print: Toggle only when switching dock install state (e.g., hardware changes).
  • Update your slicer profiles to match effective build volume (Y min 130 when docked) to avoid sliced violations.

This is the safest, most maintainable way without risking hardware.

It occurred to me that rather than modifying the dock & no-dock toggle files per Step1, I could simply move the [stepper_y] & [tmc5160 stepper_y] sections back above the variable marker where they started and remove the sections from both the dock & no-dock config files. I checked this with Grok, and he was OK with that. So, Step 1 – complete.

Step2: Grok said the [gcode_macro _limits] section could go anywhere ABOVE the toggle marker, so I put it JUST above the marker, with a comment. I also changed ‘130’ to ‘120’ as I know it works.

Other macros that needed to be modified:

  • Prime line code in [gcode_macro PRINT_START]
  • Front position in [gcode_macro FRONT]: I discovered that past-Frank had shifted this macro into the ‘Session Variables’ section (presumably so the y-value could be changed to reflect the ‘dock/no-dock’ configurations), but the corresponding macros in ‘config_wt_dock’ and ‘config_no_dock’ weren’t any different than the original version – oops!. Moved the CHOME & FRONT macros back to their original positions above the ‘Session Variables’ marker and changed the y value in ‘FRONT’ from {% set y_center = printer.toolhead.axis_maximum.y|float / 2.0 %} to {% set y_front = printer[“_limits”].effective_min_y + 5 %} and ‘G1 X{x_center} Y{y_center} F7800’ to ‘G1 X{x_center} Y{y_front} F7800’. Also added a statement to send the FRONT x,y pos to the display.
  • Removed the CHOME & FRONT macros from ‘dock’ & ‘no-dock config files (and moved the ‘#include'[include 251003_T0-Nitehawk-Revo-LDO.cfg]’ to the top)

Now I will just have to play with the printer for a while and see what happens. Fortunately by this time I have a pretty good understanding of how all the bells and whistles work. As one more safety measure, I have included printer.cfg, config_wt_dock, and config_no_dock here:

config_wt_dock.cfg:

config_no_dock.cfg:

printer.cfg

20 October 2025 Update:

Back to testing after yesterday’s marathon sessions with Grok. Started a test print with the dock in place (“variable_dock: True” in printer.cfg). Hopefully the prime line will get laid down just in front of the dock exclusion area. Hurrah – it worked! The prime line was laid down at Y=125, as expected, and the print itself turned out as well as any in the past.

28 October 2025 Update:

I spent the entire day yesterday trying to get the ‘LOAD_FILAMENT’ macro to work with toolhead T1, with no success. Every time I tried the macro, it would heat the extruder to 230C and then hang forever ‘waiting for temperature’, even though I could plainly see that extruder 1 was at 230C. For a long time I thought maybe this was happening because I hadn’t yet calibrated the PID for the extruder heater, so the temp was varying too much. After I finally figured out how (with a lot of help from Grok) to calibrate the PID, I *still* couldn’t get LOAD_FILAMENT to work. Eventually, with more help from Grok, I figured out the problem. It turns out that the LOAD_FILAMENT macro definition in printer.cfg only works for a single extruder setup, and it was blocking the execution of the multiple-extruder version of LOAD_FILAMENT in the ‘macro_general.cfg’ file that came with the MissChanger installation – oops!

Once I figured this out, I deleted the LOAD_FILAMENT (and UNLOAD_FILAMENT) versions in printer.cfg, and voila! everything started working again!

So now I understand why the example printer.cfg that came with the MissChanger installation is so simple compared to the one I had developed over time since I first got my Voron 2.4 going; it’s because many of the standard operations in my printer.cfg assume a single extruder (named ‘extruder’). This still works OK with my dual extruder setup when extruder T0 is active, as it is also named ‘extruder’. However, when T1 is active, its extruder is named ‘extruder1’, which isn’t recognized at all by the single-extruder macro definitions. The corresponding macros in ‘macro_general.cfg’ have been generalized to deal with any number of extruders, named ‘extruder’ (for T0) or ‘extruder[x]’ (where ‘x’ ranges from 0-N).

After finally figuring this out, I went back through all the macros in printer.cfg to see what other single-toolhead limited code has to be removed to avoid overriding multiple-toolhead versions in macro_general.cfg, but didn’t find any more. Apparently, the LOAD/UNLOAD_FILAMENT were the only ones.

OK, now I’m trying to figure out why my SB LEDs aren’t working, and my assumption is it has something to do with the T0/T1 issue above. I instrumented 251002_T1_stealthburner_leds.cfg to display on the status screen in the ‘Dashboard’ display, and from that I can tell that when I run the ‘status_ready’ (and others), that the correct macro is called (in this case, the one in 251002_T1_stealthburner_leds.cfg). However, nothing happens on the toolhead itself.

251029 Update:

Well, I am truly down the rabbit-hole without a crumb trail on this one. After a full day of working on the issue with Grok, I’m more lost now than when I started. Grok seems completely convinced that the issue is a hardware problem caused by trying to run the nominally 5V neopixel string from the nominally 3.3V RP2040 MCU on the NH PCB. Grok’s cure was to install a WS2812B 3.3-5V Shifter Board. I’m more than a little suspicious of this result, as I remember having the LED strings on both toolheads working not long ago. Here’s a short movie of a dock/undock cycle from 24 October and the neopixel string was working just fine then.

So, my plan is to revert my Klipper config setup to that previous one and see if the LEDs work again. If so, then it obviously is a software, not hardware, problem.

Looking through my saved config files, I found this complete set of config files:

I replaced the contents of printer.cfg with the contents of 251025_wt_dock_printer.cfg (this file uses the 251003_T0-Nitehawk-Revo-LDO.cfg tool-specific config file, which is already available on the printer), and voila! the LEDs on the T0 (gray) toolhead are back, and all the ‘STATUS_xxx’ macros work as well! So, my old “Hardware never fails – it is ALWAYS a software issue” mantra wins again.

When I told this to Grok, he(it?) congratulated me on eliminating hardware as the problem, and then decided the problem was caused when I moved the T0/T1 include files to the top of printer.cfg. This caused the T0/T1 code to be inserted in the wrong place, thereby causing the LED problems I experienced. Grok then guided me through fixing the issues with the dual toolhead config files.

30 October 2025 Update:

Well, Grok and I have been back and forth a lot over the last few days, and I’m sure by now Grok (he/she/it?) is getting frustrated with the inability of this old human to ‘grok’ (and yes, I *am* old enough to have read “Stranger in a Strange Land” when it first came out) the finer points of Klipper configuration file construction.

The basic problem is that whenever I try to implement a dual-toolhead configuration, the stealthburner LEDs are disabled. Grok has explained this is due to ‘included’ files overwriting needed LED control information (like pin numbers?), and has provided several ideas for fixing the problem via different config file edits. Unfortunately my Klipper ignorance is showing (and Grok has some real blind spots as well), so I haven’t been able to get anything to work.

While researching why this LED thing is giving me so much trouble, I came to realize that the real problem is that I started with the single-toolhead config file developed over time since I first got the Voron going, and part of that was the use of the ‘stealthburner_leds.cfg’ add-on that contains all the cool ‘STATUSxxx’ macros. However, vin’s MISSChanger project starts with just a very plain-vanilla printer.cfg file without any of the bells/whistles and adds the multiple-toolhead stuff from there. This was a situation ripe for problems and boy did I have them. I’m going to give Grok’s ideas a good try, but if I can’t make them work, I’m going to go back to Vin’s basic printer.cfg and build things up from there.

31 October 2025:

Last night I was able to verify that ‘klippy.log’ contains the entire in-lined configuration, after all includes and before parsing at the top of each entry. This should go a long way toward effective troubleshooting of the ‘No LEDs’ problem. However, when I started the process of implementing the Grok-suggested changes, I discovered that my printer will no longer connect to nhk0 or nhk1. I get the dreaded “mcu ‘nhk1’: Unable to connect” and/or “mcu ‘nhk0’: Unable to connect” error(s). Since I haven’t made any hardware changes this is kinda hard to believe, and at least so far I’m convinced this is yet another software-induced issue.

So, I plan to go back to my 251025 configuration (251025_wt_dock_printer.cfg & 251003_T0-Nitehawk-Revo-LDO.cfg). Yep! this configuration setup worked perfectly – no errors, and the restart was very rapid (maybe 2-5 seconds).

I’m going to start a new post – “MissChanger Klipper Configuration – Part 2” – as this one is getting a bit cumbersome.

Stay tuned,

Frank

Klipperizing my Flashforge Creator Pro 2 3D Printer

Posted 28 September 2024

I’ve had my Flashforge Creator Pro 2 (FFCP2) IDEX 3D Printer for about three years now, and it is my go-to printer for anything requiring internal support structures. For instance, this model is a pill dispenser that screws onto a pill bottle and dispenses one pill at a time.

The dispenser has a slide mechanism (colored grey above) that allows one pill/caplet to drop down from the bottle into a slot when the slide is positioned at one end of its travel. The captured pill is then dropped out of the mechanism when the slide is move to the other extreme. Printing this as a single piece requires the use of a dissolvable support filament, which in practice requires a dual extruder printer like the FFCP2. Although in theory this could be done on a single extruder printer with a ‘multi-material’ setup like the Prusa XL or the Bambu X1, in practice it is extremely difficult because the without a LOT of purging, the dissolvable filament contaminates the extruder head and weakens the print.

So I love my FFCP2 because it allows me to print things like the above pill dispenser, but I hate it because the supplied firmware is anything but elegant, and there have been no updates since I purchased it three years ago (and since it has been discontinued by the manufacturer, no updated are likely in the future either). However, a few days ago, while doing yet another futile search for FFCP2 firmware updates, I ran across this post, which claimed to have gotten Klipper to work on a FFCP2. At the time I wasn’t sure what ‘Klipper’ was, but after some research I realized this was what I was looking for – in spades! According to the Klipper Github page, it is hardware-agnostic 3-d printer firmware with the features described here.

Reading through the features list and the FAQ was more than a little overwhelming; I got lost pretty quickly trying to figure out what the heck this ‘Klipper’ stuff was doing. I think I finally figured out that ‘Klipper’ is a system composed of (at least) three parts, as shown below:

Klipper System Diagram

In the above diagram, the firmware in the 3D printer MCU is replaced by firmware that handles only low-level direct hardware control functions; all the calculations required for a successful print are moved to the Klipper host software on the Linux-enabled device (a Raspberry Pi or equivalent, or a Linux PC of some kind). This offloads most of the computational load from the 3D printer MCU allowing – at least in theory – the printer to actually run faster (although the physics of extrusion and motors will still limit the process). The Linux-enabled device also contains a web server (Mainsail or FLUIDD) that exposes 3D printer controls to the user, via any web browser or dedicated display like the very cool CYD program by Sims. The Klipper software in the Linux-enabled device is much more usable than my old Flashforge firmware, and since it is written in Python and is open-source, much easier to maintain/extend.

Progress to date:

Due to some hardware problems with my FFCP2, I haven’t yet gotten Klipper going on my printer. However, I have managed to connect to my printer’s MCU board using a cheap ST-LINK adaptor from Amazon and the ST-LINK Utility from ST Micro (ST Micro says that ST-LINK is now deprecated in favor of their STM32CubeProgrammer app, but I found that I could not connect to the FFCP2 MCU with this app, but I could with ST-LINK – go figure) . It took me a while to find my way around the ST-LINK utility, but I finally figured out that I could modify the default memory view ‘size’ parameter to capture more or less of the MCU’s flash memory. After a short conversation with ‘Guru’ at ST, I took his advice and expanded the ST-LINK memory view to the full 1MByte flash memory size of the STM32F407xx MCU on the FFCP2 motherboard, and then saved that image to a file for safe-keeping and, if necessary, reversion to the original firmware.

For the ‘Linux-enabled Device’, I decided to repurpose an old Dell Precision M6700 laptop that already had Debian Linux loaded from a previous project. After making sure that my Debian install was up to date, I followed the instructions in Evil Azrael’s Wiki to load Klipper onto the laptop. Here are some photos of the process:

The connections are:

           MCU SWD    ST-LINK

GRN      GND             GND

YEL       DIO              SWDIO

ORG     CLK             SWCLK

At this point, I’m waiting on a part delivery to get my FFCP2 back in working order so I can finish my ‘Klipperization’ project, but I’m really looking forward to having access to a non-moronic printer control package.

24 October 2024 Update:

When I connected up my ST-LINK/USB adapter to my FFCP2 and my Win 11 laptop, I was unable to get ST’s ST-LINK utility to connect to the MCU – bummer! After verifying all the connections and trying different things (power-cycling and/or resetting the FFCP2, disconnecting/reconnecting the USB cable, etc) I still have been unable to connect. This is a serious bummer, as if I have ‘bricked’ my FFCP2 I have no idea what to do next. I posted to the ST forum, so I’ll see how that goes.

After some more research, I found this post describing how to force a firmware reload, as follows:

I did all this using the .BIN file I captured from the ST-micro MCU, but unfortunately the printer did not respond. I have also attempted to find the original factory firmware for this printer on the FlashForge support site, but that all seems to have disappeared. :(.

28 October 2024 Update:

After crying in my beer for a while, I started looking for alternative methods for regaining access to my ‘bricked’ STM32F407 motherboard processor. I figured ST-Micro had to have some way of doing this, so I started poking around there. Eventually I came across this article that described the process, as shown below:

So I started looking for BOOT0 on my motherboard – a process that was hindered by the lack of a schematic. Apparently FlashForge printers (including the FFCP2) are ‘closed’ products and schematics are hard/impossible to find. Fortunately for me, I had developed a bit of rapport with the FlashForge tech support team, and I pleaded to them for a copy of the schematic, pointing out that since the FFCP2 is no longer supported by FlashForge, there shouldn’t be any reason to continue to hold onto the schematics. To my amazement, this actually worked, and I got an email back with the board schematic as a JPG attachment – yay!

FlashForge Creator Pro 2 Schematic with BOOT0 highlighted

As can be seen from the above schematic and photo, BOOT0 is connected to the resistive voltage divider R12/R13, and the value of R13 is 0Ω (short circuit) holding BOOT0 to GND. To raise BOOT0 to VDD (3.3V), all I have to do is remove R13 from the circuit and R1 (10K) will pull it up to VDD. Here is a photo showing R13 removed from the circuit.

After powering up the printer, I found that I was indeed able to connect to it using ST-LINK (ST32CubeProgrammer still doesn’t). Here’s a photo of the motherboard with a small SPST switch installed to make switching BOOT0 high/low easier

But not with STM32CubeProgrammer

31 October 2024 Update:

Well, bad news; although I could regain SWD connection using the BOOT0 trick, I was unable to figure out how to get my original FFCP2 firmware back onto the STM32 MCU. I can load the firmware (or at least ST-LINK utility says I loaded the firmware), but the printer won’t come back up properly after the load. I eventually succumbed and installed a new motherboard (ouch!$$$). The new motherboard seems to be from a different production run, as the ugly jumper wire is now missing.

As an experiment, I hooked up my old motherboard to my lab power supply set for 24 (actually 23.19), and was able to connect to it using ST-LINK Utility on my windows 11 box and a ‘clone’ ST-LINK adaptor. Interestingly, I was unable to connect using STM32CubeProgrammer on either my Win11 box or my Linux box. Maybe I have to have a ‘genuine’ ST-LINK adaptor for that magic to work?

Stay tuned!

Frank