hippy
Ex-Staff (retired)
Here's some example code which shows how to use Sandwich Delay techniques describe by 'Flesner' to create fairly well timed Servo Loops without having to worry about the time taken in passing through various code paths or the overhead of PICAXE commands themselves.
With traditional PULSOUT plus PAUSEUS frame timing, with no attempt to compensate for code path variations and overhead, the frame time is around 26ms, 37Hz, with a fair amount of variation on that.
Using Sandwich Delay techniques it instantly becomes 19.969ms, 50.07762Hz, with far less variation. Quite impressive.
With traditional PULSOUT plus PAUSEUS frame timing, with no attempt to compensate for code path variations and overhead, the frame time is around 26ms, 37Hz, with a fair amount of variation on that.
Using Sandwich Delay techniques it instantly becomes 19.969ms, 50.07762Hz, with far less variation. Quite impressive.
Code:
#Picaxe 20X2
#No_Data
#No_Table
; With "#Define USE_SANDWICH_TIMER" commented out this program
; implements a traditional bit-banged Servo Loop using a PAUSEUS
; of 20ms minus however long the servo pulse was. This is okay
; because the frame time isn't important but it does mean frames
; are not every 20ms as we might like them to be as the time for
; adjusting the pulse width varies depending on what code paths
; are taken and we haven't subtracted the overhead of GOSUB nor
; any other commands.
; With "#Define USE_SANDWICH_TIMER" in place we do our timing
; using SETTIMER and DOZE which gives us a more accurate 20ms
; frame time. This is using Sandwich Timing techniques developed
; by PICAXE Forum member 'Flenser' detailed at -
;
; https://picaxeforum.co.uk/threads/sandwich-delays.32523
; https://picaxeforum.co.uk/threads/sandwich-announce.32524
; With "#Define USE_SANDWICH_TIMER" commented out, and nothing
; done to compensate for code path variations or overhead the
; servo frame time is about 26ms, 37Hz, with a fair amount of
; variation on that. When included the frame time instantly
; becomes 19.969ms, 50.07762Hz, with far less variation.
#Define USE_SANDWICH_TIMER
Symbol SERVO_PIN = C.0 ; Bottom left, Leg 10
Symbol LOOP_TIME_US = 20000
Symbol SERVO_MIN_US = 1000
Symbol SERVO_MAX_US = 2000
Symbol SETTIMER_20MS = 60536
Symbol pulseWidth = w1
Symbol rampingUpFlag = w2
Main:
SetFreq M8
Gosub Init
Do
Gosub OutputServoFrame
Gosub UpdatePulseWidth
Loop
UpdatePulseWidth:
If rampingUpFlag = 1 Then
pulseWidth = pulseWidth + 1
If pulseWidth >= SERVO_MAX_US Then
rampingUpFlag = 0
End If
Else
pulseWidth = pulseWidth - 1
If pulseWidth <= SERVO_MIN_US Then
rampingUpFlag = 1
End If
End If
Return
Init:
pulseWidth = SERVO_MIN_US
rampingUpFlag = 1
#IfDef USE_SANDWICH_TIMER
SetTimer SETTIMER_20MS
#EndIf
Return
OutputServoFrame:
#IfDef USE_SANDWICH_TIMER
w0 = pulseWidth / 5 : Doze 0
PulsOut SERVO_PIN, w0
#Else
w0 = pulseWidth / 5 : PulsOut SERVO_PIN, w0
w0 = LOOP_TIME_US - pulseWidth / 10 : PauseUs w0
#EndIf
Return