Hi all, I’m new here so hopefully I’m doing this right!
I’m working on a pick and place machine, which assembles circuit boards and has two nozzles. Each nozzle has a Z motor to move it up/down and a rotation motor to spin the nozzle. All of these 4 motors are set up as manual_stepper. My nozzles act as the probe themselves. When they touch something, a pin gets triggered.
I’d like to create a Macro Gcode that is something like PICK LEFT or PICK RIGHT or PLACE LEFT, etc that would cause the nozzle to move down until the pin is triggered and then perform the rest of the Gcode in the Macro.
The thing I can’t figure out is how to do this? You can only have one [probe] in Klipper. Also my z motors for each nozzle use TMC 2209 sensorless homing, so they have a virtual end stop for this reason. It’s almost like I’d like to add a min_endstop since they home to max (sensorless) but min end stop can’t be added if you already do sensorless?
I’ve been able to add [gcode_button] to detect each nozzle’s probe pin, but because of how G1 commands are done where the loop of the command needs to finish first, it can’t be interrupted with [gcode_button] to stop the execution from what I understand.
I don’t think that Klipper is the proper software for your project.
Klipper is made to control 3D-printers. Other purpose are quite difficult up to impossible.
While Klipper does technically support homing a stepper to more than one endstop, you’ll have to go pretty deep into the Python code to expose that capability in a useful way.
@3dcoded Is there any pointers you can provide to go down this route? Is it possible for a manual_stepper to home using stall guard AND have a min_endstop at the same time?
@EddyMI3D I wasn’t able to find any other firmware/software that bundles with RPI CM5 as well as Klipper does. I’m looking to run OpenPNP on the RPI, hence why I went with Klipper. I think Klipper is able to do everything else I need it to do to make this PNP work, just the probing would be ideal addition so I don’t need to guess the height of every component that is picked/placed. It’s a huge burden to figure that out for accurate placement.
Just a heads up, the procedure isn’t exactly simple, so you’ll need to be fluent in Python.
Also yes you can do StallGuard homing with this approach. Just register another endstop with the name tmc2209__manual_stepper_test:virtual_endstop, for example.
You might also want to take a look at my guide on writing Klippy extras.
Unfortunately I’m not fluent in python Is there any other way to have the nozzle act as a probe, endstop or some other solution so that it moves down until a pin is triggered?
Unfortunately yes, snice you will need to register the endstop (and stepper to the endstop) in Python, then invoke a homing command to a specific endstop.
It could be an extras/ modification, based off of manual_stepper.py. You might want to keep an eye on this thread, since Klipper might be adding multi-endstop support to steppers.
See the updated Config_Reference.md and G-Codes.md on that branch for information on declaring additional endstops and using them during homing commands.
This is a very raw test branch, just for discussion purposes at this time.
Hi @koconnor , I can confirm it works with both manual steppers really well! They stop moving when endstop1 is triggered! Thank you so much for this! I’m hopeful you can merge this into the main branch so I don’t get left behind on a test branch Please let me know if you want me to test anything else to make this happen and I’ll happily help out.
I was also curious - with this modification, is it possible to use sensorless homing for a secondary min endstop? This would reduce hardware requirements quite a bit for my setup.
Thinking further (and I know I’m possibly asking a lot) it would be cool if you can adjust the sensitivity of sensorless homing per additional endstop or even just the min endstop so it’s different than the max. The reason being is that when you place components for a pick and place machine to assemble circuit boards, you ideally want to put as little pressure as possible on tiny components (0402, 0603, etc) and more pressure on larger components (MCU chips). Putting too much pressure on tiny components like 0402 could cause them to fly out from under the nozzle and putting too little pressure on large components could cause them to not reflow well where there’s bad contact with the pins. Something to keep in mind if you want to expand further on this
It should be possible to use sensorless homing with the manual_stepper code. It doesn’t matter which direction you home in with a manual_stepper if using sensorless homing - the stepper will stop when the driver signals a stallguard event. So, for example, MANUAL_STEPPER STEPPER=mystepper MOVE=-99 STOP_ON_ENDSTOP=1 should do sensorless homing in the min direction while MANUAL_STEPPER STEPPER=mystepper MOVE=99 STOP_ON_ENDSTOP=1 should home in the max direction.
It is possible to adjust the sensitivity using the SET_TMC_FIELD STEPPER="manual_stepper mystepper" FIELD=SGTHRS VALUE=xxx command (or depending on driver, SET_TMC_FIELD STEPPER="manual_stepper mystepper" FIELD=sgt VALUE=xxx). You can also adjust the current with SET_TMC_CURRENT. So, you can change the current and/or stallguard sensitivity prior to issuing a MANUAL_STEPPER STEPPER=mystepper MOVE=a STOP_ON_ENDSTOP=1 command.
I tried the following and at first it said out of range but then when it did move with MOVE=0, it ended up crashing into min and not detecting stall guard. My z motors do home to max using stall guard.
4:50 PM MANUAL_STEPPER STEPPER=left_z MOVE=0 STOP_ON_ENDSTOP=1
4:50 PM Move out of range
4:50 PM MANUAL_STEPPER STEPPER=left_z MOVE=-20 STOP_ON_ENDSTOP=1
4:50 PM Move out of range
4:50 PM MANUAL_STEPPER STEPPER=left_z MOVE=-99 STOP_ON_ENDSTOP=1
I’m wondering if I’m missing a setting in config for min “homing” ?
Since you’ve declared position_min: 0 in the config, you can’t move to a position less than 0. To home, use something like MANUAL_STEPPER STEPPER=left_z SET_POSITION=50 MOVE=0 STOP_ON_ENDSTOP=1 to first force the software to think the motor as at position 50 and then home to position zero (that is, move 50mm in the negative direction regardless of the position_min setting).
There’s nothing in the software that I’m aware of that cares about the direction of travel when using STOP_ON_ENDSTOP. It is possible that you may need to use different SGTHRS settings in the negative direction (as the contact observed by the driver may have a different pattern in that direction). Similarly, current and speeds may need to be tuned as well. You may need to run through the steps at TMC drivers - Klipper documentation for the min direction. (That is, you may need to determine separate tuning in each direction.) If so, just be sure to use macros that manually set the particular tuning settings (SET_TMC_FIELD) just prior to issuing the MANUAL_STEPPER STOP_ON_ENDSTOP=1 commands.
Also, as mentioned at the link above, be sure to wait 2 seconds prior to each homing attempt as it does seem the tmc drivers need some idle time to reset in order to get reliable stallguard threshold triggers.
Thanks for the feedback @koconnor . In that case, I’ll stick to the extra end stops solution as it is likely to perform better. Detecting a stall in the downward direction is likely to cause a tiny part like a 0402 capacitor to fly out due to tiny parts requiring gentler placement and is likely too difficult to tune with stallguard. The wait time to clear the drivers before stalling again isn’t ideal as well for a fast PNP machine.
What are the chances of the extra end stops getting implemented into the main branch? I’d love to stay on the main branch instead of getting left behind on a fork. Such a solution would be useful to anyone building a PNP machine so they don’t have to spend over an hour measuring and entering each component’s height and instead rely on a probe for pickup and placement of parts. And there’s quite a few people on the OpenPNP forums that want to use Klipper
I think it would be useful to add. There are also a few other common use cases for it. I think the final config parameters need more discussion and review before it would be ready for mainstream. Alas, I don’t have a good estimate for that right now - maybe sometime in early 2026.
The only important changes for this support is in klippy/extras/manual_stepper.py, so for the interim it’ll likely be possible to copy that file into later Klipper versions.
Hi @koconnor I am testing the additional endstop feature and it seems to me that it’s overshooting the endstop. I can confirm the end stops are working when I trigger them and it does stop the manual stepper. But if the Pick and Place nozzle (manual stepper) moves down fast, the spring on the nozzle gets compressed by like 3-5mm at least I’d say before the nozzle stops. Seems to me like it doesn’t react fast enough to stop the manual stepper.
Any ideas? Is there some sort of delay in the code?