Thanks folks, the combination of your feedback and my own musings has got me 'thinking aloud':
Getting long, accurate delays is trivial in assembler, but a compiled language introduces all sorts of unknown delays… I did think of cascading a microsecond and millisecond delay or working directly with interrupts.
Then I did some calculations and realised my existing gearing is about five times to coarse and ideally should be even finer.
I've ordered a 20:1 worm and gear to slow my stepper down so the delay will be around 590ms.
This is in the awkward zone where 1ms may not be good enough resolution and still too long for delay microseconds.
I think two things will improve accuracy:
Polling micros() so I don't have to introduce any reset delay.
As short-term errors won't be critical, I can also hard code patterns to add an extra millisecond to approximate 0.1ms accuracy (sort of pseudo bressenham)
Say the base time is 250ms
590.0 ms = 590 ms ten times
590.1 ms = 591, 590, 590, 590, 590, 590, 590, 590, 590, 590
590.2 ms = 591, 590, 590, 590, 590, 591, 590, 590, 590, 590
590.3 ms = 591, 590, 590, 591, 590, 590, 590, 591, 590, 590
and so on…
I can store the delay * 10 and use this sort of approach (psuedocode)
ARRAY LOOKUP(9,9) {populated with the offsets]
Stored figure *10
Base delay = stored figure/10
Fractional delay = stored figure MOD 10
FOR N= 0 TO 9
DELAY(N) = Base delay + LOOKUP (fractional delay,N)
NEXT N
The actual delay process will be:
LOOP
IF MILLIS() < COUNT GOTO LOOP
COUNT = COUNT + DELAY(N)
N ++
IF N>9 N=0
{CHECK FOR BUTTON PRESSES/LIMIT SWITCH}
GOTO LOOP
The whole loop should last much less than 1ms to execute so I should get excellent 'granularity'
Let's hope the drive train can be sorted without too much trouble.