Hi,
Back to post #1, Rob made it clear that he is basically a modeller, wanting a "Simple" solution (similar to that shown in a YouTube video) and had resorted to asking "AI" to write a program. It would be interesting to know how that "conversation" might have proceeded because the AI hadn't even "realised" that a Servo moves much too fast for the desired effect, and needs to be slowed down somehow. Then the "usual" problem is that the Servo movement can be "jerky" or erratic, but here the problem reported by Rob is that his Servo "twitches" when it is NOT supposed to be moving. I must admit that my attention has been in trying to make the SERVO(POS) instruction operate "correctly", but this is actually a rather "unusual" application of Servos and thus may need a non-standard solution:
Normally, Servo operation is a "background" task whilst the program is doing "something else", but here the main task is simply to drive the Servo motors in a specific way for a specific (and quite short) time. Thus, as described in a few other threads (e.g. using "Twitch" as a forum search term
), the instruction that we probably should be using is PULSOUT, which should be (almost) perfectly "clean", and simply stops when the program doesn't actively transmit it.
The program from post #7 hardly needs any changes; the only complication is that Rob decided/confirmed that a step rate of 30 ms is ideal, whilst the Servos update every 20 ms, so I needed to complicate the program slightly. However, adding the second Servo actually makes the timing simpler, and I've also added storage for the Last Position, to be stored over a power-down.
Cheers, Alan.
Back to post #1, Rob made it clear that he is basically a modeller, wanting a "Simple" solution (similar to that shown in a YouTube video) and had resorted to asking "AI" to write a program. It would be interesting to know how that "conversation" might have proceeded because the AI hadn't even "realised" that a Servo moves much too fast for the desired effect, and needs to be slowed down somehow. Then the "usual" problem is that the Servo movement can be "jerky" or erratic, but here the problem reported by Rob is that his Servo "twitches" when it is NOT supposed to be moving. I must admit that my attention has been in trying to make the SERVO(POS) instruction operate "correctly", but this is actually a rather "unusual" application of Servos and thus may need a non-standard solution:
Normally, Servo operation is a "background" task whilst the program is doing "something else", but here the main task is simply to drive the Servo motors in a specific way for a specific (and quite short) time. Thus, as described in a few other threads (e.g. using "Twitch" as a forum search term
The program from post #7 hardly needs any changes; the only complication is that Rob decided/confirmed that a step rate of 30 ms is ideal, whilst the Servos update every 20 ms, so I needed to complicate the program slightly. However, adding the second Servo actually makes the timing simpler, and I've also added storage for the Last Position, to be stored over a power-down.
Code:
#picaxe 08m2
#no_data ; Avoid Overwriting the last stored position in EEPROM
; PICAXE 08M2 Momentary Switch Servo Control AllyCat October 2025
; #DEFINE ACTIVELOW ; Uncomment for Alternative pushbutton operation (button to Ground)
; Control/Variables :
symbol PushButton = pinC.3 ; Press to toggle Servo to move to opposite Endstop
symbol Servo_Pin = C.4 ; Control signal to the servo 1
symbol Servo_Pin2 = C.1 ; Control signal to the servo 2
symbol Servo_Pos = b1
symbol Servo_Pos2 = b2
symbol HRPos = w2 ; High Resolution Position to permit step rate adjustment
; Constants depending on the Hardware configuration/requirements :
symbol LIMIT_CCW = 105 ; Endstop for Counter-Clockwise rotation (adjust as required)
symbol LIMIT_CW = 195 ; Endstop for Clockwise rotation (adjust as required)
symbol TRIM_S2 = 0 ; Trim Servo 2 position relative to Servo 1 (optional)
symbol LOOP_TRIM = 1100 ; Pause (* 10us) to extend pulse/loop Period to 20 ms
symbol SWEEP_RATE = 33 ; Steps per second (adjust as required)
symbol LAST_POS = 0 ; Address in EEPROM
; Calculate threshold which determines whether to move CW or CCW :
symbol MIDDLE_I = LIMIT_CCW + LIMIT_CW ; Sum the two Servo positions
symbol MIDDLE = MIDDLE_I / 2 ; Average (Middle) Servo position
symbol MIDDLEx2 = MIDDLE_I + TRIM_S2 ; To calculate Servo 2 position
#IFDEF ACTIVELOW ; Pushbutton connected to Ground (0v)
symbol PRESSED = 0 ; Logic value when button is pressed
Pullup %001000 ; Activate Pushbutton PullUp resistor
#ELSE ; Pushbutton connected to Supply (Vdd)
symbol PRESSED = 1 ; Logic value when button is pressed [Use only this line if button is connected to supply rail]
#ENDIF
init:
Low Servo_Pin , Servo_Pin2
Pause 1000 ; Allow time for system to stabilise (probably unnecessary)
Read LAST_POS , Servo_Pos
If Servo_Pos < 50 AND Servo_Pos <> LIMIT_CCW then ; Initialise starting position if necessary
Write LAST_POS , LIMIT_CCW
Endif
Read LAST_POS , Servo_Pos
Servo_Pos2 = MIDDLEx2 - Servo_Pos
PULSOUT Servo_Pin , Servo_Pos ; Starting position (assumed fully CCW)
PULSOUT Servo_Pin2 , Servo_Pos2 ; Starting position (assumed fully CW)
HRPos = Servo_Pos * 50 ; To permit partial or multiple steps between Pulses
main:
Do : Loop Until PushButton = PRESSED ; Wait for button to be pressed
If Servo_Pos <= MIDDLE then ; Position should be at LIMIT_CCW, so can step immediately
Do
HRPos = HRPos + SWEEP_RATE ; Move Clockwise [~1ms approx execution time]
Servo_Pos = HRPos / 50 ; Incremented when appropriate [~1ms]
Servo_Pos2 = MIDDLEx2 - Servo_Pos ; Complementary position [~1ms]
PULSOUT Servo_Pin , Servo_Pos ; )
PULSOUT Servo_Pin2 , Servo_Pos2 ; } Two complementary pulse widths [~4.5ms]
Pauseus LOOP_TRIM ; Trim Total loop to ~20ms [~11.5 ms]
Loop Until Servo_Pos => LIMIT_CW ; Close loop [~1ms]
Else ; Position should be at LIMIT_CW, so can step immediately
Do
HRPos = HRPos - SWEEP_RATE ; Move Counter-Clockwise
Servo_Pos = HRPos / 50 ; Decremented when appropriate
Servo_Pos2 = MIDDLEx2 - Servo_Pos
PULSOUT Servo_Pin , Servo_Pos
PULSOUT Servo_Pin2 , Servo_Pos2
Pauseus LOOP_TRIM
Loop Until Servo_Pos <= LIMIT_CCW
Endif
Do : Loop Until PushButton <> PRESSED ; Ensure button has been released
Write Last_Pos , Servo_Pos
Goto main ; Or a purist would close a DO : LOOP here
Cheers, Alan.
Last edited:
