I've put some thought into semi-automating the process of adjusting the parameters affecting stall detection.
Unfortunately the values of M915 are not exposed to the object model.
So instead they must be entered into an array.
These initial values will be applied regardless of your M915 settings,
so they should be set to the same value at the start of the process and after any changes to config are made.
For this to work I have three files.
The first is driver-stall.g
If this is called, and the axis involved is X or Y then it will call dist2home.g which will measure whether there were steps lost and re-home etc.
You can then from that call auto_adjust_stall.g which will optionally adjust M915, jerk and acceleration values up to pre-defined values.
Any changes are logged to file and the console.
At some point you should stop getting stall events during the test print
At the end of the print you should
review the settings
confirm that they will capture valid stalls without false positives
adjust your config.g to reflect the last adjustment
I've tested the system but not extensively
driver-stall.g
;0:/sys/driver-stall.g
var allowedSteps = 3 ; adjust as required. Number of measured steps to constitute a valid error
var macroLocation = "0:/macros/homing/dist2home.g" ; adjust as required
var filePos = job.filePosition
M400 ; wait for moves in queue to stop
G60 S5 ; save position to slot 5
M25 ; pause
G1 R5 X0 Y0 Z0 F3600;
M400
var Axis = "" ; start with no value
var subLoop = 0
var mainLoop = 0
echo "stall on driver " ^ param.D
while var.mainLoop < #move.axes
set var.subLoop = 0
while var.subLoop < #move.axes[var.mainLoop].drivers
if (param.D ^ "") = (move.axes[var.mainLoop].drivers[var.subLoop] ^ "")
set var.Axis = move.axes[var.mainLoop].letter
set var.subLoop = var.subLoop + 1
set var.mainLoop = var.mainLoop + 1
if var.Axis = ""
echo "No axis letter found for driver " ^ param.D
M99
else
echo "Error is on " ^ var.Axis ^ " axis"
if (var.Axis="X") || (var.Axis="Y")
M98 P{var.macroLocation} A{var.Axis} S{var.allowedSteps} R{var.filePos} D{param.D}; only run the file if it's X or Y axis fault
M24 ; resume print
dist2home.g
; dist2home.g
; should be called by driver-stall.g
; ASSUMES HOMING TO MINIMA!!
; only accepts X and Y axes
; assumes X is axes[0] and Y is axes[1]
; send axis by using A parameter
; send threshold for number of steps to constitute false positive as S parameter
; send driver number as D paramater
; send file position of error from driver-stall as R parameter
; e.g.
; M98 P"dist2home.g" A"Y" S"3" D"1" R"43251"
; **********adjust as required**********
var dist2move = -500 ; set greater than all axies length
var thisAxis = "X" ; default to x axis,but can be changed if parameter sent
var moveSpeed = 600; speed during homing moves
var homeOnError = true ; home axes is error found
var return = true ; return to start position
var logErrors = true ; save details to a log file
var logFile = "0:/sys/driver_stall_log.txt" ; location of log file
var maxErrorSteps = 3 ; can be overwritten by param.S
var zLift = 2 ; amount to lift Z before moving
var adjustOnError = true; call auto adjust on measured error
var adjustOnFalseAlarm = true ; call auto adjust on false alarm
var adjustMacro = "0:/macros/homing/auto_adjust_stall.g" ; file to run if automatic adjustments are enabled
;*****************************************
; don't edit below here
var stepX = {1 / move.axes[0].stepsPerMm}
var stepY= {1 / move.axes[1].stepsPerMm}
var microStepsX = var.stepX / move.axes[0].microstepping.value
var microStepsY = var.stepY / move.axes[1].microstepping.value
var currentXlimit = move.axes[0].min
var currentYlimit = move.axes[1].min
var currentX = move.axes[0].machinePosition
var currentY = move.axes[1].machinePosition
var currentZ = move.axes[2].machinePosition
var xMove = var.dist2move ; will be reset as needed
var yMove = var.dist2move ; will be reset as needed
var searchPosX = move.axes[0].machinePosition
var searchPosY = move.axes[1].machinePosition
var hasErrorX = false;
var hasErrorY = false;
var measuredError = 0
var filePos = 0
if exists(param.A)
set var.thisAxis = param.A
if exists(param.S)
set var.maxErrorSteps = max(1,floor(param.S)) ; set max error steps to not less than one, or param.S
if exists(param.R)
set var.filePos = param.R
var maxErrorX = var.maxErrorSteps * var.stepX
var maxErrorY = var.maxErrorSteps * var.stepY
if !move.axes[0].homed || !move.axes[1].homed || !move.axes[2].homed
echo "Machine not homed"
M99
M400 ; wait for any moves to stop
G60 S5 ; save position to slot 5
echo "selected axis is " ^ var.thisAxis
echo "start position X" ^ var.currentX ^ " Y" ^ var.currentY
if var.thisAxis = "X"
set var.yMove = 0
echo "Move amount is " ^ var.xMove
G92 X0 ; Set current X position to 0
G4 P100
G91
G1 Z{var.zLift} F120; raise Z
M400
G1 H3 X{var.xMove} F{var.moveSpeed}; Home to selected axis to minimum and set the axis limit
M400
set var.searchPosX = move.axes[0].min - var.currentXlimit
echo "Dist: " ^ abs(var.searchPosX) ^ " Start: " ^ var.currentX
set var.measuredError = abs(var.currentX - abs(var.searchPosX))
if var.measuredError <= var.maxErrorX
set var.hasErrorX = false
echo "Error amount on X ("^ var.measuredError ^ "mm) is less than or equal to " ^ var.maxErrorSteps ^ " steps " ^ "(" ^ var.maxErrorX ^ "mm)"
else
set var.hasErrorX = true
echo "Measured error on X is : " ^ var.measuredError ^ " mm"
echo "Full steps : " ^ floor(var.measuredError/var.stepX) ^ " + MicroSteps : " ^ floor(mod(var.measuredError,var.stepX)/var.microStepsX)
M208 S1 X{var.currentXlimit} Y{var.currentYlimit} ; Set axis limit back to original
M208 ; report axis setting
G90 ; absolute moves
G92 X{var.currentXlimit}
elif var.thisAxis = "Y"
set var.xMove = 0
G92 Y0 ; Set current position to 0
G91 ; set relative moves
G1 H3 Y{var.yMove} F{var.moveSpeed}; Home to selected axis to minimum and set the axis limit
M400
echo "Dist: " ^ abs(var.searchPosY) ^ " Start: " ^ var.currentY
set var.measuredError = abs(var.currentY - abs(var.searchPosY))
if var.measuredError <= var.maxErrorY
set var.hasErrorY = false
echo "Error amount on Y ("^ var.measuredError ^ "mm) is less than or equal to " ^ var.maxErrorSteps ^ " steps " ^ "(" ^ var.maxErrorY ^ "mm)"
else
set var.hasErrorY = true
echo "Measured error on Y is : " ^ var.measuredError ^ " mm : Steps = " ^ var.measuredError / var.stepY
echo "Full steps : " ^ floor(var.measuredError/var.stepY) ^ " + MicroSteps : " ^ floor(mod(var.measuredError,var.stepY)/var.microStepsY)
M208 S1 X{var.currentXlimit} Y{var.currentYlimit} ; Set axis limit back to original
M208 ; report axis settings
G90 ; absolute moves
G92 Y{var.currentYlimit}
else
echo "Undefined axis sent: " ^ param.A
echo "Exiting macro with no action"
G90 ; absolute moves
M99 ; exit macro
G90 ; absolute moves
if var.homeOnError
if var.hasErrorX
echo "homing X"
G28 X
if var.hasErrorY
echo "homing Y"
G28 Y
G1 R5 Z0 ; restore Z position
M400
if var.return
G1 R5 Z{var.zLift} F60
G1 R5 X0 Y0 Z{var.zLift} F3600; move back to original position
G1 R5 Z0 F60 ; lower Z to original
M400
echo "Position restored"
;G92 Y{var.currentYlimit}. X{var.currentX} Z{var.currentZ}; Set current position as original
if var.hasErrorX || var.hasErrorY
if var.logErrors
if !fileexists(var.logFile)
echo >{var.logFile} "Driver stall log"
echo >>{var.logFile} "*******************************************"
echo >>{var.logFile} state.time
echo >>{var.logFile} "Print job: " ^ job.file.fileName ^ ""
echo >>{var.logFile} "File position: " ^ job.filePosition ^ " : First report @ " ^ var.filePos
if var.hasErrorX
echo >>{var.logFile} "Error amount X:" ^ var.currentX - abs(var.searchPosX) ^ " mm"
echo >>{var.logFile} "Full steps : " ^ floor(var.measuredError/var.stepX) ^ " + MicroSteps : " ^ floor(mod(var.measuredError,var.stepX)/var.microStepsX)
if var.hasErrorY
echo >>{var.logFile} "Error amount Y:" ^ var.currentY - abs(var.searchPosY) ^ " mm - Steps = " ^ abs(var.currentY - abs(var.searchPosY) ) / var.stepY
"Full steps : " ^ floor(var.measuredError/var.stepY) ^ " + MicroSteps : " ^ floor(mod(var.measuredError,var.stepY)/var.microStepsY)
echo >>{var.logFile} "*******************************************"
if var.adjustOnError
M98 P{var.adjustMacro} D{param.D}
else
if !fileexists(var.logFile)
echo >{var.logFile} "Driver stall log"
echo >>{var.logFile} "*******************************************"
echo >>{var.logFile} state.time
echo >>{var.logFile} "Print job: " ^ job.file.fileName ^ ""
echo >>{var.logFile} "File position: " ^ job.filePosition ^ " : First report @ " ^ var.filePos
echo >>{var.logFile} "Stall detected on drive " ^ var.thisAxis ^ " was lower than threshold"
echo >>{var.logFile} "*******************************************"
if var.adjustOnFalseAlarm
M98 P{var.adjustMacro} D{param.D}
auto_adjust_stall.g
;auto_adjust_stall.g
; Must be called from dist2home.g
; do not run as stand alone
; NOTE: Values are not stored between boots.
; values must be applied to config.g when satisfied they capture valid stalls without false positives
; Axis diver number must be passed as D parameter
; array containing initial M915 values for X and Y drivers first value is S (threshold) second is H
; set initial values here. Must be manually set as not available from object model
; should match your config.g initially
var stallVals = {{4,250},{4,200}}
; values to change and amounts to change by. Also min/max allowed
var increaseS = true ; adjust M915 S parameter true/false
var amountS = 1 ; amount to adjust (increase) by on each stall event
var maxS = 8 ; maximum allowed value before auto adjust stops applying
var increaseH = true ; adjust M915 H parameter true/false
var amountH = 4 ; amount to adjust (increase) by on each stall event
var maxH = 300 ; maximum allowed value before auto adjust stops applying
var reduceJerk = true ; adjust (reduce) jerk value on stall event true/false
var amountJerk = 10 ; amount to adjust (decrease) jerk on each stall event
var minJerk = 500 ; minimum jerk value allowed before auto adjust stops applying
var reduceAccel = true ;adjust (reduce) acceleration value on stall event true/false
var amountAccel = 20 ;amount to adjust (decrease) acceleration on each stall event
var minAccel = 600 ; ; minimum jerk value allowed before auto adjust stops applying
var logFile = "0:/sys/driver_stall_log.txt" ; file to log changes to
if !fileexists(var.logFile)
echo >{var.logFile} "File created : " ^ state.time
if !exists(param.D)
echo "No D parameter passed. Auto stall adjust not carried out"
M99
; ensure driver number resolves to X or Y (assumes x & Y are axes 0 & 1)
var thisAxis = ""
var validDriver = false
while iterations < #move.axes[0].drivers
if (move.axes[0].drivers[iterations]) == {""^param.D^""}
set var.validDriver = true
set var.thisAxis = "X"
while iterations < #move.axes[1].drivers
if (move.axes[1].drivers[iterations]) == {""^param.D^""}
set var.validDriver = true
set var.thisAxis = "Y"
if (var.validDriver = false) || (var.thisAxis = "")
echo "Only X and Y axis supported - Auto stall not adjusted"
M99
echo "Axis to adjust is " ^ var.thisAxis
; Store the stall values in a global so they are persistant between events
; It will be updated each time the macro runs after that
if !exists(global.M915vals)
global M915vals = var.stallVals
if var.thisAxis = "X"
M915 X S{global.M915vals[0][0]} H{global.M915vals[0][1]}
if var.thisAxis = "Y"
M915 X S{global.M915vals[1][0]} H{global.M915vals[1][1]}
echo "Current M915 values..."
M915
G4 P200
echo >>{var.logFile} "******************************"
echo >>{var.logFile} "Auto stall adjust called at " ^ state.time
if var.thisAxis = "X"
G4 P100
if global.M915vals[0][0] >= var.maxS
G4 P200
echo "Maximum S value reached - no further adjustment will occur"
if global.M915vals[0][1] >= var.maxH
G4 P100
echo "Maximum H value reached - no further adjustment will occur"
if (var.increaseS = true) && (global.M915vals[0][0] <= (var.maxS-var.amountS)) ; see if values should be increased
set global.M915vals[0][0] = global.M915vals[0][0] + var.amountS
G4 P100
echo "S param set to " ^ global.M915vals[0][0]
if var.increaseH = true && (global.M915vals[0][1] <= (var.maxH-var.amountH))
set global.M915vals[0][1] = global.M915vals[0][1] + var.amountH
if (var.increaseS = true) || (var.increaseH = true) ; check if new values must be applied
M915 X S{global.M915vals[0][0]} H{global.M915vals[0][1]} ; set new values
echo >>{var.logFile} "New X axis M915 values set - S=" ^ global.M915vals[0][0] ^ " H=" ^ global.M915vals[0][1]
G4 P200
echo "New M915 values are..."
G4 P200
M915 ; echo new values to console
G4 P200
if (var.reduceJerk = true) && (move.axes[0].jerk >= (var.minJerk + var.amountJerk)) ; see if jerk is to be reduced
M566 X{move.axes[0].jerk - var.amountJerk}
echo >>{var.logFile} "X jerk reduced to " ^ {move.axes[0].jerk - var.amountJerk}
G4 P200
M566
if (var.reduceAccel = true) && (move.axes[0].acceleration >= (var.minAccel + var.amountAccel)) ; see if acceleration is to be reduced
M201 X{move.axes[0].acceleration - var.amountAccel}
echo >>{var.logFile} "X acceleration reduced to " ^ {move.axes[0].acceleration - var.amountAccel}
G4 P100
M201
if var.thisAxis = "Y"
if global.M915vals[1][0] >= var.maxS
G4 P100
echo "Maximum S value reached - no further adjustment will occur"
if global.M915vals[1][1] >= var.maxH
G4 P100
echo "Maximum H value reached - no further adjustment will occur"
if (var.increaseS = true) && (global.M915vals[0][0] <= (var.maxS-var.amountS)) ; see if values should be increased
set global.M915vals[1][0] = global.M915vals[1][0] + var.amountS
if var.increaseH = true && (global.M915vals[1][1] <= (var.maxH-var.amountH))
set global.M915vals[1][1] = global.M915vals[1][1] + var.amountH
if (var.increaseS = true) || (var.increaseH = true) ; check if new values must be applied
M915 Y S{global.M915vals[1][0]} H{global.M915vals[1][1]} ; set new values
G4 P200
echo >>{var.logFile} "New Y axis M915 values set - S=" ^ global.M915vals[1][0] ^ " H=" ^ global.M915vals[1][1]
G4 P100
echo "New M915 values are..."
G4 P200
M915 ; echo new values to console
G4 P100
if (var.reduceJerk = true) && (move.axes[1].jerk >= (var.minJerk + var.amountJerk)) ; see if jerk is to be reduced
M566 Y{move.axes[1].jerk - var.amountJerk}
echo >>{var.logFile} "Y jerk reduced to " ^ {move.axes[1].jerk - var.amountJerk}
G4 P200
M566
if (var.reduceAccel = true) && (move.axes[1].acceleration >= (var.minAccel + var.amountAccel)) ; see if acceleration is to be reduced
M201 Y{move.axes[1].acceleration - var.amountAccel}
echo >>{var.logFile} "Y acceleration reduced to " ^ {move.axes[1].acceleration - var.amountAccel}
G4 P100
M201
Files for download
driver-stall.g
auto_adjust_stall.g
dist2home.g