Wednesday, 19 August 2026

Improving homing accuracy on the Linuxcnc Bantam lathe?

Recently I've been messing with the CNC-converted Bantam lathe. This uses the Probe Basic Lathe GUI and I've been beta testing an add-in component that provides a conversational interface, for when you want to run fairly simple operations without needing to create full blown CAM toolpaths in Fusion.

The author (Chris Polanski) suggested I look at using the index pulses from the servo drive to improve accuracy of homing. Currently I have a proximity switch on the Z axis and a microswitch on the X axis but I know these have rather limited accuracy and repeatability. Given the state of the machine, that's not been an issue to date, not least due to my limited use of the thing. However, as I have closed loop positional control based on feedback from linear encoders, it seems a shame not to improve what is the main weakness in this setup. 

This is a well established concept - on the face of it, you hit the home switch, then look at the status of the Z (index) output from the servo drive. This output is software generated within the FPGA and can be scaled to suit your system. So no matter what the resolution of the encoder within the servo motor, you can generate and output the output pulse per rev (PPR) that suits your installation. This also outputs the "index" pulse that indicates when the motor has made one complete revolution.

The problem here is that LinuxCNC expects the index pulse to come from the same source (encoder) as the position signal. Trying to use the position info from a linear encoder along with the index pulse from the servo isn't quite as straightforward as you might hope.

Rather than try to "research" this subject myself, hoping to learn from other peoples' struggles, I thought I'd ask my mate Claude to do some legwork. I got the responses formatted for Blogger, since Blogger doesn't retain formatting when you try to copy and paste from a Claude chat session - and here they are:

Homing a CNC lathe on servo-drive index pulses (LinuxCNC)

Setup: linear encoders on X/Z for closed-loop feedback, no index output on the scales themselves, homing currently done with microswitches. Servo drives do provide Z (index) outputs. Controller: LinuxCNC on Mesa 5i25 + 7i76 + 7i85.

Why this is harder than it looks

  1. Index detection has to happen in hardware, not software. An index/Z pulse is too narrow to be reliably caught by LinuxCNC's servo/base thread polling a GPIO — it has to be latched by a hardware encoder counter (e.g. on a Mesa FPGA card).
  2. LinuxCNC's standard homing assumes the index belongs to the same counter as position feedback. In this setup the index comes from the drive's motor-side encoder, while position feedback comes from an independent linear scale — two different physical devices.
  3. The drive's index repeats every motor revolution, not once per axis stroke, so it can't be an absolute reference by itself — a microswitch is still needed to select the correct revolution before latching to index for fine repeatability.
  4. Gating nuance: hardware encoder counters typically only latch index when A/B are in a defined state, which normally assumes A, B, and Z all come from the same device.

Prior art

The working approach: gate the switch with the index, don't cross-correct positions

You don't need to reconcile the drive's index position with the linear scale's count. LinuxCNC's normal HOME_USE_SWITCH homing already captures the joint's real position feedback (the linear scale) at the instant home-sw-in transitions. The drive index just needs to produce one clean, hardware-latched, repeatable edge to replace the mechanical switch's mushy trip point.

A small halcompile component from the LinuxCNC forum does exactly this, confirmed working by multiple users (one reported repeatability to 1.5 tenths / 0.00015" / 3.8um):

component index_toggle "extends the limit switch area to the next index pulse";
pin io bit index-enable "connect to the index-enable of an encoder counter";
pin in bit home-sw-in "connect to the home switch input pin";
pin out bit home-sw-out "connect to the motion controller home switch input";
function _;
license "GPL";
;;
static int old_sw = 0;
if ((!old_sw) && home_sw_in) index_enable = 1;
home_sw_out = index_enable;
old_sw = home_sw_in;

Install with:

sudo halcompile --install index_toggle.comp

Logic: when the microswitch trips (rising edge), it arms index-enable on a spare encoder counter. The hardware counter auto-clears index-enable the instant it sees the next index pulse. home-sw-out mirrors index-enable, so the motion controller sees a clean transition timed to the hardware-latched index event instead of switch bounce.

Why the 5i25 + 7i76 + 7i85 stack fits well

The 7i85 provides 4 differential/TTL-selectable encoder channels. If the two linear scales already occupy channels 0/1, channels 2/3 are free — wire each drive's index (Z) output there. Since index_toggle only cares about the index-enable/detect event, that channel doesn't need to carry real position feedback; it's purely a trigger source.

Gotchas to plan for

  • A/B gating on the index — wire the drive's full A/B/Z encoder-follower output into the spare 7i85 channel, even though its count is ignored, so the index gate condition is satisfied cleanly.
  • Signal type match — confirm whether the drives' encoder-follower output is differential RS422 or single-ended TTL/open-collector and set the 7i85 channel mode accordingly.
  • Stale index-enable state — one forum user saw the axis home to its power-up position instead of true home, traced to a stale latch rather than a fresh index event; verify in HalScope.
  • Switch bounce — a bouncy microswitch could re-arm index-enable early; a debounce or tof component ahead of home-sw-in is cheap insurance.
  • Use HOME_USE_SWITCH, not HOME_USE_INDEX — since the trigger arrives via home-sw-in, configure normal switch-based homing in the INI, not the same-device index mechanism.
Where are we today?

Before getting totally carried away with this business, let's just see where we are starting from today.

Using a decent (Mitutoyo) 10um DTI, I find that ~90% of X homing moves result in a positional accuracy of around 1-2um (the needle is barely off the zero mark) - and the remaining ~10% are out by +5um, which is the minimum incremental move that my machine can make due to the linear encoder resolution. The homing switch in this axis is a reasonably decent quality microswitch. I'm happy with that result, so should let that particular sleeping dog lie.

The Z axis is a different matter, as I chose to use an Omron proximity switch for homing, despite them not really being appropriate for precision homing. And sure enough, the home position typically varies by around 30-40um, which is pretty shit.

This sounds like an ideal application for "homing to index marker", using the servo motor's encoder index. As the leadscrew pitch is 5mm and the belt reduction is less than 2:1, I should be able to significantly improve the homing accuracy. So it perhaps makes sense to implement this method on the Z axis but not bother on the X axis. No point making unnecessary work for myself.

And another thing - placing those proximity sensors face up like this, just below the toolpost doesn't get much dumber. As you can see (if you look closely), they form a nice ledge for swarf to land and trip the limit switch (the LH one). At which point the machine stops, as it should when the axis limit is exceeded.


For now, I may simply disconnect the Zlim switch but should also check what happens if the Zhome switch is triggered during operation. And the longer term solution requires some form of shielding to keep swarf away from these devices. That could simply be a bit of bent sheet metal attached to the underside of the carriage.

Let's have a go at implementing this idex mark scheme on the Z axis....

No comments:

Post a Comment

Improving homing accuracy on the Linuxcnc Bantam lathe?

Recently I've been messing with the CNC-converted Bantam lathe. This uses the Probe Basic Lathe GUI and I've been beta testing an ad...