Sunday, August 3, 2025

Circlepocket

 I need to machine what we call a circle pocket: a circle that is completely empty.  For this application, I wanted a through hole.  I could use a bdrill bit, but this gets me a through whatever size I want, even if I lack that size drill bit.

This is pretty dependent on getting the true diameter of the endmill which is sometimes slightly different from nominal size.  I also wrote this so that the gCode prolog and epilog are not added by the program.  This allows me to stack multiple features in one gCode file.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "helperdefs.h"

int main(int argc, char *argv[]) {
    if (argc < 11) {
        fprintf(stderr, "Usage:\n");
        fprintf(stderr, "  %s circleRadius xCenter yCenter zStart zStep zEnd xyFeed zFeed millDiameter outputFilename -a\n", argv[0]);
        return 1;
    }

    // Parse command-line arguments
    double circleRadius = atof(argv[1]);
    double centerX = atof(argv[2]);
    double centerY = atof(argv[3]);
    double zStart = atof(argv[4]);
    double zStep = atof(argv[5]);
    double zEnd = atof(argv[6]);
    double xyFeed = atof(argv[7]);
    double zFeed = atof(argv[8]);
    double millDiameter = atof(argv[9]);
    const char *outputFilename = argv[10];
    boolean append = FALSE;
    if (argc == 12 && argv[11] != NULL) {
        if (strcmp(argv[11], "-a") == 0) {
        append = TRUE;
        } else {
            fprintf(stderr, "Unrecognized argument: %s\n", argv[11]);
            exit(1);
        }
    }

    FILE* fp;
    if(append)
      fp = fopen(outputFilename, "a");
    else
      fp = fopen(outputFilename, "w");
    if (!fp) {
        perror("Error opening output file");
        return 1;
    }
    /* if not appending, we need prolog and epilog */
    if(append == FALSE)
      fprintf(fp, "%c\nG17 G20 G54\n", '%');
    /* clear top of workpiece */
    fprintf(fp, "G0 Z1 F25\nG0 z.2 F25\n");
    // Derived values
    double millRadius = millDiameter / 2.0;
    double toolpathRadius = circleRadius - millRadius;
    if (toolpathRadius <= 0) {
        fprintf(stderr, "Error: toolpath radius is zero or negative. Mill is too large for given circle.\n");
        fclose(fp);
        return 1;
    }

    double radialStep = millRadius / 2.0;

    fprintf(fp, "(Circular pocket: center=%.4f,%.4f radius=%.4f tool=%.3f)\n", centerX, centerY, circleRadius, millDiameter);
    fprintf(fp, "G0 X%.4f Y%.4f\n", centerX + circleRadius, centerY);
    fprintf(fp, "(position to top of workpiece)\nG0 Z%.4f F25\n", zStart);

    // Roughing passes
    double z = zStart;
    while (z > zEnd) {
        z += zStep;
        if (z < zEnd) z = zEnd;

        fprintf(fp, "G0 X%.4f Y%.4f\n", centerX + circleRadius, centerY);
        fprintf(fp, "G1 Z%.4f F%.3f\n", z, zFeed);

        for (double r = toolpathRadius; r >= 0.01; r -= radialStep) {
            fprintf(fp, "G1 X%.4f Y%.4f F%.3f\n", centerX + r, centerY, xyFeed);
            fprintf(fp, "G2 I-%.4f J0.0 F%.3f\n", r, xyFeed);
        }
    }

    // Finishing pass at full depth
    fprintf(fp, "(Finishing pass at final depth)\n");
    fprintf(fp, "G1 X%.4f Y%.4f F%.3f\n", centerX + toolpathRadius, centerY, xyFeed);
    fprintf(fp, "G2 I-%.4f J0.0 F%.3f\n", toolpathRadius, xyFeed);

    fprintf(fp, "G0 Z2\n");
    fclose(fp);
    return 0;
}

Here is the Makefile segment that creates the circle:

circlepocket.ngc: mkcirclepocket $(MAKEFILE)
    cat prolog.ngc >circlepocket.ngc
    ./mkcirclepocket .25 1 1 0 -.01 -.2 25 25 .121 circlepocket.ngc -a
    echo "m2\n%" >>circlepocket.ngc
 

prolog.ngc

%
g17 g20 g54
 

I can stack multiple features by adding the -a parameter at end of mkcirclepocket call.

 


2 comments:

  1. A "circle pocket" sounds a lot like what regular people call a hole or a blind hole.

    ReplyDelete