common toolchange macros (run "tpost.g" if "tpost#.g" not found)
-
Hi together,
I am in the process of refactoring all the macro files of my E3D ToolChanger - it got quite some conditional gcode happending.
As for tool changing, each tool has its own tpre#.g, tpost#.g and tfree#.g, despite having almost the same content. To eliminate this redundancy I created a 'global' tpre.g, tpost.g and tfree.g for all tools. Now I call each of those macros with a parameter (param.T).
With this change I can put together a common logic for all tools and call it in each specific file via 'M98 P"tpre.g" T#'.
Example of the 'global' tfree.g:
; tfree.g ; can be called with param.T: tool number to be freed ; abort if axes are not homed: 0:X 1:Y 2:Z 4:C if !move.axes[0].homed || !move.axes[1].homed || !move.axes[2].homed || !move.axes[4].homed M291 T5 P"Please home axes before a toolchange" R"Cannot change tool" abort ; create vars var toolXpos = 0 var toolYpos = 0 ; set tool dock position (and check for valid num) if param.T == 0 set var.toolXpos = -157.7 set var.toolYpos = 115.5 elif param.T == 1 set var.toolXpos = -67.5 set var.toolYpos = 115.7 elif param.T == 2 set var.toolXpos = 61.3 set var.toolYpos = 115.3 elif param.T == 3 set var.toolXpos = 170.0 set var.toolYpos = 115.2 else M291 "var.toolXpos or var.toolYpos was not set" R"error in tfree.g" abort ; drop the bed G91 G1 H4 Z5 F1200 G90 ; move to location G53 G1 X{var.toolXpos} Y55 F40000 ; move in G53 G1 Y110 F4000 ; move slowly to final position G53 G1 Y{var.toolYpos} F2500 ; open coupler M98 P"/macros/Coupler/unlock.g" ; move out G53 G1 Y113 F2000 G53 G1 Y110 F4000 G53 G1 Y100 F6000
Example of tfree1.g:
; tfree1.g ; called when tool 1 is freed M98 P"tfree.g" T1
This works well so far, but I would like to get rid of the individual toolchange files.
Therefore I would like to discuss the following ideas for calling tool change macros in RRF (changes are bold) :-
If another tool is already selected, run macro tfree#.g where # is the number of that tool. If tfree#.g is not found, run tfree.g (with parameter T = #) instead.
-
If another tool is already selected, deselect it and set its heaters to their standby temperatures (as defined by the R parameter in the most recent G10/M568 command for that tool)
-
Run macro tpre#.g where # is the number of the new tool. If tpre#.g is not found run tpre.g (with parameter T = #) instead.
-
Set the new tool to its operating temperatures specified by the S parameter in the most recent G10/M568 command for that tool
-
Run macro tpost#.g where # is the number of the new tool. If tpost#.g is not found run tpost.g (with parameter T = #) instead.
-
Apply any X, Y, Z offset for the new tool specified by G10
-
Use the new tool.
What do you guys think? Is this a good idea or am I proposing a solution where no one has a problem?
-
-
@marvineer thanks for the suggestion. I can see how it would be useful and would work. @dc42 may have a technical issue with this that I am not spotting but if not we would consider it for including in a future firmware version however that is unlikely to be before 3.6 as there are a lot of changes in (or due to be in) 3.5 already.
-
@marvineer I like the idea of a fallback to tpre.g/tpost.g/tfree.g, but I am not sure if we actually need the T parameter. There is already
state.nextTool
fortpre.g
,state.currentTool
fortpost.g
, andstate.previousTool
fortfree.g
.It's quite straight-forward to add so I'll have a look. Btw the tool offsets can remain static, better to use
G53 G1
for tool pickups and parking. -
@chrishamm I tried it with your suggestions, without the parameter it is even easier and more flexible.
The best part: It's already on the way to being implemented
Thanks a lot!
-
@marvineer could you share your new global files for tool change?
-
@marvineer Getting rid of the individual tool change files when one has created "universal" files seems like a good idea. I did something similar to you but called my "universal" files "ToolFree.g" , "ToolPost.g" and "ToolPre.g". Then every individual tool change file just a has a simple M98 to call the appropriate "Toolxxx.g" file. It wasn't too bad too do. I simply created the first file than did repeat "save as" to create the rest but it's a bit of a pain having all those unnecessary file which do the same thing.
-
@lparnell34 shure, there you have it. Let me know if you have any questions.
It's not super well structured, but it'll do for now ...
I would recommend defining the dock positions globally so they are the same everywhere.tpre.g:
; tpre.g ; called before a tool is selected ; use state.nextTool to determine witch tool is selected ; abort if axes are not homed: 0:X 1:Y 2:Z 4:C if !move.axes[0].homed || !move.axes[1].homed || !move.axes[2].homed || !move.axes[4].homed M291 T5 P"Please home axes before a toolchange" R"Cannot change tool" T-1 P0 abort ; check if toolDetectSwitch is active, if so:abort if sensors.gpIn[5] == null || sensors.gpIn[5].value == 1 M291 T5 P"toolDetectSwitch is active, but should not" R"Cannot change tool" T-1 P0 abort if move.extruders[0].filament == "" && state.status == "processing" M117 "No filament in extruder 0!" ; create vars var dockXpos = 0 var dockYpos = 0 ; set tool dock position if state.nextTool == 0 set var.dockXpos = -157.7 set var.dockYpos = 115.5 elif state.nextTool == 1 set var.dockXpos = -67.5 set var.dockYpos = 115.7 elif state.nextTool == 2 set var.dockXpos = 61.3 set var.dockYpos = 115.3 elif state.nextTool == 3 set var.dockXpos = 170.0 set var.dockYpos = 115.2 else M291 P"var.toolXpos or var.toolYpos was not set (unknown toolNum)" R"Cannot change tool" abort G91 G1 H4 Z5 F1200 ; drop the bed G90 set global.ZisLifted = false M98 P"/macros/Coupler/unlock.g" ; unlock Coupler M564 S0 ; allow movement outside the normal limits ; move to location G1 X{var.dockXpos} Y100 F40000 ; move in faster G1 Y110 F4000 ; move in slowly to final position G1 Y{var.dockYpos} F2500 M98 P"/macros/Coupler/lock.g" ; close Coupler ;wait for all movement to stop M400 ; check if toolDetectSwitch is deactive, if so:abort if sensors.gpIn[5] == null || sensors.gpIn[5].value == 0 M291 T5 P"toolDetectSwitch is not active, but should" R"Cannot change tool" T-1 P0 abort ; set speed and axes limits for this new tool if state.nextTool == 0 || state.nextTool == 1 M98 P"/macros/Speeds/set_speed.g" L"lightTool" ; set speeds, jerk and accel. for light weight bowden tool M98 P"/macros/Boundaries/V6-and-Volcano.g" ; set new limits for this tool elif state.nextTool == 2 M98 P"/macros/Speeds/set_speed.g" L"heavyTool" ; set speeds, jerk and accel. for heavy direct tool M98 P"/macros/Boundaries/Hemera-Direct.g" ; set new limits for this tool elif state.nextTool == 3 M98 P"/macros/Speeds/set_speed.g" L"spindleTool" ; set speeds, jerk and accel. for very heavy spindle M98 P"/macros/Boundaries/Mill.g" ; set new limits for this tool else M291 P"speed and limits where not set (unknown toolNum)" R"Cannot change tool" abort ;WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! ;if you are using non-standard length hotends ensure the bed is lowered enough BEFORE undocking the tool! G91 G1 H4 Z{-tools[state.nextTool].offsets[2]} F1200 G90 G1 Y113 F2000 ; move out a bit ; check if toolDetectSwitch is deactive, if so:abort if sensors.gpIn[5] == null || sensors.gpIn[5].value == 0 M291 T5 P"toolDetectSwitch is not active, but should be" R"Cannot change tool" T-1 P0 abort G1 Y110 F4000 ; move out a bit G1 Y55 F4000 ; move out ; apply new min limit for z axis so we cannot crash into bed M208 S1 Z{-tools[state.nextTool].offsets[2]} ; apply the normal limits again M564 S1
tpost.g:
; tpost.g ; called after a tool has been selected ; use state.currentTool to determine witch tool was selected ; set filament parameters ; this sets temps and other related settings for specific loaded filament M703 ; wait for heat up on active tool only M116 P{state.currentTool} ; unretract G11 ;prime nozzle M98 P"/macros/Brush/setHeightToActiveTool.g" if state.status = "processing" M98 P"/macros/Brush/wipe_activeTool.g" S"ZisLifted" M106 R1 ; restore print cooling fan speed
tfree.g:
; tfree.g ; called when a tool is freed ; use state.previousTool to determine witch tool was freed ; abort if axes are not homed: 0:X 1:Y 2:Z 4:C if !move.axes[0].homed || !move.axes[1].homed || !move.axes[2].homed || !move.axes[4].homed M291 T5 P"Please home axes before a toolchange" R"Cannot change tool" abort ; check if toolDetectSwitch is not active, if so:abort if sensors.gpIn[5] == null || sensors.gpIn[5].value == 0 M291 T5 P"toolDetectSwitch is not active, but should" R"Cannot change tool" abort ; create vars var dockXpos = 0 var dockYpos = 0 ; set tool dock position if state.previousTool == 0 set var.dockXpos = -157.7 set var.dockYpos = 115.5 elif state.previousTool == 1 set var.dockXpos = -67.5 set var.dockYpos = 115.7 elif state.previousTool == 2 set var.dockXpos = 61.3 set var.dockYpos = 115.3 elif state.previousTool == 3 set var.dockXpos = 170.0 set var.dockYpos = 115.2 else M291 "var.toolXpos or var.toolYpos was not set (unknown toolNum)" R"Cannot change tool" abort ; free out of heat wait loop M108 G91 G1 H4 Z5 F1200 ; drop the bed G90 M564 S0 ; allow movement outside the normal limits G53 G1 X{var.dockXpos} Y55 F40000 ; move to location G53 G1 Y110 F4000 ; move in G53 G1 Y{var.dockYpos} F2500 ; move in slow M98 P"/macros/Coupler/unlock.g" ; open coupler M106 P2 S0 ; fan off G53 G1 Y113 F2000 ; move out a bit ;wait for all movements to stop and sync movement queues M400 ; check if toolDetectSwitch is active, if so:abort if {sensors.gpIn[5] == null || sensors.gpIn[5].value == 1} M291 T5 P"toolDetectSwitch is active, but should not" R"Cannot change tool" T-1 P0 abort G53 G1 Y110 F4000 ; move out a bit G53 G1 Y100 F4000 ; move Out ; set speeds, jerk and accel. for no active tool M98 P"/macros/Speeds/set_speed.g" ; reset X and Y limits M98 P"/macros/Boundaries/ToolHead.g" ; reset Z min limit M208 S1 Z0 M564 S1 ; apply the normal limits again
-
-
@marvineer said in common toolchange macros (run "tpost.g" if "tpost#.g" not found):
@chrishamm I tried it with your suggestions, without the parameter it is even easier and more flexible.
The best part: It's already on the way to being implemented
Thanks a lot!
Not to go off on a tangent here, but I've skimmed through the last two months worth of commits on the 3.5dev branch without seeing that mentioned anywere, where did you find it?
🤔
-
@Exerqtor have a look at this:
Added support for tool macro fallbacks (commit)It is already included in the latest version (3.5.0-beta.4).