Back to printer -
New Z Hopper motors arrived - bought full linear actuators - which I will take apart - as seems to be most cost effective way to source Nema 11 lead screw motors

Tap sensoring now working.
Logic is
1.Home All
2. G32 Z motor alignment
3. Then for each print head
4. Move other print heads 2mm up so that they are out of the way
5. Align Z hopper to just trigger optical sensor
6. Move head down about 0.02 mm to just past the trigger point.
7. Switch probes/endstops so that the Z axis now has the Z hopper end stop as its trigger. (inverted)
8. Move Z down until print head hits to bed and then pushes up slightly within the play of the print head to disable the triggered optical sensor.
9. Repeat for various points of the print bed,
Short demo - showing tapping and play/flex - which might end up being a problem
https://youtu.be/5FGALqWV4t8
Example Tap test macro.
;tap A.g
M98.1 A"B On"
;reset probes to correct values
M574 Z1 S2 K0; configure Z axis endstop
M574 A1 P"122.io2.in" S1 ; configure A axis endstop
G90
G1 Z3 F1000
G1 D{global.dOffset+2} F1000
G1 B{global.bOffset+2} F1000
var speed = 400
;var w = {224, 224, 324, 324}
;var v = {310, 210, 210, 310}
var w = {160, 200, 200, 160, 324}
var v = {160, 160, 240, 240, 310}
var point1 = -1
while iterations < 5
var iGrid = iterations
G1 W{var.w[var.iGrid]} V{var.v[var.iGrid]} F10000
;echo "W",var.w[iterations],"V",var.v[iterations]
while iterations < 2
M574 Z1 S2 K0; configure Z axis endstop
M574 A1 P"122.io2.in" S1 ; configure A axis endstop
var aMax = 0
var aPos = 0
var aMin = 99
while iterations < 1
G1 A3 F{var.speed}
M400
var aProbe = sensors.endstops[6].triggered
if var.aProbe
abort "A Probe already triggered"
G1 H4 A-2 F{var.speed}
set var.aPos = move.axes[6].machinePosition
;echo "D trigger pos",var.dPos
if var.aPos > var.aMax
set var.aMax = var.aPos
if var.aPos < var.aMin
set var.aMin = var.aPos
var aProbe = false
if var.aMax-var.aMin > 0.03
echo "variation",var.aMax-var.aMin,var.aMin,var.aMax
while iterations < 4
;echo "i",iterations
G1 A{var.aPos-0.01*iterations} F{var.speed}
M400
set var.aProbe = sensors.endstops[6].triggered
if !var.aProbe
abort "A Probe not triggered"
else
if iterations > 1
echo "lowered head ",0.01*iterations,"mm"
break
M574 A1 P"122.io3.in" S1 ; configure A axis to temporary Endstop
M574 Z1 P"!122.io2.in" S1 ; configure Z Axis to A end stop inverted
var zPos = 0
G1 Z{var.zPos+2} F500
M400
set var.aProbe = sensors.endstops[2].triggered
if var.aProbe
abort "AZ Probe already triggered"
G1 H4 Z-7 F{var.speed}
set var.zPos = move.axes[2].machinePosition
if var.point1 == -1
set var.point1 = var.zPos
echo "A zPos",var.zPos,"W",var.w[var.iGrid],"V",var.v[var.iGrid],"point",var.iGrid,"var",var.zPos-var.point1
G1 Z3 F1000
;restore probes
M574 Z1 S2 K0; configure Z axis endstop
M574 A1 P"122.io2.in" S1 ; configure A axis endstop
; 122.io3.in - dummy endstop when A swapped out