"Servopos" Command : servo jerks! :((

zorgloub

Member
Hello to the Community.

I have just completed a program using the "Servopos" command.
It is a system that positions a servo to two programmable positions, depending on the logic state of a control input. ("ON/OFF Servo")

Unfortunately, I am experiencing instability in the servo positions.
Is there a solution to avoid this problem?

Thanks.

Code:
'----------------------------------------------------------------------------------
' SERVO_TR.bas   -    "ON/OFF" Servo   -   Servo "Tout ou Rien"
'
' V1.0 - 09/05/2022 - RGL
'
' Moves a servo to two preset positions, depending on the state of a logic input
' Servo signals adjustable from 0.75 ms to 2.25 ms
'----------------------------------------------------------------------------------
'
'      TWO POSITION SETTING PROCEDURE
'     °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° 
' - In Normal Mode (Input Mode=1), the LED is on.
' - Set the logic input (S_Pos) to 0V or 5V to select either servo position.
'
' - In Configuration Mode (Input Mode=0), the LED is blinking.
' - The state of the S_Pos input will determine which position you are setting !
' - Turn the potentiometer in either direction: The servo follows the movement.
' - When the desired position is reached the LED goes out after a few seconds.
' - Then, return the configuration input to normal mode (High)
'     The LED lights up again and the new position is stored in Eeprom.
'     The system returns to Normal Mode with the new programmed position.
' - Do the same for the other position by changing the state of the S_Pos input.
'----------------------------------------------------------------------------------

'PotADC gives values from 0 to 255
'ServoPos delivers pulse values from 75 to 225 (0,75msec to 2,25msec)
'Pulse = PotADC*59/100+75

'*** Programming Directives *******************************************************
' #SimSpeed 500
' #Terminal 4800 'Only used in test mode with messages Sertxd

'*** PICAXE Pinouts ***************************************************************

             #Picaxe 08M2
'                 __ __
'          Vcc  o|  U  |o  Gnd
'          C.5  x|Rx Tx|>  C.0 Led
' Config.  C.4  >|     |>  C.1 Servo
' Position C.3  >|     |<  C.2 Pot 
'                 -----

'*** In/Out pins ..................................................
 Symbol Led = C.0        'Output Led
 Symbol S_OUT = C.1        'Output Servo
 Symbol Potar= C.2        'Input Pot
 Symbol S_Pos = pinC.3    'Input Control Position (Left/Right)
 Symbol Mode = pinC.4    'Input Mode (Normal/Calibration)

'*** Variables ....................................................
 Symbol Position1 = b0    'W0    Position1 servo
 Symbol Position2 = b1    'W0    Position2 Servo
 Symbol PotADC = b2       'W1    Pot ADC Value
 Symbol NewADC = b3       'W1    New ADC Conversion
 Symbol _PotADC = b4      'W2    =PotADC/10
 Symbol _NewADC= b5       'W2    =NewADC/10
 Symbol Pulse = b6        'W3    Pulse value to servo   
 Symbol State = b7        'W3    Normal/Configuration
 Symbol Flashing = b8     'W4     Counter for Led Flashing Frequency       
 Symbol Waiting = w5      'b10-11 Counter for Validation Delay

'*** Constants ....................................................
 Symbol FrBlink = 10        'Flashing Frequency of the Led
 Symbol TValid = 250        'Waiting Time for Validation

'==================================================================================
INIT:

Read 0,Position1    'Read Positions in Eeprom
Read 1,Position2

If Position1<75 Or Position1>225 Or Position2<75 Or Position2>225 then
    Position1=170    'if values outside the limits of a servo
    Position2=130    'Preset Values
Endif

Let Flashing=0
Let Waiting=0

Servo S_Out,150    'Servo Timer initialization
Servopos S_Out,150    '1,5 msec(NEUTRAL Position Equivalent at PotADC=128)
Pause 2000

'---------------------------------------------------------------------------
MAIN:

DO 'Main Loop
 If Mode = 1 then    'NORMAL Mode
    High Led
        
    If S_Pos=0 then        'Read the Desired Position
     Servopos S_OUT,Position1    'Servo to Position1
    Else
     Servopos S_OUT,Position2    'Servo to Position2           
    Endif
    
 Else    'CALIBRATION Mode !
   DO Until Waiting = TValid 'Configuration Loop
      State = S_Pos
    ReadADC Potar,PotADC
    Pulse=PotADC*59/100+75    'Converting ADC to Pulse
    Servopos S_OUT,Pulse        'Visualisation of the new position
            
    _PotADC=PotADC/10        'Stabilisation of the inaccuracy
    _NewADC=NewADC/10        'of the Pot ADC reading 
    
        If _PotADC=_NewADC then    'If Pot Position Unchanged
        INC Waiting        'Increase Waiting Time (Until=TValid)
      Else
       NewADC=PotADC        'Reset of the Waiting Time
       Waiting=0
      Endif

    INC Flashing
    If Flashing=FrBlink then
     Toggle Led    'Blinking Led
     Flashing=0    'Reset cpt Led           
    Endif
   LOOP 'Configuration Loop
  Gosub Validation    'The position of the Pot is Stabilised
 Endif
LOOP 'Main Loop
End
'=================================================================================
' --- SUBROUTINE ---
'=================================================================================

VALIDATION: 'Storage of the New Position in Eeprom

Low Led    'Waiting to Deselect Configuration Switch Mode !
 DO
 LOOP Until Mode = 1 'Mode=1 -->NORMAL Mode
High Led        'OK, Ready to return to Normal Mode

  If State=0 then    'New position Writing in Eeprom
    Position1=Pulse     
    Write 0,Position1                     
  Else   
    Position2=Pulse
    Write 1,Position2
  Endif

 Flashing=1 : Waiting=0    'Reset Counters           
return 'to Normal Mode

'== END OF PROGRAM ================================================================
 

hippy

Technical Support
Staff member
Unfortunately some servos can jerk more than others and some programs seem to fall into the category of those which cause more jerkiness than others. do.

The best way to remove jerkiness is to use a PULSOUT + PAUSEUS timing loop rather than SERVO and SERVOPOS. For example -
Code:
Low S_OUT

DO 'Main Loop
 If Mode = 1 then     'NORMAL Mode
    If S_Pos=0 then   'Read the Desired Position
     w0 = Position1   'Servo to Position1
    Else
     w0 = Position2   'Servo to Position2           
    Endif
    Gosub UpdateServo 'Update the servo
  Else

  End If
LOOP

UpdateServo:
  PulsOut S_OUT, w0
  w0 = 2000 - w0
  PauseUs w0
  Return
 

mikeyBoo

Senior Member
for rock-solid servo positioning (I use for setting trolling motor steering):

(use Picaxe pwmout to set update freq, pwmduty to set pulse width)
(note: on my servo I used 0.8ms…2.2mS, depends on servo travel allowed)

For a standard servo:
given that: a servo is controlled by sending it a pulse = 1mS…2mS
1.0mS = max CCW position
1.5mS = center position
2.0mS = max CW position

for example:
I want to update the servo at 245Hz (may use 50Hz…330Hz)
so that: PWM output period = 1/245 = 0.004082 seconds
pwmPeriod = 0.004082

Find dutyCycle value needed for servo positions:
max CCW position = 1.0mS
so that y = 0.001
dutyCycle = y(1023)/pwmPeriod = 0.001(1023)/.004082 = 251
dutyCycle = 251

center position = 1.5mS
so that y = 0.0015
dutyCycle = y(1023)/pwmPeriod = 0.0015(1023)/.004082 = 376
dutyCycle = 376

max CW position = 2.0mS
so that y = 0.002
dutyCycle = y(1023)/pwmPeriod = 0.002(1023)/.004082 = 501
dutyCycle = 501

we now know that center position = 376
set pwmout to free-run at 245Hz with servo at center position
need to select a Picaxe pin that supports pwmout
pwmout pwmdiv16, pin, 254, 376 ; 245Hz at servo neutral (center) position

now we can move the servo by specifying dutyCycle 251…501
(i.e. 0…100% travel aka full CCW to full CW)
pwmduty pin,dutyCycle
 

zorgloub

Member
Good evening Community.

I have just modified with Hippy's routine and I get a perfect stability.
The code is short, simple, clean and efficient.
Thanks ;)

For my documentation I will also look at MickeyBoo's solution but this process seems to me more complicated with no guarantee that it is more stable than Hippy's soluton (?).

Thanks to you for your great availability!
 

Goeytex

Senior Member
When using the servo/servpos commands, jerkiness/Jitter is likely due to to background tasks such as periodic checking of of the supply voltage for brownout detection and periodic checking for a download. These can be stopped by using 'disablebod' and 'disconnect'. Also per Manual2 the Time counter automatically starts on a 'Power On Reset' (POR). So it may be a good idea to also issue a 'disabletime' command at the beginning of the program. This will prevent background code from periodically incrementing the time variable which could possibly interfere with other tasks. These steps may minimize or even stop the jitter but no guarantees.

A little jitter is not a big problem with toy robots and such, but in applications where jitter is not acceptable, either Hippy's or MikeyBoos's solution should work fine.
 

erco

Senior Member
Power supply/battery, wiring size & routing, filter & decoupling caps and servo quality and servo load (current requirements) make big differences. I use servopos with mostly good results, it's one of my favorite reasons to use Picaxes. Have you tried 2 different power supplies, one for Picaxe and one for the servo?

I built the 6-axis arm below which operates smoothly using servopos and a single 6V NiMH pack. Keith's tai chi robot is even more impressive, operating from 4x AAA cells, but I'm not certain if he used servopos: https://picaxeforum.co.uk/threads/9g-tai-chi-stepper.27524/

 

zorgloub

Member
I think that controlling one or more servos with the ServoPos command which uses an internal timer is not a good solution especially if this command is included in a processing loop performing other tasks.
Which is usually the case...
Indeed, the management of these additional tasks seems to disturb the use of this timer.
I note that the use of the Pulsout/Pause commands is efficient and particularly stable, even if it must be considered that during the Pause period the process monitoring is on hold.
If this waiting time is not a major problem, this method works for me.
Note that it is also possible to adapt the pause time according to the processing time of the following tasks.
 

hippy

Technical Support
Staff member
Indeed, the management of these additional tasks seems to disturb the use of this timer.
That can be the case. The SERVO and SERVOPOS commands are mostly there for those doing simple school projects and similar where a bit of jitter doesn't matter if it does occur.

For a simple level-crossing project say, where a servo may lift a hinged barrier, some bounce is to be expected anyway. Servo consistency isn't as important as allowing students and learners to easily control the servo.

Having the servo just do its thing automatically in the background while other commands execute makes things easier to code but can sometimes cause jitter when the main program affects the timing or the program itself wants to update I/O at exactly the same time the servo control task needs to. The chance of that should be incredibly low but Sod's Law has it that those who least want jitter will most likely experience it.

It's just the unfortunate nature of doing two things at the same time within a framework designed for one, like having two people go in and out of a room to collect things to do their jobs. Sometimes both will try and leave or enter at the same time and one or the other has to give way at the doorway, delaying them. If one is controlling a servo their being delayed can mean jitter. It is unfortunately often luck of the draw as to how long any task takes, whether collisions will occur and how frequently, if at all.

What the PULSOUT and PAUSEUS does is two fold; ensures the servo pulse occurs by itself and is the exact length it should be. It is the consistent period of this pulse which is critical to avoiding jitter, rather than the length of any pause between them which has a much greater tolerance to variance.

The pause can be reduced so it doesn't hold up the program so much and it is possible to use interrupts and other tricks to generate the pulse every 20ms or so and not have any pause or delay other than the PULSOUT itself.

The PWMOUT and PWMDUTY approach is to move the servo control to background hardware so it keeps running consistently no matter what the program is doing. There's nothing wrong with that approach but, if the program does something which causes the firmware to briefly change its operating frequency which can happen with some commands, that can disrupt the PWM signal.
 

mikeyBoo

Senior Member
The PWMOUT and PWMDUTY approach is to move the servo control to background hardware so it keeps running consistently no matter what the program is doing. There's nothing wrong with that approach but, if the program does something which causes the firmware to briefly change its operating frequency which can happen with some commands, that can disrupt the PWM signal.
hi hippy,
Excellent info on using servos with a Picaxe!

I have been running both the speed & steering on my kayak trolling motor since Spring 2015 using the PWMOUT and PWMDUTY approach with no problems. However, over the past couple of months I have seen a few (albeit rare) malfunctions where the steering servo suddenly goes full right turn. Cycle the power & all is good again.

I have never been able to duplicate the error on the shop bench no matter how long I let it run. The only thing new this year is my fish finder, so maybe a sonar bounce is the culprit. Since the glitch has been weeks in interval, it’s a minor nuisance. The glitch has occurred with 2 different sets of hardware (i.e. controller, cables, servo).

However, your comment “…if the program does something which causes the firmware to briefly change its operating frequency which can happen with some commands, that can disrupt the PWM signal” did pique my interest.

Do you have any idea which Picaxe commands could inadvertently change a running PWMOUT or PWMDUTY output at a hardware level?
 

hippy

Technical Support
Staff member
Do you have any idea which Picaxe commands could inadvertently change a running PWMOUT or PWMDUTY output at a hardware level?
Off-hand I don't, not sure now if I ever knew for sure.

It will be I/O commands which rely on timing, work and give the same result whatever the frequency . So things like READTEMP, IRIN, IROUT are the type of things, where firmware size limits require dropping then restoring the frequency rather than having multiple, almost duplicate versions, for each frequency.

As it's only happening rarely I wouldn't have thought you would be falling foul of those, would have seen issues much more frequently if you were. Also any disruption to PWM would only be temporary, things should return to how they were once the frequency is restored.

Could it be that some external interference is causing a PICAXE reset, and it's that which causes a glitch ?
 

oracacle

Senior Member
It's a bit of hardware work around and depends on what you need the servos doing but I have, in the past, had the power for servos controlled by a MOSFET. Ideally you need to stop sending the signal to the servos, and in most cases have the MOSFET on the ground side of the servo. This will stop the servos trying to parisitically powering themselves through the signal wire from the PICAXE.
Now this will need an additional output to control the MOSFET which maybe be an issue. It also means that the servo can switched off only when the interfering commands are executed - this would be; disconnect the servos, run the command, reconnect the servos.
The other side of this is of you need to save power.
 

mikeyBoo

Senior Member
Could it be that some external interference is causing a PICAXE reset, and it's that which causes a glitch ?
That's what I'm thinking. I changed the servo but haven't had a glitch yet (maybe 7 years is asking too much of a servo).
I also added an LED to the controller display box that toggles at the end of each main loop iteration. I'm thinking that if the Picaxe program goes off the rails, the LED will stop blinking.
Code:
main:
    gosub ElapsedTime_Get                ; elapsed time -> EThours_RAM  ETminutes_RAM  ETseconds_RAM ETtotalSecs_RAM
    gosub TMotor.amps_Get               ; trolling motor amps -> TMotorAmps_RAM (0...255 = 0 to 25.5 Amps)
    gosub ampUsage_Update             ; update amps used & calc ampHours
    gosub Battery.voltage_Get            ; battery voltage -> BattVoltage_RAM (0...150 = 0 to 15.0 Volts)
    gosub TMotor.speed_Get              ; trolling motor speed PWM duty cycle -> TMotorSpeed_RAM (0...100 = 0...100%)
    gosub TMotor.servoPosition_Get  ; steering servo position -> SteeringSPT_RAM (0...18 is -9 to +9)
    gosub Joystick.io_Get                   ; Joystick Inputs/Outputs image -> JoystickPortA_RAM & JoystickPortB_RAM
    gosub Picaxe.portC_Get               ; Picaxe port C image -> XL -> PicaxePortC_RAM
    gosub ladder_Eval                        ; evaluate ladder logic
    gosub OLED.page_Update           ; update data on currently-selected serial OLED display page
    gosub LED.program_Step            ; if an LED Pgm is running, do a step
    toggle STATUS                              ; status LED (can be monitored to measure main loop timing)
    toggle SREQ1                    ; TEST ONLY Blink LED on Joystick to help find out reason for intermittent malfunctions
    goto main
 

hippy

Technical Support
Staff member
That's what I'm thinking. I changed the servo but haven't had a glitch yet (maybe 7 years is asking too much of a servo).
There is that. It could be the servo saw a minor glitch which pushed it to an extent of travel and it jammed there rather than recovering, perhaps due to age and wear and tear. Though it's not clear why power cycling would resolve that.

Toggling a LED as some kind of "I'm alive" indicator is a sensible thing to add, though it wouldn't show when there has been an actual reset, or something failed in such a way that a reset effectively occurred. It is possible that something amounting to a reset occurred which had it run code with settings in variables other than they would be expected to be.

Unfortunately, without being able to easily replicate the issue, one can only guess as to what's going on.
 

erco

Senior Member
Could the set/reset latch be used as an indicator of a Picaxe reset? On a Basic Stamp project long ago, I had the Stamp latch an SCR & LED on power up, then I manually turned off with a pushbutton. Any reset left the LED glowing.
 
Last edited:

mikeyBoo

Senior Member
Could the set/reset latch be used as an indicator of a Picaxe reset? On a Basic Stamp project long ago, I had the Stamp latch an SCR & LED on power up, then I manually turned off with a pushbutton. Any reset left the LED glowing.
Yep, that would work. The only way to know 100% if a reset has occurred is to connect a 1-shot that must be toggled within 500mS or it will set an LED on (the main loop always runs less than that).

I have changed both yak servos to a different brand & have not had another fault yet. If it runs all summer without a glitch I’ll call it fixed. If not, I’ll have to git’ analytical with it.

Of course, if things in the USA continue on the current track, we’ll all have RMUs (reality modification units) installed in our brains, so it won’t matter. I think I’m gonna’ marry my grandma’s poodle & take the next UFO outa’ here, this place is gettin’ too crazy for me!
Y’all have a fun day!
 

papaof2

Senior Member
Seems that some of the US politicians have had those RMU's for a long time - most noticeably the RMU that creates "magic" funding for any "green" project with no source of funds specified for that $XX billion project... Possibly they're not alone?
 
Top