The Smell of Molten Projects in the Morning

Ed Nisley's Blog: Shop notes, electronics, firmware, machinery, 3D printing, laser cuttery, and curiosities. Contents: 100% human thinking, 0% AI slop.

Tag: CNC-3018XL

Small gantry router

  • CNC-3018XL: Reversing the Axes

    CNC-3018XL: Reversing the Axes

    The CNC-3018XL fit into its new home with the Run/Hold buttons toward the front:

    3018CNC - new orientation
    3018CNC – new orientation

    Which is rotated 180° from its previous orientation, putting Quadrant I and the most-positive coordinates in the left-front corner. Rather than stand on my head while trying to use the jog keypad upside-down, I reversed the axis directions by changing the GRBL Direction port invert mask value from its previous 4:

    $3=7

    Because the home switch positions haven’t changed, reverse the Homing dir invert mask from 0:

    $23=3

    The XY origin remains in the center of the platform, so the G54 XY offset didn’t change. The Z offset puts the Pilot pen tip 10 mm above the platform, which will change as you (well, I) touch it off on the paper:

    G10 L2 P1 X-169.0 Y-149.5 Z-44.0

    Jog to the left rear corner (with Z at the home position) and set the G28 park position:

    G28.1

    Jog to the right front corner (also Z homed) where (manual) tool changes take place:

    G30.1

    Configure bCNC for manual tool changes without probing at the G30 position:

    bCNC probe config
    bCNC probe config

    The machine will move to the tool change position at each Tn M6, the operator (that would be me) inserts tool pen n as needed, pokes the Run button, and watches it draw pretty pictures in a resolutely techie manner:

    3018CNC - Spirograph test pattern
    3018CNC – Spirograph test pattern

    For completeness, the current GRBL settings:

    $$
    $0=10
    $1=100
    $2=0
    $3=7
    $4=0
    $5=0
    $6=0
    $10=1
    $11=0.010
    $12=0.020
    $13=0
    $20=1
    $21=0
    $22=1
    $23=3
    $24=100.000
    $25=2000.000
    $26=25
    $27=1.250
    $30=1000
    $31=0
    $32=0
    $100=401.284
    $101=400.000
    $102=400.000
    $110=3000.000
    $111=3000.000
    $112=3000.000
    $120=1000.000
    $121=1000.000
    $122=1000.000
    $130=338.000
    $131=299.000
    $132=44.000
    $#
    [G54:-169.000,-149.500,-34.450]
    [G55:0.000,0.000,0.000]
    [G56:0.000,0.000,0.000]
    [G57:0.000,0.000,0.000]
    [G58:0.000,0.000,0.000]
    [G59:0.000,0.000,0.000]
    [G28:-335.000,-3.310,-3.450]
    [G30:-1.000,-297.000,-1.000]
    [G92:0.000,0.000,0.000]
    [TLO:0.000]
    [PRB:0.000,0.000,0.000:0]
    

    The weird $100 X axis step/mm value is correct, because QC escapes are a thing.

  • CNC-3018XL: Foam Feet

    CNC-3018XL: Foam Feet

    The 3018XL plotter now lives on a different bench than it grew up on and the stepper motors resonate the plywood benchtop wonderfully well. After finding the machine weighs enough to flatten small foam blocks under the Official Feet, I cut out four 60×80 mm foot pad brackets:

    3018XL - foam foot pad bracket
    3018XL – foam foot pad bracket

    They’re attached to the 2040 frame extrusions with M4 screws into tee nuts; the third hole is there just in case it became necessary. I’m not sure whether MDF will bend under that offset load, but having all four brackets perfectly fit into two pieces of MDF left over from previous projects was a compelling justification.

    Some utility knife work produced the foam pads from a big sheet of polyethylene packing material:

    3018XL - foam foot pad - installed
    3018XL – foam foot pad – installed

    A piece of double-sided duct tape with amazingly gooey adhesive joins foam and bracket.

    If the resonance was annoying to my deflicted hearing, it must have been pretty bad. Now, even Mary thinks it sounds OK.

    Now, to discover whether the machine’s weight squashes those big foam blocks.

  • CNC-3018XL Setup: Table Riser Blocks

    CNC-3018XL Setup: Table Riser Blocks

    After fixing the X axis drive, the CNC-3018XL table moved properly again, so I measured its overall alignment:

    3018CNC - table height measurement
    3018CNC – table height measurement

    The +Y side (on the left in the photo, keeping in mind I’ve rotated the axes) turned out to be 0.7 mm too low, so I made a set of riser blocks to level the tabletop:

    Table Riser - solid model
    Table Riser – solid model

    The 10 mm height would ram the tip of a Pilot pen about 10 mm below the tabletop surface, were it not for the spring-loaded pen holder:

    Pilot V5RT holder - installed
    Pilot V5RT holder – installed

    The 0.7 mm difference in height levels the tabletop:

    CNC3018XL - table riser positions
    CNC3018XL – table riser positions

    The OpenSCAD code produces an SVG outline I intended to use for a foam pad, but then I found a quartet of springs that worked even better:

    CNC3018XL - table spring mount
    CNC3018XL – table spring mount

    So it’s now aligned within ±0.3-ish mm across the surface, with the unflatness of a slab cut from a 1955-era Formica kitchen countertop accounting for most of the difference in a swale from Quadrant III across the origin to Quadrant I.

    Which a check plot using an old file shows will be Flat Enough for my simple needs:

    CNC3018XL - test plot
    CNC3018XL – test plot

    Having the camera alignment remain exactly spot on came as a pleasant surprise:

    Camera Alignment check
    Camera Alignment check

    The faded cross to the left came from the table’s previous position; there’s no positive index between the countertop slab and the underlying T-slots.

    Part of the motivation for these blocks was to verify PrusaSlicer automagically handles filament / color changes between two objects, as long as OpenSCAD hasn’t unioned them as part of a common transformation. Not having to cut out the socket around the text simplifies the code from what I’d been doing with previous objects.

    The OpenSCAD source code as a GitHub Gist:

    // CNC 3018 table riser blocks
    // Ed Nisley – KE4ZNU
    // 2025-06-29
    include <BOSL2/std.scad>
    Layout = "Show"; // [Show,Build,Outlines]
    /* [Hidden] */
    HoleWindage = 0.2;
    Protrusion = 0.1;
    BlockOA = [40.0,30.0,10.0]; // riser block size
    SlotBlock = [8.0,BlockOA.y,3.0]; // alignment in slot
    BoltOD = 6.0 + HoleWindage; // central bolt
    LogoFont = "Fira Sans Condensed:style=SemiBold";
    LogoSize = 7.5;
    LogoColor = "Red";
    LogoThick = 0.4;
    //———-
    // Define Shapes
    module Riser(thick=1,matl="Block") {
    LogoText = format_fixed(thick,1);
    if (matl == "Text" || matl == "All")
    right(BlockOA.x/4) zrot(90)
    color(LogoColor)
    up(thick + SlotBlock.z + ((matl == "All") ? 0.01 : 0))
    text3d(LogoText,LogoThick + ((matl == "All") ? 0.01 : 0),LogoSize,LogoFont,
    anchor=TOP,atype="ycenter");
    if (matl == "Block" || matl == "All")
    difference() {
    cuboid(SlotBlock,$fn=8*3,anchor=BOTTOM,rounding=2.0,except=[BOTTOM,TOP]) position(TOP)
    cuboid(BlockOA,$fn=8*3,anchor=BOTTOM,rounding=2.0,except=[BOTTOM,TOP]);
    down(Protrusion)
    zrot(180/6)
    cyl(2*BlockOA.z,d=BoltOD,$fn=6,anchor=BOTTOM,circum=true);
    }
    }
    //———-
    // Build things
    if (Layout == "Show")
    down(SlotBlock.z)
    Riser(BlockOA.z,matl="All");
    if (Layout == "Outlines") {
    projection(cut=false)
    Riser(BlockOA.z,matl="Block");
    }
    if (Layout == "Build") {
    up(BlockOA.z + SlotBlock.z) xrot(180)
    Riser(BlockOA.z,matl="Block");
    up(BlockOA.z + SlotBlock.z) xrot(180)
    Riser(BlockOA.z,matl="Text");
    }

  • CNC-3018XL: Table Drive Nut Overstress

    CNC-3018XL: Table Drive Nut Overstress

    A confluence of unrelated events led me to unboxing and setting up the CNC-3018XL most recently used to plot Homage Tek Circuit Computer decks, but the table slid along its rods entirely too easily. A peek at the leadscrew revealed an assortment of parts last seen when I extended the frame:

    3018CNC - table drive - as found
    3018CNC – table drive – as found

    The featureless cylinder is the leadscrew follower nut, which evidently popped out of its proper place in the table drive block:

    3018CNC - table drive parts
    3018CNC – table drive parts

    The crude chamfer suggests that end went into the block first, so that’s what I did:

    3018CNC - table drive - follower nut installed
    3018CNC – table drive – follower nut installed

    It seems snug enough in there, at least for a machine used solely for plotting and maybe drag knife cuttery, so I’ll assume the box received some rough handling during our move.

    It’s now back in place and seems to work well enough:

    3018CNC - table drive - installed
    3018CNC – table drive – installed

    I briefly considered adding some setscrews to hold it in place, but came to my senses. If it pops out again, maybe it’ll be time to rebuild that block with proper retention.

    The software side of the thing surely needs TLC, too.

  • CNC-3018XL X-Axis Recalibration

    CNC-3018XL X-Axis Recalibration

    Plotting the backlash / calibration target on both the CNC-3018XL and the MPCNC quickly showed, contrary to what I expected, the MPCNC was dead-on accurate, albeit with some wobbulation and a trace of backlash:

    MPCNC - Backlash test - detail
    MPCNC – Backlash test – detail

    Although it looks ug-u-lee, the (lower speed) drag knife cuts come out nice and, because the entry and exit moves match the main cut, the minimal backlash wasn’t a problem.

    Turns out only the X axis on the 3018XL had a problem:

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

    Apparently the longer leadscrew I installed as part of the “XL” conversion has a small thread pitch error: about 1 mm short in every 250 mm of travel. I don’t have any (definite, non-handwavy) method to measure the pitch directly, other than by running the follower nut and measuring the results, but it’s consistently short.

    Quite some time ago (after blowing up the OEM controller board), I set up the Protoneer CNC board in 1:8 microstep mode, making the GRBL $100 setting a nice, round 400 step/mm for a two-start leadscrew with 2 mm pitch and 4 mm lead:

    400 step/mm = (200 step/rev * 8 µstep/step) / 4 mm 

    After a few more measurements suggesting the leadscrew actually traveled 249.2 mm, the correct value will be:

    401.28 step/mm = 400 step/mm × 250 mm / 249.2 mm

    To verify I understood the problem and solution, I set $100 to a few integer values around the goal:

    Cal Target - stacked - 399-402 step-mm
    Cal Target – stacked – 399-402 step-mm

    The top image shows the leftmost line at the 10 mm mark on the scale, because it’s easier for me to match the ink line with an engraved line, rather than the non-line at the end of the ruler.

    The other images show the results for $100 set to 399, 400, 401, and 402 step/mm, respectively. The results last two results bracket the desired 250 mm outcome, with 401 step/mm being Close Enough™. GRBL accepts a floating point step/mm value, so I set $100 to 401.28, but I was unable to convince myself the result came out consistently different than 401.00.

    Plotting both the tick marks (green) and the knife path (red) on the 3018XL, then cutting the bare paper on the MPCNC, showed the two machines now agree on where the knife should fall. The outer end of the tick marks extends 1 mm beyond the cut line to ensure small misalignments do not produce an obvious white gap around the edge of the deck.

    The Y axis continues to match:

    Tek CC - 2022-02-14 - Y detail
    Tek CC – 2022-02-14 – Y detail

    And now the X axis looks just as good:

    Tek CC - 2022-02-14 - X detail
    Tek CC – 2022-02-14 – X detail

    The drag knife corners are rounded, as you’d expect. The cut seems slightly offset from a small origin touch-off error, but the scales now match.

  • GCMC XY Axis Calibration Target

    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
  • CNC-3018XL: Improved X-Axis Home Switch Mount

    CNC-3018XL: Improved X-Axis Home Switch Mount

    A few months of inactivity left the CNC-3018XL table parked in its homed position where the gentle-but-inexorable pressure of the switch lever displaced the foam holding the plastic actuator tab on the X-axis bearing enough that it would no longer operate reliably:

    3018 CNC - Y axis endstop
    3018 CNC – Y axis endstop

    Putting foam tape in a highly leveraged position produces the same poor results as in finance.

    The fix requires reorienting the switch so a solid block on the bearing can push directly on the actuator lever:

    CNC-3018 X Home Switch - bottom view
    CNC-3018 X Home Switch – bottom view

    The block must curve around the bearing to give the tape enough surface area for a good grip:

    CNC-3018 X Home Switch - oblique view
    CNC-3018 X Home Switch – oblique view

    The solid model for the new X-axis mount looks about like you’d expect:

    CNC-3018 X Home Switch Mount - solid model
    CNC-3018 X Home Switch Mount – solid model

    I increased the home switch pulloff to 2 mm, although it’s not clear that will make any difference in the current orientation.

    The OpenSCAD source code as a GitHub Gist:

    // 3018-Pro Mount for Makerbot Endstop PCB
    // Ed Nisley KE4ZNU – 2019-07 (using OEM machine axes)
    // 2022-02-02 rotate X block (after renaming axes to match new layout)
    /* [Build Options] */
    Layout = "Show"; // [Build, Show]
    /* [Hidden] */
    ThreadThick = 0.25; // [0.20, 0.25]
    ThreadWidth = 0.40; // [0.40]
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    Protrusion = 0.01; // [0.01, 0.1]
    HoleWindage = 0.2;
    ID = 0;
    OD = 1;
    LENGTH = 2;
    //- Shapes
    // Basic PCB with hole for switch pins
    // origin at switch actuator corner, as seen looking at component side
    SwitchClear = [15.0,5.0,2.0]; // clearance around switch pins
    SwitchOffset = [12.5,9.0,0.0]; // center of switch pins from actuator corner
    PCB = [26.0,16.4,2*SwitchClear.z]; // switch PCB beyond connector, pin height
    //XBlock = [PCB.x + 10.0,PCB.y,20.0];
    XBlock = [PCB.x,PCB.y,10.0];
    XBearing = [10.0,26.5,28.5];
    XPin = [10.0,20.0,10.0];
    module XMount() {
    if (false) // side-push switch tended to slip
    difference() {
    translate([-10.0,0,0])
    cube(XBlock,center=false);
    translate([0,-Protrusion,10.0])
    cube(XBlock + [0,2*Protrusion,0],center=false);
    translate(SwitchOffset + [0,0,10.0 – SwitchClear.z/2])
    cube(SwitchClear + [0,0,Protrusion],center=true);
    }
    else {
    difference() {
    cube(XBlock,center=false);
    translate(SwitchOffset + [0,0,XBlock.z – SwitchClear.z/2])
    cube(SwitchClear + [0,0,Protrusion],center=true);
    }
    translate([1.25*XBlock.x,0,0])
    difference() {
    cube(XPin + [0,0,XBearing[OD]/4],center=false);
    translate([-Protrusion,XPin.y/2,XPin.z + XBearing[OD]/2])
    rotate([0,90,0])
    cylinder(d=XBearing[OD],h=XPin.x + 2*Protrusion,center=false);
    translate([-Protrusion,-XPin.y/2,XPin.z])
    cube(XPin + [2*Protrusion,0,0],center=false);
    }
    }
    }
    YBlock = [PCB.x,PCB.y,5.0];
    module YMount() {
    difference() {
    cube(YBlock,center=false);
    translate(SwitchOffset + [0,0,YBlock.z – SwitchClear.z/2])
    cube(SwitchClear + [0,0,Protrusion],center=true);
    }
    }
    ZBlock = [PCB.x,PCB.y,6.0];
    ZPin = [20.0,10.0,5.5];
    module ZMount() {
    difference() {
    cube(ZBlock,center=false);
    translate(SwitchOffset + [0,0,ZBlock.z – SwitchClear.z/2])
    cube(SwitchClear + [0,0,Protrusion],center=true);
    }
    translate([1.25*ZBlock.x,0,0])
    difference() {
    cube(ZPin,center=false);
    translate([ZPin.x/2,-Protrusion,4.0])
    cube(ZPin + [0,2*Protrusion,0],center=false);
    }
    }
    //- Build things
    if (Layout == "Show") {
    translate([0,XBlock.y,0])
    YMount();
    translate([0,-XBlock.y/2])
    XMount();
    translate([0,-(ZBlock.y + XBlock.y)])
    ZMount();
    }