qpocket.ngc
1 (info: Quadrilateral pocketing using cutter radius compensation) 2 3 ; Use with care, test in simulator first. 4 5 ; Notes: 6 ; Defaults herein are inch based 7 ; Uses tool diameter from tool table for cutter radius compensation 8 ; Supports conventional or climb milling 9 ; Ramps to depth for each z increment 10 ; Mirror about x axis for negative scale 11 12 ; too small diameter tools and/or small stepovers may exceed outlinepasslimit 13 ; too large diameter tools may case gouging errors 14 15 ; Works for most rectangles and parallelograms but may require some care 16 ; for specifying: 17 ; point ordering (see entry move notes below) 18 ; tool diameter (in tool table) 19 ; stepover 20 21 ; Entry moves: 22 ; Input point ordering Requested Direction Entry line 23 ; -------------------- ------------------------ ------------------ 24 ; 1234 == CW 2 == CW == Conventional point1 --> point2 25 ; 1234 == CW 3 == CCW == Climb point1 --> point4 26 27 ; 1234 == CCW 2 == CW == Conventional point1 --> point4 28 ; 1234 == CCW 3 == CCW == Climb point1 --> point2 29 30 ; To accomodate the widest range of tool diameters, order the point sequence 31 ; (1234) so that the entry move is not directed towards an acute angle. 32 33 ; Scaling, rotations, and offsets are supported. 34 ; Scaling is applied first. 35 ; Rotation is then applied (with respect to origin). It is often simplest 36 ; to specify the feature so that it is centered at the origin. 37 ; Offsets are applied last. 38 39 ;---------------------------------------------------------------------- 40 ; Copyright: 2012,2014 41 ; Author: Dewey Garrett <dgarrett@panix.com> 42 ; 43 ; This program is free software; you can redistribute it and/or modify 44 ; it under the terms of the GNU General Public License as published by 45 ; the Free Software Foundation; either version 2 of the License, or 46 ; (at your option) any later version. 47 ; 48 ; This program is distributed in the hope that it will be useful, 49 ; but WITHOUT ANY WARRANTY; without even the implied warranty of 50 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 51 ; GNU General Public License for more details. 52 ; 53 ; You should have received a copy of the GNU General Public License 54 ; along with this program; if not, write to the Free Software 55 ; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 56 ;---------------------------------------------------------------------- 57 58 o<qpocket> sub 59 60 #<toolno> = #1 (=1) 61 #<rpm> = #2 (=1000) 62 #<dir> = #3 (=2 2conv|3climb) ; conventional=cw, climb=ccw 63 #<feedrate> = #4 (=10) 64 #<cutdepth> = #5 (=0.1) 65 #<zincr> = #6 (=0.02) 66 #<zsafe> = #7 (=0.2) 67 #<zstart> = #8 (=0) 68 69 #<x1> = #9 70 #<y1> = #10 71 #<x2> = #11 72 #<y2> = #12 73 #<x3> = #13 74 #<y3> = #14 75 #<x4> = #15 76 #<y4> = #16 77 78 #<scale> = #17 (=1) ; use neg value for mirroring 79 #<rotate> = #18 (=0) ; angle in degrees 80 #<xoff> = #19 (=0) 81 #<yoff> = #20 (=0) 82 #<stepover> = #21 (=0.5) ; tooldiameter fraction 83 #<g64tol> = #22 (=0.002) 84 #<spin_notify> = #23 (=1) ; 1 == prompt user 85 #<use_g43> = #24 (=1) 86 #<h_for_g43> = #25 (=0) 87 #<verbose> = #26 (=0) 88 89 #<depthpasslimit> = 100 ; outer loop 90 #<outlinepasslimit> = 100 ; inner loop 91 #<tdelta> = 0.01 ; small increment to tool diameter 92 #<cutdepth> = [0 - #<cutdepth>] 93 #<zincr> = [0 - #<zincr>] 94 95 g40 ; make sure cutter radius compensation off at start 96 g64 p #<g64tol> ; path tolerance 97 98 o<if10> if [#<scale> EQ 0] 99 (print, qpocket: zero scale #<scale> - EXITING) 100 (debug, qpocket: zero scale #<scale> - EXITING) 101 (AXIS,notify, qpocket: zero scale - EXITING) 102 m2 103 o<if10> endif 104 105 o<if11> if [#<scale> LT 0] 106 (print, qpocket: MIRROR about x axis for negative scale #<scale>) 107 (debug, qpocket: MIRROR about x axis for negative scale #<scale>) 108 (AXIS,notify, qpocket: MIRROR about x axis for negative scale) 109 o<if11> endif 110 #<x1> = [#<scale> * #<x1>] 111 #<x2> = [#<scale> * #<x2>] 112 #<x3> = [#<scale> * #<x3>] 113 #<x4> = [#<scale> * #<x4>] 114 115 #<scale> = [ABS[#<scale>]] 116 #<y1> = [#<scale> * #<y1>] 117 #<y2> = [#<scale> * #<y2>] 118 #<y3> = [#<scale> * #<y3>] 119 #<y4> = [#<scale> * #<y4>] 120 121 #<scale> = 1 122 123 o<if20> if [[#<stepover> GT 1] OR [#<stepover> LE 0]] 124 (print, qpocket: invalid stepover=#<stepover> - EXITING) 125 (debug, qpocket: invalid stepover=#<stepover> - EXITING) 126 (AXIS,notify, qpocket: invalid stepover - EXITING) 127 m2 128 o<if20> endif 129 130 o<if30> if [[#<dir> NE 2] AND [#<dir> NE 3]] 131 (print, qpocket:bad dir=#<dir> - EXITING) 132 (debug, qpocket:bad dir=#<dir> - EXITING) 133 (AXIS,notify, qpocket:bad dir - EXITING) 134 m2 135 o<if30> endif 136 137 ;compute direction eg 2==cw,3==ccw for points as ordered: 138 o<dir> call [4][#<x1>][#<y1>][#<x2>][#<y2>][#<x3>][#<y3>][#<x4>][#<y4>] 139 #<pointsdir> = #<_dir:> ; direction of input points 2==cw 140 #<xctr> = #<_dir:cx> ; centroid 141 #<yctr> = #<_dir:cy> ; centroid 142 143 o<ifdir1> if [#<pointsdir> LE 0] 144 ; failed to get direction -- pathological case 145 (print, failed to compute direction - EXITING) 146 (debug, failed to compute direction - EXITING) 147 (AXIS,notify, failed to compute direction - EXITING) 148 m2 149 o<ifdir1> endif 150 151 ; Get data for x,y points 152 #<npoints> = 4 153 o<pointsdata> call [#<npoints>] [#<x1>][#<x2>][#<x3>][#<x4>] 154 #<xc> = #<_pointsdata:ctr> 155 #<xmin> = [#<_pointsdata:min> - #<xctr>] 156 #<xmax> = [#<_pointsdata:max> - #<xctr>] 157 o<pointsdata> call [#<npoints>] [#<y1>][#<y2>][#<y3>][#<y4>] 158 #<yc> = #<_pointsdata:ctr> 159 #<ymin> = [#<_pointsdata:min> - #<yctr>] 160 #<ymax> = [#<_pointsdata:max> - #<yctr>] 161 162 ; Respecify input points about the x,y centroid 163 o<ifv0> if [#<verbose> GT 0] 164 (debug, centroid: #<xctr> #<yctr>) 165 o<ifv0> endif 166 167 #<x1> = [#<x1> - #<xctr>] 168 #<x2> = [#<x2> - #<xctr>] 169 #<x3> = [#<x3> - #<xctr>] 170 #<x4> = [#<x4> - #<xctr>] 171 172 #<y1> = [#<y1> - #<yctr>] 173 #<y2> = [#<y2> - #<yctr>] 174 #<y3> = [#<y3> - #<yctr>] 175 #<y4> = [#<y4> - #<yctr>] 176 177 ; make order of points agree with input direction request 178 o<if40> if [#<pointsdir> NE #<dir>] 179 o<ifv1> if [#<verbose> GT 0] 180 (debug, reversing input point sequence: 1-4-3-2) 181 o<ifv1> endif 182 ; swap points ordering: 1234 --> 1432 183 #<xt> = #<x2> 184 #<yt> = #<y2> 185 #<x2> = #<x4> 186 #<y2> = #<y4> 187 #<x4> = #<xt> 188 #<y4> = #<yt> 189 o<if40> endif 190 191 ; determine min size for first outline pass 192 o<if50> if [[#<xmax>-#<xmin>] GT [#<ymax>-#<ymin>]] 193 #<minor> = [ABS[#<ymax>-#<ymin>]/2] 194 o<if50> else 195 #<minor> = [ABS[#<xmax>-#<xmin>]/2] 196 o<if50> endif 197 198 ; load tool and establish scaling for first outline pass 199 o<loadtool> call [#<toolno>][#<use_g43>][#<h_for_g43>][#<verbose>] 200 #<thetooldiam> = #5410 201 #<tooldiam> = [#5410 + #<tdelta>] 202 #<r> = [#<tooldiam> / 2] 203 #<sizei> = [#<tooldiam> / #<minor>] 204 #<qscalei> = [#<scale> * #<sizei>] 205 206 o<ifsc> if [#<qscalei> GE #<scale>] 207 (print, qpocket: tooldiam is too big #<thetooldiam> - EXITING) 208 (debug, qpocket: tooldiam is too big #<thetooldiam> - EXITING) 209 (AXIS,notify, qpocket: tooldiam is too big - EXITING) 210 m2 211 o<ifsc> endif 212 213 ; scale the centered feature and translate to original position 214 o<move> call [#<x1>][#<y1>][0][#<qscalei>][#<xctr>][#<yctr>] 215 #<x1i> = #<_move:x> 216 #<y1i> = #<_move:y> 217 o<move> call [#<x2>][#<y2>][0][#<qscalei>][#<xctr>][#<yctr>] 218 #<x2i> = #<_move:x> 219 #<y2i> = #<_move:y> 220 o<move> call [#<x3>][#<y3>][0][#<qscalei>][#<xctr>][#<yctr>] 221 #<x3i> = #<_move:x> 222 #<y3i> = #<_move:y> 223 o<move> call [#<x4>][#<y4>][0][#<qscalei>][#<xctr>][#<yctr>] 224 #<x4i> = #<_move:x> 225 #<y4i> = #<_move:y> 226 ; xni,yni are the initial points at the smallest scaling 227 228 ; apply input rotation and offset 229 o<move> call [#<x1i>][#<y1i>][#<rotate>][1][#<xoff>][#<yoff>] 230 #<x1i> = #<_move:x> 231 #<y1i> = #<_move:y> 232 o<move> call [#<x2i>][#<y2i>][#<rotate>][1][#<xoff>][#<yoff>] 233 #<x2i> = #<_move:x> 234 #<y2i> = #<_move:y> 235 o<move> call [#<x3i>][#<y3i>][#<rotate>][1][#<xoff>][#<yoff>] 236 #<x3i> = #<_move:x> 237 #<y3i> = #<_move:y> 238 o<move> call [#<x4i>][#<y4i>][#<rotate>][1][#<xoff>][#<yoff>] 239 #<x4i> = #<_move:x> 240 #<y4i> = #<_move:y> 241 242 ;get angles for connecting lines 243 o<line> call [#<x1i>][#<y1i>][#<x2i>][#<y2i>] 244 #<cos12> = #<_line:cos> 245 #<sin12> = #<_line:sin> 246 o<line> call [#<x2i>][#<y2i>][#<x3i>][#<y3i>] 247 #<cos23> = #<_line:cos> 248 #<sin23> = #<_line:sin> 249 o<line> call [#<x3i>][#<y3i>][#<x4i>][#<y4i>] 250 #<cos34> = #<_line:cos> 251 #<sin34> = #<_line:sin> 252 o<line> call [#<x4i>][#<y4i>][#<x1i>][#<y1i>] 253 #<cos41> = #<_line:cos> 254 #<sin41> = #<_line:sin> 255 256 ;compute angles at line interesctions: 257 o<dot> call [#<x1i>][#<y1i>][#<x2i>][#<y2i>][#<x3i>][#<y3i>] 258 #<ang123> = #<_dot:ang> 259 o<dot> call [#<x2i>][#<y2i>][#<x3i>][#<y3i>][#<x4i>][#<y4i>] 260 #<ang234> = #<_dot:ang> 261 o<dot> call [#<x3i>][#<y3i>][#<x4i>][#<y4i>][#<x1i>][#<y1i>] 262 #<ang341> = #<_dot:ang> 263 o<dot> call [#<x4i>][#<y4i>][#<x1i>][#<y1i>][#<x2i>][#<y2i>] 264 #<ang412> = #<_dot:ang> 265 266 f #<feedrate> 267 s #<rpm> m3 ;spindle cw 268 o<if60> if [#<spin_notify> GT 0] 269 o<spin> call [#<rpm>] ; optionally prompt user 270 o<if60> endif 271 g0 z#<zsafe> 272 273 ; depth loop (outer) 274 #<zcurrent> = #<zstart> 275 #<depthpass> = 1 276 o<wh10> while [#<zcurrent> GT #<cutdepth>] 277 #<zlast> = #<zcurrent> 278 #<zcurrent> = [#<zcurrent> + #<zincr>] 279 o<wh11> if [#<zcurrent> LT #<cutdepth>] 280 #<zcurrent> = #<cutdepth> 281 o<wh11> endif 282 o<wh12> if [#<depthpass> GT #<depthpasslimit>] 283 (print, qpocket: depthpasslimit exceeded #<depthpasslimit> - EXITING) 284 (debug, qpocket: depthpasslimit exceeded #<depthpasslimit> - EXITING) 285 (AXIS,notify, qpocket: depthpasslimit exceeded - EXITING) 286 m2 287 o<wh12> endif 288 289 o<pas1> if [#<depthpass> EQ 1] 290 ;entry point: 291 ;go along the 1-->2 line to enter at a point where tool will fit 292 293 #<elen12> = [ #<r> / [TAN[#<ang412>/2]]] 294 #<k12> = [#<elen12> / #<r>] 295 ;(print, entry 12 k=#<k12> elen12=#<elen12> angle=#<angle>) 296 #<xentry> = [#<x1i> + #<elen12> * #<cos12>] 297 #<yentry> = [#<y1i> + #<elen12> * #<sin12>] 298 ;compute pre-entry points: 299 o<dir00> if [#<dir> EQ 2] ; dir EQ 2 CW (conventional) 300 #<prex2> = [#<xentry> + #<r> * #<sin12> - #<r> * #<cos12>] 301 #<prey2> = [#<yentry> - #<r> * #<cos12> - #<r> * #<sin12>] 302 #<prex1> = [#<prex2> + #<r> * #<cos12>] 303 #<prey1> = [#<prey2> + #<r> * #<sin12>] 304 #<vx> = [ #<r> * #<cos12>] 305 #<vy> = [ #<r> * #<sin12>] 306 o<dir00> else ;dir EQ 3 CCW (climb) 307 #<prex2> = [#<xentry> - #<r> * #<sin12> - #<r> * #<cos12>] 308 #<prey2> = [#<yentry> + #<r> * #<cos12> - #<r> * #<sin12>] 309 #<prex1> = [#<prex2> + #<r> * #<cos12>] 310 #<prey1> = [#<prey2> + #<r> * #<sin12>] 311 #<vx> = [ #<r> * #<cos12>] 312 #<vy> = [ #<r> * #<sin12>] 313 o<dir00> endif 314 g0 x #<prex1> y #<prey1> ;preentry 1 315 g0 x #<prex2> y #<prey2> ;preentry 2 316 o<dir10> if [#<dir> EQ 2] ; CW 317 / g42 ;cutter radius comp right of path 318 g2 x #<xentry> y #<yentry> i #<vx> j #<vy> ;arc entry 319 o<dir10> else ;dir EQ 3 CCW 320 / g41 ;cutter radius comp left of path 321 g3 x #<xentry> y #<yentry> i #<vx> j #<vy> ;arc entry 322 o<dir10> endif 323 g1 z #<zstart> ;plunge to start height from zsafe 324 o<pas1> else 325 ; depthpass GT 1: return to interior entry point 326 g1 x #<xentry> y #<yentry> z#<zlast> ; use zlast 327 o<pas1> endif 328 329 ; outline loop (inner) 330 #<outlinepass> = 1 331 #<qscale> = #<qscalei> 332 #<size> = #<sizei> 333 o<wh20> do 334 o<wh22> if [#<outlinepass> GT #<outlinepasslimit>] 335 (print, qpocket: outlinepasslimit exceeded #<outlinepasslimit> - EXITING) 336 (debug, qpocket: outlinepasslimit exceeded #<outlinepasslimit> - EXITING) 337 (AXIS,notify,qpocket: outlinepasslimit exceeded - EXITING) 338 m2 339 o<wh22> endif 340 341 #<seq> = [#<outlinepass> mod 4] 342 o<wh23> if [#<outlinepass> EQ 1] 343 ; move through smallest interior outline 344 345 o<ramp1> if [#<seq> EQ 1] 346 g1 x #<x2i> y #<y2i> z#<zcurrent> ;ramp down to zcurrent 347 g1 x #<x3i> y #<y3i> 348 g1 x #<x4i> y #<y4i> 349 g1 x #<x1i> y #<y1i> 350 g1 x #<x2i> y #<y2i> 351 o<ramp1> endif 352 o<ramp2> if [#<seq> EQ 2] 353 g1 x #<x3i> y #<y3i> z#<zcurrent> ;ramp down to zcurrent 354 g1 x #<x4i> y #<y4i> 355 g1 x #<x1i> y #<y1i> 356 g1 x #<x2i> y #<y2i> 357 g1 x #<x3i> y #<y3i> 358 o<ramp2> endif 359 o<ramp3> if [#<seq> EQ 3] 360 g1 x #<x4i> y #<y4i> z#<zcurrent> ;ramp down to zcurrent 361 g1 x #<x1i> y #<y1i> 362 g1 x #<x2i> y #<y2i> 363 g1 x #<x3i> y #<y3i> 364 g1 x #<x4i> y #<y4i> 365 o<ramp3> endif 366 o<ramp0> if [#<seq> EQ 0] 367 g1 x #<x1i> y #<y1i> z#<zcurrent> ;ramp down to zcurrent 368 g1 x #<x2i> y #<y2i> 369 g1 x #<x3i> y #<y3i> 370 g1 x #<x4i> y #<y4i> 371 g1 x #<x1i> y #<y1i> 372 o<ramp0> endif 373 374 #<outlinepass> = [#<outlinepass> + 1] 375 o<wh23> else 376 ; increasingly larger outlines 377 #<size> = [#<size> + #<stepover> * #<sizei>] 378 #<qscale> = [#<scale> * #<size>] 379 #<outlinepass> = [#<outlinepass> + 1] 380 o<wh24> if [#<qscale> GE #<scale>] 381 #<qscale> = #<scale> 382 #<outlinepass> = 0 ;terminate after this pass 383 o<wh24> endif 384 ; scale the centered feature and translate to original position 385 o<move> call [#<x1>][#<y1>][0][#<qscale>][#<xctr>][#<yctr>] 386 #<x1t> = #<_move:x> 387 #<y1t> = #<_move:y> 388 o<move> call [#<x2>][#<y2>][0][#<qscale>][#<xctr>][#<yctr>] 389 #<x2t> = #<_move:x> 390 #<y2t> = #<_move:y> 391 o<move> call [#<x3>][#<y3>][0][#<qscale>][#<xctr>][#<yctr>] 392 #<x3t> = #<_move:x> 393 #<y3t> = #<_move:y> 394 o<move> call [#<x4>][#<y4>][0][#<qscale>][#<xctr>][#<yctr>] 395 #<x4t> = #<_move:x> 396 #<y4t> = #<_move:y> 397 398 ; apply input rotation and offset 399 o<move> call [#<x1t>][#<y1t>][#<rotate>][1][#<xoff>][#<yoff>] 400 #<x1s> = #<_move:x> 401 #<y1s> = #<_move:y> 402 o<move> call [#<x2t>][#<y2t>][#<rotate>][1][#<xoff>][#<yoff>] 403 #<x2s> = #<_move:x> 404 #<y2s> = #<_move:y> 405 o<move> call [#<x3t>][#<y3t>][#<rotate>][1][#<xoff>][#<yoff>] 406 #<x3s> = #<_move:x> 407 #<y3s> = #<_move:y> 408 o<move> call [#<x4t>][#<y4t>][#<rotate>][1][#<xoff>][#<yoff>] 409 #<x4s> = #<_move:x> 410 #<y4s> = #<_move:y> 411 412 ; move through scaled interior outline 413 o<seq0> if [#<seq> EQ 0] 414 g1 x #<x1s> y #<y1s> z #<zcurrent> 415 x #<x2s> y #<y2s> 416 x #<x3s> y #<y3s> 417 x #<x4s> y #<y4s> 418 x #<x1s> y #<y1s> 419 o<seq0> endif 420 o<seq1> if [#<seq> EQ 1] 421 g1 x #<x2s> y #<y2s> z #<zcurrent> 422 x #<x3s> y #<y3s> 423 x #<x4s> y #<y4s> 424 x #<x1s> y #<y1s> 425 x #<x2s> y #<y2s> 426 o<seq1> endif 427 o<seq2> if [#<seq> EQ 2] 428 g1 x #<x3s> y #<y3s> z #<zcurrent> 429 x #<x4s> y #<y4s> 430 x #<x1s> y #<y1s> 431 x #<x2s> y #<y2s> 432 x #<x3s> y #<y3s> 433 o<seq2> endif 434 o<seq3> if [#<seq> EQ 3] 435 g1 x #<x4s> y #<y4s> z #<zcurrent> 436 x #<x1s> y #<y1s> 437 x #<x2s> y #<y2s> 438 x #<x3s> y #<y3s> 439 x #<x4s> y #<y4s> 440 o<seq3> endif 441 442 o<wh23> endif 443 444 o<wh20> while [#<outlinepass> GT 0] 445 #<depthpass> = [#<depthpass> + 1] 446 o<wh10> endwhile 447 448 ; after finishing at input scale, need to turn corner 449 ; and go along the next line enough to turn off compensation 450 o<fin0> if [#<seq> EQ 0] ;end at pt 1 451 #<xfinal_a> = #<x1s> 452 #<yfinal_a> = #<y1s> 453 #<elen12> = [#<r> / [TAN[#<ang412>/2]]] 454 #<xfinal_b> = [#<x1s> + #<elen12> * #<cos12>] 455 #<yfinal_b> = [#<y1s> + #<elen12> * #<sin12>] 456 o<fin0> endif 457 o<fin1> if [#<seq> EQ 1] ;end at pt 2 458 #<xfinal_a> = #<x2s> 459 #<yfinal_a> = #<y2s> 460 #<elen23> = [#<r> / [TAN[#<ang123>/2]]] 461 #<xfinal_b> = [#<x2s> + #<elen23> * #<cos23>] 462 #<yfinal_b> = [#<y2s> + #<elen23> * #<sin23>] 463 o<fin1> endif 464 o<fin2> if [#<seq> EQ 2] ;end at pt 3 465 #<xfinal_a> = #<x3s> 466 #<yfinal_a> = #<y3s> 467 #<elen34> = [#<r> / [TAN[#<ang234>/2]]] 468 #<xfinal_b> = [#<x3s> + #<elen34> * #<cos34>] 469 #<yfinal_b> = [#<y3s> + #<elen34> * #<sin34>] 470 o<fin2> endif 471 o<fin3> if [#<seq> EQ 3] ;end at pt 4 472 #<xfinal_a> = #<x4s> 473 #<yfinal_a> = #<y4s> 474 #<elen41> = [#<r> / [TAN[#<ang341>/2]]] 475 #<xfinal_b> = [#<x4s> + #<elen41> * #<cos41>] 476 #<yfinal_b> = [#<y4s> + #<elen41> * #<sin41>] 477 o<fin3> endif 478 479 g1 x #<xfinal_a> y #<yfinal_a> 480 g1 x #<xfinal_b> y #<yfinal_b> 481 482 g0 z #<zsafe> 483 g40 ;cutter radius compensation off 484 485 o<qpocket> endsub