Laser XY zeroing

Yet another “let’s do something to beat procrastination tonight” moment.
The other day I bought a couple of those laser cross-hairs for $15 on Amazon:

This was on my todo list of things to try to have a better way to eyeball X/Y zeroing in cases where a probe for X and Y is not convenient (think V-bit)

I started thinking about how to route a 5V wire from the controller, started 3D printing something to mount the laser onto my dust shoe arms, adding a switch, etc…and then thought, there’s no time for thinking tonight, let’s just slap this thing on the side of the spindle with blue tape, use a separate 5V power supply, and get to work.

So here’s take #1

  • I first made a note of how far along X and Y the laser dot is from the center of the spindle, and wrote a oneline G-code macro to move by that amount.
  • then jogged to the target point on the stock (not quite visible, circled cross)
  • clicked the macro: spindle moves to where the laser dot was.

It does not get more basic, but I feel there’s potential there for a cool feature, if I integrate this correctly.

My intended workflow would be to turn the laser on, then first use the crosshair to help aligning stock to machine axes when installing it onto the wasteboard. Then use the crosshair to define X0Y0. Finally click a button to move there and probe Z normally.

Things I have to do now:

  • route the 5V from the board to the top of the Z and down to the laser
  • add a switch/pushbutton
  • design and print an attachment that is adjustable in height, to be able to focus the crosshair when stock thickness varies.

To be continued…


As those are 12mm diameter and round, why not print up a mount to just insert one in a large collet in your ER20 spindle?

That would let you use it to quickly find X, Y zero and then tool change to Z.

1 Like

I could, but I’m pretty sure I would soon give up the effort of inserting the laser for zeroing then swapping it with the real tool. I need this always available at the push of a button.


It might also throw off the bitsetter, wouldn’t it?

OK @Julien…so now you’ve got me thinking. I have a JTech Laser…already mounted to my spindle. I’d imagine the laser is a consistent distance from the spindle center…probably spot on. If CM could fire the laser at 3% power, I could use it to easily set center.

The added bene to this comes when I do a mixed router/laser project…where I’m cutting shapes with the router first and then adding etching with the laser. The original problem I faced was moving the design from CC to LightBurn (you remember this post) - but the LightBurn guys solved that problem…but now I need to find the exact starting point for the laser run after the router work is done. This would solve that problem. I’d return to xy zero in CM, and run a macro to move by the offset, putting the laser exactly on the CM XY Zero mark, then run LightBurn to burn the rest! I like this…New Feature Request!

1 Like

I did consider using my JTech as the “jogging laser”, but I thought using it would interfere with my spindle control, since both get the same PWM signal. It is probably doable though to setup the VFD so that it does not start spinning the spindle below say 0.15V, and then the laser would still see 3% power.
The other minor inconvenience would be that you loose the crosshair pattern, so it would not be useful to align the stock anymore (but there are others ways, e.g. using a corner square, this crosshair alignment thing is useful for me since I use a wasteboard with no holes)

Until CM supports macros, you could use the workflow you suggest by using the MDI console to send commands:

M3S{0.03 x the value of your $30 param} to start the laser dot,
M5 to stop it,
G0 X{fixed laser offset along X in inches} Y{fixed laser offset along Y in inches}
to move the spindle by the laser dot offset

or maybe put those lines in G-code files and run that. Not as convenient as a button in the UI, but simple enough.

1 Like

Gentlemen, why not use a more mechanical method to spot the offset in the same manner? Produce a mount for a “skewer-shaped” pointer that you move toward the Z-zero level when needed. Manually lower this pointer down to mark the non-precise XY starting point, and you don’t need to change to a pointy bit (or build an new electronic system. :smiley: )

I was threatening myself to do this while I was having my “Bitsetter Meltdown.”


but…lasers are cool, what can I do… :slight_smile:


This is great for my scenario even if I don’t use the JTech as the centering tool. The idea is that I’d like to burn onto the same piece that I’ve already cut with the router (or vice-versa). Synching the designs on a center point is easy (now), but finding the EXACT same center by eye is difficult. This would do it every time. l would zero one or the other device, run the job, and then run the appropriate commands to compensate for the offset between the devices, and run the other device’s jobs. Voila!

I don’t know the GRBL codes, I’m sure there’s a reference to find out what they mean (EDIT: I just found the Github reference for GRBL 1.1 ( I know LightBurn supports macros, so I could build them into LB.


And I don’t have to worry about this, I don’t think, because I turn my router on and off manually. Correct?

1 Like

Cool beans, then.

FYI I wrote a very small G-code intro with the most common commands here:
And indeed you can use macros in LightBurn, I was too focused on CM.

Absolutely, I was mislead by your mentioning your “spindle”, not “router” (it’s funny how one initially uses “spindle” or “router” interchangeably, and then becomes very picky about that term after upgrading to a spindle :wink: ).

And even if you had a BitRunner it would be ok, because it only triggers around 1.8V


Newbie Question: Why not use a $J (Jog) command? Or, are they apples and oranges?

$J is for continuous (smooth) jogging, so it could work too but that would just be less “natural” than using a plain G0 (move) command.

Can you set the feed rate in a G0, or do you have to set the rapid rate before? Or am I talking gibberish?

G0 moves always move at the defined rapid rate.

G1/2/3 move at the specified feedrate.


Got it…So one command, “$J=X-5 Y-10 F100” would move me back 5 and left 10 (if I have +/- right) at 100% of rapid…right?

Not understanding the $J syntax.

G1 X-5 Y-10 F100

would move to that coordinate at 100 units (Inches or whatever the metric standard is (mm in Grbl I believe)) per min.


G0 X-5 Y-10

would make the same move at rapid speed.

You are right (of course) about the F parameter 100 units/min.

Wonder why they have the Jog command at all. Seems you can combine a lot on the line, including some G settings…not sure… it’s all new to me.

EDIT: Answered my own question from the Github documentation discussing the new Jog Commands:

These commands differ because they can be cancelled and all queued motions are automatically purged with a simple jog-cancel (0x85 as explained in Extended Ascii Realtime Command ) or feed hold real-time command. Jogging commands do not alter the g-code parser state in any way, so you no longer have to worry if you remembered to set the distance mode back to G90 prior to starting a job. Also, jogging works well with an analog joysticks and rotary dials!

$J=line - Run jogging motion

New to Grbl v1.1, this command will execute a special jogging motion. There are three main differences between a jogging motion and a motion commanded by a g-code line.

  • Like normal g-code commands, several jog motions may be queued into the planner buffer, but the jogging can be easily canceled by a jog-cancel or feed-hold real-time command. Grbl will immediately hold the current jog and then automatically purge the buffers of any remaining commands.
  • Jog commands are completely independent of the g-code parser state. It will not change any modes like G91 incremental distance mode. So, you no longer have to make sure that you change it back to G90 absolute distance mode afterwards. This helps reduce the chance of starting with the wrong g-code modes enabled.
  • If soft-limits are enabled, any jog command that exceeds a soft-limit will simply return an error. It will not throw an alarm as it would with a normal g-code command. This allows for a much more enjoyable and fluid GUI or joystick interaction.

Executing a jog requires a specific command structure, as described below:

  • The first three characters must be ‘$J=’ to indicate the jog.
  • The jog command follows immediate after the ‘=’ and works like a normal G1 command.
  • Feed rate is only interpreted in G94 units per minute. A prior G93 state is ignored during jog.
  • Required words:
    • XYZ: One or more axis words with target value.
    • F - Feed rate value. NOTE: Each jog requires this value and is not treated as modal.
  • Optional words: Jog executes based on current G20/G21 and G90/G91 g-code parser state. If one of the following optional words is passed, that state is overridden for one command only.
    • G20 or G21 - Inch and millimeter mode
    • G90 or G91 - Absolute and incremental distances
    • G53 - Move in machine coordinates
  • All other g-codes, m-codes, and value words are not accepted in the jog command.
  • Spaces and comments are allowed in the command. These are removed by the pre-parser.
  • Example: G21 and G90 are active modal states prior to jogging. These are sequential commands.
    • $J=X10.0 Y-1.5 F100 will move to X=10.0mm and Y=-1.5mm in work coordinate frame (WPos) at a feed rate of 100.
    • $J=G91 G20 X0.5 F10 will move +0.5 inches (12.7mm) to X=22.7mm (WPos) at a feed rate of 10. Note that G91 and G20 are only applied to this jog command.
    • $J=G53 Y5.0 F10 will move the machine to Y=5.0mm in the machine coordinate frame (MPos) at a feed rate of 10. If the work coordinate offset for the y-axis is 2.0mm, then Y is 3.0mm in (WPos).

Jog commands behave almost identically to normal g-code streaming. Every jog command will return an ‘ok’ when the jogging motion has been parsed and is setup for execution. If a command is not valid or exceeds a soft-limit, Grbl will return an ‘error:’. Multiple jogging commands may be queued in sequence.

1 Like

Careful using jog commands without explicitly setting the distance mode. Your controller is usually in absolute mode (G90), so that jog command would move TO work position X-5 Y-10. That could be crash of zero is set front left and you’re in G20 (inches) mode. The nice thing about the $J is that any change to those modes only apply during that jog move. So, by adding a G91 to the jog, you don’t have to work about resetting G90 after.
I don’t think you gain much by manually sending the $J commands though.

Edit: I scrolled and saw you pasted the GRBL wiki, so I’m assuming you know this now.

Ha! Make no assumptions. I’m a total newbie when it comes to GRBL. Thanks for the info.

1 Like