There’s a fix to the $CD=config.yaml bug in the FluidNC Fix1320 branch. I verified that the behavior is now what I expect but it sounds like fixing it was rather impacting so there’s quite a bit of testing to do.
Here’s an updated Z Leveling Script. It adds a configuration value at the top so you can set if Z0 or Z1 is on the left. It also uses the new “print” messages so I can use variables in message output.
#<zMotorLeft> = 0 (Left Z Motor - 0 if Z0 is on the left, 1 if Z1 is on the left)
Note: Until that $CD bug ends up in a release, you may want to not resume when prompted to “Continue to Update Pulloff Values”. Otherwise, you’ll need to manually update your config.yaml anyway to remove the garbage values.
Z Leveling GCode
(PRINT, LowRider Z Leveling for FluidNC v3.8.2 or higher)
(UPDATE REQUIRED)
#<probeYPos> = 50 (Y position to probe at dependent upon condition of spoilboard)
#<probeXLeftPos> = 0 (Left X position to probe at dependent upon condition of spoilboard)
#<probeXRightPos> = 880 (Right X position to probe at, should be close to max X)
#<xTotalDistance> = 1080 (Total X Distance - On LR3, this is from left bearing to Y rail)
#<zMotorLeft> = 0 (Left Z Motor - 0 if Z0 is on the left, 1 if Z1 is on the left)
(UPDATE OPTIONAL)
#<minPulloff> = 4.0 (Minimum pulloff value)
#<jogXYFeedrate> = 1000 (Feedrate for X and Y jogging)
#<jogZFeedrate> = 500 (Feedrate for Z jogging)
#<jogHeight> = 30 (Z height when jogging in X or Y)
#<probeDistance> = -80 (Max probe distance, should be negative)
#<probeFeedrate> = 200 (Feedrate when probing)
#<probeCount> = 3 (Number of times to probe on each side)
(PRINT, Home All)
$H
(PRINT, Move to Initial Y Position %d#<probeYPos>)
G00 Y#<probeYPos> F#<jogXYFeedrate>
(PRINT, Move to Initial X Position %d#<probeXLeftPos>)
G00 X#<probeXLeftPos> F#<jogXYFeedrate>
M0 (PRINT, Attach Probe and Probe Left x%d#<probeCount>)
#<probeSum> = 0
o100 repeat [#<probeCount>]
G38.2 Z#<probeDistance> F#<probeFeedrate>
#<probeSum> = [#<probeSum> + #5063]
G00 Z10 F#<jogZFeedrate>
(PRINT, Probe Left Z: #5063)
o100 endrepeat
#<probeLeftAvg> = [#<probeSum>/3]
M0 (PRINT, Detach Probe Before Moving to Z%d#<jogHeight> and X%d#<probeXRightPos>)
G00 Z#<jogHeight> F#<jogZFeedrate>
G00 X#<probeXRightPos> F#<jogXYFeedrate>
M0 (PRINT, Re-attach Probe and Probe Right x%d#<probeCount>)
(MSG Probe Right)
#<probeSum> = 0
o101 repeat [#<probeCount>]
G38.2 Z#<probeDistance> F#<probeFeedrate>
#<probeSum> = [#<probeSum> + #5063]
G00 Z10 F#<jogZFeedrate>
(PRINT, Probe Right Z: #5063)
o101 endrepeat
#<probeRightAvg> = [#<probeSum>/3]
(PRINT, Z Average: Left=#<probeLeftAvg>, Right=#<probeRightAvg>)
#<zDifference> = [ABS[ABS[#<probeLeftAvg>] - ABS[#<probeRightAvg>]]]
(PRINT, Z Difference: #<zDifference>)
#<xDistance> = [#<probeXRightPos> - #<probeXLeftPos>]
#<zOffsetChange> = [[#<zDifference> / #<xDistance>] * #<xTotalDistance>]
(Get current Z pulloff values)
#<z0Pulloff> = #</axes/z/motor0/pulloff_mm>
#<z1Pulloff> = #</axes/z/motor1/pulloff_mm>
(Calculate New Pulloff Values)
#<z0PulloffNew> = #<z0Pulloff>
#<z1PulloffNew> = #<z1Pulloff>
o102 if [[#<zMotorLeft> EQ 0] AND [#<probeLeftAvg> GT #<probeRightAvg>]]
#<z1PulloffNew> = [#<z1PulloffNew> + #<zOffsetChange>]
o102 elseif [[#<zMotorLeft> EQ 1] AND [#<probeLeftAvg> GT #<probeRightAvg>]]
#<z0PulloffNew> = [#<z0PulloffNew> + #<zOffsetChange>]
o102 elseif [[#<zMotorLeft> EQ 0] AND [#<probeRightAvg> GT #<probeLeftAvg>]]
#<z0PulloffNew> = [#<z0PulloffNew> + #<zOffsetChange>]
o102 elseif [[#<zMotorLeft> EQ 1] AND [#<probeRightAvg> GT #<probeLeftAvg>]]
#<z1PulloffNew> = [#<z1PulloffNew> + #<zOffsetChange>]
o102 endif
(PRINT, New Pulloff Values Prior to Normalizing: Z0=#<z0PulloffNew>, Z1=#<z1PulloffNew>)
(Normalize New Pulloff Values to Minimum Pulloff)
#<change> = 0
o103 if [#<z0PulloffNew> LT #<z1PulloffNew>]
#<change> = [#<minPulloff> - #<z0PulloffNew>]
#<z0PulloffNew> = #<minPulloff>
#<z1PulloffNew> = [#<z1PulloffNew> + #<change>]
o103 elseif [#<z0PulloffNew> GT #<z1PulloffNew>]
#<change> = [#<minPulloff> - #<z1PulloffNew>]
#<z1PulloffNew> = #<minPulloff>
#<z0PulloffNew> = [#<z0PulloffNew> + #<change>]
o103 endif
(PRINT, Z0 Pulloff: Current=#<z0Pulloff>, New=#<z0PulloffNew>)
(PRINT, Z1 Pulloff: Current=#<z1Pulloff>, New=#<z1PulloffNew>)
M0 (PRINT, Continue to Update Pulloff Values)
(Set Pulloff Values)
#</axes/z/motor0/pulloff_mm> = #<z0PulloffNew>
#</axes/z/motor1/pulloff_mm> = #<z1PulloffNew>
(Save Pulloff Values to Config File)
$CD=config.yaml
(PRINT, Z Leveling Complete)
Also, since sometimes I can’t turn my brain off, I have this idea that by having the gcode output a message in a certain format, an extension could be created to process that message and translate it into the modal popup functionality of WebUI v3. This would allow you to create a gcode script that can prompt the user instead of having to manually set them in the gcode before running.
I’ve successfully been able to trigger a modal popup via an extension based on messages followed by a hold. Separately, I created a sample modal dialog using the built-in functionality.
@DougJoseph You had mentioned about possibly creating a “Setup Wizard”. An extension like I describe could facilitate this with just gcode files.
No promises on this one, but initial investigation at least makes this look feasible. Even a simpler version of this where when a hold is created via M0, just showing the latest message and allowing you to resume via clicking Ok to a popup would be nice. I had that working too.
I’m wondering if you can get away with measuring a single diagonal. If you can assume that the motors are moving the exact distance and you’re moving Y on the rail side, I think you can figure out the measurement to make it a right triangle. Either way, being able to prompt for user input would be helpful.
I also wonder if you just put a framing square up against the Y rail and draw a line across. Move the machine to match the line on the rail side, move to the X left side and measure the distance from there to the line. You would still have to extrapolate for the full X distance.
I just know measuring both diagonals is a pain, then adjust and do it again.
A single one is fine. The reason I have people manually do two is so they can see the actual error. Like a magnified less than 1mm error across a 8 foot diagonal really should drive home the accuracy at that point. But on paper if some said a little less than a mm and off people scream about crap accuracy. Not understanding it is magnified.
If you are trying to automate it one should be fine, but it would be great to verify and check both directions.
I’m more thinking about the new user who might be intimidated messing with pull off settings and all in fluidNC. Your Z code takes all that away and does it for you. That’s what made me think about the Y axis. I have no issue doing it with the big X like Ryan shows. So please don’t go out of your way to figure it out just for me lol. But I do think having it might drive more people to want to verify their machines are right on the money instead of skipping it because they are nervous about the pull off distance adjustments
Yea, this is on my list to try at some point, but not at the moment.
I was also thinking this functionality could be used for probing a grid of the spoilboard to see high and low spots similar to 3d printers. No mesh leveling or anything like that, but it might lead you to shim table legs or decide flattening is worth it. Although that also makes me wonder if you can hook up a 3d printer style probe or at least rig something up so you don’t have to hold it.
My time and interest ebbs and flows, so someday. Or at least just throw these ideas out there, maybe this Z level gcode will be a good example to give someone else a starting point to give it a shot.
I have always thought the most automatic thing in V carves or sheet work is to probe a grid only over the pattern. Automatically defining the grid to probe before the job and doing a mesh level would be awesome. Marlin has custom grid gcode. At one point I thought of trying to add it to octoprint when you have a gcode loaded to generate the mesh probe pattern and send it before cutting. The probe would be quick, so the touch plate would work (if you could reach).