Post up them handmade G-codes

Hey Aiph5u,
I did originally have it like you do. But I found it not very readable since the forum does not keep tabs or even extra space characters. It really looked a mess.

Yah I know what you are saying about the AI. But I found it interesting that the AI did return the same error on the code.

That is the same error the buildbotics controller reports until I took the apostrophe out.

By the way if I am breaking any g-code syntax rules please point them out. I started this thread to learn.

Hey Chris,

then you did not discover yet that Markdown which is used in this discourse.org forum supports code input and syntax highlighting.

#include <stdio.h>

int main(void)
{
    printf("hello, world\n");
}
o10 sub
    #31 = [#<_z> + #<_offset_z>]
    o20 if [#31 LT #3]
                ; check whether current Z position is at
                ; safe height
        (debug, Z position is #31, so first moving Z to safe height #3,
            only then going to X=#1 Y=#2)
        G53 G0 Z#3
        G0 X#1 Y#2
    o20 else
        (debug, Z position is #31, which is already at the safe height #3,
            so directly going to X=#1 Y=#2)
        G53 G0 Z#3
        G0 X#1 Y#2

    o20 endif
o10 endsub

o10 call [123] [321] [-10]
                ; set X and Y to move to; also set safe Z
                ; height here (the latter in G53 machine
                ; coordinates)

.xinitrc.diff

--- .xinitrc_orig       2021-05-24 19:24:48.139999053 +0200
+++ .xinitrc    2023-11-26 02:29:35.549773119 +0100
@@ -18,7 +18,7 @@
 
         # Start browser
         /usr/local/bin/browser --no-first-run --disable-infobars \
-         --noerrdialogs --disable-3d-apis http://localhost/
+         --noerrdialogs --disable-3d-apis --start-fullscreen http://localhost/
     fi

PS: For even more pretty print, I use a HTML Table, e.g. here. Not all elements and attributes are supported in markdown, but “table”, “tr”, “td” and “th” are. “colspan” is unfortunately not.

<table>
  <tr><th>This is the table header row</th><th></th></tr>
  <tr><td>This is a table cell.</td><td>This is another table cell</td></tr>
  <tr><td>And one more table row.</td><td>This is another table cell.</td></tr>
</table>

gives:

This is the table header row
This is a table cell.This is another table cell.
And one more table row.This is another table cell.
1 Like

Hey thanks, I will read up on it.

Ok, after reading up on it - this is the jist of it for g-code:
In order to maintain original formatting of your code in posts on this forum (indenting etc.) and to add the handy “copy code” button to the top right corner.
just ad this before your g-code - without the “(” and “)”

(```none)

and this at the end - without the “(” and “)”

(```)

2 Likes

Hey Chris,

here is the spec:

https://spec.commonmark.org/0.31.2/#fenced-code-blocks

There seems to be no extension for g-code so I use “none” to prevent that it uses a default syntax highlighting (which would not be useful with g-code).

1 Like

@Aiph5u I was just playing around with ChatGPT. Given the formal structure of programming languages, including Gcode, it is something those systems can interpret in a way that can help us humans to more quickly learn the details. If you are suggesting that we can’t just expect an AI system to do the work for us, then I completely agree. It can, however, be a tool in our own learning process.

When it tried to put named parameters into the code, it did so incorrectly. I had already looked at some of the links that you had previously shared, and when I saw the defect in the generated code I was easily able to find the correct syntax for those errors and update it accordingly.

2 Likes

Hey Gabe, hey Chris, hey all,

my experience is you learn a programming or a markup language only by using it, by having a project that you want to achieve. That is the fastest and most reliable way to learn a language. This is how I learned every programming or markup language I actually know today.

Conversely, I can say that no matter how many books and tutorials I have read for a language, I have not learned that language unless I had a project for which I needed the language. This supports the theory that you only learn by doing and achieving results for which the knowledge is required.

By the way, this also applies to other languages. You usually have to move to a country and need to use the language in everyday life in order to learn it properly.

3 Likes

Just so happens I. am working on an iOS app called GCodeGen for iPhone, iPad, and Mac that will do just that. I am almost ready to release it and if anyone wants a preview to help test send me you name and email and I will add you to the beta testers. Lots of neat features including the ability to send the file straight to the controller.

Here is a program I use to surface 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 pattern 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 ). Then fill in the 6 settings in the config section at the top of the code. For boards I go a little extra all around on the size to make it easy.
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.

Z0 for this is the top of the workpiece and the tool will start .10" above Z0 and ramp at 5 degrees for each pass.

For metric people you will have to find and change:
G20 and change it to G21
G0 Z.1 and change it to G0 Z2.5 ( 2 places to change for that )
“#<_ramp_depth> = .087” and change it to “#<_ramp_depth> = 2.21”
“X-[#<_xpos> - 1]” and change it to “X-[#<_xpos> - 25.4]” ( 4 places )

The Masso controller has a surfacing macro built right in and I want this to be as good for the Buildbotics.

% (SURFACE RECTANGE FROM OUTSIDE - ORIGIN IS CENTER, Z0 TOP)
(WIDTH ON X)
#<x_width> = 6   
(LENGTH ON Y)
#<y_length> = 3.5                
(DEPTH TO GO DOWN IN ONE PASS, USE NEGATIVE)
#<pass_depth> = -.02
(FINAL DEPTH, USE NEGATIVE)
#<final_depth> = -.04
(STEPOVER, DON'T GO OVER 80% OF CUTTER DIAMETER)
#<stepover> = 1
(FEEDRATE)
#<_feedrate> = 300
(END OF CONFIG SECTION)

; Final depth must be below, or equal to, pass depth
o100 IF [#<final_depth> GT #<pass_depth>]
  M0 (MSG, FINAL DEPTH MUST NOT BE HIGHER THAN PASS DEPTH - ABORTING)
  M2
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_depth> ; Set current depth to pass depth above Z0
#<_depth> = #<pass_depth>    ; Set first pass depth
#<_ramp_feed> = [#<_feedrate> / 2]  ; Reduce feedrate by 50% for ramp

; Ramping sub
o101 SUB
  G0 Z.1                            ; Reset for next pass
  X-[#<_xpos> - 1] 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> = .087 ; 5 degree ramp over 1 inch
  #<ramps> = [FIX[#<dist> / #<_ramp_depth>]] ; number of 5 deg. ramps we need to make
 
  o102 REPEAT [#<ramps>]
    #<_curr_depth> = [#<_curr_depth> - #<_ramp_depth>]  
    G1 X-[#<_xpos> - 1] Y-#<_ypos> F#<_feedrate>      ; Ramp position    
    X-#<_xpos> Z#<_curr_depth> F#<_ramp_feed>      ; Ramp 
  o102 ENDREPEAT

  ; If current depth is not yet to pass depth
  o103 IF [#<_curr_depth> GT #<_depth>]
    G1 X-[#<_xpos> - 1] 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 G17 G20          
G53 G0 Z0               
X-[#<_xpos> - 1] 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_depth>] 
  ; When x or y reach center pass is done
  o105 WHILE [#<_xpos> GT 0 AND #<_ypos> GT 0] 
    Y#<_ypos> 
    X#<_xpos>
    Y-#<_ypos>
    X-#<_xpos>
    #<_xpos> = [#<_xpos> - #<stepover>] ; Reduce path by stepover amount
    #<_ypos> = [#<_ypos> - #<stepover>] 
	; If X has gone past center then pass is done
    o106 IF [#<_xpos> LT 0]
      #<_xpos> = 0
      X#<_xpos> Y-#<_ypos> 
      Y#<_ypos>        
	; Else if Y has gone past center then pass is done
    o106 ELSEIF [#<_ypos> LT 0]
      #<_ypos> = 0
      X-#<_xpos> Y#<_ypos>   
      X#<_xpos>   
    o106 ELSE    
      X-#<_xpos> Y-#<_ypos>               ; Moves toward center to next path position
    o106 ENDIF 
  o105 ENDWHILE
  
  ; If depth is equal to final depth
  o107 IF [#<_depth> EQ #<final_depth>] 
    #<_depth> = [#<_depth> + #<pass_depth>] ; Set too deep to trigger while exit
  o107 ELSE
    #<_depth> = [#<_depth> + #<pass_depth>] ; Set to next pass depth
    
    ; If depth is less than final depth
    o108 IF [#<_depth> LT #<final_depth>] 
      #<_depth> = #<final_depth>            ; 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.1                  
G53 G0 Z0
M30
%

2 Likes

I happened upon this thread while learning more about g-code. It occurred to me that your surfacing macro could potentially be enhanced by using a technique I use in my Go To Midpoint macro. which reads the current coordinates when it runs. My thought is that you could

  1. xyz probe the lower left corner to set origin.
  2. raise z the negative amount you’d like to use for either pass depth or final depth
  3. manually jog the machine to the top right corner of your workpiece (eyeball it or use known dimensions)
  4. then run the macro, which would use the current x y z parameters to populate your macro parameters, eg. (untested)
#<x_width> = #5420 (use the current x position as workpiece width)
#<y_length> = #5421  (use the current y position as workpiece length)
#<final_depth> = #5422  (use the current z position as surfacing final depth)

You’d still need to have the feedrate and stepover configured, but if you commonly used the same tool and similar materials, it would mean you wouldn’t need to customize the script to run it on the fly.

Anyway- just an idea that could be handy. If i get around to trying to implement i’ll follow up here. Usually I end up using my planer to surface prior to the cnc.

1 Like

Hey tmuka,
Interesting idea. Im a little busy with other things right now so will not get around to trying it any time soon. So would like to see what you can do.

The original idea when I made that macro was: we can make changes to gcode on the controller now so I don’t have to start the laptop. However it is not easy making changes with the little 10" touch screen I still have. So your idea has real merit.

I don’t have a planer so everything must be flattened on the 1F. So I do use this macro all the time. But there is an update to it. I can’t edit that post so I will post the new one below.
It gives the ability to choose which corner to make the origin.

(SURFACE RECTANGE CW OUTSIDE TO IN)
(REMEMBER TO CALCULATE FROM CENTER OF TOOL)
(CHOOSE ORIGIN, Z0 IS TOP)
(Cntr=0 FL=1 FR=2 BR=3 BL=4) #<origin>= 1
(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
(END OF SETUP SECTION)

(PREFERENCES)
(20 FOR IMPERIAL, 21 FOR METRIC)
#<units> = 20

(LENGTH BACK FROM FRONT LEFT CORNER TO START RAMP)
#<_ramp_length> = 1

(ANGLE IN DEGREES TO RAMP TO THE FRONT LEFT CORNER)
#<_ramp_angle> = 5 

(RAPID BETWEEN PASSES AT THIS HEIGHT)
#<_rapid_height> = .1 

(RAPID TO Z HOME AT START AND END, 1 FOR YES, 0 FOR NO)
#<rapid_to_home> = 1 

(END OF PREFERENCES)

; Sanity checks on user input
o100 IF [#<pass> GT 0]
  M0 (MSG, PASS DEPTH MUST A NEGATIVE NUMBER - ABORTING)
  M2
o100 ELSEIF [#<final> GT 0]
  M0 (MSG, FINAL DEPTH MUST A NEGATIVE NUMBER - ABORTING)
  M2  
o100 ELSEIF [#<final> GT #<pass>]
  M0 (MSG, FINAL DEPTH MUST NOT BE HIGHER THAN PASS DEPTH - ABORTING)
  M2
o100 ELSEIF [#<step_over> LE 0]
  M0 (MSG, STEP OVER MUST BE A POSITIVE NUMBER - ABORTING)
  M2    
o100 ENDIF 

G#<units> 

; Unset G54
G10 L2 P1 X0 Y0

; Set origin from whatever corner selected to the center
#<_xcent> = [#<x_width> / 2] ; Origin is center so set x to half width
#<_ycent> = [#<y_length> / 2] ; Origin is center so set y to half length 

; If origin is 0 (Center) then do nothing
o100 IF [#<origin> EQ 0]
  ; doing nothing - G92 is already set to center
; If origin is 1 (front left) then make center X+ Y+
o100 ELSEIF [#<origin> EQ 1]
  G10 L2 P1 X#<_xcent> Y#<_ycent>
; If origin is 2 (front right) then make center X- Y+ 
o100 ELSEIF [#<origin> EQ 2]
  G10 L2 P1 X-#<_xcent> Y#<_ycent>   
; If origin is 3 (back right) then make center X- Y- 
o100 ELSEIF [#<origin> EQ 3]
  G10 L2 P1 X-#<_xcent> Y-#<_ycent> 
; If origin is 4 (back left) then make center X+ Y- 
o100 ELSEIF [#<origin> EQ 4]
  G10 L2 P1 X#<_xcent> Y-#<_ycent>  
; Something not allowed was entered  
o100 ELSE
  M0 (MSG, Origin Must Be 0 to 4 - ABORTING)
  M2  
o100 ENDIF 
G54

#<_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 
  o102 ENDREPEAT

  ; 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

o100 IF [#<rapid_to_home>]       
  G53 G0 G90 Z0       
o100 ELSE
  G0 G90 Z#<_rapid_height>
o100 ENDIF
        
G0 G90 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] 
    Y#<_ypos> 
    X#<_xpos>
    Y-#<_ypos>
    X-#<_xpos>
    ; 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> 
      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>   
      X#<_xpos>  
      #<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 
  o105 ENDWHILE
  
  ; 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

; Unset G54
G10 L2 P1 X0 Y0
M2
2 Likes

Thanks, @ChrisM .

I played with the code a little from my desk. I didn’t actually surface anything, but it appears that it is working. I left the dynamic final depth commented out so it’s still static since that might be more error prone. I added a pause and debug output to display the width and height and other parameters for sanity check, but there could be weirdness if aborting the macro since it doesn’t run the M72 at the end to clean up and unset G10 offsets or units the user had previously.

Hope this is helpful, it was fun for me to learn by reading your code.

M70	; Save modal states
G54 ; use the onefinity default work offset
(20 FOR IMPERIAL, 21 FOR METRIC)
#<units> = 20
G#<units>

% (SURFACE RECTANGE FROM OUTSIDE - ORIGIN IS CENTER, Z0 TOP)

(SURFACE RECTANGE CW OUTSIDE TO IN)
(REMEMBER TO CALCULATE FROM CENTER OF TOOL)
(CHOOSE ORIGIN, Z0 IS TOP)
(Cntr=0 FL=1 FR=2 BR=3 BL=4) #<origin>= 1
(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>= 0.2
(FEEDRATE) #<_feedrate>= 50
(END OF SETUP SECTION)

#<x_width>=[#5420] ; use the current x position as workpiece width
#<y_length>=[#5421]  ; use the current y position as workpiece length
(#<final>=[#5422/-1]  ; use the negation of current z position as surfacing final depth

(the next line pauses and displays the parameters prompting to stop or continue. using stop aborts without running M72 afterwards to restore previous modal states)
M0 (debug, Surface width: #<x_width>, length: #<y_length>, height: #<final>, stepover: #<step_over>, feedrate: #<_feedrate>, pass depth: #<pass>, units in 20 or mm 21: #<units>. continue? if stop, manually run M72 ) 

(PREFERENCES)

(LENGTH BACK FROM FRONT LEFT CORNER TO START RAMP)
#<_ramp_length> = 1

(ANGLE IN DEGREES TO RAMP TO THE FRONT LEFT CORNER)
#<_ramp_angle> = 5 

(RAPID BETWEEN PASSES AT THIS HEIGHT)
#<_rapid_height> = .1 

(RAPID TO Z HOME AT START AND END, 1 FOR YES, 0 FOR NO)
#<rapid_to_home> = 1 

(END OF PREFERENCES)

; Sanity checks on user input
o100 IF [#<pass> GT 0]
  M0 (MSG, PASS DEPTH MUST A NEGATIVE NUMBER - ABORTING)
  M2
o100 ELSEIF [#<final> GT 0]
  M0 (MSG, FINAL DEPTH MUST A NEGATIVE NUMBER - ABORTING)
  M2  
o100 ELSEIF [#<final> GT #<pass>]
  M0 (MSG, FINAL DEPTH MUST NOT BE HIGHER THAN PASS DEPTH - ABORTING)
  M2
o100 ELSEIF [#<step_over> LE 0]
  M0 (MSG, STEP OVER MUST BE A POSITIVE NUMBER - ABORTING)
  M2    
o100 ENDIF 

G#<units> 

; Unset G54
G10 L2 P1 X0 Y0

; Set origin from whatever corner selected to the center
#<_xcent> = [#<x_width> / 2] ; Origin is center so set x to half width
#<_ycent> = [#<y_length> / 2] ; Origin is center so set y to half length 

; If origin is 0 (Center) then do nothing
o100 IF [#<origin> EQ 0]
  ; doing nothing - G92 is already set to center
; If origin is 1 (front left) then make center X+ Y+
o100 ELSEIF [#<origin> EQ 1]
  G10 L2 P1 X#<_xcent> Y#<_ycent>
; If origin is 2 (front right) then make center X- Y+ 
o100 ELSEIF [#<origin> EQ 2]
  G10 L2 P1 X-#<_xcent> Y#<_ycent>   
; If origin is 3 (back right) then make center X- Y- 
o100 ELSEIF [#<origin> EQ 3]
  G10 L2 P1 X-#<_xcent> Y-#<_ycent> 
; If origin is 4 (back left) then make center X+ Y- 
o100 ELSEIF [#<origin> EQ 4]
  G10 L2 P1 X#<_xcent> Y-#<_ycent>  
; Something not allowed was entered  
o100 ELSE
  M0 (MSG, Origin Must Be 0 to 4 - ABORTING)
  M2  
o100 ENDIF 
G54

#<_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 
  o102 ENDREPEAT

  ; 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

o100 IF [#<rapid_to_home>]       
  G53 G0 G90 Z0       
o100 ELSE
  G0 G90 Z#<_rapid_height>
o100 ENDIF
        
G0 G90 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] 
    Y#<_ypos> 
    X#<_xpos>
    Y-#<_ypos>
    X-#<_xpos>
    ; 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> 
      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>   
      X#<_xpos>  
      #<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 
  o105 ENDWHILE
  
  ; 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

; Unset G54
G10 L2 P1 X0 Y0

M72	; Restore modal states
M2 ; Program End

1 Like

I think I figured out the weirdness. I had to add G54 at the top to make sure it used the default onefinity machine work offsets. Without that, it would find center between the current position and absolute zero (G53). And when I would press “stop” before it finished it would leave me in G20 ; inches instead of my normal G21 ;mm units. So i edited my previously shared imperial version, and here is my metric version.

M70	; Save modal states
#<units> = 21 ; 20 FOR IMPERIAL, 21 FOR METRIC
G#<units>
G54

% (SURFACE RECTANGE FROM OUTSIDE - ORIGIN IS CENTER, Z0 TOP)

(SURFACE RECTANGE CW OUTSIDE TO IN)
(REMEMBER TO CALCULATE FROM CENTER OF TOOL)
(CHOOSE ORIGIN, Z0 IS TOP)
(Cntr=0 FL=1 FR=2 BR=3 BL=4) #<origin>= 1
(WIDTH ON X) #<x_width>= 3  
(LENGTH ON Y) #<y_length>= 1.1                
(PASS DEPTH) #<pass>= -0.5
(FINAL DEPTH) #<final>= -0.75
(STEP OVER) #<step_over>= 20
(FEEDRATE) #<_feedrate>= 2000
(END OF SETUP SECTION)

#<x_width>=[#5420] ; use the current x position as workpiece width
#<y_length>=[#5421] ; use the current y position as workpiece length
(#<final>=[#5422/-1] ; use the negation of current z position as surfacing final depth

(the next line pauses and displays the parameters prompting to stop or continue. using stop aborts without running M72 afterwards to restore previous modal states)
M0 (debug, Surface width: #<x_width>, length: #<y_length>, height: #<final>, stepover: #<step_over>, feedrate: #<_feedrate>, pass depth: #<pass>, units in 20 or mm 21: #<units>. continue? if stop, manually run M72 ) 

(PREFERENCES)

(LENGTH BACK FROM FRONT LEFT CORNER TO START RAMP)
#<_ramp_length> = 25

(ANGLE IN DEGREES TO RAMP TO THE FRONT LEFT CORNER)
#<_ramp_angle> = 5 

(RAPID BETWEEN PASSES AT THIS HEIGHT)
#<_rapid_height> = 3

(RAPID TO Z HOME AT START AND END, 1 FOR YES, 0 FOR NO)
#<rapid_to_home> = 1 

(END OF PREFERENCES)

; Sanity checks on user input
o100 IF [#<pass> GT 0]
  M0 (MSG, PASS DEPTH MUST A NEGATIVE NUMBER - ABORTING)
  M2
o100 ELSEIF [#<final> GT 0]
  M0 (MSG, FINAL DEPTH MUST A NEGATIVE NUMBER - ABORTING)
  M2  
o100 ELSEIF [#<final> GT #<pass>]
  M0 (MSG, FINAL DEPTH MUST NOT BE HIGHER THAN PASS DEPTH - ABORTING)
  M2
o100 ELSEIF [#<step_over> LE 0]
  M0 (MSG, STEP OVER MUST BE A POSITIVE NUMBER - ABORTING)
  M2    
o100 ENDIF 

G#<units> 

; Unset G54
G10 L2 P1 X0 Y0

; Set origin from whatever corner selected to the center
#<_xcent> = [#<x_width> / 2] ; Origin is center so set x to half width
#<_ycent> = [#<y_length> / 2] ; Origin is center so set y to half length 

; If origin is 0 (Center) then do nothing
o100 IF [#<origin> EQ 0]
  ; doing nothing - G92 is already set to center
; If origin is 1 (front left) then make center X+ Y+
o100 ELSEIF [#<origin> EQ 1]
  G10 L2 P1 X#<_xcent> Y#<_ycent>
; If origin is 2 (front right) then make center X- Y+ 
o100 ELSEIF [#<origin> EQ 2]
  G10 L2 P1 X-#<_xcent> Y#<_ycent>   
; If origin is 3 (back right) then make center X- Y- 
o100 ELSEIF [#<origin> EQ 3]
  G10 L2 P1 X-#<_xcent> Y-#<_ycent> 
; If origin is 4 (back left) then make center X+ Y- 
o100 ELSEIF [#<origin> EQ 4]
  G10 L2 P1 X#<_xcent> Y-#<_ycent>  
; Something not allowed was entered  
o100 ELSE
  M0 (MSG, Origin Must Be 0 to 4 - ABORTING)
  M2  
o100 ENDIF 
G54

#<_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 
  o102 ENDREPEAT

  ; 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

o100 IF [#<rapid_to_home>]       
  G53 G0 G90 Z0       
o100 ELSE
  G0 G90 Z#<_rapid_height>
o100 ENDIF
        
G0 G90 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] 
    Y#<_ypos> 
    X#<_xpos>
    Y-#<_ypos>
    X-#<_xpos>
    ; 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> 
      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>   
      X#<_xpos>  
      #<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 
  o105 ENDWHILE
  
  ; 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

G10 L2 P1 X0 Y0 ; Unset G54
M72	; Restore modal states
M2 ; Program End
1 Like