Friday, 21 August 2026

Measuring and optimising the homing setup - proximity switch vs servo index mark

As mentioned in the last post, I'm not convinced the  homing setup on the Colchester bantam CNC is quite optimised. I'm thinking it might be helpful to connect up the servo driver synthesised encoder output to one of the spare 7i85 encoder inputs. But first, let's see what we are dealing with. I have to get an idea how much backlash there is in the system as well as optimising the actual homing setup. No point trying to get precise homing if the backlash is all over the place.

I ran a backlash test, where the carriage

  • moves 1mm away from starting position in Z
  • returns to starting position, dwells for 1 second (read position on encoder)
  • moves 1mm in other direction
  • returns to starting position, dwells for 1 second (reread position on encoder and compare)
  • ...repeats for a total of 10 times
The difference between the 2 readings in each cycle is the backlash of the (unloaded) axis. Obviously this will be worse when there is a cutting load on the tool and there will also be some compliance (springiness) associated with the applied load. 

Here are the results:

Z axis settling trace

Commanded vs. actual feedback position from hm2_5i25.0.encoder.03 during the ±1mm backlash-check program, sampled at the 3ms servo period via sampler/halsampler. Ten cycles shown below; the shaded band marks the ±4.5µm PID deadband.

Peak overshoot (mean)
28.5µm
Peak overshoot (max)
70.0µm
Settled error (mean)
3.5µm
Dwells sampled
20






Per-dwell readings

Peak deviation during each 1s hold, and the error remaining once the dwell ends

#t (s)peak dev (µm)settled err (µm)
10.00+15.00.0
21.65-20.00.0
33.29-50.0+5.0
44.93+25.0+5.0
56.57-70.0+10.0
68.21+40.0+5.0
79.85-45.00.0
811.49+40.00.0
913.13-15.0+5.0
1014.77+30.0+5.0
1116.41+10.00.0
1218.05+20.0-5.0
1319.69-35.0-5.0
1421.33+40.0-5.0
1522.97-15.0-5.0
1624.61+20.00.0
1726.25-10.0-5.0
1827.89+30.00.0
1929.53-20.0-5.0
2031.17+20.0-5.0
Captured from a live run of z_backlash_check.ngc (10 cycles, 200mm/min, 1s dwells). Servo period 3ms. Raw samples: z_trajectory.txt.

Now for the actual homing tests. Logging the raw encoder position (which doesn't vary between homing events) shows the variation between homing events.

At the instant home_sw_out falls (ie when the index mark is captured) across 12 capture events from 6 homing cycles:

t(s)fb (mm)cmd (mm)following error (µm)
27.2013.01502.953861.2
29.9013.01002.965844.2
35.8743.00502.958846.2
38.5653.02002.961858.2
44.4513.01502.983831.2
47.1213.00002.965834.2
52.6083.02002.963856.2
55.3053.01502.972842.2
60.9752.99502.963831.2
63.6543.01003.00881.2
68.7993.01502.993821.2
71.4573.01002.999810.2

Two observations:
  1. The linear scale reading itself (fb) at the capture instant spans 2.9950–3.0200mm — a 25µm spread, even though the underlying index event is electrically identical every time.
  2. The following error at that instant swings from 1.2µm to 61.2µm — because the capture happens mid-motion (during the backoff/re-approach), and how much the axis is lagging or overshooting its commanded trajectory at that precise 3ms tick varies a lot cycle to cycle.
The index event is perfectly repeatable, but LinuxCNC only ever sees "the signal changed" at ordinary software-polling resolution, and captures whatever the linear scale happens to read at that moving instant — which inherits the servo loop's in-motion dynamics rather than a settled, at-rest value. That 25µm scale-reading spread is a real, substantial chunk of the ~70µm total homing scatter we measured.

So the index-gating mechanism is working as designed, but although it can gate when the position gets read, it can't make that reading immune to whatever the servo loop is doing at that mid-motion moment. Fixing that further would mean a different approach entirely (e.g. capturing position only once the axis has fully stopped and settled after the index fires, rather than during the backoff move itself) - that level of work isn't going to happen.

After some buggering about with the PID values, the search distance and the homing velocity, the error is much better and it matches the DTI readings I've made by eye:

mean |err|max |err|gap
Original switch position24.0µm56.2µm~2119µm
Best prior (884µm gap)10.7µm56.2µm~886µm
Current11.4µm28.8µm~482µm

Matching the best mean we've seen, but with a tighter max (28.8 vs 56.2µm) and less than half the wasted travel. This lines up well with the DTI's 3-40µm read (our computed range is 1.0-28.8µm — DTI rounding easily accounts for the difference). We've gone from ~2.1mm of unnecessary travel and 24µm mean error down to ~0.5mm and ~11µm mean error.

At this point we have: index_toggle + mux_generic wiring validated, HOME_FINAL_VEL and HOME_LATCH_VEL tuned, the switch repositioned to a good phase alignment, and PID reverted to its best values. 

The current HAL/INI state uploaded to Github repo and the Claude project memory updated with the final settings and results.

  • Committed and pushed (becc808 on feature/qt-lathe-macros): the index_toggle/mux_generic HAL wiring, HOME_FINAL_VEL/HOME_LATCH_VEL tuning, and the new index_toggle.comp source.
  • Currently defaults to legacy switch homing on boot (mux-gen.00.sel-bit-00=FALSE) — flip to index-gated live with halcmd setp mux-gen.00.sel-bit-00 1 whenever you want it, or say the word if you'd like it made the permanent default.
  • PID gains reverted to the original P=50/D=3 — the tuning experiments there didn't pan out.
  • Final result: mean home-position error down to ~11µm from the original ~24-36µm, matching your DTI reading — driven mostly by HOME_FINAL_VEL and the switch repositioning, with index-gating itself turning out to be a smaller factor than expected once the real bottleneck (mid-motion capture during the software-polled switch/index transition) was understood.
  • Memory's consolidated into a single clean record for next time, including the reusable debugging techniques (halrun dry-testing, sampler/halsampler, the shell-arrow gotcha) in case this comes up again.
Comparing both axes on the same basis (ie how does the index mark homing scheme compare wit the original proximity switch scheme?)

Z home repeatability, both schemes

Each dot is one homing cycle's resting hm2_5i25.0.encoder.03.position (the raw Z scale feedback, not the DRO -- unaffected by the homing offset reset). Jog-away and settle time were held constant between cycles; only the homing method changes.


I think we can honestly say that there is no discernible difference between the 2 methods. Hmm. Wiring the servo driver up to the 7i85 may well have been a waste of time.


https://claude.ai/code/artifact/be0d16d4-ab58-42b8-bfda-7fb55a812683

After some similar messing about (sorry, "optimising"), we have implemented the "learnings" from the Z axis activity over to the the X axis. I'd like to think we are better than when we started - and also close to the optimal point.


Servo homing results, Z and X

Each dot is one homing cycle's resting position (raw linear-scale feedback, not the DRO -- unaffected by the homing offset reset), shown as deviation from that group's own mean so spreads are directly comparable across groups measured in different sessions. Same jog-away and settle protocol throughout.


Legacy: prox switch trigger. Index-gated: index_toggle HAL component arming the servo's hardware index pulse off the same switch. Same jog-away distance, same settle time, same HOME_FINAL_VEL for both.


Legacy: prox switch trigger. Index-gated: index_toggle HAL component arming the servo's hardware index pulse off the same switch. Same jog-away distance, same settle time, same HOME_FINAL_VEL for both.


Both charts show deviation from each group's own mean (in µm), so spreads are directly comparable — hover any dot for its exact reading and cycle number.

  • Z: legacy vs. index-gated — 75µm vs 70µm spread, essentially a tie once HOME_FINAL_VEL was fixed
  • X: before vs. after the fix — 120µm → 70µm spread, with the same improvement made.
I have to say there is still work to be done, as these are still shit numbers, given that we have a 5um resolution on the encoders. Let's leave it here until next time.....


No comments:

Post a Comment

Bantam CNC - final homing and backlash optimisation (phew) - index homing no more.

There's still some work to be done on this homing accuracy business. Let's see if we can crack it finally. The decision to use the C...