Macro for "automatic" calibration of BL Touch
-
@owend maybe it makes sense to preheat the nozzle near working temperature before probing? That would compensate for any heat expansion related discrepancies. At least I do that normally when setting Z-offset manually.
-
@jeloneal honnestly i just used that macro i think this is a good start to set up the bltouch parameter, and after that you jsut set the baby step to get correct adjustement.
i did it for my 3 tool heads on my printer -
I've only just discovered this and it works great, however the M564 command at the end needs to be changed to
M564 S1 H1
Otherwise the printer can still be moved outside of the axis.
-
-
@owend said in Macro for "automatic" calibration of BL Touch:
var ProbeSpeedHigh = sensors.probes[0].speeds[0]*60 ; Speeds are saved in mm/sec in the object model but M558 uses mm/min var ProbeSpeedLow = sensors.probes[0].speeds[1]*60
Object model say mm/s but the stored value seems to be in mm/min
-
The object model and config.g now save the probe speeds in mm/min, so no conversion is necessary.
Not sure when that changed.
Original version would have left probe speed at incorrect value until config.g was run again.This is an amended version with corrections suggested by users above,
;Calibrate BL Touch ; Reprap firmware version 3.3b2 or later required! ; if two speed probing is configured in M558,we probably want to reduce the speed for this test var ProbeSpeedHigh = sensors.probes[0].speeds[0] ; save currently configured speed for fast probe var ProbeSpeedLow = sensors.probes[0].speeds[1] ; save currently configured speed for slow probe M558 F60 ; reduce probe speed to 60mm/min for accuracy - adjust F parameter as required ;define some variables to store readings var NumTests=10 ; modify this value to define number of tests ; Do not change below this line var RunningTotal=0 var Average=0 var Lowest=0 var Highest=0 ; If the printer hasn't been homed, home it if !move.axes[0].homed || !move.axes[1].homed || !move.axes[2].homed G28 else G1 Z{sensors.probes[0].diveHeight} F360 ; if axes homed move to dive height M561 ; clear any bed transform M290 R0 S0 ; clear babystepping ; move nozzle to centre of bed G1 X{(move.axes[0].min + move.axes[0].max)/2} Y{(move.axes[1].min + move.axes[1].max)/2} F3600 M564 S0 H0 ; Allow movement beyond limits ;ensure you have room for the probe if move.axes[2].machinePosition < sensors.probes[0].diveHeight G1 Z{sensors.probes[0].diveHeight} M280 P0 S160 I1 ; reset BL Touch G4 S0.5 M98 P"0:/sys/retractprobe.g" ; Ensure probe is retracted & reset G4 S0.5 M561 ; clear any bed transform ; Jog head to position M291 P"Jog nozzle to touch bed" R"Set nozzle to zero" S3 Z1 G92 Z0 ; set Z position to zero M291 P"Press OK to begin" R"Ready?" S3; ; Move probe over top of same point that nozzle was when zero was set G1 Z{sensors.probes[0].diveHeight}; lift head G1 X{move.axes[0].machinePosition - sensors.probes[0].offsets[0]} Y{move.axes[1].machinePosition - sensors.probes[0].offsets[1]} F1800 echo "Current probe offset = " ^ sensors.probes[0].triggerHeight ^ "mm" ; carry out 10 probes (or what is set in NumTests variable) while iterations < var.NumTests G1 Z{sensors.probes[0].diveHeight} ; move to dive height if sensors.probes[0].value[0]=1000 ; if probe is in error state echo "Probe in error state - resetting" M280 P0 S160 I1 ; reset BL Touch G4 S0.5 M98 P"0:/sys/retractprobe.g" ; Ensure probe is retracted & reset G4 S0.5 G30 S-1 M118 P2 S{"Test # " ^ (iterations+1) ^ " Triggered @ " ^ move.axes[2].machinePosition ^ "mm"} ; send trigger height to Paneldue console M118 P3 S{"Test # " ^ (iterations+1) ^ " Triggered @ " ^ move.axes[2].machinePosition ^ "mm"} ; send trigger height to DWC console if iterations == 0 set var.Lowest={move.axes[2].machinePosition} ; set the new lowest reading to first probe height set var.Highest={move.axes[2].machinePosition} ; set the new highest reading to first probe height if move.axes[2].machinePosition < var.Lowest set var.Lowest={move.axes[2].machinePosition} ; set the new lowest reading ;M118 P3 S{"new low reading = " ^ move.axes[2].machinePosition} ; send trigger height to DWC console G4 S0.3 if move.axes[2].machinePosition > var.Highest set var.Highest={move.axes[2].machinePosition} ; set the new highest reading ;M118 P3 S{"new high reading = " ^ move.axes[2].machinePosition} ; send trigger height to DWC console G4 S0.3 set var.RunningTotal={var.RunningTotal + move.axes[2].machinePosition} ; set new running total ;M118 P3 S{"running total = " ^ var.RunningTotal} ; send running total to DWC console G4 S0.5 set var.Average = {(var.RunningTotal - var.Highest - var.Lowest) / (var.NumTests - 2)} ; calculate the average after discarding th ehigh & low reading ;M118 P3 S{"running total = " ^ var.RunningTotal} ; send running total to DWC console ;M118 P3 S{"low reading = " ^ var.Lowest} ; send low reading to DWC console ;M118 P3 S{"high reading = " ^ var.Highest} ; send high reading to DWC console M118 P2 S{"Average excluding high and low reading = " ^ var.Average} ; send average to PanelDue console M118 P3 S{"Average excluding high and low reading = " ^ var.Average} ; send average to DWC console ;suggest new G31 values echo "suggested edit for G31 in config.g if not saved to config-overide.g" echo "change G1 Z parameter from Z" ^ sensors.probes[0].triggerHeight echo "to Z" ^ var.Average G31 P500 Z{var.Average} ; set Z probe offset to the average reading M564 S1 H1 ; Reset limits M558 F{var.ProbeSpeedHigh}:{var.ProbeSpeedLow} ; reset probe speed to original G1 Z{sensors.probes[0].diveHeight} F360 ; move head back to dive height M291 P{"Trigger height set to : " ^ sensors.probes[0].triggerHeight ^ " OK to save to config-overide.g, cancel to use until next restart"} R"Finished" S3 M500 P31 ; optionally save result to config-overide.g
-
@owend, do we have a place to collect those useful user contributed scripts?
-
@zapta
This section of the forum is for both posting macros and asking about conditional g-code and meta commands.
It is a little hard to "browse" though.There are a couple of github repositories mentioned here
https://duet3d.dozuki.com/Wiki/Macros#Section_RepositoryI have put most of my macros and associated printer config files here
https://github.com/owendare/RepRapFirmware-MacrosIt would make sense to do pull requests to a single repository to allow people to find things easier.
file naming conflicts may arise and dependencies could be an issue in that instance.
edit: It looks like sub folders are created to avoid that -
@owend said in Macro for "automatic" calibration of BL Touch:
There are a couple of github repositories mentioned here
https://duet3d.dozuki.com/Wiki/Macros#Section_RepositoryThose might be the most official ones to use.
I've been thinking of the best way to collect and share them on the forum. Having a dedicated forum section is one option, but then I think it would likely end up just being a duplicate of this forum section. So then I thought maybe having a more curated collection as a single pinned thread in this section with links to the thread for the individual macros. Or another option, maybe adding a section to the community projects section for gcode programs.
https://duet3d.dozuki.com/c/Community_Projects
What do you think?
-
@phaedrux
A central GitHub repository such as that which is in place, seems on the surface to be suitable.
Except that the ultimate goal of a repository is to merge all submissions into a single common code base.
That's fine excepting for cases where there may be several different valid approaches to a task which require the file to have the same filename.
Branches can cater to that somewhat bit become difficult for people to navigate to find what they want.
Plus it creates just one more job that someone at Duet has to do (acting on pull requests etc)Perhaps contributors should just create their own repositories and they can be listed in community projects as you suggest?
The ideal solution would be a browse-able directory tree where macros could be placed.
At the top level would be links based on intended kinematics, category and description.
But I can't think how to implement that without an FTP server and/or database , which opens up a whole other can of worms.The up side of the current situation (leaving it on the forum) is that it allows easy peer review and comments on submitted macros.
This is probably worth the extra time it may take in finding what you want as there will inevitably be errors and revisions required for different reasons.
New users will obviously be looking for drop-in solutions, but the reality is that there are to many variables in printer configuration and hardware to make any submitted macro more than a starting point that will require review and modification by them before use.
Leaving it here probably forces them to learn more. -
@owend, FYI, this is how the Voron community does it. A single github repository with a directory for each contributing user. Users can clone the repository, develop in their own copy and then submit a pull request to the maintainers.
Users that don't want to deal with github can just submit their files to the maintainers.
https://github.com/VoronDesign/VoronUsers/tree/master/printer_mods
-
I've revised the main macro yet again and submitted a pull request on the github repository.
This mod is to allow parameters to be passed to it for speeds, nozzle & bed temps etc.
This is shown in the macro call_calibrate.g
If no parameters are passed or the macro is run directly, the default values will be used.I've also added some error & sanity checking.
calling macro/command
; call_calibrate_BLtouch.g ; should be located in same folder as calibrate_BLtouch.g ; Reprap firmware version 3.3b2 or later required! ; If macro is called using parameters these will be used in testing ; If any parameters are omitted, the default values will be used. ; parameters which can be passed are ; T - Tool to use ; B - bed temperature to use ; R - Nozzle temperature to use (may be turned off before probing commences if configuerd to do so in config.g) ; P - probe number to use ; F - X/Y travel speed to use (in mm/sec) var F = 80 ; Z - Z travel speed to use var Z = 6 ; S - Probe speed to use (in mm/sec) var S = 1 ; I - Number of times to probe (high and low value will be discarded) ; the following variables are re-set at run time var R = 0 var B = 0 var T = 0 var P = 0 var maxBedTemp = floor(heat.heaters[heat.bedHeaters[0]].max) var I = 10 ; default number of probes (two extra will be done and high/low discarded) var choice = 0 M291 S5 R"Tool" P"Select Tool Number" L0 H{#tools-1} F0 J1 set var.T = input var Heater = tools[var.T].heaters[0] var maxTemp = floor(heat.heaters[var.Heater].max) echo "maxTemp="^var.maxTemp var minTemp = floor(heat.coldExtrudeTemperature + 5) echo "minTemp="^var.minTemp M291 S4 R"Heat" P"Heat tool/bed ?" K{"None","Nozzle only","Bed only","Both",} F0 J1 set var.choice = input if var.choice!=0 ;echo "Heat choice " ^ var.choice if (var.choice = 1) || (var.choice = 3) ;echo var.minTemp ;echo var.maxTemp M291 S6 R"Nozzle temp" P"Set temperature for nozzle" L{var.minTemp} H{var.maxTemp} F{var.minTemp} J1 set var.R = floor(input) if (var.choice = 2) || (var.choice = 3) M291 S6 R"Bed temp" P"Set temperature for bed" L0 H{var.maxBedTemp} F40 J1 set var.B = floor(input) if #sensors.probes > 1 M291 S5 R"Probe" P"Select probe" L0 H{#sensors.probes-1} F0 J1 set var.P = input M291 S5 R"Cycles" P"Enter number of cycles to sample" L3 H22 F{var.I} J1 set var.I = input + 2 ;echo "M98 P0:/macros/bl_touch/calibrate_BLtouch.g B"^{var.B}^" T"^{var.T}^" R"^{var.R}^" P"^{var.P}^" F"^{var.F}^" Z"^{var.Z}^" S"^{var.S}^" I"^{var.I} if state.atxPower = false M80 G4 S1 ; If the printer hasn't been homed, home it if !move.axes[0].homed || !move.axes[1].homed || !move.axes[2].homed echo "Homing - please wait" G28 M400 M98 P"0:/macros/bl_touch/calibrate_BLtouch.g" B{var.B} T{var.T} R{var.R} P{var.P} F{var.F} Z{var.Z} S{var.S} I{var.I}
revised macro
;Calibrate BL Touch - (modified to use arrays. requires RRF3.5b2 or later) ; If macro is called using parameters these will be used in testing ; parameters which can be passed are ; T - Tool to use ; B - bed temperature to use ; R - Nozzle temperature to use (may be turned off before probing commences if configuerd to do so in config.g by M558 B1) ; P - probe number to use ; F - X/Y travel speed to use (in mm/sec) ; Z - Z travel speed to use ; S - Probe speed to use (in mm/sec) ; I - Number of times to probe (high and low value will be discarded) var NumTests = 10 ; modify this value to define default number of tests var travelSpeed = 3600 ; modify this value to define the default travel speed in mm/min var ZtravelSpeed = 360 ; modify this value to define default Z travel speed in mm/min (not probe speed) var probeSpeed = 60 ; modify this value to define default Z travel speed during probing in m/min var ProbePointX = (move.axes[0].min + move.axes[0].max)/2 ; modify to specify the X probe point. var ProbePointY = (move.axes[1].min + move.axes[1].max)/2 ; modify to specify the Y probe point. var ThisTool=0 ; default tool to use ; Do not change below this line if exists(param.T) set var.ThisTool=param.T var bedTemp = 0 ; default to not heating bed if exists(param.B) set var.bedTemp = param.B if !(var.bedTemp >=0) || (var.bedTemp > heat.heaters[heat.bedHeaters[0]].max) abort "invalid bed temp - test aborted" var nozzleTemp = 0 ; default to not heating nozzle if exists(param.R) if !exists(param.T) abort "Nozzle temp set, but no tool specified" set var.nozzleTemp = param.R if !(var.nozzleTemp >= 0) || (var.nozzleTemp > heat.heaters[tools[var.ThisTool].heaters[0]].max); validate temp abort "Invalid nozzle temp - test aborted" var probeNumber = 0 if exists(param.P) set var.probeNumber = param.P if (var.probeNumber > #sensors.probes - 1) || (var.probeNumber < 0) ; validate probe number echo "Invalid probe number (" ^ var.probeNumber ^ ") , test will be carried out using probe 0" set var.probeNumber = 0 if exists(param.I) if param.I<=2 abort "I parameter must be > 2 - Test aborted" else set var.NumTests = param.I var probeResults = vector(var.NumTests,0) if exists(param.F) set var.travelSpeed = param.F * 60 if exists(param.Z) set var.ZtravelSpeed = param.Z * 60 if exists(param.S) set var.probeSpeed = param.S * 60 if var.probeSpeed <=0 ; validate set var.probeSpeed = 60 ; set to 1mm/sec if invalid parameter passed ; if two speed probing is configured in M558,we probably want to reduce the speed for this test var ProbeSpeedHigh = sensors.probes[0].speeds[0] ; save currently configured speed for fast probe var ProbeSpeedLow = sensors.probes[0].speeds[1] ; save currently configured speed for slow probe ; validate probe speed if var.probeSpeed > var.ProbeSpeedLow var ErrorMsg = "Probe speed (" ^ var.probeSpeed ^ "mm/min) is set higher than defined in config.g (" ^ var.ProbeSpeedLow ^ "mm/min) Continue?" M291 S3 R"Warning" P{var.ErrorMsg} M558 F{var.probeSpeed} ; reduce probe speed for accuracy var RunningTotal=0 var Average=0 if (var.nozzleTemp > 0) || (var.bedTemp > 0) if exists(param.T) if param.T > {#tools - 1} abort "Invalid T parameter - cannot be higher than " ^ {#tools - 1} T{var.ThisTool} ; select the tool passed else T0 ; default to T0 if (var.nozzleTemp > 0) M568 P{var.ThisTool} S{var.nozzleTemp} S{var.nozzleTemp} A2 ; set active temperatures for tool if (var.bedTemp > 0) M140 H0 S{var.bedTemp} if state.gpOut[0].pwm<0.035 ; check if probe is already deployed echo "Probe is already deployed - retracting" M280 P0 S80 ; retract BLTouch G4 S0.5 if sensors.endstops[2].triggered ; check if probe is already triggered echo "Probe is already triggered - resetting" M280 P0 S160 ; reset BL Touch G4 S0.5 if sensors.probes[0].value[0]=1000 ; check if probe is in error state echo "Probe in error state - resetting" M280 P0 S160 I1 ; reset BL Touch G4 S0.5 M280 P0 S80 ; retract BLTouch G4 S0.5 M561 ; clear any bed transform M290 R0 S0 ; clear babystepping ; If the printer hasn't been homed, home it if !move.axes[0].homed || !move.axes[1].homed || !move.axes[2].homed echo "Homing - please wait" G28 M400 else G1 Z{sensors.probes[0].diveHeights[0]} F{var.ZtravelSpeed} ; if axes homed move to dive height M400 M291 P{"Press OK to move to probe point X" ^ floor(var.ProbePointX) ^ " Y" ^ floor(var.ProbePointY)} R"Ready?" S3; ; move nozzle to defined probe point G1 X{var.ProbePointX} Y{var.ProbePointY} F{var.travelSpeed} if (var.nozzleTemp > 0) || (var.bedTemp > 0) echo "Waiting for temps to stabilise" M116 ; wait for temps M564 S0 H0 ; Allow movement beyond limits ;ensure you have room for the probe if sensors.probes[0].lastStopHeight < sensors.probes[0].diveHeights[0] G1 Z{sensors.probes[0].diveHeights[0]} F{var.ZtravelSpeed} ; Notify user to jog nozzle to start position M291 P"Jog nozzle to touch bed" R"Set nozzle to zero" S3 Z1 G92 Z0 ; set Z position to zero M291 P"Press OK to begin probing" R"Ready?" S3; ; Move probe over top of same point that nozzle was when zero was set G1 Z{sensors.probes[0].diveHeights[0]} F{var.ZtravelSpeed}; lift head G1 X{move.axes[0].machinePosition - sensors.probes[0].offsets[0]} Y{move.axes[1].machinePosition - sensors.probes[0].offsets[1]} F{var.travelSpeed} echo "Current probe offset = " ^ sensors.probes[0].triggerHeight ^ "mm" ; carry out 10 probes (or what is set in NumTests variable) while iterations < var.NumTests G1 Z{sensors.probes[0].diveHeights[0]} F{var.ZtravelSpeed}; move to dive height if state.gpOut[0].pwm<0.035 echo "Probe ia already deployed - retracting" M280 P0 S80 ; retract BLTouch G4 S0.5 if sensors.endstops[2].triggered echo "Probe ia already triggered - resetting" M280 P0 S160 ; reset BL Touch G4 S0.5 if sensors.probes[0].value[0]=1000 ; if probe is in error state echo "Probe in error state - resetting" M280 P0 S160 I1 ; reset BL Touch G4 S0.5 M280 P0 S80 ; retract BLTouch G4 S0.5 G30 S-1 ; do probe at current point M118 P2 S{"Test # " ^ (iterations+1) ^ " Triggered @ " ^ sensors.probes[0].lastStopHeight ^ "mm"} ; send trigger height to Paneldue console M118 P3 S{"Test # " ^ (iterations+1) ^ " Triggered @ " ^ sensors.probes[0].lastStopHeight ^ "mm"} ; send trigger height to DWC console set var.probeResults[iterations] = sensors.probes[0].lastStopHeight set var.RunningTotal={var.RunningTotal + var.probeResults[iterations]} ; set new running total set var.Average = {(var.RunningTotal - max(var.probeResults) - min(var.probeResults)) / (var.NumTests - 2)} ; calculate the average after discarding the high & low reading M118 P2 S{"Average excluding high and low reading = " ^ var.Average} ; send average to PanelDue console M118 P3 S{"Average excluding high and low reading = " ^ var.Average} ; send average to DWC console echo "High reading =", max(var.probeResults) , " : Low reading =", min(var.probeResults) echo "Trigger values: " , var.probeResults ;suggest new G31 values echo "suggested edit for G31 in config.g if not saved to config-overide.g" echo "change G31 Z parameter from Z" ^ sensors.probes[0].triggerHeight ^ " to Z" ^ var.Average G31 P500 Z{var.Average} ; set Z probe offset to the average reading M564 S1 H1 ; Reset limits M558 F{var.ProbeSpeedHigh}:{var.ProbeSpeedLow} ; reset probe speed to original G1 Z{sensors.probes[0].diveHeights[0]} F{var.ZtravelSpeed} ; move head back to dive height if var.bedTemp > 0 M140 R0 S0 ; set bed to zero M140 S-276 ; turn off bed if (var.nozzleTemp > 0) && (state.currentTool >-1) M568 R0 S0 ; set heater to zero M568 A0 ; turn off heater on current tool M291 P{"Trigger height set to : " ^ sensors.probes[0].triggerHeight ^ "mm. Press OK to save to config-overide.g, cancel to use until next restart"} R"Finished" S3 M500 P31 ; optionally save result to config-overide.g M291 P{"Reload config.g to restore defaults?"} R"Restore?" S3 M98 P"0:/sys/config.g"
-
Im late to the party but how do i use this macro do i add it to the macro section or the config section ?
-
@sacred-serpent
You would typically put it in the macros folder -