[Home]Oword

LinuxCNCKnowledgeBase | RecentChanges | PageIndex | Preferences | LinuxCNC.org

Showing revision 56
Difference (from revision 56 to revision 56) (minor diff, author diff)
(The revisions are identical or unavailable.)
This page will become a comprehensive reference page for LinuxCNC's O word.

Contents

1. Introduction
2. Notes
3. Sample Programs
3.1. Sample 1 -- One side of a ball in cage
3.2. Sample 2 -- Subroutine Sample (ellipse)
3.3. Sample 3 -- loops/math example (spirograph)
3.4. Sample 4 -- Subroutine for helical hole milling using radius comp
3.5. Sample 5 -- Subroutine for generating multiple parts using Local and Global coordinates
3.6. Sample 6 -- box endwrench program
3.7. Sample 7 -- spur gear program
3.8. Sample 8 -- cycloid gears program
3.9. Sample 9 -- rack and pinion program
3.10. Sample 10 -- ring and pinion program

1. Introduction

The O word was devised by Ken Lerman as a way to implement several branching routines into the LinuxCNC interpreter. By using the O word a gcode programmer can build subroutines, loops, and conditionals while taking advantage of the interpreter's use of variables and computation.
The canonical documentation for O-words is in the LinuxCNC documentation: [1]. As clarifications and documentation improvements made on this page are incorporated in the official documentation, they should be removed from this page.

2. Notes

3. Sample Programs

These sample programs are offered without any warranty as to their suitability for any task whatsoever! Use these or model your program after these at your own risk.

3.1. Sample 1 -- One side of a ball in cage

Here is a short program that uses a ball end mill to create part of a sphere. The comments in the code explain what each variable does. There is no error checking so you could create sphere that doesn't exist. Here is LinuxCNC+axis running this program. [LinuxCNC+axis] I am sure the program could be simplified also not 100% sure the math is right. Here is 4 sides done - [cube]

#1=1.25 (size of box)
#2=.0625 (cutter radius)
#3=.125 (size of box bars)
#4=5 (degrees of resolusion)
#5=#4 (COUNTER)
#6=[[#1/2]+#2] (ACTUAL RADIUS OF CIRCLE - CUTTER RADIUS + RADIUS) 
G01X0Y0F10
o140 do 
   #8 = [[SIN[#5]*#6]*SIN[45]] ( X AND Y POSISION)
   #9 = [0-[[1-COS[#5]]*#6]] (Z HIGHT)
   G1X[#8]Y[#8]F3 
   Z[#9]
   G18 G02 X[0-#8]Z[#9]I[0-#8]K[0-[#9+[#6]]]F5
   G19 G03 Y[0-#8]Z[#9]J[0-#8]K[0-[#9+[#6]]]
   G18 G03 X[#8]Z[#9]I[#8]K[0-[#9+[#6]]]
   G19 G02 Y[#8]Z[#9]J[#8]K[0-[#9+[#6]]]
   #5=[#5+#4]
o140 while [#8 LT [#1/2-#2-#3]]
G1Z1
X0Y0
M30

3.2. Sample 2 -- Subroutine Sample (ellipse)

Code originally by jepler, converted to gcode by KennethLerman (lerman), fixed by jepler. This code will machine an approximation to a ellipse.

(#1=xc #2=yc #3=xr #4=yr #5=subdiv #6=depth #7=rapid ht)
o1000 sub
 (#10 = theta)
 (#11 = i)
 (#12 = x)
 (#13 = y)
 
 #14 = 360
 #11 = 1
 g0 x[#1+#3] y#2
 g0 z#6
 o1001 while [#11 LE #5]
   #10 = [#14 * #11 / #5]
   #12 = [#1 + [#3 * cos[#10]]]
   #13 = [#2 + [#4 * sin[#10]]]
   g1 x#12 y#13
   #11 = [#11 + 1]
 o1001 endwhile
 g0 z#7
 o1000 endsub
 (call it like this)
 f10
 o1000 call [0] [0] [1] [2] [200] [-1] [2]
 m2

3.3. Sample 3 -- loops/math example (spirograph)

I did this on a whim just to see if it could be done with the current math and loop abilities of LinuxCNC. Here is example output of the below program. [spiro]. It creates pretty big files - again not sure if everything is correct. Use at your own risk :).

#1=3.1 ( R in this formula {R+r}*cos{t} - {r+O}*cos{{{R+r}/r}*t} ) 
#2=2 ( r in above)
#3=.6  ( O in above)
#4=0  (starting t Deg)
#5=.2 (deg of resolution)

(check which of the R/r is bigger)
o100 if [abs[#1] GT abs[#2]]
	#6=#1 (6 and 7 are temp locations for the R and r )
	#7=#2
	#8=1
o100 else
	#6=#2
	#7=#1
	#8=2
o100 endif

(now we make them whole numbers if they are not.)
(this is the start of figuring the number of degrees)
(it has to go to do a complete cycle.)
#9=#6
#10=#7
#11=2
o150 while [[fix[#6] NE #6] or [fix[#7] NE #7]]
	#6=[#9*#11]
	#7=[#10*#11]
	#11=[#11+1]
o150 endwhile
(now lets figure out if we can simplify the R/r fraction) 
(this is using Euclidean algorithm to get the gcd)

#12=#6
#13=#7

o200 do
	#14=[#12 mod #13]
	#12=#13
	#13=#14
o200 while [#13 NE 0]
(#12 is now the gcd)


(the Number of times around in degrees)
(using the correct denominator.)
o225 if[#8 eq 1]
	#14=[[#7/#12]*360]
o225 else
	#14=[[#6/#12]*360]
o225 endif


(here is the actual cutting - I don't have any z in it yet)
o250 do
	#15=[[#1+#2]*COS[#4] - [#2+#3]*COS[[[#1+#2]/#2]*#4]]
	#16=[[#1+#2]*sin[#4] - [#2+#3]*sin[[[#1+#2]/#2]*#4]]
	g1 x[#15]y[#16]f200
	#4=[#4+#5]
o250 while [#4 LE #14]
m30

3.4. Sample 4 -- Subroutine for helical hole milling using radius comp

o100 sub
  (helical hole milling, load tool and set feed first, then use like so:)
  (o100 call [x pos] [y pos] [safety height] [hole depth] [hole dia] [tool dia])
  (tool dia doesn't have to be specified exactly.)
#7=[#6/2] (#7 is depth per circle = half of tool diameter)
#8=#7     (#8 is current depth step)
g0 z#3
(start above and right so we make a convex corner for entry to the ccw arcs)
g0 x[#1 + [#7 * 2]] y[#2 + [#5 / 2]]
g41 g0 x#1 y[#2 + [#5 / 2]]
o101 while [#8 LT #4]
(down toward the specified depth a bit at a time)
g3 x#1 y[#2 + [#5 / 2]] i0 j[0 - [#5 / 2]] z[0 - #8]
#8=[#8 + #7]
o101 endwhile
(down to the actual depth)
g3 x#1 y[#2 + [#5 / 2]] i0 j[0 - [#5 / 2]] z[0 - #4]
(full circle at the actual depth)
g3 x#1 y[#2 + [#5 / 2]] i0 j[0 - [#5 / 2]]
(nice quarter-circle helical exit move)
g3 x[#1 - [#5 / 2]] y#2 i0 j[0 - [#5 / 2]] z#3
g40
o100 endsub

(here is the actual usage: T1 is a 1/16th end mill)
g20 g64 g17 g90
t1 m6
s1000 m3
f5
o100 call [0] [0] [.01] [.125] [.125] [.0625]
o100 call [.25] [0] [.01] [.125] [.5] [.0625]
t0 m6
m2

Note: Link 1 is broken

3.5. Sample 5 -- Subroutine for generating multiple parts using Local and Global coordinates

I asked in the LinuxCNC mailing list in 12/2008 how Gcode could create multiple copies of of an identical part. To make the request easy, I asked to cut out a series of squares. Many thanks to Jeff Epler for his response. The following code uses global and local coordinate systems in addition to the Oword calls. As with all new code, test this by cutting air first!

O100 sub (square [x0] [y0] [z0] [zr] [f1] [f2])
        (cut a 1x1 square)
        (#1 = z0 = depth of cut)
        (#2 = zr = retract after cut)
        (#3 = f1 = feed to cutting depth)
        (#4 = f2 = feed for square)
        (assumes already at safety height)
G0 X0 Y0
        (Can replace the following 4-6 lines with custon code)
G1 Z#1 F#3
G1 X1 F#4
G1 Y1
G1 X0
G1 Y0
G0 Z#2

O100 endsub

O200 sub (l2r [x0] [y0] [dx] [count] [z0] [zr] [f1] [f2])
        (#1 = x0 = least x coordinate)
        (#2 = y0 = common y coordinate for all squares)
        (#3 = dx = increment between x coordinates)
        (#4 = count = number of squares in row)
        (#5 = z0 = depth of cut)
        (#6 = zr = retract after cut)
        (#7 = f1 = feed to cutting depth)
        (#8 = f2 = feed for square)
        (cut squares from left to right at constant Y)
(#9 = temporary for count of squares in row)
#9=0
O210 while [#9 LT #4]

G0 X[#1+#9*#3] Y#2
G92 X0 Y0
O100 call [#5] [#6] [#7] [#8]
G92.1

#9=[#9+1]
O210 endwhile
O200 endsub

O300 sub (r2l [x0] [y0] [dx] [count] [z0] [zr] [f1] [f2])
        (parameters as for O200 sub)
        (cut squares from right to left at constant Y)
#9=[#4-1]
O310 while [#9 GE 0]

G0 X[#1+#9*#3] Y#2
G92 X0 Y0
O100 call [#5] [#6] [#7] [#8]
G92.1

#9=[#9-1]
O310 endwhile
O300 endsub

O400 sub (squares [x0] [y0] [dx] [dy] [xcount] [ycount] [z0] [zr] [f1] [f2])
        (#1 = x0 = least x coordinate)
        (#2 = y0 = least y coordinate)
        (#3 = dx = increment between x coordinates)
        (#4 = dy = increment between y coordinates)
        (#5 = xcount = number of squares in row)
        (#6 = ycount = number of rows)
        (#7 = z0 = depth of cut)
        (#8 = zr = retract after cut)
        (#9 = f1 = feed to cutting depth)
       (#10 = f2 = feed for square)
(#11 = temporary for count of rows)
#11=0
O410 while [#11 LE #6]
O420 if [[#11 MOD 2] EQ 0]
O200 call [#1] [#2+#11*#4] [#3] [#5] [#7] [#8] [#9] [#10]
O420 else
O300 call [#1] [#2+#11*#4] [#3] [#5] [#7] [#8] [#9] [#10]
O420 endif
#11=[#11+1]
O410 endwhile
O400 endsub

G92.1

G20
M3 S1000
O400 call [0] [0] [1.5] [1.5] [4] [5] [-1] [1] [12] [30]
M2

3.6. Sample 6 -- box endwrench program

Heres a sample program to cut a box endwrench out of a sheet of material, editing allows any sizes Also uses tool change command and pause,DEBUG and MSG all wrapped up in one pgm
%
(Joseph Peitz, may20 2013 revision #3)
(Joseph Peitz, may25 2013 revision #4, bugfix, 2x cutterwidth )
(    subtracted from holewidth instead of one,)
()
(bug fixes, added independent wall thicknesses)
(the universal box end-wrench program : 12pt, 6, 8, and other )
(assumes a non-metric Sherline mill, all english measurements)
()
(two subroutines here:)
(first subroutine cuts the number of flats passed in)
(eg: make a ten sided wrench for a ten sided nut)
()
(second subroutine cuts twice the number of flats passed in)
(eg: cut a 12 pointed wrench for a six sided nut)
()
(each subroutine takes 4 params: nut diameter, number of flats, currentx,)
(currenty positions)
(if your nut has an even number of points, the distance across opposing flats)
(through nut axis is the size wrench to make. If odd, twice the distance )
(from the center of one flat to the axis of the nut is needed)
()
(zero the cutter on the part centerline, holes are offset from that in x dir)
(handle width is width of the nut at each end)
(wrench looks like: O=O when finished)
(length of equal sign is length specified, actual wrench length will)
(include hole width and edge thickness, center to center length)
(is displayed before cutting starts)
(a 5/64 diameter endmill is assumed, I've cut 10mm wrenches)
(if you use a larger cutter you may have to finish corners with a file)
(no g-code cutter comp is used in the program, you can change the head)
(dimensions and make it as tight or loose as you wish)

(here subroutines:)
(both assume that other code has made a plunge,cutter has been zeroed,)
(plate or sheet is firmly attached to the slide)
()
(this routine cuts one pass, one point for each flat)
o1000 sub
#<flats> = #2
#<curx> = #3
#<cury> = #4
#<diam> = [#1/[cos[180.0/#<flats>]]]
#305 = #<curx>
#301 = #<cury>
#303 = [[360.0/#<flats>] / 2.0]
#306 = [#<diam>*[sin[180.0/#<flats>]]]
#305 = [#305 + [#306 * cos[270.0 + #303]]]
#301 = [#301 + [#306 * sin[270.0 + #303]]]
o140 while [#303 lt 360.000]
g1 x [#305] y [#301]
#303 = [#303 + [360.0/#<flats>]]
#305 = [#305 + [#306 * cos[270.0 + #303]]]
#301 = [#301 + [#306 * sin[270.0 + #303]]]
o140 endwhile
g1 x [#<curx>] y [#<cury>]
o1000 endsub
()
(heres the subroutine that makes one pass with two points per flat)
o1001 sub
#<flats> = #2
#<curx> = #3
#<cury> = #4
#<diam> = [#1/[cos[180.0/#<flats>]]]
#305 = #<curx>
#301 = #<cury>
#303 = [[360.0/#<flats>] / 2.0]
#306 = [#<diam>*[sin[180.0/#<flats>]]/[2.0*[1.0+cos[180.0/#<flats>]]]]
#305 = [#305 + [#306 * cos[270.0 + #303]]]
#301 = [#301 + [#306 * sin[270.0 + #303]]]
g1 x [#305] y [#301]
o140 while [#303 lt 360.000]
#303 = [#303 -[360.0/[#<flats>*2.0]]]
#305 = [#305 + [#306 * cos[270.0 + #303]]]
#301 = [#301 + [#306 * sin[270.0 + #303]]]
g1 x [#305] y  [#301]
#303 = [#303 + [360.0/[#<flats>]]]
#305 = [#305 + [#306 * cos[270.0 + #303]]]
#301 = [#301 + [#306 * sin[270.0 + #303]]]
g1 x [#305] y  [#301]
o140 endwhile
g1 x [#<curx>] y [#<cury>]
o1001 endsub

(here starts the main program)
(protocol leadin an english sherline mill is assumed)
(preliminary code was run on a Sherline model 2000 )
g17 g20 g40 g49 g54 g80 g90.1 g94
g10 l2 p1 x0 y0 z0 (make axis set 1 be absolute)
(This says to use tool m6, in the tools file, but its not used)
t1 m6 (tellit we're using a tool, 3/16 endmill used here hardcoded)
f 100
g0 x0 y0 z0
(end protocol)

(wrench looks like O=o and the space between the -'s of the equal sign)
(are the radius of the holes at each end. with very small o, we'll get)
(O>o as our output)
#<cutterdiam> = [5.0/64.0] (a 5/64 diameter endmill)
#<bigwidth> = [4.500 - 2.0*#<cutterdiam>] (flat to flat nut width inches)
(this is the dimension for the bigger opening:,our nut size)
(this is a very snug fit, this setting leaves endmill wobble)
(about .002, as the only clearance and adjust this if its too tight)
(make cutterdiam be 5.0/64 - .005 and get .007 clearance....)
#<bigflats> = 5.0
#<littlewidth> = [3/8 - 2.0*#<cutterdiam>]
(this is the size of the smaller nut, actually a socket wrench)
#<littleflats> = 4.0 (the number of flats on the smaller bolt)
#<handlelength> = [2.01]
#<bigwallwidth> = [0.550]
#<littlewallwidth> = [0.400]
#<passesneeded> = 5.0 (number of times to go around)
#<passdepth> = 0.0450 (passesneeded times passdepth = sheet thickness)
(use passdepth = 0.005 for aluminum or steel)
#<cuttingfeed> = 100.0 (ok for cutting air)
(#<cuttingfeed> = 10.0 for plastic or wood)
(use 5.0 meaning 5% for steel or aluminum)


(derived params)
#200 = [#<bigwidth>/[2.0*[cos[[180.0/#<bigflats>]]]]+#<bigwallwidth>]
(200 is x-offset to center of first hexhole)
#201 = 0.000 (y-offset to axis of wrench)

#206 = [#<littlewallwidth>+[#<littlewidth>/[2.0*[cos[180.0/#<littleflats>]]]]]
(206 is radius of 2nd hole)

#207 = [#200 * 2.0]
#207 = [#207 + [#<handlelength>]]
#210 = [#207 + [#206 * 0.1340]]
(210 is intersection of handle and 2nd circle)

#207 = [#207 + [#206]]
(207 is center of second hole)
#208 = [#207 - #206 + #<littlewallwidth> ]
(208 is the cut point of the smaller hole)

#310 = [#207 - #200]
(DEBUG, Center to center length is [#310] )
(MSG, press pause button "||" to proceed)
M0
(this is where we start cutting the first hole)
g1 f #<cuttingfeed> z +.250 (retract )
g0 x #<bigwallwidth> y   0.0
#302 = 0
o100 while  [#302 lt #<passesneeded>]
#302 = [#302 + 1]
g1 f #<cuttingfeed> z - [#302 * #<passdepth>] (start with  a plunge cut here)
o1000 call [#<bigwidth>] [#<bigflats>] [#<bigwallwidth>] [0.0]
(o1001 call [#<bigwidth>] [#<bigflats>] [#<bigwallwidth>] [0.0])
o100 endwhile
g1 f #<cuttingfeed> z +.250 (retract )

(cut the second hole here)
g0 x #208 y 0.0 (go to the cut point of the 2nd hole)
#302 = 0
o110 while  [#302 lt #<passesneeded>]
#302 = [#302 + 1]
g1 f #<cuttingfeed> z - [#302 * #<passdepth>] (start with  a plunge cut here)
o1000 call [#<littlewidth>] [#<littleflats>] [#208] [0.0]
(o1001 call [#<littlewidth>] [#<littleflats>] [#208] [0.0])
o110 endwhile
g1  z +.25 (retract)

(cut the outer border of the wrench)
g0 x0 y0
#302 = 0
o150 while [#302 lt #<passesneeded>]
#302 = [#302 + 1]
g1 f #<cuttingfeed> z - [#302 * #<passdepth>] (start plunge )
g2 x [#200 + [#200 * .8660]] y [#200 / 2] i [#200] j 0 (back into handle)
g1 x [#210] y [#206 /2]
g2 x [#210] y -[#206/2] i [#207] j0
g1 x [#200 + [#200 * 0.8660]] y -[#200 / 2]
g2 x 0 y 0 i [#200] j 0
o150 endwhile
g1  z +.25
g0 x0 y0
m2
%

3.7. Sample 7 -- spur gear program

... ... As of 17 Mar 2014, gearcap round over (when it fits) As of 20 Mar 2014, fixed cw bug symmetry,gt->ge As of 29 Mar 2014, fixed interference ginc->cap

%
(Spur gear program: set variables pressure angle, base radius, )
(number of teeth,ratio, program figures out what to use for a gear specifics)
("prints" involute tooth parameters and mills the gears)
(linuxcnc must be started from within a terminal window,)
(/usr/bin/linuxcnc '/home/you/linuxcnc/configs/axis/sim/axis.ini')
(entered on a terminal prompt, the value in ''is the path to your .ini)
(two gears are displayed, first gear is "stock". Program attempts to adjust)
(the fudge variables of the second gear for a good fit. once the )
(fudge variables are close, autosizing can be shut off by entering a)
(non-zero value for them at the start of the if statements)
(After adjusting parameters, and before milling, uncomment cutter comp lines,)
(adjust comp offset, set variable #<_ginc> for desired beginning offset and)
(set ginc limit. Only one set of laminates can be milled at a time)
(Joseph Peitz 2014, JAN16 ,minor bugfixes and better laminated pinion support) 
(Joseph Peitz 2014, MAR8, added roundover to toothtop, {and cutterdiam/3} )
(Joseph Peitz 2014, MAR28, fixed ginc interference with roundover)
(email: joseph.peitz@makeitlabs.com)

o413 sub
(this subroutine draws one whole gear tooth with cap if it fits and one gap)
(first is x,2nd is y third parm is baseradius 4th is compass,5th pitch)
(6th is numberteeth,7=diametralpitch, 9 is pangle,10th is ratio)
#11= 0.00(hardcode the first value of our involute,0 may interfere undercut)
 #18 = 0.0 (18&20  is used to track surface samples)
 #20 = 0.0
 #<inva>= 0.0
 o515 if [#<_raddendum> eq 0]
 o514 if [#7 eq 0] (if diametral pitch is zero,get addendum from pa)
 #<_raddendum>=[#3*[1/cos[#9]-1]] (compute raddendum from pa)
 o514 else
  #3=[[cos[#9]*#6]/[#7*2.0]] (compute a new base and raddendum from dp)
  #<_raddendum>=[#3*[1/cos[#9]-1]]
 o514 endif
 o516 if [#10 ne 0] (adjust tooth height to match its mate)
   #<_fudgeh> = [#<_raddendum>/#10 - #<_raddendum>]
 o516 endif
 #96 = [2.0*#<_raddendum>+#<_fudgeh>]
 o515 endif
   #80 = [[#11]/57.2957779] (degrees and radians!!!)
   #16 = [#3*[cos[#11] + #80*sin[#11]]](involute equations)
   #17 = [#3*[sin[#11] - #80*cos[#11]]]
   #12 = #16
   #13 = #17
   #54 = [#3+2.0*#<_raddendum>+#<_fudgeh>]
 o1001 while [[SQRT[[#12]**2+[#13]**2]]lt[#54]]
   #80 = [[#11]/57.2957779] (degrees and radians!!!)
   #12 = [#3*[cos[#11] + #80*sin[#11]]](involute equations)
   #13 = [#3*[sin[#11] - #80*cos[#11]]]
   #14 = [#12*cos[#4-#<_fudgewc>] -#13*[sin[#4-#<_fudgewc>]]+#1]
   #15 = [#12*sin[#4-#<_fudgewc>] +#13*[cos[#4-#<_fudgewc>]]+#2]
   #18 = [#18 + 1]
   o510 if [[SQRT[[#12]**2+[#13]**2]]lt[#3+#<_raddendum>]]
     #<inva> = [[atan[#13]/[#12]]]
     #<_incangle> = [[360.0/[2.0*#6]]+2.0*#<inva>+#<_fudgewccw>]
   o510 endif
   o5008 if [[atan[#13]/[#12]] ge [#<_incangle>/2.0]]
    (Save the total distance above baseradius)
     #96 = [[[SQRT[[#12]**2+[#13]**2]]-#3]]
     ;(PRINT, gotta break,#96,#<_raddendum>)
     o1001 break
   o5008 endif
   g1 x#14 y#15
   #11 = [#11 + #<_precision>] 
 o1001 endwhile (end make ccw active gear face)
  #<_gsamples> = #18
   #<native> = [atan[#13]/[#12]] (angular width of one face)
    o511 if[#<native> gt [[360/[2.0*#6]]]]
     (PRINT,program error,can't fit full teeth:bad pressure angle?)
    o511 endif
   #30 = 0
   #<_gincscale>=#<_ginc> (adjustment for gear ginc, less for pinions)
   #55 = 800.0 (roundover control for gear)
   o5006 if [#7 ne 0](all this to make a point?)
      ;#55 = 20000.00 (no roundover, control for pinion toothtop)
      ;#55 = 800.0 (lots of roundover)
      #<_gincscale>=[-#5*#<_ginc>](pinion rotates cw, gear rotates ccw....)
      #55=1000.0
   o5006 endif
   (raddendum is different when pressure angle is big)
   #54 = [#3+#96+#<_cutterdiam>/3]
   o5001 while [[SQRT[[#12]**2+[#13]**2]]lt[#54]]
    #80 = [[#11]/57.2957779]
    #12 = [#3*[cos[#11] + #80*sin[#11]]](involute equations)
    #13 = [#3*[sin[#11] - #80*cos[#11]]]
    #31 = [#6*[#30]*[#30/#55]*[atan[#<_cutterdiam>]/[#3]]*[1/60.0] +#4]
    #14 = [#12*cos[#31-#<_fudgewc>] -#13*[sin[#31-#<_fudgewc>]]+#1]
    #15 = [#12*sin[#31-#<_fudgewc>] +#13*[cos[#31-#<_fudgewc>]]+#2]
    #89 = [ABS[[atan[#15-#2]/[#14-#1]-[#<_offsetangle>+#<_gincscale>]]MOD[180.0/#6]]]
    o5007 if [[#89] gt [#<_incangle>/2]]
      ;(PRINT, hit a cap break,#89,#30)
      o5001 break
    o5007 endif
     #11 = [#11 + #<_precision>]
     #30 = [#30+1.0]
     g1 x#14 y#15 
   o5001 endwhile  (end make ccw cap)
   #11 = [#11 -1.0* #<_precision>]
   #30 = [#30-1.0] 
   #86 = [[SQRT[[[#15-#2]**2]+[[#14-#1]**2]]]-#3] (compute height above baseradius) (this is actually one involute click bigger than real)
   o5005 while [#30 ge 0.0]
     #80 = [[#11]/57.2957779]
     #12 = [#3*[cos[#11] + #80*sin[#11]]]
     #13 = [#3*[-sin[#11] + #80*cos[#11]]]
     #31 = [-#6*[#30]*[#30/#55]*[atan[#<_cutterdiam>]/[#3]/60.0] +#4+#<_incangle>]
     #14 = [#12*cos[#31] -#13*[sin[#31]]+#1]
     #15 = [#12*sin[#31] +#13*[cos[#31]]+#2]
     #11 = [#11-#<_precision>]
     #30 = [#30-1.0]
     g1 x#14 y#15
   o5005 endwhile (end make cw cap)
  #20 = 0
  o2003 while [#11 gt 0.00] (four reduces cutter comp problems???)
   #80 = [[#11]/57.2957779]
   #12 = [#3*[cos[#11] + #80*sin[#11]]]
   #13 = [#3*[-sin[#11] + #80*cos[#11]]]
   #14 = [#12*cos[+#4+#<_incangle>] -#13*sin[+#4+#<_incangle>] + #1]
   #15 = [#12*sin[+#4+#<_incangle>] +#13*cos[+#4+#<_incangle>] + #2]
   #20 = [#20 + 1]
   #11 = [#11 - #<_precision>] 
   g1 x#14 y#15
 o2003 endwhile (end make cw face)
   #14 = [#3*cos[+#4+#<_incangle>] + #1]
   #15 = [#3*sin[+#4+#<_incangle>] + #2]
   g1 x#14 y#15
     #<_endangle> = [#<_incangle>]
     #<_chkangle> = [#<_endangle>-2.0*#<inva>]
#23 = [2*#<_raddendum>+#<_fudgeh>]
#24 = [#6/[2.0* [#3 + #<_raddendum>]]]
#25 = [#<_endangle>+#<_fudgewc>]
#26 = [#<_chkangle>+#<_fudgewc>]
#21 = [2.0*[#3+#<_raddendum>]*sin[#26/2.0]]
#22 = [2.0*#3*sin[#25/2.0]]
    o404 if [#<_printflag> eq 1]
(PRINT, base angle=#25degrees,pitch angle=#26degrees,base-thickness=#22",pitch-thick=#21",addendum=#<_raddendum>",active tooth above baseradius=#23",diametral pitch=#24,#samples=#<_gsamples>,faceangle=#<native>degrees,total tooth above baseradius=#86)
    #<_printflag> = 0
    o404 endif
 #34 = #3 (return the value for baseradius just in case we used dp)
 #35 = #24 (return dp too)
(end of make one tooth, begin some math for the tooth gap)
#<segangle> = [360.0/[#6]] (wholesegment)
#32 = [#4+#<segangle>-#<_fudgewc>] (next tooth)
#33 = [#32-[[#<segangle>-#<_endangle>-#<_fudgewc>]/2.0]](midpoint to next tooth)
#40 = [#3-#<_cutterdiam>/2.0]
o501 if [[[#6] gt 6]or[SQRT[[[#40*cos[#33]]**2]+[[#40*sin[#33]]**2]]lt[1.6*#<_cutterdiam>]]](use different gullet for small pinions)
#50=[#3-#<_cutterdiam>/6](cutterdiam divisor controls undercut)
g2 x[#1+[#3*cos[#32]]] y[#2+[#3*sin[#32]]] i[#1+[[#50]*cos[#33]]] j[#2+[[#50]*sin[#33]]]
o501 else
#49 = [#<_cutterdiam>+#<_cutterdiam>/6] (cutterdiam divisor controls undercut)
#45 = [asin[[+#49]/[#3*2]]](jog angle)
#46 = [#32-[#<segangle>-#<_endangle>-#<_fudgewc>]](start here)
#47 = [#46+#<segangle>]
#48 = [#3-#3*cos[#45]] (fillet center located inboard of base radius)
g2 x[#1+[[#3-#48-#49/2]*cos[#46+#45]]] y[#2+[[#3-#48-#49/2.0]*sin[#46+#45]]] i [#1 +[[#3-#48] *cos[#46+#45]]] j[#2 +[[#3-#48]*sin[#46+#45]]]
g3 x[#1+[[#3-#48-#49/2.0]*cos[#32-#45]]] y[#2+[[#3-#48-#49/2.0]*sin[#32-#45]]] i [#1] j[#2]
g2 x[#1+[#3]*cos[#32]] y[#2+[#3]*sin[#32]] i [#1 +[[#3-#48]*cos[#32-#45]]] j[#2 +[#3-#48]*sin[#32-#45]]
o501 endif
o413 endsub

o414 sub
(this subroutine computes offsetangle and tooth width for a gear)
(first is x,2nd is y third parm is baseradius 4th is compass)
(5th is pitch 6th is numberteeth,7=diametralpitch, 9 is pangle)
(11 is the midpoint of the line betwen gears' centers,currently pitchradius) 
(this sub only uses parameters 3,4,6,9,11, returns 35,36,37,38)
 #10 = [#9/2.0] (this sb 0 for the general case but doesn't matterhere)
 #14 = 0
 o1001 while [#14 lt #11](this works with the raw involute)
   #80 = [[#10]/57.2957779] (degrees and radians!!!)
   #12 = [#3*[cos[#10] + #80*sin[#10]]](involute equations)
   #13 = [#3*[sin[#10] - #80*cos[#10]]]
   #14 = [#12*cos[-#<_fudgewc>] -#13*[sin[-#<_fudgewc>]]]
   #15 = [#12*sin[-#<_fudgewc>] +#13*[cos[-#<_fudgewc>]]]
   #10 = [#10 + .010] 
   o510 if [[SQRT[[#12]**2+[#13]**2]]lt[#3+#<_raddendum>]]
     #<inva> = [[atan[#13]/[#12]]]
   o510 endif
 o1001 endwhile
   #10 = [#10 - .010]
   #80 = [[#10]/57.2957779] (degrees and radians!!!)
   #36 = [atan[#15]/[#14]] (return this and #35 below)
   #<_incangle> = [[360.0/[2.0*#6]]+2.0*#<inva>+#<_fudgewccw>]
   #12 = [#3*[cos[#10] + #80*sin[#10]]]
   #13 = [#3*[-sin[#10] + #80*cos[#10]]]
   #14 = [#12*cos[#<_incangle>] -#13*sin[#<_incangle>]]
   #15 = [#12*sin[#<_incangle>] +#13*cos[#<_incangle>]]
   #35 = [[atan[#15]/[#14]]-#36] (angle subtended by one tooth@contact)
   #37 = [2.0*#11*sin[#35/2.0]] (tooth@contact,inches)
   #38 = [2.0*#11*sin[[360/#6-#35]/2.0]](gap@contact inches)
;(print #15,#14,#11,#35,#36,#37,#38,#<_incangle>,#<inva>,internals)
o414 endsub

(main: protocol leadin, non-metric Sherline mill assumed)
g17 g20 g40 g49 g54 g80 g90.1 g94
g10 l2 p1 x0 y0 z0 (make axis set 1 be absolute)
;t1 m1 (setup first bit in the tools file,just to have a tool,cutter size is hardcoded)
f 100
g0 x0 y0 z0
;(debug cutter is zeroed, press pause button to proceed)
;m0

#<_ginc> = -0.0  (used  to incline both gears from center quarterflat hole)
o800 while [#<_ginc> lt [+2]] (set the ginc limit)

(gear parameters:)
#<pressangle> = 20.00000 (std are 14.5,20,25)
#<baseradius> = 2.000000 (inch, 2.0 w/36 teeth&14.5 smallest 1/8 ratio12)
#<numberteeth> = 36 (this must be divisible by ratio without remainder!!)
#<ratio> = 6.0(first gear teeth / second gear teeth)
#<gearcenterx> = 2.50 (co-ordinates of gear center)
#<gearcentery> = 2.50 (parameters beyond this are computed by the code)
#<_fudgeh> = -0.000 (adjust top, must be less than addendum,inches first gear)
#<_fudgewc> = -0.000 (adjust the clockwise gear face width degrees)
#<_fudgewccw> = -0.000 (adjust the counter clockwise gear facewidth degrees)
#<_raddendum> = 0 (must be zero, outer radius - pitch radius inches)
#<pitchradius>=0  (must be zero, this becomes baseradius + addendum inches)
#<_chkangle> = 0  (must be zero, used for measuring the tooth)
#<_endangle> = 0  (must be zero)
#<_incangle> = 0  (must be zero)
#<diametralpitch> = 0
#<_offsetangle>=0

(machine parameters:)
#<_precision> = 0.400 (degrees, adjust accuracy,.01 and .001 take long)
#<_printflag> = 1
#<_cutterdiam> = [5.0/64.0] (a 5/64 diameter endmill)
;#<centerholediam> = [0.50 - 2* #<_cutterdiam>] (A center hole gear center)
#<centerholediam> = 0.50
#<passesneeded> = 2.0 (this times depth is total milling depth)
#<cuttingdepth> = 0.05 (50 thou, okay for wood plastic, small endmill)
#<cuttingfeed> = 100.0 (for cutting air0.0% for al,05.0% steel)

(cut a center hole here without programmed cutter comp)
g0 z 0.25 (retract)
x[#<gearcenterx>-#<centerholediam>/2] y #<gearcentery> 
#302 = 0
o100 while  [#302 lt #<passesneeded>]
 #302 = [#302 + 1]
 g1 f#<cuttingfeed> z [0.0 - #302*#<cuttingdepth>] (plunge)
 g1 x[#<gearcenterx>] y[#<gearcentery>+#<centerholediam>/2.0]
 g2 x[#<gearcenterx>-#<centerholediam>/2]y#<gearcentery> i [#<gearcenterx>] j [#<gearcentery>]
o100 endwhile (end of cut gear centerhole)
g0 z 0.25
g0 x #<gearcenterx> y #<gearcentery>

;g42.1 D [#<_cutterdiam>/2.0] (uncomment this comp line before milling first gear)
g1 x[#<gearcenterx>+[#<baseradius>]*cos[+#<_ginc>]] y [#<gearcentery>+[#<baseradius>]*sin[+#<_ginc>]]
#<plunger> = [360.0 +#<_ginc>]
#302 = 1
g1 f#<cuttingfeed> z [0.0 - #302*#<cuttingdepth>] (plunge)
#<compass_point> = [0.0 + #<_ginc>]
o3001 while [#<compass_point> lt [#<passesneeded>*[360.0 +#<_ginc>]]]
(cut first gear tooth here, lots of unused parameters here, sorry)
o413 call [#<gearcenterx>][#<gearcentery>][#<baseradius>][#<compass_point>][#<pitchradius>-#<_raddendum>][#<numberteeth>][0][#<pitchradius>+#<_raddendum>] [#<pressangle>][#<ratio>]
#<baseradius> = #34 (get a new value for baseradius& dp)
#<diametralpitch> = #35
#<pitchradius> = [#<baseradius> + #<_raddendum>]
#<segangle> = [360.0/[#<numberteeth>]] (wholesegment)
#<compass_point> = [#<compass_point>+[360.0/[#<numberteeth>]]]
o301 if  [[#<compass_point> ge #<plunger>] and [#302 lt #<passesneeded>]]
 #302 = [#302 + 1]
 g1 f#<cuttingfeed> z [0.0 - #302*#<cuttingdepth>] (plunge)
 #<plunger>=[#302*[360.0+#<_ginc>]]
o301 endif
o3001 endwhile (end of cut gear)
g40 (turn off compensation after cutting/comping first gear)
g0 z 0.25
(draw a reference circle above the first gear at the pitch radius)
;g0 x [#<gearcenterx>-#<baseradius>-#<_raddendum>] y[#<gearcentery>]
;g2 i [#<gearcenterx>] j [#<gearcentery>]
#<baseradius> = [[#<pitchradius>-#<_raddendum>]/#<ratio>] (for second gear)
(pitch radius is for the old gear, baseradius is new,next line has comp offset)
#<gearcenterx> = [#<gearcenterx>+#<pitchradius>+#<_raddendum>/#<ratio>+#<baseradius>+0.0*#<_cutterdiam>] ;make this 2*cutterdiam here to cut/comp both gears
(print, #<gearcenterx>,#<gearcentery> is second gear center)
#<_offsetangle> = 0 (this is relative rotation between gears)
o414 call [0][0][#<pitchradius>-#<_raddendum>][0][0][#<numberteeth>][0][0][#<pressangle>][0][#<pitchradius>]
#<_offsetangle> = [-#<ratio>*#36] (have to callit again & accumulate)
(print, first gear tooth is #37" thick at contact point,gap is #38")
#<_fudgewc> = -0.00 (second gear)
#<_fudgewccw> = +0.0000 (second gear)
o202 if [#<_fudgewccw> eq 0] 
#<_fudgewccw> = [[180.0/#<numberteeth>-#35]]
o202 endif

(setup for cutting pinion)
#<numberteeth>= [#<numberteeth>/#<ratio>]
;#<centerholediam> = [0.180 - 2* #<_cutterdiam>] (A second gear center hole)
#<centerholediam> = [0.125] (for pinion center)
#<_raddendum> = [#<_raddendum>/#<ratio>](new and dangerous value)
o414 call [0][0][#<baseradius>][0][0][#<numberteeth>][0][0][#<pressangle>][0][#<baseradius>+#<_raddendum>]
(print, second gear tooth is #37" thick at contact point,gap is #38")
#<_offsetangle> = [#<_offsetangle> - #36]
#<_raddendum> = [#<_raddendum>*#<ratio>](new and dangerous value restored)
(PRINT, offsetangle:#<_offsetangle>,fudgewccw:#<_fudgewccw>,fudgewc:#<_fudgewc>,fudgeh:#<_fudgeh>)
#<gearcentery> = [#<gearcentery>] 
#<pitchradius> = [#<baseradius> + #<_raddendum>/#<ratio>]
#<_incangle> = 0.0
#<_fudgeh>= -0.00(second gear)
o203 if [#<_fudgeh> eq 0]
#<_fudgeh> = [#<_raddendum> -#<_raddendum>/#<ratio>]
o203 endif

(cut a 2nd gear center hole here without cutter comp)
#<_printflag>=1
g0 z 0.25 (retract)
x[#<gearcenterx>-#<centerholediam>/2] y #<gearcentery> 
#302 = 0
o200 while  [#302 lt #<passesneeded>]
 #302 = [#302 + 1]
 g1 f#<cuttingfeed> z [0.0 - #302*#<cuttingdepth>] (plunge)
 g1 x[#<gearcenterx>] y[#<gearcentery>+#<centerholediam>/2.0]
 g2 x[#<gearcenterx>-#<centerholediam>/2]y#<gearcentery> i [#<gearcenterx>] j [#<gearcentery>]
o200 endwhile (end of cut pinion centerhole)
g0 z 0.25
g0 x #<gearcenterx> y #<gearcentery>
;g42.1 D [#<_cutterdiam>/2.0] (this is cutter comp line for 2nd gear or pinion)
g1 x[#<gearcenterx>+[#<baseradius>]*cos[180+#<_offsetangle>-#<_ginc>*#<ratio>]] y [#<gearcentery>+[#<baseradius>]*sin[180.0+#<_offsetangle>-#<_ginc>*#<ratio>]]
#302 = 1.0
g1 f#<cuttingfeed> z [0.0 - #302*#<cuttingdepth>] (plunge)
#<plunger>=[180.0+#<_offsetangle>-#<_ginc>*#<ratio>+#302*360.0]
g1 f#<cuttingfeed> z [0.0 - #302*#<cuttingdepth>] (plunge)
#<compass_point> = [[180.0+#<_offsetangle>]-#<_ginc>*#<ratio>]
o4001 while [#<compass_point> lt [180.0+#<_offsetangle>-#<_ginc>*#<ratio>+#<passesneeded>*360.0]]
#<_raddendum> = 0
(call with diametral pitch pitch instead of press angle here for pinion)
o413 call [#<gearcenterx>][#<gearcentery>][#<baseradius>][#<compass_point>][#<ratio>][#<numberteeth>][#<diametralpitch>][#<pitchradius>+#<_raddendum>] [#<pressangle>][0]
#<compass_point> = [#<compass_point>+[360.0/[#<numberteeth>]]]
o401 if  [[#<compass_point> ge #<plunger>] and [#302 lt #<passesneeded>]]
 #302 = [#302 + 1]
 #<plunger>=[180.0+#<_offsetangle>-#<_ginc>*#<ratio>+#302*360.0]
 g1 f#<cuttingfeed> z [0.0 - #302*#<cuttingdepth>] (plunge)
o401 endif
o4001 endwhile (end of cut pinion)
g40 (shut off compensation for second gear or pinion)
g0 z 0.25
(draw a reference circle above the second gear @ pitch radius)
;g0 x [#<gearcenterx>-#<baseradius>-#<_raddendum>] y[#<gearcentery>]
;g2 i [#<gearcenterx>] j [#<gearcentery>]
 #<_ginc> = [#<_ginc> + 02.50] (ginc offset each pass)
o800 endwhile
g0 x0 y0
m2
%



3.8. Sample 8 -- cycloid gears program

15 Jun 2014 bug fixes and added automatic undercutting feature 20 Jul 2014, improved automatic undercutting, improved accuracy


%
(Cycloid gears program: set variables pitchradius,number of teeth,ratio.Program)
(figures out what to use for a gear and its conjugate pinion dimensions)
(Generator circle diameter may be "adjusted" within a narrow range,see gcratio)
(linuxcnc must be started from within a terminal window,)
(/usr/bin/linuxcnc '/home/you/linuxcnc/configs/axis/sim/axis.ini')
(entered on a terminal prompt, the value in ''is the path to your .ini)
(fudge variables may be adjusted for a better fit )
(After adjusting parameters, and before milling, uncomment cutter comp lines,)
(adjust comp offset, set variable #<_ginc> for desired beginning offset)
(Joseph Peitz,Jun 26 2014, improve accuracy at the tooth base, adjust auto undercut)
(Joseph Peitz,Jul 18 2014, use first derivative for slope matching, fit a circle into)
(the dedendum {or not} to trade comp problems for interference problems)

o412 sub
(this subroutine computes globals used by everybody, must be called first)
(first is x,2nd is y third parm is pitchradius 4th is compass,5th pitch)
(6th is numberteeth,10th is ratio)
(PRINT, fudgeh=#<_fudgeh>,fudgewccw=#<_fudgewccw>,fudgewc=#<_fudgewc>)
   o519 if [#5 eq 0]
   #<_littler> = [[#3/[#10*2.0]]*#<_gcratio>] (little r,gen. circle radius)
   #<_bigRplus> = [#3+#<_littler>] (big R + little r for epicycloid)
   #<_bigRminus> = [#3-#<_littler>] (big R - little r for our wheel for hypocycloid)
   o519 else (swap calling pos if 5 not 0)
   #<_littler> = [[#5/[#10*2.0]]*#<_gcratio>] (little r,gen. circle radius)
   #<_bigRplus> = [#3+#<_littler>] (big R + little r for epicycloid)
   #<_bigRminus> = [#3-#<_littler>] (big R - little r for our wheel for hypocycloid)
   o519 endif
   #<_dedendum> = 0.0
   #11 = 0.0
   #12 = 0
   #13 = 0
   #82 = [360.0/[#6*4.0]+#<_fudgewccw>+#<_fudgewc>] (angular half tooth)
  o1008 while [atan[#13]/[#12]lt[#82]] 
   #12 = [#<_bigRplus>*cos[#11] - [#<_littler>]*cos[[#<_bigRplus>/#<_littler>]*#11]](epicycloid equations)
   #13 = [#<_bigRplus>*sin[#11] - [#<_littler>]*sin[[#<_bigRplus>/#<_littler>]*#11]]
   #11 = [#11+#<_precision>]
  o1008 endwhile
  o1009 while [atan[#13]/[#12]gt[#82]] 
   #12 = [#<_bigRplus>*cos[#11] - [#<_littler>]*cos[[#<_bigRplus>/#<_littler>]*#11]](epicycloid equations)
   #13 = [#<_bigRplus>*sin[#11] - [#<_littler>]*sin[[#<_bigRplus>/#<_littler>]*#11]]
   #11 = [#11-0.001000]
  o1009 endwhile
 #<_raddendum> = [SQRT[[#13]**2+[#12]**2]-#3](almost a gear addendum)
 #<_eclix> = [#11 -0.0*#<_precision>]
  #11 = 0
  #13 = #3
  #12 = 0
  #91 = 0
  #92 = [ABS[#82 - [asin[#<_cutterdiam>/[[#3-#<_raddendum>]*1.90]]]]](s/b 2)
  o1010 while [[SQRT[[#13]**2+[#12]**2]]gt[#3-#<_raddendum>]] 
   #11 = [#11 + #<_precision>]
   #34 = #11
   #12 = [#<_bigRminus>*cos[#11] + [#<_littler>]*cos[[#<_bigRminus>/#<_littler>]*#11]](hypocycloid equations)
   #13 = [+#<_bigRminus>*sin[#11] - [#<_littler>]*sin[[#<_bigRminus>/#<_littler>]*#11]]
   #91 = [atan[#13]/[#12]]
  o530 if [[#91 gt #92] AND [#<_dedendum> eq 0]]
(find an accurate addendum adjustment for #91 > #92)
     o1030 while [[ATAN[#13]/[#12]] gt #92]
        #12 = [#<_bigRminus>*cos[#11] + [#<_littler>]*cos[[#<_bigRminus>/#<_littler>]*#11]](hypocycloid equations)
        #13 = [+#<_bigRminus>*sin[#11] - [#<_littler>]*sin[[#<_bigRminus>/#<_littler>]*#11]]
     #11 = [#11 -0.0100]
    o1030 endwhile
     o1040 while [[ATAN[#13]/[#12]] lt #92]
        #12 = [#<_bigRminus>*cos[#11] + [#<_littler>]*cos[[#<_bigRminus>/#<_littler>]*#11]](hypocycloid equations)
        #13 = [+#<_bigRminus>*sin[#11] - [#<_littler>]*sin[[#<_bigRminus>/#<_littler>]*#11]]
     #11 = [#11 +0.000100]
    o1040 endwhile
     #<_dedendum> = [#3-[SQRT[[#13]**2+[#12]**2]]]
     #<_rclix> = [#11-0.00000]
     #<_ngcoffset>= [-[atan[#13]/[#12]]]
   #11 = #34 (restore & re-compute)
   #12 = [#<_bigRminus>*cos[#11] + [#<_littler>]*cos[[#<_bigRminus>/#<_littler>]*#11]](hypocycloid equations)
   #13 = [+#<_bigRminus>*sin[#11] - [#<_littler>]*sin[[#<_bigRminus>/#<_littler>]*#11]]
  o530 endif
 o1010 endwhile
  o1011 while [[SQRT[[#13]**2+[#12]**2]]lt[#3-#<_raddendum>]]
   #12 = [#<_bigRminus>*cos[#11] + [#<_littler>]*cos[[#<_bigRminus>/#<_littler>]*#11]](hypocycloid equations)
   #13 = [+#<_bigRminus>*sin[#11] - [#<_littler>]*sin[[#<_bigRminus>/#<_littler>]*#11]]
   #11 = [#11-0.000500]
  o1011 endwhile
  o1012 while [[SQRT[[#13]**2+[#12]**2]]gt[#3-#<_raddendum>]] 
   #12 = [#<_bigRminus>*cos[#11] + [#<_littler>]*cos[[#<_bigRminus>/#<_littler>]*#11]](hypocycloid equations)
   #13 = [+#<_bigRminus>*sin[#11] - [#<_littler>]*sin[[#<_bigRminus>/#<_littler>]*#11]]
   #11 = [#11+0.0000005]
  o1012 endwhile
  
o531 if [#91 lt #92] (use this to get artificial tooth shortening)
;o531 if [0 eq 0] (uncomment this {or not} to stop shrinking dedendum)
   #<_ngcoffset> = 0.0
   #<_dedendum> = #<_raddendum>
   #<_hclix> = [#11-0.0000005]
   #<_gcoffset> = [-[atan[#13]/[#12]]]
   #12 = [-#<_bigRminus>*sin[#11]-[#<_bigRminus>]*sin[[#<_bigRminus>/#<_littler>]*#11]](real hypocycloid slope equations, first derivative)
   #13 = [+#<_bigRminus>*cos[#11]-[#<_bigRminus>]*cos[[#<_bigRminus>/#<_littler>]*#11]]
o531 else
   #<_hclix> = #<_rclix>
   (PRINT, WARNING:PROBABLE INTERFERENCE PROBLEMS, adjusted dedendum for cutterdiam)
   #12 = [-#<_bigRminus>*sin[#<_hclix>]-[#<_bigRminus>]*sin[[#<_bigRminus>/#<_littler>]*#<_hclix>]](hypocycloid slope equations, first derivative)
   #13 = [+#<_bigRminus>*cos[#<_hclix>]-[#<_bigRminus>]*cos[[#<_bigRminus>/#<_littler>]*#<_hclix>]](hypocycloid slope)
   #<_gcoffset> = #<_ngcoffset>
o531 endif
   #<_toothangle> = [180.0/#6 + 2.0*#<_gcoffset>]
   #<hypoprime> = [#13/[#12*.01745329]]
   #<_autooffset> = 00.0
   o513 if [[#<hypoprime> ne 0]AND[#<hypoprime>ne 180.0]]
    o514 if [#<hypoprime> lt -0.0]
      #<_autooffset> = [-270.0-[-90.0 + #<hypoprime>]]
    o514 else
      #<_autooffset> = [180.0-[#<hypoprime>]]
    o514 endif 
   o513 endif
;(PRINT, hclix:#<_hclix>,#<_eclix>,#<_raddendum>,#<_gcoffset>,#<_autooffset>,#<hypoprime>,#87,#91,#92,#<_raddendum>,#<_rclix>,#<_dedendum>)
o412 endsub

o413 sub
(this subroutine draws one whole cycloid gear tooth and one gap)
(first is x,2nd is y third parm is pitchradius 4th is compass,5th pitch)
(6th is numberteeth,10th is ratio)
 #18 = 0.0 (18  is used to track surface samples)
  #11 = [#<_hclix>-1.0*#<_precision>] 
  o5001 while [#11 gt [#<_precision>]] (just the ccw leg)
   #12 = [#<_bigRminus>*cos[#11] + [#<_littler>]*cos[[#<_bigRminus>/#<_littler>]*#11]](hypocycloid equations)
   #13 = [-#<_bigRminus>*sin[#11] + [#<_littler>]*sin[[#<_bigRminus>/#<_littler>]*#11]]
   #14 = [#12*cos[#4-#<_fudgewc>] -#13*[sin[#4-#<_fudgewc>]]+#1]
   #15 = [#12*sin[#4-#<_fudgewc>] +#13*[cos[#4-#<_fudgewc>]]+#2]
   #18 = [#18 + 1]
   #11 = [#11 - #<_precision>] 
   g1 x#14 y#15
 o5001 endwhile (end make inner pinion tooth face)
   #82 = [360.0/[#6*4.0]] (angular half tooth)
  o1001 while [[#11 lt [#<_eclix>-1.0*#<_precision>]]AND[atan[#13]/[#12]]lt[#82+#<_fudgewc>+#<_fudgewccw>]AND[[[SQRT[[#12**2]+[#13**2]]]-#3]lt[[#<_raddendum>]-#<_fudgeh>]]]
   #12 = [#<_bigRplus>*cos[#11] - [#<_littler>]*cos[[#<_bigRplus>/#<_littler>]*#11]](epicycloid equations)
   #13 = [#<_bigRplus>*sin[#11] - [#<_littler>]*sin[[#<_bigRplus>/#<_littler>]*#11]]
   #14 = [#12*cos[#4-#<_fudgewc>] -#13*[sin[#4-#<_fudgewc>]]+#1]
   #15 = [#12*sin[#4-#<_fudgewc>] +#13*[cos[#4-#<_fudgewc>]]+#2]
   #18 = [#18 + 1]
   #11 = [#11+#<_precision>] 
   o509 if [#11 gt 2.0* #<_precision>]
     #42 = #11
     g1 x#86 y#87
   o509 endif 
   #86 = #14
   #87 = #15
 o1001 endwhile (end make outer gear tooth face)
  #<_gsamples> = #18
  #<_incangle> = [2*#82+#<_fudgewccw>]
  #11 = #42
  #11 = [#11 - 2.0*#<_precision>]
  o2003 while [#11 ge 1.0*#<_precision>]
   #12 = [#<_bigRplus>*cos[#11] - [#<_littler>]*cos[[#<_bigRplus>/#<_littler>]*#11]](neg. epicycloid equations)
   #13 = [-#<_bigRplus>*sin[#11] + [#<_littler>]*sin[[#<_bigRplus>/#<_littler>]*#11]]
   #14 = [#12*cos[+#4+#<_incangle>] -#13*sin[+#4+#<_incangle>] + #1]
   #15 = [#12*sin[+#4+#<_incangle>] +#13*cos[+#4+#<_incangle>] + #2]
   #11 = [#11 - #<_precision>] 
   g1 x#14 y#15
 o2003 endwhile (end make other outer gear tooth face)
  o5002 while [#11 lt [#<_hclix>+1.0*0.0000005]]
   #12 = [#<_bigRminus>*cos[#11] + [#<_littler>]*cos[[#<_bigRminus>/#<_littler>]*#11]](hypocycloid equations)
   #13 = [+#<_bigRminus>*sin[#11] - [#<_littler>]*sin[[#<_bigRminus>/#<_littler>]*#11]]
   #14 = [#12*cos[#4+#<_incangle>] -#13*[sin[#4+#<_incangle>]]+#1]
   #15 = [#12*sin[#4+#<_incangle>] +#13*[cos[#4+#<_incangle>]]+#2]
   #11 = [#11 + #<_precision>] 
   g1 x#14 y#15
 o5002 endwhile (end make other inner tooth face)
#23 = [[#<_raddendum>]-#<_fudgeh>]
#25 = [#<_incangle>-#<_fudgewc>]
#22 = [2.0*#3*sin[#25/2.0]]
    o404 if [#<_printflag> eq 1]
(PRINT, base angle=#25degrees,base-thickness=#22",addendum=#<_raddendum>",dedendum=#<_dedendum>",tooth above pitchradius=#23",#samples=#<_gsamples>)
    #<_printflag> = 0
    o404 endif
#<segangle> = [360.0/[#6]] (wholesegment begin tooth gap math)
#32 = [#4+#<segangle>-#<_fudgewc>+1.0*#<_gcoffset>] (next tooth)
#35 = [#32-[ABS[#<_toothangle>]]+#<_fudgewc>+#<_fudgewccw>]
#33 = [[#35+#32]/2.0]
#51 =[2.0*[#3-[#<_dedendum>]]*sin[[#32-#33]]] (length of chord,its half angle)
#52 = [#3-[#<_dedendum>]-[2.0*[#3-[#<_dedendum>]]*[[sin[[#32-#33]/2.0]]**2]]]
;#50=[#52+[#51/2.0]*tan[#<_autooffset>]] (divisor s/b 2.0???)
#50=[#52+[#51/1.5]*tan[#<_autooffset>]]

(uncomment the next 4 lines to use manual undercutting if needed)
;#50=[#3-[#<_dedendum>]-#<_cutterdiam>/6](manual undercut divisor controls)
;o520 if [#5 ne 0.0] (manual undercut for each gear)
 ;#50=[#3-[#<_dedendum>]-+#<_cutterdiam>/2](manual divisor controls undercut)
;o520 endif (manual undercut if you wish, uncomment 4 lines)
(uncomment next 2 lines to see fillet fit, comp must be off)
;g1 x[#1+[[#50]*cos[#33]]] y[#2+[[#50]*sin[#33]]](uncomment these two see fit)
;g1 x[#1+[[#3-[#<_dedendum>]]*cos[#32]]] y[#2+[[#3-[#<_dedendum>]]*sin[#32]]]
g2 x[#1+[[#3-[#<_dedendum>]]*cos[#32]]] y[#2+[[#3-[#<_dedendum>]]*sin[#32]]] i[#1+[[#50]*cos[#33]]] j[#2+[[#50]*sin[#33]]]
o413 endsub

(main: protocol leadin, non-metric Sherline mill assumed)
g17 g20 g40 g49 g54 g80 g90.1 g94
g10 l2 p1 x0 y0 z0 (make axis set 1 be absolute)
;t1 m1 (setup first bit in the tools file,just to have a tool,cutter size is hardcode )
f 100
g0 x0 y0 z0
;(debug, cutter is zeroed, press pause button to proceed)
;m0
#<_ginc> =  -0.00  (used  to incline both gears from center quarterflat hole)
;#<_ginc> =  -0.00  (used  to incline both gears from center quarterflat hole)
o800 while [#<_ginc> lt [+1.0]] (ginc limit)
(gear parameters:)
#<pitchradius> = 2.0
#<numberteeth> = 64 (this must be divisible by ratio without remainder!!)
#<ratio> = [4.000](~1=< #<ratio> < ~8 )
#<gearcenterx> = 2.50 (co-ordinates of gear center)
#<gearcentery> = 2.50 
#<_gcratio> = 1.05(.75 < gcratio <1.03 this s/b 1.0 or very close to 1)
(this setting interacts with pinion undercut setting a lot..)
#<_fudgeh> = [ABS[-0.00]] (lop off the top of a wheel tooth inches,can't add)
#<_fudgewc> = [-asin[0.000/#<pitchradius>]] (clockwise gear face width degrees)
#<_fudgewccw> = [-asin[.000/#<pitchradius>]](parameters beyond this must be 0)
#<_raddendum> = 0
#<_dedendum> = 0
#<_eclix> = 0 (epicycle count, number of steps of precision )
#<_hclix> = 0 (hypocycle count, number of steps of precision )
#<_chkangle> = 0  (must be zero, used for measuring the tooth)
#<_incangle> = 0  (must be zero)
#<_gcoffset> = 0  (angular offset caused by non-unary generating circle)
#<_littler> = 0
#<_bigRplus> = 0
#<_bigRminus> = 0
#<_autooffset> = 0
#<_toothangle> = 0

(machine parameters:)
#<_precision> = 0.400 (degrees, adjust accuracy,.01 and .001 take long)
#<_printflag> = 1
#<_cutterdiam> = [5.0/64.0] (a 5/64 diameter endmill)
#<centerholediam> = [0.30 - 2* #<_cutterdiam>] (A center hole)
#<passesneeded> = 2.0 (this times depth is total milling depth)
#<cuttingdepth> = 0.05 (50 thou, okay for wood plastic, small endmill)
#<cuttingfeed> = 100.0 (for cutting air, 10.0% for al,05.0% steel)

(cut a center hole here without programmed cutter comp)
g0 z 0.25 (retract)
x[#<gearcenterx>-#<centerholediam>/2] y #<gearcentery> 
#302 = 0
o100 while  [#302 lt #<passesneeded>]
 #302 = [#302 + 1]
 g1 f#<cuttingfeed> z [0.0 - #302*#<cuttingdepth>] (plunge)
 g1 x[#<gearcenterx>] y[#<gearcentery>+#<centerholediam>/2.0]
 g2 x[#<gearcenterx>-#<centerholediam>/2]y#<gearcentery> i [#<gearcenterx>] j [#<gearcentery>]
o100 endwhile
#<_printflag> = 1.0
(setup globals for "wheel" cutting)
#<compass_point> = 0 (setup first gear or wheel)
o412 call [#<gearcenterx>][#<gearcentery>][#<pitchradius>][#<compass_point>][0][#<numberteeth>][0][0][0][#<ratio>]
g0 z 0.25
g0 x #<gearcenterx> y #<gearcentery>
;g42.1 D [#<_cutterdiam>/2.0] (uncomment this comp line before milling first gear)
g1 x[#<gearcenterx>+[#<pitchradius>-#<_dedendum>]*cos[+#<_ginc>-#<_fudgewc>+#<_gcoffset>]] y [#<gearcentery>+[#<pitchradius>-#<_dedendum>]*sin[+#<_ginc>-#<_fudgewc>+#<_gcoffset>]]
#<plunger> = [360.0 +#<_ginc>]
#302 = 1
g1 f#<cuttingfeed> z [0.0 - #302*#<cuttingdepth>] (plunge)
#<compass_point> = [0.0 + #<_ginc>]
o3001 while [#<compass_point> le [#<_ginc>+#<passesneeded>*[360.0]+180.0/#<numberteeth>]]
o413 call [#<gearcenterx>][#<gearcentery>][#<pitchradius>][#<compass_point>][0][#<numberteeth>][0][0][0][#<ratio>](first gear here)
#<segangle> = [360.0/[#<numberteeth>]] (wholesegment)
#<compass_point> = [#<compass_point>+[360.0/[#<numberteeth>]]]
o301 if  [[#<compass_point> ge #<plunger>] and [#302 lt #<passesneeded>]]
 #302 = [#302 + 1]
 g1 f#<cuttingfeed> z [0.0 - #302*#<cuttingdepth>] (plunge)
 #<plunger>=[#<plunger>+360.00]
o301 endif
o3001 endwhile
g40 (turn off compensation after cutting/comping first gear)
g0 z 0.25
(draw a reference circle above the gear at the pitch radius)
g0 x [#<gearcenterx>-#<pitchradius>] y[#<gearcentery>]
;g2 i [#<gearcenterx>] j [#<gearcentery>]
#<ppitchradius> = [[#<pitchradius>]/#<ratio>]
(PRINT, radii:#<pitchradius>,#<ppitchradius>)
#<gearcenterx> =[#<gearcenterx>+#<ppitchradius>+#<pitchradius>+0.0*#<_cutterdiam>](make this 4.0*cutterdiam here to cut/comp both gears comp offset)
(print, pinion cntr:#<gearcenterx>,#<gearcentery>)
#<_fudgeh> = [ABS[0.060]] (pinion fudges,lop off pinion tooth top)
#<_fudgewc> = [-asin[.000/#<ppitchradius>]] 
#<_fudgewccw> = [-asin[.000/#<ppitchradius>]]
#<pnumberteeth>= [#<numberteeth>/#<ratio>]
;#<centerholediam> = [0.180 - 2* #<_cutterdiam>] (A second gear center hole)
#<_incangle> = 0.0
(cut a pinion gear center hole here without cutter comp)
#<_printflag>=1
g0 z 0.25 (retract)
x[#<gearcenterx>-#<centerholediam>/2] y #<gearcentery> 
#302 = 0
o200 while  [#302 lt #<passesneeded>]
 #302 = [#302 + 1]
 g1 f#<cuttingfeed> z [0.0 - #302*#<cuttingdepth>] (plunge)
 g1 x[#<gearcenterx>] y[#<gearcentery>+#<centerholediam>/2.0]
 g2 x[#<gearcenterx>-#<centerholediam>/2]y#<gearcentery> i [#<gearcenterx>] j [#<gearcentery>]
o200 endwhile
(second gear or pinion)
o412 call [#<gearcenterx>][#<gearcentery>][#<ppitchradius>][0][#<pitchradius>][#<pnumberteeth>][0][0][0][#<ratio>]
g0 z 0.25
g0 x #<gearcenterx> y #<gearcentery>
;g42.1 D [#<_cutterdiam>/2.0] ( uncomment this cutter comp line pinion)
g1 x[#<gearcenterx>+[#<ppitchradius>-#<_dedendum>]*cos[180.0-#<_ginc>*#<ratio>+#<_gcoffset>-#<_fudgewc>]] y [#<gearcentery>+[#<ppitchradius>-#<_dedendum>]*sin[180.0-#<_ginc>*#<ratio>+#<_gcoffset>-#<_fudgewc>]]
#302 = 1.0
g1 f#<cuttingfeed> z [0.0 - #302*#<cuttingdepth>] (plunge)
#<plunger>=[180.0-#<_ginc>*#<ratio>+360.0]
g1 f#<cuttingfeed> z [0.0 - #302*#<cuttingdepth>] (plunge)
#<compass_point> = [[180.0]-#<_ginc>*#<ratio>]
o4001 while [#<compass_point> le [180.0-#<_ginc>*#<ratio>+#<passesneeded>*360.0+180/#<pnumberteeth>]]
o413 call [#<gearcenterx>][#<gearcentery>][#<ppitchradius>][#<compass_point>][#<pitchradius>][#<pnumberteeth>][0][0][0][#<ratio>] (pinion cutting)
#<compass_point> = [#<compass_point>+[360.0/[#<pnumberteeth>]]]
o401 if  [[#<compass_point> ge #<plunger>] and [#302 lt #<passesneeded>]]
 #302 = [#302 + 1]
 #<plunger>=[#<plunger>+360.00]
 g1 f#<cuttingfeed> z [0.0 - #302*#<cuttingdepth>] (plunge)
o401 endif
o4001 endwhile
g40 (shut off compensation for pinion)
g0 z 0.25
(draw a reference circle above the pinion @ pitchradius)
g0 x [#<gearcenterx>-[#<ppitchradius>]] y[#<gearcentery>]
;g2 i [#<gearcenterx>] j [#<gearcentery>]
 #<_ginc> = [#<_ginc> + 2.50] (ginc offset each pass)
o800 endwhile
g0 x0 y0
m2
%

3.9. Sample 9 -- rack and pinion program

31 March 2014: rack teeth need a top roundover, but I may not get to it for awhile


%
(rack program: set variables pressure angle, base radius, )
(number of teeth, program figures out what to use for a gear specifics)
("prints" involute tooth parameters and mills the gear & rack)
(linuxcnc must be started from within a terminal window,)
(/usr/bin/linuxcnc '/home/you/linuxcnc/configs/axis/sim/axis.ini')
(entered on a terminal prompt, the value in ''is the path to your .ini)
(one gear and one rack are displayed)
(Joseph Peitz )

(After adjusting parameters, and before milling, uncomment cutter comp lines)
(and compoffset, make sure the program still runs error free)

o413 sub
(this subroutine draws one whole gear tooth with cap if it fits and one gap)
(first is x,2nd is y third parm is baseradius 4th is compass,5th pitch)
(6th is numberteeth,7=diametralpitch, 9 is pangle,10th is 1.0)
#11= 4.00(hardcode, this may need to change if you change undercutting)
 #18 = 0.0 (18&20 used to track surface samples)
 #20 = 0.0
 #<inva>= 0.0
 o515 if [#<_raddendum> eq 0]
 o514 if [#7 eq 0] (if diametral pitch is zero,get addendum from pa)
 #<_raddendum>=[#3*[1/cos[#9]-1]] (compute raddendum from pa)
 o514 else
  #3=[[cos[#9]*#6]/[#7*2.0]] (compute a new base and raddendum from dp)
  #<_raddendum>=[#3*[1/cos[#9]-1]]
 o514 endif
 #96 = [2.0*#<_raddendum>+#<_fudgeh>]
 o515 endif
   #80 = [[#11]/57.2957779] (degrees and radians!!!)
   #16 = [#3*[cos[#11] + #80*sin[#11]]](involute equations)
   #17 = [#3*[sin[#11] - #80*cos[#11]]]
   #12 = #16
   #13 = #17
   #14 = #1
   #15 = #2
   #54 = [#3+2.0*#<_raddendum>+#<_fudgeh>]
 o1001 while [[SQRT[[#14-#1]**2+[#15-#2]**2]]lt[#54]]
   #80 = [[#11]/57.2957779] (degrees and radians!!!)
   #12 = [#3*[cos[#11] + #80*sin[#11]]](involute equations)
   #13 = [#3*[sin[#11] - #80*cos[#11]]]
   #14 = [#12*cos[#4-#<_fudgewc>] -#13*[sin[#4-#<_fudgewc>]]+#1]
   #15 = [#12*sin[#4-#<_fudgewc>] +#13*[cos[#4-#<_fudgewc>]]+#2]
   #18 = [#18 + 1]
   o510 if [[SQRT[[#12]**2+[#13]**2]]lt[#3+#<_raddendum>]]
     #<inva> = [[atan[#13]/[#12]]]
     #<_incangle> = [[360.0/[2.0*#6]]+2.0*#<inva>+#<_fudgewccw>]
   o510 endif
   o5008 if [[atan[#13]/[#12]] ge [#<_incangle>/2.0]]
    (Save the total distance above baseradius)
     #96 = [[[SQRT[[#12]**2+[#13]**2]]-#3]]
     ;(PRINT, gotta break,#96,#<_raddendum>)
     o1001 break
   o5008 endif
   #11 = [#11 + #<_precision>] 
   g1 x#14 y#15
 o1001 endwhile (end make ccw active gear face)
  #<_gsamples> = #18
   #<native> = [atan[#13]/[#12]] (angular width of one face)
    o511 if[#<native> gt [[360/[2.0*#6]]]]
     (PRINT,program error,can't fit full teeth:bad pressure angle?)
    o511 endif
   #30 = 0
   #55 = 1000.0 (roundover control for gear)
   (raddendum is just a bit different here when pressure angle is big)
   #54 = [#3+#96+#<_cutterdiam>/3]
   o5001 while [[SQRT[[#12]**2+[#13]**2]]lt[#54]]
    #80 = [[#11]/57.2957779]
    #12 = [#3*[cos[#11] + #80*sin[#11]]](involute equations)
    #13 = [#3*[sin[#11] - #80*cos[#11]]]
    #31 = [#6*[#30]*[#30/#55]*[atan[#<_cutterdiam>]/[#3]]*[1/60.0] +#4]
    #14 = [#12*[cos[#31-#<_fudgewc>]] -#13*[sin[#31-#<_fudgewc>]]+#1]
    #15 = [#12*[sin[#31-#<_fudgewc>]] +#13*[cos[#31-#<_fudgewc>]]+#2]
    #89 = [ABS[[atan[#15-#2]/[#14-#1]-[+#<_ginc>]]MOD[180.0/#6]]]
    o5007 if [#89 gt [#<_incangle>/2]]
      ;(PRINT, hit a cap break,#<_incangle>,#89,#30)
      o5001 break
    o5007 endif
     #11 = [#11 + #<_precision>]
     #30 = [#30+1.0]
     g1 x#14 y#15 
   o5001 endwhile  (end make ccw cap)
   #11 = [#11 -1.0* #<_precision>]
   #30 = [#30-1.0] 
   #86 = [[SQRT[[[#15-#2]**2]+[[#14-#1]**2]]]-#3] (compute height above baseradius) (this is actually one involute click bigger than real)
   o5005 while [#30 ge 0.0]
     #80 = [[#11]/57.2957779]
     #12 = [#3*[cos[#11] + #80*sin[#11]]]
     #13 = [#3*[-sin[#11] + #80*cos[#11]]]
     #31 = [-#6*[#30]*[#30/#55]*[atan[#<_cutterdiam>]/[#3]/60.0] +#4+#<_incangle>]
     #14 = [#12*cos[#31] -#13*[sin[#31]]+#1]
     #15 = [#12*sin[#31] +#13*[cos[#31]]+#2]
     #11 = [#11-#<_precision>]
     #30 = [#30-1.0]
     g1 x#14 y#15
   o5005 endwhile (end make cw cap)
  #20 = 0
  o2003 while [#11 gt 4.00] (4.0 reduces cutter comp problems???)
   #80 = [[#11]/57.2957779]
   #12 = [#3*[cos[#11] + #80*sin[#11]]]
   #13 = [#3*[-sin[#11] + #80*cos[#11]]]
   #14 = [#12*cos[+#4+#<_incangle>] -#13*sin[+#4+#<_incangle>] + #1]
   #15 = [#12*sin[+#4+#<_incangle>] +#13*cos[+#4+#<_incangle>] + #2]
   #20 = [#20 + 1]
   #11 = [#11 - #<_precision>] 
   g1 x#14 y#15
 o2003 endwhile (end make cw face)
   #14 = [#3*cos[+#4+#<_incangle>] + #1]
   #15 = [#3*sin[+#4+#<_incangle>] + #2]
   g1 x#14 y#15
     #<_endangle> = [#<_incangle>]
     #<_chkangle> = [#<_endangle>-2.0*#<inva>]
#23 = [2*#<_raddendum>+#<_fudgeh>]
#24 = [#6/[2.0* [#3 + #<_raddendum>]]]
#25 = [#<_endangle>+#<_fudgewc>]
#26 = [#<_chkangle>+#<_fudgewc>]
#21 = [2.0*[#3+#<_raddendum>]*sin[#26/2.0]]
#22 = [2.0*#3*sin[#25/2.0]]
    o404 if [#<_printflag> eq 1]
(PRINT, base angle=#25degrees,pitch angle=#26degrees,base-thickness=#22",pitch-thick=#21",addendum=#<_raddendum>",active tooth above baseradius=#23",diametral pitch=#24,#samples=#<_gsamples>,faceangle=#<native>degrees,total tooth above baseradius=#86)
    #<_printflag> = 0
    o404 endif
 #34 = #3 (return the value for baseradius just in case we used dp)
 #35 = #24 (return dp too)
(end of make one tooth, begin some math for the tooth gap)
#<segangle> = [360.0/[#6]] (wholesegment)
#32 = [#4+#<segangle>-#<_fudgewc>] (next tooth)
#33 = [#32-[[#<segangle>-#<_endangle>-#<_fudgewc>]/2.0]](midpoint to next tooth)
#40 = [#3-#<_cutterdiam>/2.0]
o501 if [[[#6] gt 6]or[SQRT[[[#40*cos[#33]]**2]+[[#40*sin[#33]]**2]]lt[1.6*#<_cutterdiam>]]](use different gullet for small pinions)
#50=[#3-#<_cutterdiam>/6](cutterdiam divisor controls undercut)
g2 x[#1+[#3*cos[#32]]] y[#2+[#3*sin[#32]]] i[#1+[[#50]*cos[#33]]] j[#2+[[#50]*sin[#33]]]
o501 else
#49 = [#<_cutterdiam>+#<_cutterdiam>/6] (cutterdiam divisor controls undercut)
#45 = [asin[[+#49]/[#3*2]]](jog angle)
#46 = [#32-[#<segangle>-#<_endangle>-#<_fudgewc>]](start here)
#47 = [#46+#<segangle>]
#48 = [#3-#3*cos[#45]] (fillet center located inboard of base radius)
g2 x[#1+[[#3-#48-#49/2]*cos[#46+#45]]] y[#2+[[#3-#48-#49/2.0]*sin[#46+#45]]] i [#1 +[[#3-#48] *cos[#46+#45]]] j[#2 +[[#3-#48]*sin[#46+#45]]]
g3 x[#1+[[#3-#48-#49/2.0]*cos[#32-#45]]] y[#2+[[#3-#48-#49/2.0]*sin[#32-#45]]] i [#1] j[#2]
g2 x[#1+[#3]*cos[#32]] y[#2+[#3]*sin[#32]] i [#1 +[[#3-#48]*cos[#32-#45]]] j[#2 +[#3-#48]*sin[#32-#45]]
o501 endif
o413 endsub

(main: protocol leadin, non-metric Sherline mill assumed)
g17 g20 g40 g49 g54 g80 g90.1 g94
g10 l2 p1 x0 y0 z0 (make axis set 1 be absolute)
;t1 m1 (first mill in the tools file not used)
f 100
g0 x0 y0 z0
;(debug, cutter is zeroed, press pause button to proceed)
;m0
#<racktoothlength>=0 (initialize this outside the main while)

#<_ginc>=-4.5900  (degrees of gear rotation, movement of rack)
o800 while [#<_ginc> lt [-4.0]]
(gear parameters:)
#<pressangle> = 14.50000 (std are 14.5,20,25)
#<baseradius> = 0.900000 (.9,14.5,5/64,50 comps ok)
#<numberteeth> = 50
#<nrackteeth> = 40 
#<rackthick> = .5 (rack thickness between base of teeth and rack bottom)
(length of rack is dependent on nrackteeth, total rack height is twice)
(pinion addendum + rackthick, dimensions are displayed in consolewin)
#<_fudgeh> = -0.000 (adjust top, must be less than addendum,inches first gear)
#<_fudgewc> = +0.000 (adjust the clockwise gear face width degrees)
#<_fudgewccw> = -0.000 (adjust the counter clockwise gear facewidth degrees)
#<gearcenterx> = [1.00+#<racktoothlength>] (co-ordinates of gear center)
#<gearcentery> = 1.00(parameters beyond this are computed by the code)
#<_raddendum> = 0 (must be zero, outer radius - pitch radius)
#<pitchradius>=0  (must be zero, this becomes baseradius + addendum)
#<_chkangle> = 0  (must be zero, used for measuring the tooth)
#<_endangle> = 0  (must be zero)
#<_incangle> = 0  (must be zero)
#<diametralpitch> = 0
#<_precision> = 0.200 (adjust accuracy,.01 and .001 take long)
#<_printflag> = 1

(machine parameters:)
#<_cutterdiam> = [5.0/64.0] (a 5/64 diameter endmill)
;#<centerholediam> = [0.50 - 2* #<_cutterdiam>] (A center hole)
#<centerholediam> = [0.25 ] (A center hole without comp)
#<passesneeded> = 2.0
#<cuttingdepth> = 0.05 (50 thou, okay for wood plastic, small endmill)
#<cuttingfeed> = 100.0 (for cutting air, 10.0% for al,05.0% steel)
#<compoffset> = [0.0*#<_cutterdiam>] (displace gear to allow cutter through)

(cut a center hole here without cutter comp)
g0 z 0.25 (retract)
x[#<gearcenterx>-#<centerholediam>/2] y [#<gearcentery>+#<compoffset>]
#302 = 0
o100 while  [#302 lt #<passesneeded>]
#302 = [#302 + 1]
g1 f#<cuttingfeed> z [0.0 - #302*#<cuttingdepth>] (plunge)
g1 x[#<gearcenterx>] y[#<gearcentery>+#<centerholediam>/2.0+#<compoffset>]
g2 x[#<gearcenterx>-#<centerholediam>/2]y[#<gearcentery>+#<compoffset>] i [#<gearcenterx>] j [#<gearcentery>+#<compoffset>]
o100 endwhile
g0 z 0.25

(draw a reference circle above the part at the base radius)
;g0 x [#<gearcenterx>-#<baseradius>] y[#<gearcentery>+#<compoffset>]
;g2 i [#<gearcenterx>] j [#<gearcentery>]

g0 x [#<gearcenterx>] y[#<gearcentery>+#<compoffset>]
;g42.1 D [#<_cutterdiam>/2.0] (uncomment this cutter comp line before milling)
g1 x[#<gearcenterx>+[#<baseradius>]*cos[+#<_ginc>+270.0]] y [#<gearcentery>+[#<baseradius>]*sin[+#<_ginc>+270.0]+#<compoffset>]
#<plunger> = [360.0 +#<_ginc>]
#302 = 0
o301 while  [#302 lt #<passesneeded>]
#302 = [#302 + 1]
g1 f#<cuttingfeed> z [0.0 - #302*#<cuttingdepth>] (plunge)
#<compass_point> = [270.0 + #<_ginc>]
o3001 while [#<compass_point> lt [630.0 +#<_ginc>-180.0/#<numberteeth>]]

(cut one gear tooth here, lots of unused parameters here, sorry)
o413 call [#<gearcenterx>][#<gearcentery>+#<compoffset>][#<baseradius>][#<compass_point>][#<pitchradius>-#<_raddendum>][#<numberteeth>][0][#<pitchradius>+#<_raddendum>] [#<pressangle>][1.0]
#<pitchradius> = [#<baseradius> + #<_raddendum>]
#<compass_point> = [#<compass_point>+[360.0/[#<numberteeth>]]]
o3001 endwhile
o301 endwhile
g40 (turn off compensation after cutting/comping one gear)
g0 z 0.25
(draw a reference circle above the part at the pitch radius)
;g0 x [#<gearcenterx>-#<baseradius>-#<_raddendum>] y[#<gearcentery>+#<compoffset>]
;g2 i [#<gearcenterx>] j [#<gearcentery>+#<compoffset>]

(cut a rack here )
g0 x [#<gearcenterx>] y[#<gearcentery>+#<compoffset>]
#<_fudgeh> = [ABS[0.000]] (adjust rack tooth height,less than addendum,inches)
#<basefudge> = +0.000 (adjust rack tooth base thickness inches)
#<_printflag>=1
g0 z 0.25 (retract)
#302 = 0
#23=[#<baseradius>+2.0*#<_raddendum>]
(arc length is radius*pi/180.0*degrees, hence the .01745...)
#24=[[#<pitchradius>]*[#<_endangle>-#<_chkangle>]/2.0*0.01745329]
#27=[[2.0*[#<pitchradius>]*sin[#<_chkangle>/2.0]]-2.0*#<_raddendum>*[tan[#<pressangle>]]](gullet length)
#92=[[2.0*[#<pitchradius>]*sin[#<_chkangle>/2.0]]]
;#27=[[+#<pitchradius>*#<_chkangle>*0.01745329]-2.0*#<_raddendum>*[tan[#<pressangle>]]] (this is an approximation,.004 makes a sloppy rack)
#27=[#27+#<basefudge>]
#26=[[#<pitchradius>]*360/#<numberteeth>*0.01745329](arc length)
#28=[[2.0*#<_raddendum>]*tan[#<pressangle>]](x due to facelength no fudgeh allowed)
#60=[[#<_fudgeh>]*tan[#<pressangle>]](x due to fudgeheight)
#29=[#26-#27-2.0*#28] (length of toothtop)
#90=[#<nrackteeth>*#26+#26](length of whole rack)
#91=[#29+2.0*#28](rack toothe thickness at pitch point)
(PRINT, rack is #90"long,gaplength:#27,tooththick:#91contact thick:#92)
#<tempcenterx>= [#<gearcenterx>-2.0*[#26]+[#<pitchradius>]*[#<_ginc>]*0.01745329+1.0*#24+ #<_raddendum>*tan[#<pressangle>]-#<basefudge>/2]
#<rackend>=#<tempcenterx>
g0 x[#<tempcenterx>-2.0*#29]y[#<gearcentery>-#23]
;g41.1 D [#<_cutterdiam>/2.0] ( uncomment this cutter comp line 2nd gear)
g1 x[#<tempcenterx>-1.0*#29]y[#<gearcentery>-#23]
o401 while  [#302 lt #<passesneeded>]
#302 = [#302 + 1]
#<tempcenterx>=#<rackend>
#<rackteeth>= 0
g1 f#<cuttingfeed> z [0.0 - #302*#<cuttingdepth>] (plunge)
o4001 while [#<rackteeth> lt #<nrackteeth>]
g1 x[#<tempcenterx>]y[#<gearcentery>-#23]
g3 x[#<tempcenterx>+#27]y[#<gearcentery>-#23]i[#<tempcenterx>+#27/2.0] j[#<gearcentery>-#23]
g1 x[#<tempcenterx>+#27+#28-#60]y[#<gearcentery>-#<baseradius>-#<_fudgeh>](face)
g1 x[#<tempcenterx>+#27+#28+#29+#60]y[#<gearcentery>-#<baseradius>-#<_fudgeh>](top1)
g1 x[#<tempcenterx>+#27+#29+2.0*#28]y[#<gearcentery>-#23]
#30= [[#27+2*#28+#29]]
#<tempcenterx> = [#<tempcenterx> + #27+#29+2.0*#28]
#<rackteeth> = [#<rackteeth>+1]
o4001 endwhile
g1 y[#<gearcentery>-#23-#<rackthick>]
x[#<rackend>-1.0*#29]
g1 y[#<gearcentery>-#23]
o401 endwhile
g0 z 0.25 (retract)
g40
 #<_ginc> = [#<_ginc> + 7.5]
;#<racktoothlength>=[#<racktoothlength>+#26]
o800 endwhile

g0 x0 y0
m2
%

3.10. Sample 10 -- ring and pinion program

16 April 2014: ring teeth need a bottom roundover, but I may not get to it for awhile 30 Nov 2014: added ring roundover and facility to shorten ring teeth from the "bottom"

%
(ring and pinion program set variables pressure angle, base radius, )
(number of teeth,ratio, program figures out what to use for a gear specifics)
("prints" involute tooth parameters and mills the ring and pinion meshed)
(linuxcnc must be started from within a terminal window,)
(/usr/bin/linuxcnc '/home/you/linuxcnc/configs/axis/sim/axis.ini')
(entered on a terminal prompt, the value in ''is the path to your .ini)
(After adjusting parameters, and before milling, uncomment cutter comp lines,)
(adjust comp offset, set variable #<_ginc> for desired beginning offset and)
(Joseph Peitz, begun 5 Apr 2014)
(added feature to clip ring teeth, and roundover {or not} 7 Nov 2014 )

o413 sub (make one involute pinion tooth{with cap} and one gap)
(first is x,2nd is y third parm is baseradius 4th is compass,5th pitch)
(6th is numberteeth,7=0, 9 is pangle,10th is ratio)
#11= 0.00(hardcode the first value of our involute,0 may interfere undercut)
 #18 = 0.0 (18&20  is used to track surface samples)
 #20 = 0.0
 #<inva>= 0.0
 o515 if [#<_raddendum> eq 0]
 o514 if [#7 eq 0] (if diametral pitch is zero,get addendum from pa)
 #<_raddendum>=[#3*[1/cos[#9]-1]] (compute raddendum from pa)
 o514 else
  #3=[[cos[#9]*#6]/[#7*2.0]] (compute a new base and raddendum from dp)
  #<_raddendum>=[#3*[1/cos[#9]-1]]
 o514 endif
 #96 = [2.0*#<_raddendum>+#<_fudgeh>]
 o515 endif
   #12 = #3
   #13 = 0
   #54 = [#3+2.0*#<_raddendum>+#<_fudgeh>]
 o1001 while [[SQRT[[#12]**2+[#13]**2]]lt[#54]]
   #11 = [#11 + #<_precision>] 
   #80 = [[#11]/57.2957779] (degrees and radians!!!)
   #12 = [#3*[cos[#11] + #80*sin[#11]]](involute equations)
   #13 = [#3*[sin[#11] - #80*cos[#11]]]
   #14 = [#12*cos[#4-#<_fudgewc>] -#13*[sin[#4-#<_fudgewc>]]+#1]
   #15 = [#12*sin[#4-#<_fudgewc>] +#13*[cos[#4-#<_fudgewc>]]+#2]
   #18 = [#18 + 1]
   g1 x#14 y#15
   o510 if [[SQRT[[#12]**2+[#13]**2]]gt[#3+#<_raddendum>]AND[#<inva>eq 0.0]]
   #16 = #11
   o1002 while [[SQRT[[#12]**2+[#13]**2]]gt[#3+#<_raddendum>]]
     #80 = [[#11]/57.2957779] 
     #12 = [#3*[cos[#11] + #80*sin[#11]]]
     #13 = [#3*[sin[#11] - #80*cos[#11]]]
     #11 = [#11 - .005]
    o1002 endwhile
    o1003 while [[SQRT[[#12]**2+[#13]**2]]lt[#3+#<_raddendum>]]
     #80 = [[#11]/57.2957779]
     #12 = [#3*[cos[#11] + #80*sin[#11]]]
     #13 = [#3*[sin[#11] - #80*cos[#11]]]
     #11 = [#11 + .000050] 
    o1003 endwhile
    o1004 while [[SQRT[[#12]**2+[#13]**2]]gt[#3+#<_raddendum>]]
     #80 = [[#11]/57.2957779]
     #12 = [#3*[cos[#11] + #80*sin[#11]]]
     #13 = [#3*[sin[#11] - #80*cos[#11]]]
     #11 = [#11 - .0000001]
    o1004 endwhile
     #<inva> = [[atan[#13]/[#12]]]
     #<_incangle> = [[360.0/[2.0*#6]]+2.0*#<inva>+#<_fudgewccw>]
     #11 = #16
   o510 endif
 o1001 endwhile 
  #<_gsamples> = #18
   #<_native> = [atan[#13]/[#12]] (angular width of one face)
    o511 if[#<_native> gt [[360/[2.0*#6]]]]
     (PRINT,program error,can't fit full teeth:bad pressure angle?)
    o511 endif (error checking is still tbd...)
   #30 = 0
   #<_gincscale>=#<_ginc> (adjustment for pinion)
   #55 = 10.0 (roundover control for pinion)
   #54 = [#3+#96+#<_cutterdiam>/3]
   o5001 while [[SQRT[[#12]**2+[#13]**2]]lt[#54]]
    #80 = [[#11]/57.2957779]
    #12 = [#3*[cos[#11] + #80*sin[#11]]](involute equations)
    #13 = [#3*[sin[#11] - #80*cos[#11]]]
    #31 = [#6*[#30]*[#30/#55]*[atan[#<_cutterdiam>]/[#3]]*[1/60.0] +#4]
    #14 = [#12*cos[#31-#<_fudgewc>] -#13*[sin[#31-#<_fudgewc>]]+#1]
    #15 = [#12*sin[#31-#<_fudgewc>] +#13*[cos[#31-#<_fudgewc>]]+#2]
    #89 = [ABS[[atan[#15-#2]/[#14-#1]-[+#<_gincscale>]]MOD[180.0/#6]]]
    o5007 if [[#89] gt [#<_incangle>/2]]
      ;(PRINT, hit a cap break,#89,#30)
      o5001 break (this is a normal exit here)
    o5007 endif
     #11 = [#11 + #<_precision>]
     #30 = [#30+1.0]
     g1 x#14 y#15 
   o5001 endwhile  (end make pinion cw cap)
   #11 = [#11 -1.0* #<_precision>]
   #30 = [#30-1.0] 
   #86 = [[SQRT[[[#15-#2]**2]+[[#14-#1]**2]]]-#3] (height above baseradius) 
   o5005 while [#30 ge 0.0]
     #80 = [[#11]/57.2957779]
     #12 = [#3*[cos[#11] + #80*sin[#11]]]
     #13 = [#3*[-sin[#11] + #80*cos[#11]]]
     #31 = [-#6*[#30]*[#30/#55]*[atan[#<_cutterdiam>]/[#3]/60.0] +#4+#<_incangle>]
     #14 = [#12*cos[#31] -#13*[sin[#31]]+#1]
     #15 = [#12*sin[#31] +#13*[cos[#31]]+#2]
     #11 = [#11-#<_precision>]
     #30 = [#30-1.0]
     g1 x#14 y#15
   o5005 endwhile (end make pinion ccw cap)
  #20 = 0
  o2003 while [#11 ge 0.00] 
   #80 = [[#11]/57.2957779]
   #12 = [#3*[cos[#11] + #80*sin[#11]]]
   #13 = [#3*[-sin[#11] + #80*cos[#11]]]
   #14 = [#12*cos[+#4+#<_incangle>] -#13*sin[+#4+#<_incangle>] + #1]
   #15 = [#12*sin[+#4+#<_incangle>] +#13*cos[+#4+#<_incangle>] + #2]
   #20 = [#20 + 1]
   #11 = [#11 - #<_precision>] 
   g1 x#14 y#15
 o2003 endwhile (end make pinion ccw face)
   ;#14 = [#3*cos[+#4+#<_incangle>] + #1]
   ;#15 = [#3*sin[+#4+#<_incangle>] + #2]
   ;g1 x#14 y#15
     #<_endangle> = [#<_incangle>]
     #<_chkangle> = [#<_endangle>-2.0*#<inva>]
#23 = [2*#<_raddendum>+#<_fudgeh>]
#24 = [#6/[2.0* [#3 + #<_raddendum>]]]
#25 = [#<_endangle>+#<_fudgewc>] 
#26 = [#<_chkangle>+#<_fudgewc>] 
#21 = [2.0*[#3+#<_raddendum>]*sin[#26/2.0]]
#22 = [2.0*#3*sin[#25/2.0]]
   o550 if [#<_rinclen> eq 0]
      #<_rinclen>=[2.0*#3*sin[[#<_incangle>-#<_fudgewccw>]/2.0]]
   o550 endif
    o404 if [#<_printflag> eq 1]
(PRINT, base angle=#25degrees,base-thickness=#22",pitch-thick=#21",addendum=#<_raddendum>",active tooth above baseradius=#23",diametral pitch=#24,#samples=#<_gsamples>,faceangle=#<_native>degrees,total tooth above baseradius=#86)
    #<_printflag> = 0
    o404 endif
(end of make one pinion tooth, begin some math for the tooth gap)
#<segangle> = [360.0/[#6]] (wholesegment)
#32 = [#4+#<segangle>-#<_fudgewc>] (next tooth)
#33 = [#32-[[#<segangle>-#<_endangle>-#<_fudgewc>]/2.0]](midpoint to next tooth)
#40 = [#3-#<_cutterdiam>/2.0]
#50=[#3-#<_cutterdiam>/6](cutterdiam divisor controls undercut)
g2 x[#1+[#3*cos[#32]]] y[#2+[#3*sin[#32]]] i[#1+[[#50]*cos[#33]]] j[#2+[[#50]*sin[#33]]]
o413 endsub

o414 sub (this subroutine sets up ringclix and fudged for use by others)
 #11 = 0
 #12 = #3
 #13 = 0
 o541 while [[SQRT[[#12]**2+[#13]**2]]lt[#3+#<_fudged>]]
   #80 = [[#11]/57.2957779] (degrees and radians!!!)
   #12 = [#3*[cos[#11] + #80*sin[#11]]](involute equations)
   #13 = [#3*[sin[#11] - #80*cos[#11]]]
   #11 = [#11 + #<_precision>]
 o541 endwhile
 o542 while [[SQRT[[#12]**2+[#13]**2]]gt[#3+#<_fudged>]]
   #80 = [[#11]/57.2957779] 
   #12 = [#3*[cos[#11] + #80*sin[#11]]]
   #13 = [#3*[sin[#11] - #80*cos[#11]]]
   #11 = [#11 - 0.005]
 o542 endwhile
 o543 while [[SQRT[[#12]**2+[#13]**2]]lt[#3+#<_fudged>]]
   #80 = [[#11]/57.2957779] 
   #12 = [#3*[cos[#11] + #80*sin[#11]]]
   #13 = [#3*[sin[#11] - #80*cos[#11]]]
   #11 = [#11 + 0.00001]
 o543 endwhile
#80 = [[#11]/57.2957779]
#12 = [#3*[cos[#11] + #80*sin[#11]]]
#13 = [#3*[sin[#11] - #80*cos[#11]]]
   #<_fudged> = [SQRT[[#12]**2+[#13]**2] -#3] (quantize fudged)
   #<_ffoffset> = [atan[#13]/[#12]] (the offset generted by fudged)
   #<_nextxbottom> = [#12*cos[#4-#<_fudgewc>] -#13*[sin[#4-#<_fudgewc>]]+#1]
   #<_nextybottom> = [#12*sin[#4-#<_fudgewc>] +#13*[cos[#4-#<_fudgewc>]]+#2]
   #<_ringclix> = [#11] (save the last value for doing the face)
o414 endsub

o415 sub (make one involute ring gear "pinion toothhole" and its gap here)
   #11 = #<_ringclix> 
   #18 = 0
   #20 = 0
   #12 = #3
   #13 = 0
   #54 = [#3+2.0*#<_raddendum>]
 o2009 while [[SQRT[[#12]**2+[#13]**2]]le[#54]] (wow bug here)
   #11 = [#11 + #<_precision>] 
   #80 = [[#11]/57.2957779] 
   #12 = [#3*[cos[#11] + #80*sin[#11]]]
   #13 = [#3*[sin[#11] - #80*cos[#11]]]
   #14 = [#12*cos[#4-#<_fudgewc>] -#13*[sin[#4-#<_fudgewc>]]+#1]
   #15 = [#12*sin[#4-#<_fudgewc>] +#13*[cos[#4-#<_fudgewc>]]+#2]
   #18 = [#18 + 1]
   o5008 if [[atan[#13]/[#12]] gt [#<_incangle>/2.0]]
     #96 = [[#3-[SQRT[[#12]**2+[#13]**2]]]]
     (PRINT, gotta break,#96,#<_raddendum>)
     ;o1001 break (error handling ?)
   o5008 endif
   g1 x#14 y#15
   #86 = #14
   #87 = #15
 o2009 endwhile (end make cw active ring gear face here!!)
 #<_rrincangle> = [asin[#<_rinclen>/#3]+#<_fudgewccw> ]
  #80 = [[#11]/57.2957779] 
  #12 = [#3*[cos[#11] + #80*sin[#11]]]
  #13 = [#3*[sin[#11] - #80*cos[#11]]]
  #14 = [#12*cos[#4-#<_fudgewc>] -#13*[sin[#4-#<_fudgewc>]]+#1]
  #15 = [#12*sin[#4-#<_fudgewc>] +#13*[cos[#4-#<_fudgewc>]]+#2]
  g1 x#14 y#15
  #86 = #14
  #87 = #15
   #12 = [#3*[cos[#11] + #80*sin[#11]]] (other ring face here)
   #13 = [#3*[-sin[#11] + #80*cos[#11]]]
   #14 = [#12*cos[#4+#<_rrincangle>] -#13*sin[#4+#<_rrincangle>] + #1]
   #15 = [#12*sin[#4+#<_rrincangle>] +#13*cos[#4+#<_rrincangle>] + #2]
   ;g1 x [[#14 + #86]/2.0] y[[#15+#87]/2.0] (uncomment to see fit)
   ;g1 x #14 y #15 (uncomment to see fit)
   g3 x #14 y #15 i[[#14 + #86]/2.0] j[[#15+#87]/2.0]
   #11 = [#11 - #<_precision>] (re-compute all here!!)
  o2008 while [#11 ge #<_ringclix>] 
   #80 = [[#11]/57.2957779]
   #12 = [#3*[cos[#11] + #80*sin[#11]]]
   #13 = [#3*[-sin[#11] + #80*cos[#11]]]
   #14 = [#12*cos[+#4+#<_rrincangle>] -#13*sin[+#4+#<_rrincangle>] + #1]
   #15 = [#12*sin[+#4+#<_rrincangle>] +#13*cos[+#4+#<_rrincangle>] + #2]
   g1 x#14 y#15
   #11 = [#11 - #<_precision>] 
 o2008 endwhile (end make ccw face)
   #80 = [[#11]/57.2957779] 
   #12 = [#3*[cos[#11] + #80*sin[#11]]]
   #13 = [#3*[-sin[#11] + #80*cos[#11]]]
   #14 = [#12*cos[+#4+#<_rrincangle>] -#13*sin[+#4+#<_rrincangle>] + #1]
   #15 = [#12*sin[+#4+#<_rrincangle>] +#13*cos[+#4+#<_rrincangle>] + #2]
   g1 x#14 y#15
   #16 = #14
   #17 = #15
   #80 = [#11/57.2957779] 
   #12 = [#3*[cos[#11] + #80*sin[#11]]]
   #13 = [#3*[sin[#11] - #80*cos[#11]]]
   #14 = [#12*cos[#4-#<_fudgewc>+360/#6] -#13*[sin[#4-#<_fudgewc>+360/#6]]+#1]
   #15 = [#12*sin[#4-#<_fudgewc>+360/#6] +#13*[cos[#4-#<_fudgewc>+360/#6]]+#2]
   #<halfchord> = [SQRT[[#17-#15]**2 + [#16-#14]**2]/2.0]
   ;g1 x #14 y #15 (uncomment this and comment g2 below for flat bottom)
   #152 = [#4+#<_rrincangle>-#<_fudgewc>+[360.0/#6-#<_rrincangle>+1.0*#<_fudgewc>]/2.0]
  o526 if [#<_radoffset> eq -1.0] (only execute this once, ???)
   #<dx> = [#3*[#80*cos[#<_ringclix>]]](x=rcost+rtsint ...we want dy/dx)
   #<dy> = [#3*[#80*sin[#<_ringclix>]]] 
  o519 if [#<dx> ne 0]
   #<deriv> = [atan[#<dy>]/[#<dx>]] (first derivative aka slope)
 o519 else
   #<deriv> = 90.0
 o519 endif
   #<_radoffset> = [+0.0*[#3+#<_fudged>]*[[sin[90/#6]]**2] ] (s/b +0.0* for correct slope, may interfere anyway??? 0-30 work okay)
  o523 if [#<deriv> ne 90.0]
   #<ciroffset> = [180.0-[#<deriv>]]
   #<_radoffset> = [#<_radoffset> + ABS[#<halfchord>*tan[#<ciroffset>]]] 
  o523 endif
  o526 endif
   ;g1 x[#1+[#3+#<_radoffset>+#<_fudged>]*cos[#152]] y[#2+[#3+#<_radoffset>+#<_fudged>]*sin[#152]] (uncomment to see fit)
   ;g1 x #14 y #15 (uncomment to see fit)
   g2 x #14 y #15 i[#1+[#3+#<_radoffset>+#<_fudged>]*cos[#152]] j[#2+[#3+#<_radoffset>+#<_fudged>]*sin[#152]]
o415 endsub

(main: protocol leadin, non-metric Sherline mill assumed)
g17 g20 g40 g49 g54 g80 g90.1 g94
g10 l2 p1 x0 y0 z0 (make axis set 1 be absolute)
;t1 m1 (setup first bit in the tools file,just to have a tool,cutter size is hardcoded)
f 100
g0 x0 y0 z0
;(debug cutter is zeroed, press pause button to proceed)
;m0

#<_ginc> = -4.500(used  to incline both gears from center quarterflat hole)
o800 while [#<_ginc> lt [-04.0]] (set the ginc limit)
(gear params:)
#<pressangle> = 25.00000 (std are 14.5,20,25)
#<baseradius> = 0.6000 (only a single decimal place?? allowed)
#<numberteeth> = 20 (pinionteeth, ratio * numberteeth = ringteeth)
#<ratio> = 5.0 
#<_fudgeh> = -0.000 (fudge height top, must be less than addendum pinion )
(while walking from gear tip to gear center, fudgewc controls clearance)
(on your left and fudgewccw controls clearance on your right. They make the)
(pinion tooth skinnier)
#<_fudgewc> = [-asin[0.00/#<baseradius>]] (reduce the cw gear degrees )
#<_fudgewccw> = [-asin[0.000/#<baseradius>]] (reduce the ccw gear face degrees)
#<gearcenterx> = 6.80 (co-ordinate of pinion gear center,ring is neg offset)
#<gearcentery> = 5.20 (parameters beyond this are computed by the code)
#<_raddendum> = 0 (outer radius - pitch radius inches)
#<pitchradius>=0  (this becomes baseradius + addendum inches)
#<_chkangle> = 0  (used for measuring the tooth)
#<_endangle> = 0  
#<_incangle> = 0  
#<_rinclen> = 0  
#<_rrincangle> = 0 
#<_native> = 0    
#<_ringclix> = 0
#<_nextxbottom> = 0
#<_nextybottom> = 0
#<_ffoffset> = 0
#<_radoffset> = -1.0 (must be -1)
(machine parameters:)
#<_precision> = 0.400 (degrees, adjust accuracy,.01 and .001 take long)
#<_printflag> = 1
#<_cutterdiam> = [5.0/64.0] (a 5/64 diameter endmill)
;#<centerholediam> = [0.50 - 2* #<_cutterdiam>] (A center hole gear center)
#<centerholediam> = 0.25
#<ringthick> = [0.5+8.0*#<_cutterdiam>] (ring thickness inches)
#<passesneeded> = 2.0 (this times depth is total milling depth)
#<cuttingdepth> = 0.05 (50 thou, okay for wood plastic, small endmill)
#<cuttingfeed> = 100.0 (for cutting air, 10.0% for al,05.0% steel)

g0 z 0.25 (retract before cuttiong pinion centerhole)
x[#<gearcenterx>-#<centerholediam>/2] y #<gearcentery> 
#302 = 0
o100 while  [#302 lt #<passesneeded>]
 #302 = [#302 + 1]
 g1 f#<cuttingfeed> z [0.0 - #302*#<cuttingdepth>] (plunge)
 g1 x[#<gearcenterx>] y[#<gearcentery>+#<centerholediam>/2.0]
 g2 x[#<gearcenterx>-#<centerholediam>/2]y#<gearcentery> i [#<gearcenterx>] j [#<gearcentery>]
o100 endwhile (end of cut pinion centerhole)

(cut pinion teeth here)
g0 z 0.25
g0 x #<gearcenterx> y #<gearcentery>
;g42.1 D [#<_cutterdiam>/2.0] (uncomment this comp line before milling first gear)
g1 x[#<gearcenterx>+[#<baseradius>]*cos[+#<_ginc>-#<_fudgewc>]] y [#<gearcentery>+[#<baseradius>]*sin[+#<_ginc>-#<_fudgewc>]]
#<plunger> = [360.0 +#<_ginc>]
#302 = 1
g1 f#<cuttingfeed> z [0.0 - #302*#<cuttingdepth>] (plunge)
#<compass_point> = [0.0 + #<_ginc>]
o3001 while [#<compass_point> lt [#<_ginc>+#<passesneeded>*360.0]-180.0/#<numberteeth>]
o413 call [#<gearcenterx>][#<gearcentery>][#<baseradius>][#<compass_point>][#<pitchradius>-#<_raddendum>][#<numberteeth>][0][#<pitchradius>+#<_raddendum>] [#<pressangle>][#<ratio>] (cut one pinion tooth & gap here)
#<pitchradius> = [#<baseradius> + #<_raddendum>]
#<segangle> = [360.0/[#<numberteeth>]] (wholesegment)
#<compass_point> = [#<compass_point>+[360.0/[#<numberteeth>]]]
o301 if  [[#<compass_point> ge #<plunger>] and [#302 lt #<passesneeded>]]
 #302 = [#302 + 1]
 g1 f#<cuttingfeed> z [0.0 - #302*#<cuttingdepth>] (plunge)
 #<plunger>=[#<_ginc>+#302*360.0]
o301 endif
o3001 endwhile (end of cut pinion teeth)
g40 (turn off compensation after cutting/comping pinion)
g0 z 0.25
;g0 x [#<gearcenterx>-#<baseradius>-#<_raddendum>] y[#<gearcentery>]
;g2 i [#<gearcenterx>] j [#<gearcentery>] (pinion ref circle)

(setup for ring teeth & gap)
#<rbaseradius> = [[#<ratio>*[#<baseradius>+#<_raddendum>]]*cos[#<pressangle>]] 
#<_rraddendum>=[#<rbaseradius>*[1/cos[#<pressangle>]-1]] 
#<gearcenterx> = [#<gearcenterx>+#<baseradius>-[#<rbaseradius>-0.0*#<_cutterdiam>]] (make this 4*cutterdiam here to cut/comp both gears comp offset)
(print, ring center:#<gearcenterx>,#<gearcentery>)
#<_fudged> = [ABS[0.0050]] (lop this much of the bottom of ring gear teeth)
(while walking on a line from "toothhole" to ring gear center, fudgewc)
(controls clearance on your left,fudgewccw controls clearance on your right,)
(either or both of them make the pinion "toothhole" in the ring get fatter)
#<_fudgewc> = [+asin[0.005/#<rbaseradius>]] 
#<_fudgewccw> = [+asin[0.003/#<rbaseradius>]] 
#<numberteeth>= [#<numberteeth>*#<ratio>] (ring gear)
#<compass_point> = [#<_ginc>/#<ratio>]
o414 call [#<gearcenterx>][#<gearcentery>][#<rbaseradius>][#<compass_point>][#<ratio>][#<numberteeth>][0][0] [#<pressangle>][#<ratio>]
g0 z 0.25
g0 x #<gearcenterx> y #<gearcentery>
;g41.1 D [#<_cutterdiam>/2.0] (this is cutter comp line for ring gear )
#302 = 1.0
g0 x #<_nextxbottom> y #<_nextybottom>
#<plunger>=[#<_ginc>/#<ratio>+#302*360.0]
g1 f#<cuttingfeed> z [0.0 - #302*#<cuttingdepth>] (plunge)
o4001 while [#<compass_point> lt [#<_ginc>/#<ratio>+#<passesneeded>*360.0]]
o415 call [#<gearcenterx>][#<gearcentery>][#<rbaseradius>][#<compass_point>][0][#<numberteeth>][0][0] [#<pressangle>][#<ratio>]
#<compass_point> = [#<compass_point>+[360.0/[#<numberteeth>]]]
o401 if  [[#<compass_point> ge #<plunger>] and [#302 lt #<passesneeded>]]
 #302 = [#302 + 1]
 #<plunger>=[#<_ginc>/#<ratio>+#302*360.0]
 g1 f#<cuttingfeed> z [0.0 - #302*#<cuttingdepth>] (plunge)
o401 endif
o4001 endwhile (end of cut ring gear)
g40 (shut off compensation for ring gear)
g0 z 0.25
#302 = 0.0
g0 x [#<gearcenterx>+#<rbaseradius>+#<_raddendum>*2.0+#<ringthick>] y[#<gearcentery>]
o509 while [#302 lt #<passesneeded>]
#302 = [#302 + 1.0]
g1 f#<cuttingfeed> z [0.0 - #302*#<cuttingdepth>] (plunge)
g2 i [#<gearcenterx>] j [#<gearcentery>]
o509 endwhile
g0 z 0.25
;g0 x [#<gearcenterx>+#<_raddendum>+#<rbaseradius>] y[#<gearcentery>]
;g2 i [#<gearcenterx>] j [#<gearcentery>] (ring ref circle)
 #<_ginc> = [#<_ginc> + 1.20] (ginc offset each pass)
o800 endwhile
g0 x0 y0
m2
%


LinuxCNCKnowledgeBase | RecentChanges | PageIndex | Preferences | LinuxCNC.org
This page is read-only. Follow the BasicSteps to edit pages. | View other revisions | View current revision
Edited June 2, 2015 6:37 am by Herbivore102 (diff)
Search:
Published under a Creative Commons License