Macros Files for BB | Official Thread

Hey Craig,

if you want to move in machine coordinates, you got to prepend G53 (Move in machine coordinates). Unlike G54 –G59.2, it is not a modal command and need to be specified on every line where you want it to be applied to the subsequent motion command.

E.g. if you have your workpiece zero coordinate somewhere, with G53 G0 X0 Y0 Z0 you still move the gantries to their machine home positions. No offsets currently active will be changed.

Be aware that G53 only works in G90 (Set Absolute Distance Mode). Note that G53 will fail silently if G91 (Set Incremental Distance Mode) is active (this is a bug). So as a workaround it is good to specify G90 prepended to any G53 command. G90 however is modal and will remain active from then on.

1 Like

Thank You Aiph5u… once again you have saved the day. I was missing the G53 command, this has solved my issue so thanks again!



Previously, I had a Workbee CNC, and in its software called OpenBuild Control, there was an option called “Check size,” which Draws the bounding box of where the job for machining is in XY space, helps you to check if the job fits your stock.
Or for laser, helps to see if you are right where you want to burn position it above the workpiece, do the setzeroes. Then run checksize after loading gcode.
Now that macros have been implemented, could someone help me create one to perform this task since it is very useful for checking if we might collide with something along the toolpath, or to verify that we are making an appropriate adjustment before cutting.
Thank you, and I hope this will be a great contribution to the community.

Hey Isaac,

there already exists something that shows you where you will mill with a loaded g-code program:

Unfortunately this 3D simulation is not shown on a HDMI monitor that is directly connected to the Onefinity Controller, because the internal Raspberry Pi has neither the resources nor the 3D acceleration drives installed to display it.

If you would program a macro for the function you describe, how would you enter the dimensions of your blank?

1 Like

Thank you for your response, but the option I mentioned in the Openbuild control program (check size) does not just simulate the cutting path. What it does is physically move the router across the entire area to be cut (forming a square that delineates the final cutting area to be machined). Therefore, I would first set our router at the origin (offset), and then the router would start moving around the cutting area (square). Most laser programs like LightBurn also implement this option to physically see where the laser will pass before making the cut. This helps a lot to ensure that the selected area is correct before starting the actual machining, and also to check that the router bit will not collide with something like a clamp during machining.
To explain better, I’m including a link to a video about the option I mentioned, which is shown on a laser, but it uses the same principle as OpenBuilds Control’s “check size” option on their CNC machines. I currently have a Onefinity CNC and I miss this option a lot as it was very helpful. Video:

1 Like

Hey Isaac,

so what you would like to create is a function that creates on the fly a “dry” version of your g-code toolpath, where the spindle is at a safe height and not running, at a very high feed rate to not loose too much time, that you can run prior to the actual g-code program? Or even more, just calculate the boundary of the program, and drive along these limits? That should be possible, but not with g-code alone. You would have to edit your g-code with some programming language inside the Onefinity Controller. There is python installed on the Onefinity Controller.

It would be a nice function.

That’s the advantage of LinuxCNC, where you can call python scripts from the g-code. But LinuxCNC is only a cnc controller software, not a cnc controller hardware. You need to build a pc and put together some cnc hardware drivers. I don’t know when calling python from g-code will be implemented on the Onefinity Controller.

In this test performed with the “check size” option, the router is never activated, so the bit doesn’t rotate and there’s no danger of cutting anything. It’s done at a suitable height above the material and at a moderate speed.

understood, my assumption is right. A very useful function. That would require a computation based on the loaded g-code program and the creation of a new g-code toolpath. Since you cannot create g-code with g-code, if you wanted to try this with g-code alone, you would need a LOT of conditional expressions.

I don’t know when calling python (or another interpreter) from g-code will be implemented on the Onefinity Controller.

1 Like

Here is a macro I use to surfacing all boards and I use it to surface the table as well.
The origin is in the center to make it easy and useful no mater which corner my real origin will be for the job.
Once the board is surfaced then I can probe the origin properly.

The toolpath starts at the front left corner and moves clockwise around the board and spirals in to the center. I prefer this over parallel lace patterns for surfacing since this will eliminates the risk of chipping out or splintering the wood around the edges.

For boards I just set the origin to the center of the board ( eye ball and tape measure is all I use ). For surfacing the table of course I find the center of the travels accurately and enter the full travel as the X and Y numbers.

The top of the macro looks like this to make it easy to change the 6 settings most often changed.

Below that is less often used preferences that will usually just need to be changed once - like imperial or metric, ramp length and angle, etc.

Hover your mouse over the code below and click the copy icon that appears in the top right corner.

(WIDTH ON X) #<x_width>= 3  
(LENGTH ON Y) #<y_length>= 1.1                
(PASS DEPTH) #<pass>= -.02
(FINAL DEPTH) #<final>= -.03
(STEP OVER) #<step_over>= .2
(FEEDRATE) #<_feedrate>= 50

#<units> = 20

#<_ramp_length> = 1

#<_ramp_angle> = 5 

#<_rapid_height> = .1 

#<rapid_to_home> = 1 


; Sanity checks on user input
o100 IF [#<pass> GT 0]
o100 ELSEIF [#<final> GT 0]
o100 ELSEIF [#<final> GT #<pass>]
o100 ELSEIF [#<step_over> LE 0]
o100 ENDIF 

#<_xpos> = [#<x_width> / 2] ; Origin is center so set x to half width
#<_ypos> = [#<y_length> / 2] ; Origin is center so set y to half length
#<_curr_depth> = -#<pass> ; Set current depth to pass depth above Z0
#<_depth> = #<pass> ; Set first pass depth
#<_ramp_feed> = [#<_feedrate> / 2] ; Reduce feedrate by 50% for ramp
#<half_step> = [#<step_over> / 2] ; half the step over for checking end of pass

; Ramping sub
o101 SUB
  G0 Z#<_rapid_height> ; Reset for next pass
  X-[#<_xpos> - #<_ramp_length>] Y-#<_ypos> ; Ramp position                      
  G1 Z#<_curr_depth> F#<_ramp_feed> ; Starting point height
  #<dist> = [#<_curr_depth> - #<_depth>] ; distance down we need to go
  #<_ramp_depth> = [#<_ramp_length> * TAN[#<_ramp_angle>]]
  #<ramps> = [FIX[#<dist> / #<_ramp_depth>]] ; number of ramps we need to make
  o102 REPEAT [#<ramps>]
    #<_curr_depth> = [#<_curr_depth> - #<_ramp_depth>]  
    G1 X-[#<_xpos> - #<_ramp_length>] Y-#<_ypos> F#<_feedrate> ; Ramp position    
    X-#<_xpos> Z#<_curr_depth> F#<_ramp_feed> ; Ramp 

  ; If current depth is not yet to pass depth
  o103 IF [#<_curr_depth> GT #<_depth>]
    G1 X-[#<_xpos> - #<_ramp_length>] Y-#<_ypos> F#<_feedrate> ; Ramp position
    X-#<_xpos> Z#<_depth> F#<_ramp_feed> ; Ramp  
  o103 ENDIF 

  #<_curr_depth> = #<_depth> 
  F#<_feedrate> ; Feedrate 100% to mill pass
o101 endsub

G0 G90 G#<units>  
o100 IF [#<rapid_to_home>]       
  G53 G0 Z0       
o100 ENDIF        
X-[#<_xpos> - #<_ramp_length>] Y-#<_ypos> ; Ramp position                    

; Call sub to do ramps
o101 call

; While depth is greater than or equal to final depth
o104 WHILE [#<_depth> GE #<final>] 

  ; When flag is 1 pass is done
  #<flag> = 0  
  o105 WHILE [#<flag> EQ 0] 
    ; If X is between step over and half step over finish down middle
    o106 IF [#<_xpos> LT #<step_over> AND #<_xpos> GT #<half_step>]
      #<_xpos> = 0
      X#<_xpos> Y-#<_ypos> 
      #<flag> = 1 ; Pass is done
    ; If Y is between step over and half step over finish down middle      
    o106 ELSEIF [#<_ypos> LT #<step_over> AND #<_ypos> GT #<half_step>]
      #<_ypos> = 0
      X-#<_xpos> Y#<_ypos>   
      #<flag> = 1 ; Pass is done 
    ; If X is less or equal to half step over pass is done           
    o106 ELSEIF [#<_xpos> LE #<half_step>]
      #<flag> = 1 ; Pass is done
    ; If Y is less or equal to half step over pass is done
    o106 ELSEIF [#<_ypos> LE #<half_step>]
      #<flag> = 1 ; Pass is done
    o106 ELSE  
      #<_xpos> = [#<_xpos> - #<step_over>] ; Reduce path by step over amount
      #<_ypos> = [#<_ypos> - #<step_over>]   
      X-#<_xpos> Y-#<_ypos> ; Moves toward center to next path position
    o106 ENDIF 
  ; If depth is equal to final depth
  o107 IF [#<_depth> EQ #<final>] 
    #<_depth> = [#<_depth> + #<pass>] ; Set too deep to trigger while exit
  o107 ELSE
    #<_depth> = [#<_depth> + #<pass>] ; Set to next pass depth   
    ; If depth is less than final depth
    o108 IF [#<_depth> LT #<final>] 
      #<_depth> = #<final> ; Set to final depth 
    o108 ENDIF    
    #<_xpos> = [#<x_width> / 2] ; Reset x to start position
    #<_ypos> = [#<y_length> / 2] ; Reset y to start position     
    ; Call sub to do ramps
    o101 call    
  o107 ENDIF 
o104 ENDWHILE   

G1 Z#<_rapid_height>                  
o100 IF [#<rapid_to_home>]       
  G53 G0 Z0       
o100 ENDIF

A very beginners question, as I work towards macros, entering the G0 X123 Y123 G92 X0 Y0 only works if the G0 string is entered and the G92 string is entered after, how do we cause both to work sequentially in the MDI field?
I am assuming that in a macro we would enter the strings on separate lines, no worries.

Hey Tony,

Many commands cause the controller to change from one mode to another, and the mode stays active until some other command changes it implicitly or explicitly. Such commands are called modal. For example, if coolant is turned on, it stays on until it is explicitly turned off.

The G-codes for motion are also modal. If a G1 (straight move) command is given on one line, for example, it will be executed again on the next line if one or more axis words is available on the line, unless an explicit command is given on that next line using the axis words or canceling motion.

Non-modal codes have effect only on the lines on which they occur. For example, G4 (dwell) is non-modal.

It is an error to put a G-code from group 1 and a G-code from group 0 on the same line if both of them use axis words. If an axis word-using G-code from group 1 is implicitly in effect on a line (by having been activated on an earlier line), and a group 0 G-code that uses axis words appears on the line, the activity of the group 1 G-code is suspended for that line. The axis word-using G-codes from group 0 are G10, G28, G30, G52 and G92.

– Source: Modal Groups – LinuxCNC Documentation

Those are some really practical ideas!

Love this macro feature! Seems like the community could make a more complete library – is there somewhere else I should be looking? Supposing this is it so far, I’m attaching the few quickies I made which have proven useful (not all have been tested much, so caveat emptor). Also note that these probing macros don’t have the benefit of being able to read machine configuration or present UI for picking tool diameters &c, so there are hardcoded values, e.g., for the size of the probing block, that you may need to update. I recommend setting each to show a warning when started, in case they’re activated by accident – they don’t have confirmations built-in. One final warning: running a macro seems to replace the currently loaded file, so I frequently find myself loading a file, running a probing macro, then getting confused by “Over” or “Under” errors, before realizing I need to reload the toolpath.

I use 3 super-simple “Park” macros that send the cutter to the back, either left, right, or wherever it happened to be in x already. (These are specific to the 32+" Woodworker, and don’t quite go ALL THE WAY to the corners, as I had problems with homing a machine that started right at X0, so these go 5mm from back & corners, e.g. X5 Y811 in mm)
ParkRearLeft.ngc (19 Bytes)
ParkRear.ngc (16 Bytes)
ParkRearRight.ngc (21 Bytes)

A series of probing routines for 1/4 or 1/8" bits that permit the probe block to be in upper-left or lower-right corners, in addition to the built-in lower-left functionality:
ProbeUL_1-4.ngc (759 Bytes)
ProbeUL_1-8.ngc (759 Bytes)
ProbeLR_1-4.ngc (948 Bytes)
Note that all the probing macros start with the familiar requirement to touch off the bit to the block before starting, to confirm connections are good – careful watchers may notice that the probe is moving extremely slowly upwards while waiting for this “test contact.” (Not sure if I could use M66 or something to avoid this motion, but works well as is, so I’m trying not to be a perfectionist.)

Next, a couple of Z probe routines designed to make it faster to deal with a tool change where the 0 is no longer easily probe-able – you put the probe block anywhere, do a quick Z probe with the “before” tool using the:
ProbeZsave.ngc (458 Bytes)
macro, then change tools and probe the “after” tool with:
ProbeZrestore.ngc (420 Bytes)
That should adjust coordinates appropriately as long as the probe block was at the same Z for both. (Haven’t tested this much, made it after I accidentally used top of stock for a reference where the stock gets carved into an uneven surface and then the tool is changed.)

Finally, in order to get the most Z travel I can on my Woodworker I have the Z carriage mounted pretty high, so I sometimes get in trouble with short bits not being able to go much below the wasteboard, or even reach it sometimes. There’s a related problem where, even when my tool can make it everywhere it needs to go, using the built-in probing dialogs generates an error because they ask the probe to move way farther down than it needs to to find the block. Probing fails even though the probe would stop long before it gets to the unreachable Z depth. For these situations I created
ProbeZshallow.ngc (413 Bytes)
which does a regular Z probe, except it only probes 1cm down looking for the block, so it should be started with the bit pretty close.

Hope some of those are useful to someone, and that my first go at CNC macros aren’t too bad!