Thoughts on Multi-Tool Alignment (long)
-
There is M675 to probe the center of a cavity. This should simplify the probing for metal on metal contact. Unlike for CNC work coordinate systems there doesn't seem to way to set tool offsets relative to the current position. So without extensions it can't currently not be for setting tool offsets. If WCS are useable in 3D printing mode each tool could probe and use a separate WCS instead of tool offsets.
-
Nice! I'd missed that one.
Given the dynamic nature of Duet configuration, several of these alternatives will work if I make the io4.in pin the endstop for that axis. The only problem with that is, I have to undefine the regular endstop... and of course I'd want to set it back after executing this process. I worry about what would happen if the process is interrupted.
I have actually considered ending the whole process with an M999. That would reliably ensure that the contents of config.g were in force.
Hmmm....
-
It might also be possible to sense the centre of the nozzle using an inductive sensor, but only if the range of the sensor is short enough for the heater block not to throw it off. Or perhaps use a vertical rod as a capacitive sensor?
-
OK, so people have been talking about sensing. Could be camera, microswitch(es), piezo, inductive, and more. I'm still going to pursue metal-metal for now.
Now let us think about G-Code vs Scripting on the Pi.
Q1: Do we believe that tool-to-tool offset could be done ENTIRELY in G-Code?
- Prior to conditional G-Code?
- With conditional G-Code?
Q2: What fundamental probing technique/command is best for this?
- G1 H3?
- M585?
- M675?
- Other?
Q3: If scripted on the Pi, what language?
- Python
- Perl
- bash (or similar)
Or all above in one generic question: SPECIFICALLY how to do this, right now?
-
The only way I think it could be done now is using M675. But for XY offset measurement, I think a capacitive sensor and special firmware support may be a better option. Two options in particular spring to mind:
- Probe above a vertical rod or above a disc on the top surface of a PCB, measuring the capacitance between the rod or disc and the nozzle. It should be a maximum when the nozzle and the rod are aligned on the same axis, unless the capacitance to the heater block is significant.
- Lower the nozzle into a cone and probe inside that.
To measure the Z offset, I favour a nozzle-contact sensor. We've already tested one type with the E3D tool changer, but it didn't work as well as we had hoped. We have another design planned.
-
Why a cone for XY? When probing X, Y has not yet been set with absolute certainty, and therefore contacting a chord of X (instead of a radius of X) would throw things off.
I'm thinking a square hole would be better. Aligned XY as best as possible. That way, when probing X, small errors in Y don't matter.
This piece has a Z touch area, and a square hole.
-
At the moment, I'm still shooting for metal to metal contact. I do like the "capacitance to rod" idea. A .5mm rod should "peak" really well with most nozzle tips. May have to look at that some more.
In fact, with regard to metal-to-metal, I have a prototype working as a Python script on the Pi. It uses the 'CodeConsole' interface over and over. Because I can't get M558/M585 style probing to work at the moment, and because it needs to probe on all three Axis, it dynamically re-configures the M574 style endstops and uses G1 H3 probes. It then has to reset the axis limit that was changed by the H3, and reset the endstop as well. To ensure that these 'reset' reconfigurations never vary from what is in config.g, the python scripts extracts the proper commands from config.g. and runs them.
The plate (photo a couple of posts up) is on a corner of the bed (for now) and is grounded. Each tool nozzle has a wire... these wires (plural) come back to a common point, where they join a single wire headed for io4.in.
The python code, in addition to being able to issue any G-Code command, can issue M408, parse the output, and retrieve the position of any axis.
It is quite nifty that Duet RRF allows dynamic reconfiguration... but... this is all very much a hack, and I look forward to doing it a different way in the future.
Anyway, it does work. I'm still seeing how consistent it is. An experimental run on one tool, with just "print" statements of the results, looks like this:
# Start of probing for Tool 0 G0('','',10,1000) # Lower bed to avoid collision with square hole plate. Gcode('T0') # Pick up Tool zero Gcode('G10 P0 Z0 X0 Y0') # Remove all offsets from Tool zero # Z Axis Gcode('M574 Z1 S1 P"!io4.in"') G0('','',10,1000) # Lower bed to avoid collision with square hole plate. G0(290,285,'',10000) # Move nozzle to spot above flat part of plate Gcode('G1 H3 Z0') toolZ = getPos()[2] # Capture the Z position at point of contact print('>>>>>>>>>> ToolZ '+str(toolZ)) G0('','',10,1000 ) # Lower bed to avoid collision with square hole plate. resetAxisLimits() Gcode('M574 Z1 S1 P"nil"') # X Axis Gcode('M574 X1 S1 P"!io4.in"') G0('','',10,1000) # Move the bed to ensure no dragging G0(290,270,'',1000) # Place the nozzle tip in center of square hole. G0('','',toolZ-1,100) # Place the nozzle tip just below surface. Gcode('G1 H3 X270') toolX = getPos()[0] # Capture the X position at point of contact print('>>>>>>>>>> ToolX '+str(toolX)) G0(290,270,'',1000) # Place the nozzle tip in center of square hole. resetAxisLimits() Gcode('M574 X1 S1 P"nil"') # Y Axis Gcode('M574 Y1 S1 P"!io4.in"') G0('','',10,1000) # Move the bed to ensure no dragging G0(290,270,'',1000) # Place the nozzle tip in center of square hole. G0('','',toolZ-1,100) # Place the nozzle tip just below surface. Gcode('G1 H3 Y250') toolY = getPos()[1] # Capture the X position at point of contact print('>>>>>>>>>> ToolY '+str(toolY)) G0(290,270,'',1000) # Place the nozzle tip in center of square hole. resetAxisLimits() Gcode('M574 Y1 S1 P"nil"') resetEndstops()
The output of the print statements from a run against a single tool:
>>>>>>>>>> ToolZ 4.962 >>>>>>>>>> ToolX 281.681 >>>>>>>>>> ToolY 260.3
-
the usual technique is:
-
probe one axis inside a circle - find the ends of the chord
-
move the axis to mid-point of the chord - now you should be on the radius of the other axis
-
probe the other axis - find the ends of the chord
-
move to the mid-point of the chord ( which should be the diameter )
-
re-probe the first axis now that you are centered in the circle
-
midpoint of the chord should be a high accuracy center point
-
-
Got it, thanks!
-
OK, switched over to M675 for XY. Works great. Doing the X, Y, X again thing... still in the square hole. I will make a round hole plate tomorrow.