GCode Variables and Loops

My programmer brain is going off the deep end on how useful variables and loops could be in GCode. I know FluidNC doesn’t support this. I’m looking for feedback on if this is crazy or not and what current functionality exists elsewhere.

I want to be able to do things like this without having to create new GCode:

  • Cut the same thing in materials of different thicknesses. If I could specify the thickness and depth per pass, it could loop over the shape to handle any thickness.
  • Scale a part.
  • Adjust tolerances for fit.
  • Adjust speeds. I know there’s an override in the WebUI but I’d like to specify it directly.

I am oversimplifying this a bit and it would certainly have limitations. Some of these options would be easier than others. This really only applies to flat parts.

My thoughts are that this could be implemented in the WebUI of FluidNC. It could certainly be added to FluidNC itself, but C++ programming isn’t my strength. Basically, it would have to read a header of the GCode file, prompt for the parameters, and then basically transpile this special GCode into standard GCode using JavaScript. I think this generated file could then be automatically “uploaded” and run on the fly.

Getting a GCode file in this special format would likely require some manual editing and/or some kind of post processor.

I’m not sure if it would be worth the effort to try and implement this or how often I would actually want to utilize this functionality.

Best I know of is gcode playlists. Not sure if Fluid allows this or not…maybe becuase some use it for the Zenxy.

I will say though, all of those things are very simple in CAM as well. Scaling and depth per pass would also recalculate to keep proper chip load as well.

The one feature I think would be ultra useful is cut recovery. Being able to back up from the current location and resume the file, or rehome and fast forward through the file and chose a place to start. If you break a bit you could re home and pickup where you left off instead of rerunning the whole file or manually editing it.

1 Like

I saw that for ZenXY they were using an Octoprint plugin with M32. It doesn’t appear that FluidNC supports that.

I agree it’s simple in CAM but that requires me going on my computer instead of being able to do it from a tablet/phone. It’s all a matter of unnecessary convenience. I only have a basic understanding of chip loads.

That’s an interesting idea. It could list each part as a sort of bookmark (assuming I actually name parts in Estlcam) to choose a starting place. Perhaps then let you choose a specific line. Or you could drive it to the X/Y position where it failed and have it automatically find the closest gcode lines to choose from.

1 Like

If you just scaled up your gcode you would also scale the speed and quickly get in trouble. Moves are combined with speed, so if you scaled both it would be disaster (move further and arrive faster), if you only scaled size (move further and arrive at the same time…still faster). The only way that could work is if you scaled speed inversely.

If you want to use CMA on your phone tablet, use Kiri:moto.

Not sure how it would work, I also use linuxCNC and it has it. Looks just like feedrate control, You can move forward and reverse, even shows a display of where that line of code is.

Klipper running on a raspberry Pi with glorious amounts of memory relative to current ESP32s supports macros, variables, conditions, loops, etc… Klipper supports templated gcode via Jinja Commands templates - Klipper documentation

I need to look at kiri:moto. But was hopeful we’d see a mobile/tablet friendly parametric STL/SVG/DXF to CAM/gcode tool by now, maybe kiri or something else does this well?

Thought we’d see something that nailed 80% use case scenarios with a web frontend wrapping WebAssembly implemented version of OpenScad, with CAM/gcode support, or something with less declarative/functional, more imperative GitHub - jscad/OpenJSCAD.org: JSCAD is an open source set of modular, browser and command line tools for creating parametric 2D and 3D designs with JavaScript code. It provides a quick, precise and reproducible method for generating 3D models, and is especially useful for 3D printing applications.

There’s GitHub - MaslowCNC/Maslow-Create: A community cloud CAD program for cooperative design. too

And GitHub - vector76/Web_OpenSCAD_Customizer: Client side OpenSCAD customizer

I think so. It is set up differently from most other CAM but if you watch a quick video of it in use I think you will get it quickly. Browser based CAM.

1 Like

RepRap Firmware (typically for Duet boards, but a port for then SKR Pro 1.2 exists) supports looping structures, variables and conditionals.

They are a very simple structure, of course, but they are useful.

I have used them for things like changing coordinate systems for multiple cuts of the same objects, and a few repetitive tasks, but really it’s not generally useful.

I suppose that I could use it for some hand-coded Gcode projects, but those are few and far between.

Yes, the Klipper functionality sounds like what I was hoping for. Due to the limited amount of memory of the ESP32, that’s why I was thinking of using JavaScript on the client side to generate the gcode.

kiri:moto looks interesting but not sure I want to deviate from Estlcam yet. It’s also only helpful if I run FluidNC in STA mode so I don’t have to switch networks to get internet access. The docs recommend AP mode but the FluidNC wiki suggests STA. Although, I understand that recommendation based on networking knowledge. I’ll give that a shot anyway.

EstlCam is implemented in VB.net, technically portable to webassembly/blazor/maui, but then I guess everything is. File format is compressed binary serialized types. Was hoping an export EstlCam 11 to documented json format, that can be imported to EstlCam 12 would help EstlCam Customers migrate their existing projects.

But, this could also create an opportunity for 3rd party, opensource tools to generate json that EstlCam 12 can import. Just a thought… @christian-knuell :blush:

:100:

2 Likes

Remember, when you scale a part to let’s say 120%, the diameter of the bit is not changed so the coordinates of the path are not simply scaled by 120%. Given the tool path and the bit radius, you can calculate the edge of the part or the hole, then scale that path by the scale factor, then offset again by the bit radius to get the path of the tool center. Not a simple operation.

3 Likes

I knew that one was more difficult but I hadn’t considered that detail. That would be way more difficult than I would want to attempt.

It’s not in a FluidNC release yet, but basic support for gcode parameters and expressions has been added. I’m not quite sure what I would do with it yet but it has some potential.

GCode Parameters and Expression | Wiki.js (fluidnc.com)

It doesn’t sound like loops are feasible but they might add conditional (if) statement support.

3 Likes

Looks like if statement and looping features are coming soon to FluidNC as mentioned in today’s FluidNC 3.8.1 release notes:

Combining this with the parameter and expression functionality should be pretty powerful.

Coming Soon

  • Adding if statements to gcode (if, elseif, else, endif)
  • Adding Looping to gcode (while, do, repeat)
  • Adding Print and Debug statements to gcode.
2 Likes

Do any postprocessors generate these constructs or is this for people who sling gcode by hand?

I’m not aware of postprocessors doing this. I honestly don’t have a good reason to use this right now, but I’m willing to make up something. :laughing:

Would this be a way to drill holes for a cribbage board by just repeating a commad ?

Ok, I’m more excited about this than I probably should be but I have a good use for this and it works.

Previously, I had created an extension I was still working on to perform Z leveling. It works well, but honestly an extension is a bit overkill. Now, I’ve recreated that functionality with a gcode file that will run on FluidNC 3.8.2 or higher regardless of WebUI version.

Anyways, check this out. You need to set the first 4 variables as appropriate for your build. It performs these steps:

  1. Home All
  2. Move to starting left probe position.
  3. Prompt to attach probe before continuing.
  4. Probe at left 3x and calculate average.
  5. Prompt to remove probe before moving to right position.
  6. Move to right probe position.
  7. Prompt to attach probe before probing at right position.
  8. Probe at right 3x and calculate average
  9. Calculate new pulloff values.
  10. Prompt before updating values and saving.
(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)

(UPDATE OPTIONAL)
#<minPulloff> = 4.0 (Minimum pulloff value)
#<jogXYFeedrate> = 1000 (Feedrate for X and Y jogging)
#<jogZFeedrate> = 500 (Feedrate for Z jogging)
#<jogHeight> = 50 (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)

(MSG Home All)
$H

(MSG Move to Initial Y Position)
G00 Y#<probeYPos> F#<jogXYFeedrate>
(MSG Move to Initial X Position)
G00 X#<probeXLeftPos> F#<jogXYFeedrate>

M0 (MSG Attach Probe and Probe Left)
#<probeSum> = 0
o100 repeat [#<probeCount>]
  G38.2 Z#<probeDistance> F#<probeFeedrate>
  #<probeSum> = [#<probeSum> + #5063]
  G00 Z10 F#<jogZFeedrate>
  D#5063 (Z Result of G38 Probe)
o100 endrepeat
#<probeLeftAvg> = [#<probeSum>/3]

M0 (MSG Detach Probe Before Move Up and Right)
G00 Z#<jogHeight> F#<jogZFeedrate>
G00 X#<probeXRightPos> F#<jogXYFeedrate>

M0 (MSG Re-attach Probe and Probe Right)

(MSG Probe Right)
#<probeSum> = 0
o101 repeat [#<probeCount>]
  G38.2 Z#<probeDistance> F#<probeFeedrate>
  #<probeSum> = [#<probeSum> + #5063]
  G00 Z10 F#<jogZFeedrate>
  D#5063 (Z Result of G38 Probe)
o101 endrepeat
#<probeRightAvg> = [#<probeSum>/3]

(MSG Average Left Z)
D#<probeLeftAvg>
(MSG Average Right Z)
D#<probeRightAvg>

#<zDifference> = [ABS[ABS[#<probeLeftAvg>] - ABS[#<probeRightAvg>]]]
#<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 [#<probeLeftAvg> GT #<probeRightAvg>]
  #<z1PulloffNew> = [#<z1PulloffNew> + #<zOffsetChange>]
o102 elseif [#<probeRightAvg> GT #<probeLeftAvg>]
  #<z0PulloffNew> = [#<z0PulloffNew> + #<zOffsetChange>]
o102 endif

(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

(MSG Old Pulloff Z0)
D#<z0Pulloff>
(MSG New Pulloff Z0)
D#<z0PulloffNew>

(MSG Old Pulloff Z1)
D#<z1Pulloff>
(MSG New Pulloff Z1)
D#<z1PulloffNew>

M0 (MSG Continue to Update Pulloff Values)

(MSG Set Pulloff Values)
#</axes/z/motor0/pulloff_mm> = #<z0PulloffNew>
#</axes/z/motor1/pulloff_mm> = #<z1PulloffNew>

(MSG Save Pulloff Values)
$CD=config.yaml
11 Likes

I think this kicks butt !

2 Likes

Wait, that is all in gcode? No freaking way :exploding_head:

Sounds like I need to add that to the site, I can’t wait to try it.

ZLevelingReminder

2 Likes

Yes. I know, right?

1 Like