Been working today on tidying up probing and tool change macros which is proving quite difficult.
I'm currently on 3.5.4

Biggest issue I am having is with occasional 'Tool is in use or Axis is in use messages' - the biggest problem with these are that they don't stop execution so a) It can cause head clashes and b) They are quick tricky to track down.
I got a surprising tool temperature requirement - absolute zero - which I need to try and track down the cause.

UPDATE: Solved this issue - I had missed out the S on my M568 - so just had 0 - handy to know for the future.
Also I am getting some quite strange behaviour with the U and Z axis - where sometimes when I do a Z move down it seems to also move U left (probably to where X currently is).
If I then move Z up again and U right - it goes a lot further than I am asking - presumably back to its proper position.
It's interesting seeing the head move in 45 degrees - but it is messing up my probing.
See <<< on line 74 in here for the place where it does the strange move.
Update - Solved - I removed all T0 and T1 commands from alignment/homing/cleaning sequences and that seems to have stopped the odd behaviour.
It left the possibility of parts of the macro's being multi threaded by replacing all T0,T1's with M596.1 T0/T1 - which will still do the tool switches when needed.
;AlignUVZ.g
;
if exists(global.ballProbeX) == false
abort "XY alignment not found"
G90
G1 Z50 F10000
T0
G1 X30 Y30 F20000
M400
M98 P"0:/macros/FindProbeUV.g"
M574 Z1 S2 K3; Set Z to Ball Probe
G1 H4 Z{global.zHit-1} F300
if sensors.probes[3].value[0] = 0
echo "Probe not found"
break
;G1 U204 V149 F10000
T1
; Find basic Z position
var Zpos = {50,49,48,48,48}
var Zrate = {300,200,100,100,100}
var Upos = {10,8,8,8,8}
var Vpos = {10,8,8,8,8}
var UVrate = {1000,800,300,300,300}
var prev = false
var pVM = 0
var pUM = 0
var VM=0
var UM=0
while iterations < 2
M574 Z1 S2 K3; Set Z to Ball Probe
G90
G1 Z{var.Zpos[iterations]} F300
G91
G1 H4 Z-12 F{var.Zrate[iterations]}
;echo "Z", {move.axes[2].userPosition}
var ZP = move.axes[2].userPosition
G1 Z5 F5000
M574 Z1 S2 K0; configure Z axis endstop
; Now find U middle
G91
G1 U{0-var.Upos[iterations]} F5000
G90
G1 Z{var.ZP-0.2} F300
G91
M574 U1 S2 K3 ; Configure U axis with Z ball probe
G1 H4 U+10 F{var.UVrate[iterations]}
;echo "X1", {move.axes[0].userPosition}
M400
var U1 = move.axes[3].userPosition
G1 Z5 F300
G1 U{var.Upos[iterations]} F5000
G1 Z-5 ; <<< Strange move - where it also moves U back
M400
G1 H4 U-10 F{var.UVrate[iterations]}
;echo "X2", {move.axes[0].userPosition}
M400
var U2 = move.axes[3].userPosition
G1 Z5
G90
set var.UM = (var.U1+var.U2)/2
;echo "XM", {var.XM}
G1 U{var.UM}
M574 U2 P"!122.io0.in" S1 ; configure U axis endstop
; Now V
G91
G1 V{0-var.Vpos[iterations]} F5000
G1 Z-5 F300
M574 V1 S2 K3
G1 H4 V+10 F{var.UVrate[iterations]}
;echo "Y1", {move.axes[1].userPosition}
M400
var V1 = move.axes[4].userPosition
G1 Z5 F300
G1 V{var.Vpos[iterations]} F5000
G1 Z-5 F300
G1 H4 V-10 F{var.UVrate[iterations]}
;echo "Y2", {move.axes[1].userPosition}
M400
var V2 = move.axes[4].userPosition
set var.VM = (var.V1 + var.V2) / 2
echo "UM", {var.UM},"VM", {var.VM},"ZP", {var.ZP},"---U1,2",{var.U1},{var.U2},"--V1,2",{var.V1},{var.V2}
if (var.prev == true)
echo "variation U:",{var.pUM-var.UM}, "V:", {var.pVM-var.VM}
set var.pVM = var.VM
set var.pUM = var.UM
set var.prev = true
G1 Z5 F300
G90
G1 U{var.UM} V{var.VM} F2000
M574 V2 P"io4.in" S1 ; U Axis optical
M574 Z1 S2 K3; Set Z to Ball Probe
G91
G1 H4 Z-5
var Z1 = move.axes[2].machinePosition
echo "z1",{var.Z1}
G1 Z5 F1000
G1 U4 F10000
G1 H4 Z-10
var Z2 = move.axes[2].machinePosition
echo "z2",{var.Z2}
G1 Z5 F1000
M574 Z1 S2 K0; configure Z axis endstop
if var.Z1-var.Z2 < 1
echo "z1,z2",{var.Z1},{var.Z2}
abort "possible issue with UV alignment"
G90
var adjust = var.UM - global.ballProbeX
echo "adjusting U",{global.ballProbeX - var.UM},"V",{global.ballProbeY - var.VM}
G92 U{global.ballProbeX} V{global.ballProbeY}
if exists(global.UVAdjusted) == false
global UVAdjusted = true
I have written a little wrapper macro form M596 - M596.1 - which a) Has the ability for M596's to be switched off, and be allows the tool to be specified instead of the motion system.
NB/ At present my tools and motion systems are swapped round - i.e. T0 is in motion system 1, and T1 in ms 0 - This was due to issues I was having when I have a servo on T1 (UV axis) - so I may well swap them back around at some point.
;M596.1,g
;M596.1 P-1 ; Ignore M596.1 commands until P-2
if exists(global.M596_stat) == false
global M596_stat = -1
if exists(param.P)
if param.P < 0
set global.M596_stat = param.P
else
if global.M596_stat == -2
M596 P{param.P}
if exists(param.T) && global.M596_stat == -2
if param.T == 0
M596 P1
T0
else
M596 P0
T1
if exists(param.Z) && global.M596_stat == -2
M596 P0
T1