GCMC XY Axis Calibration Target

The CNC-3018XL drawing the scales on a Tek Circuit Computer disagreed with the MPCNC cutting the perimeter. The Y axis edges looked OK:

Tek CC - 2021-11 - Y detail
Tek CC – 2021-11 – Y detail

But the cut on the X axis edges went too close to the tips:

Tek CC - 2021-11 - X detail
Tek CC – 2021-11 – X detail

I conjured a calibration target to help measure the two machines:

Cal Target - CNC3018XL
Cal Target – CNC3018XL

The X- side of the plot gives the general idea:

CNC-3018XL - Backlash Test - 400step-mm
CNC-3018XL – Backlash Test – 400step-mm

The vertical lines consist of two halves, drawn in order from left to right on the top and right to left on the bottom, meeting in the middle at the Y=0 axis. If they do, in fact, meet in the middle, then there’s no problem with backlash.

The 25 mm distance between adjacent lines verifies the linear calibration; the total distance along the X and Y axes provides more travel for more error accumulation.

The circles provide some reassurance the machine can draw a smooth circle, because they come from GRBL’s (or whatever) G2 G-Code commands, not a linear approximation.

Spoiler: after a considerable amount of drawing, measuring, and muttering, the problem emerged from the CNC-3018XL’s X-axis leadscrew:

Cal Target - 400 step-mm - merged
Cal Target – 400 step-mm – merged

It’s half a millimeter short on each end!

More on this tomorrow …

The GCMC source code as a GitHub Gist:

(epilog begins)
(bCNC may regard plot as done before this returns)
M2
(epilog ends)
view raw epilog.gcmc hosted with ❤ by GitHub
(prolog begins)
G17 (XY plane)
G21 (mm)
G40 (no cutter comp)
G49 (no tool length comp)
G80 (no motion mode)
G90 (abs distance)
G94 (units per minute)
(prolog ends)
view raw prolog.gcmc hosted with ❤ by GitHub
// Grid pattern to check XY scaling
// Ed Nisley KE4ZNU - 2021-11
// gcmc -P 4 --pedantic --prolog prolog.gcmc --epilog epilog.gcmc --output 'Scale Grid.ngc' 'Scale Grid.gcmc'
include("engrave.inc.gcmc");
FALSE = 0;
TRUE = !FALSE;
//-----
// Define useful constants
SafeZ = [-,-,10.0mm]; // above all obstructions
TravelZ = [-,-,2.0mm]; // within engraving / milling area
PenZ = [-,-,-1.0mm]; // depth for good inking
PenSpeed = 2000mm;
//-----
// Overall values
PlotSize = [250mm,200mm,-];
comment("PlotSize: ",PlotSize);
GridSize = [25mm,25mm,-];
Margins = [5mm,5mm,-];
CenterOD = 5.0mm;
TextFont = FONT_HSANS_1_RS; // single stroke stick font
TextSize = 3.0 * [1.0mm,1.0mm];
//-----
// Draw it
feedrate(PenSpeed);
comment("Draw title info");
tp = scale(typeset("Scale & Backlash Test Pattern",TextFont),TextSize);
tp += [-PlotSize.x/2 + GridSize.x/2,PlotSize.y/2 - GridSize.y/2,-];
engrave(tp,TravelZ.z,PenZ.z);
tp = scale(typeset("Grid " + GridSize,TextFont),TextSize);
tp += [-PlotSize.x/2 + GridSize.x/2,PlotSize.y/2 - GridSize.y/2 - 1.5*TextSize.y,-];
engrave(tp,TravelZ.z,PenZ.z);
tp = scale(typeset("F " + PenSpeed + "/min",TextFont),TextSize);
tp += [-PlotSize.x/2 + GridSize.x/2,PlotSize.y/2 - GridSize.y/2 - 3.0*TextSize.y,-];
engrave(tp,TravelZ.z,PenZ.z);
tp = scale(typeset("Ed Nisley - KE4ZNU",TextFont),TextSize);
tp += [-PlotSize.x/2 + GridSize.x/2,-(PlotSize.y/2 - GridSize.y/2),-];
engrave(tp,TravelZ.z,PenZ.z);
tp = scale(typeset("softsolder.com",TextFont),TextSize);
tp += [-PlotSize.x/2 + GridSize.x/2,-(PlotSize.y/2 - GridSize.y/2 + 1.5*TextSize.y),-];
engrave(tp,TravelZ.z,PenZ.z);
comment("Mark center point");
goto(SafeZ);
goto([CenterOD/2,0,-]);
move(PenZ);
circle_cw([0,0]);
comment("Label axes");
tp = scale(typeset("X+",TextFont),TextSize);
tp += [GridSize.x + 0.5*TextSize.x,-TextSize.y/2,-];
engrave(tp,TravelZ.z,PenZ.z);
tp = scale(typeset("Y+",TextFont),TextSize);
tp += [-TextSize.x/2,GridSize.y + 0.5*TextSize.y,-];
engrave(tp,TravelZ.z,PenZ.z);
comment("Draw left-to-right");
tp = scale(typeset("L to R →",TextFont),TextSize);
tp += [-PlotSize.x/2 + GridSize.x/2 - tp[-1].x/2,GridSize.y/2,-];
engrave(tp,TravelZ.z,PenZ.z);
goto([-(PlotSize.x/2 + Margins.x),GridSize.y,-]);
for (p=[-PlotSize.x/2,GridSize.y,-] ; p.x <= PlotSize.x/2 ; p.x += GridSize.x ) {
comment(" p: ",p);
goto(p);
move(PenZ);
move_r([-,-GridSize.y,-]);
goto(TravelZ);
}
comment("Draw right-to-left");
tp = scale(typeset("R to L ←",TextFont),TextSize);
tp += [PlotSize.x/2 - GridSize.x/2 - tp[-1].x/2,-GridSize.y/2,-];
engrave(tp,TravelZ.z,PenZ.z);
goto([(PlotSize.x/2 + Margins.x),-GridSize.y,-]);
for (p=[PlotSize.x/2,-GridSize.y,-] ; p.x >= -PlotSize.x/2 ; p.x -= GridSize.x ) {
comment(" p: ",p);
goto(p);
move(PenZ);
move_r([-,GridSize.y,-]);
goto(TravelZ);
}
comment("Draw bottom-to-top");
tp = scale(typeset("B to T ↑",TextFont),TextSize);
tp += [-GridSize.x/2 - tp[-1].x/2,-(PlotSize.y/2 - TextSize.y),-];
engrave(tp,TravelZ.z,PenZ.z);
goto([-GridSize.x,-(PlotSize.y/2 + Margins.y),-]);
for (p=[-GridSize.x,-PlotSize.y/2,-] ; p.y <= PlotSize.y/2 ; p.y += GridSize.y ) {
comment(" p: ",p);
goto(p);
move(PenZ);
move_r([GridSize.x,-,-]);
goto(TravelZ);
}
comment("Draw top-to-bottom");
tp = scale(typeset("T to B ↓",TextFont),TextSize);
tp += [GridSize.x/2 - tp[-1].x/2,(PlotSize.y/2 - 1.5*TextSize.y),-];
engrave(tp,TravelZ.z,PenZ.z);
goto([GridSize.x,(PlotSize.y/2 + Margins.y),-]);
for (p=[GridSize.x,PlotSize.y/2,-] ; p.y >= -PlotSize.y/2 ; p.y -= GridSize.y ) {
comment(" p: ",p);
goto(p);
move(PenZ);
move_r([-GridSize.x,-,-]);
goto(TravelZ);
}
comment("Draw circles");
maxr = (PlotSize.x < PlotSize.y) ? PlotSize.x/2 : PlotSize.y/2;
for (r=GridSize.x/2 ; r <= maxr ; r += GridSize.x) {
comment(" r: ",r);
goto([-r,0,-]);
move(PenZ);
circle_cw([0,0,-]);
goto(TravelZ);
}
goto(SafeZ);
goto([0,0,-]);
view raw Scale Grid.gcmc hosted with ❤ by GitHub

One thought on “GCMC XY Axis Calibration Target

Comments are closed.