GCode Variables and Loops

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.

Problem: Config Dump ($CD=config.yaml) Adds Invalid Lines to YAML, increases time to connect · Issue #1320 · bdring/FluidNC (github.com)

Configurable and non-configurable modules to keep the config tidy by MitchBradley · Pull Request #1321 · bdring/FluidNC (github.com)

I can get back to making my Z level script handle Z0 and Z1 sides being swapped. I was most of the way there before this little detour.

3 Likes

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)

1 Like

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.

image

https://esp3d.io/ESP3D-WebUI/Version_3.X/documentation/api/extensions/#modal-dialog-documentation

@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.

2 Likes

Could you also send messages to the FluidDial pendant if present?

Wow, that’s cool!

That would have to be a completely separate implementation in the FluidDial code. I’m not a C++ guy so it’s not something I would attempt.

I thought on FluidNC the gcode can send prompts to the pendant, no C++ required. I’ll see if I can find the docs that I read about that.

2 Likes

This was the #1 thing I wanted WebUI v3 for.

It’s always been a goal of mine to replace the built-in terminal or something with a custom one, so I can get modal prompts for “attach probe” etc…

Because sometimes I’m just staring at the machine waiting, until I realize what’s going on.

Or I have accidentally pressed PLAY a 2nd time forgetting I was supposed to be doing something…

Unfortunately, too many other things took over my time so I never got to it…

3 Likes

I can not wait to test this.

This gave me a few ideas as well but I need to try this one first. So pumped to try this. Honestly, seems like a game changer for ease of use.

4 Likes

It worked great when I tested it but my motors were wired backwards lol. I am excited to try it again for sure.

Now we need one for setting Y squareness LOL. But I’m not even sure how you could go about that one

1 Like

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.

3 Likes

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.

2 Likes

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

2 Likes

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.

6 Likes

I get that completely!! What you have done with the Z leveling is amazing and very much appreciated!!

2 Likes

The input prompting stuff may come later, but this is super helpful.

2 Likes

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).

2 Likes

This just got merged into the main branch so that’s promising.

2 Likes

Awesome! I just got back in town so looking forward to trying it!

2 Likes

Fix is in the new 3.8.3 release. I haven’t installed it yet.

3 Likes