Servo ???

hippy

Ex-Staff (retired)
It's the latter, the unwanted action/s happen when not using the toggle switch sometimes it can be a single movement, other times the movement is a regular constant rhythmic movement.
When using servos it is best to minimise interactions with other I/O as there can be times when the PICAXE tries to update both simultaneously and some jitter may be unavoidable. It's like two people hammering a nail in; when in sync it works fine but occasionally both may try to hammer the nail at the same time.

If the program is idling in 'waitforinput' when the jittering occurs it would be worth removing the 'toggle 0' to see if that improves things, and likewise elsewhere in the code.

A guaranteed way to remove all jitter is to forego the 'servo' and 'servopos' and put the servo control completely under program control, controlling the servo frame time and pulse, but that can make for more complicated code.
 

sid

Senior Member
@sid,

You do not indicate precisely when the unwanted actions start to occur. Is it when you operate the toggle switch to initiate a point/turnout operation or at some completely random time when you are not operating the toggle switch?

You are using a 7805 voltage regulator to power the PICAXE and the servo motor.
The 7805 is rated for a maximum of 1 Amp. The servo motor could well reach or exceed this current rating briefly as the servo motor starts.
This will cause the voltage to dip and the PICAXE to reset. If pin1 = 1 then you enter program mode and the servo goes to the centre position with the line "servo 4,150".

Relative to you diagram, you could try adding a diode between the servo connector the the second 1000uF capacitor (closest to the 08M) which would prevent the capacitor being discharged by the servo motor which will help keep the PICAXE voltage up.
As Angie (SD70M) has also intimated, a separate supply for the servo motor is also an often recommeded option. Then as Angie states, you need to keep the 0V/common line between the two supplies linked as this is the reference voltage for the PIACXE to Servo control signal.

If the servo motor posiiton is fluctuating when you are not moving the points/turnout then it would be warranted to recheck you power supply for bad connections. To have the PICAXE reset when the servo is not actively moving suggests a loose connection causing a momentary power loss to the PICAXE.

When a Servo does not have a signal to control the position, it cannot actively correct itself to maintain or move to a new position. However, the servos I have do not move when the signal is lost. The arm/horn will only turn if there is sufficient external force to drive the gears and motor – but a model railway point/turnout would not generally have sufficient force and many (eg PECO) have a spring to retain the moving part(s) in position.

On further investigation the servo will either continually stutter after a download or and this is the more common (and annoying) situation the servo will stutter while the program is looped in this part of the program which is waiting for an input
Code:
waitfortoggle:
if pin1 =1 and b4=1 then goto servoleft
if pin2 =1 and b4=0 then goto servoright
goto waitfortoggle
Basically you can switch a turnout left or right and the above code recognizes an input, but if the input is telling the code to switch the turnout right and the turnout is already right then the code should ignore the input and continue to loop until both conditions have been met.

To check for power spikes/loses I connected a voltmeter across pins 1&8 of the o8m and continually operated the toggle switch in one direction only which caused the servo to stutter but the voltage supplying the chip remained a constant 5.14v.
Because the voltage is stable this would indicate that the chip isn't resetting so I'm assuming that the extra capacitance and the diode suggested aren't necessary ?
And because the stutter is happening in the part of code without the toggle I assume that this can be left in as well.

Although I do find Hippy's point interesting re I/O commands...
"the PICAXE tries to update both simultaneously and some jitter may be unavoidable. It's like two people hammering a nail in; when in sync it works fine but occasionally both may try to hammer the nail at the same time."

Perhaps this is the cause, the chip recognises the input from the switch then does the if pin1 =1 and b4=1 then goto servoleft
if pin2 =1 and b4=0 then goto servoright thing and while this is happening this is interfering with the servo command ?

I'd be interested to know how to operate a servo without using the servo/servopos commands that Hippy eludes to
 

sid

Senior Member
It's been a week or so since my last post and I can't get this annoying judder to stop.
I've narrowed it down to the part of the program where it monitors input pins 1 & 2 waiting for an input
Code:
waitfortoggle:
if pin1 =1 and b4=1 then goto servoleft
if pin2 =1 and b4=0 then goto servoright
goto waitfortoggle
And I've also observed that the judder happens regularly once every six seconds.
Can anyone suggest a fix ?
What is the other way of controlling a servo that Hippy mentions in a earlier post?
 
Last edited:

SD70M

Senior Member
@sid

The circuit I created is here and the code is here

I connected a single servo to a test board with single turnout attached and it worked first time.

Angie
 

sid

Senior Member
@sid

The circuit I created is here and the code is here

I connected a single servo to a test board with single turnout attached and it worked first time.

Angie
Thanks Angie
I confess to not understanding a lot of your code as you are obviously more advanced than I am when it comes to programming.
I did notice the lack of servo and servopos commands and couldn't understand how you were controlling the servos
But I'd be interested to know.


I made my circuit up on a pcb
The first attachment shows the pcb as was
The second attachment shows the pcb having modified it to provide a duel power supply which I have to say does seem to eliminate most if not all of the judder. The small download pcb is attached to the main board vertically to save space

I'd really like to know how to ....
A. provide a duel power supply from one input power supply ie: a mains psu
B. operate the servos not using the servo and servopos commands

servo pcb1.JPGservo pcb2.JPG
 

hippy

Ex-Staff (retired)
I'd really like to know how to ....
B. operate the servos not using the servo and servopos commands
The basic trick is to generate your servo pulse and keep the 20ms servo frame timing in a loop ...

Do
PulsOut <positioning pulse>
Pause <some time to make the loop 20ms>
Loop

Most servos are tolerant to the loop time being out so that can be written in PICAXE Basic as ...

Do
w0 = ?
PulsOut <pin>, w0
Pause 20
Loop

PulsOut generates pulses in multiples of 10us@ 4MHz so, for example, a 1.5ms pulse is 1500us, or 150 x 10us, so w0=150.

Adjust the w0 as required within the loop for what pulse width / positioning you need.
 

lbenson

Senior Member
Here is my code for using pulseout to smoothly move a servo from one spot to another. This works with an 08M for the HiTec HS-422 servo, but did not for a cheaper ebay servo (or for the 08M2--I didn't pursue the issue--maybe default-speed related).

The code allows control of 2 servos based on the variable, activeServo. It moves from "lastSpot" to "activeSpot". I found by trial and error that I needed to do the pulsout and pause twice to get it to work. I increment or decrement the location based on the value of b3 (1 or $FF, which is equivalent to minus 1).

Code:
servoOut:  ' smoothly move from lastSpot
  b2 = activeSpot - lastSpot
  b3 = 1
  if activeSpot < lastSpot then
    b2 = lastSpot - activeSpot
    b3 = $FF   ' minus one
  endif
  sertxd ("|",b1," ",#b2, " ", #b3, " ", #lastSpot, " ", #activeSpot,13,10)
'  serout 0,N2400,(#b2, " ", #b3, " ", #lastSpot, " ", #activeSpot,13,10)
  activeSpot = lastSpot
  for b4 = 1 to b2       ' move smoothly to new activeSpot
    activeSpot = activeSpot + b3
'  sertxd (":  ",#b4, " ", #b3, " ", #b2, " ", #activeSpot,10,13)
'  serout 0,N2400,(#b4, " ", #b3, " ", #b2, " ", #activeSpot,10,13)
      pulsout activeServo,activeSpot
      pause 20
      pulsout activeServo,activeSpot  ' twice seems to make it work
      pause 20
  next b4
  return
This code is from my pan and tilt rivercam setup:

http://www.picaxeforum.co.uk/showthread.php?13705-Rivercam-with-PICAXE-pan-tilt-control

http://www.picaxeforum.co.uk/showthread.php?9425-Pan-and-tilt-control-of-webcam-with-PICAXE-08M
 

sid

Senior Member
Thanks Hippy,
The instructions for servo control in manual two explain that the servo and servopos commands continue in the background allowing the program to go and do other things, so would I be right in thinking that when using the puslout instruction the program needs to be pretty much constantly in the do loop or the servo won't receive its pulse and will lose where it is, or if another line of code needs to be followed it has to fit within the 20ms time frame?
 

lbenson

Senior Member
The servos which I have used do not lose position after the pulseout and pause. They will sit for days where they have been left.
 

sid

Senior Member
Cool,
I shall go and have a play with pulsout commands and see what happens
Thanks for the advice,
Rgds,
Sid
 

SD70M

Senior Member
I confess to not understanding a lot of your code as you are obviously more advanced than I am when it comes to programming.
I did notice the lack of servo and servopos commands and couldn't understand how you were controlling the servos
But I'd be interested to know.
As you say in your post #46, 'the servo and servopos commands continue in the background'. So I start the servos once in the init section (lines 63-68), then each of the 6 servos has a servopos command after any movement (lines 139,163,185,207,229 and 251). It doesn't need any more than that.

There are 6 sections in the 'if is_anything_moving' part (line 116), one per servo, which only get visited if
.....A) any servos are moving (see the is_anything_moving flag, line 116) and
.....B) if the ismoving flag for each specific servo is set (lines 117,141,165,187,209 and 231)
otherwise that section of code is ignored on that loop.

I'm adding onboard programming so, if the progflag is set, the program won't go looking for other buttons being pressed (line 96), but any turnout movements are completed before going to the programming section (line 90) but this is not currently in the code.

Hope this helps.

Angie
 

SD70M

Senior Member
A. provide a duel power supply from one input power supply ie: a mains psu
@sid
This is actually 2 seperate power supplies, not two seperate inputs from one supply. The negatives of each mutst be common to each other, this means connected, it's just the positive that is, in essence, seperate.
Angie
 

sid

Senior Member
I've gone off and had a play with the pulsout command and have also discovered inc and dec commands; plus I now understand do,loop,until commands as well, so all in all a good learning exercise on this one.
Code:
#picaxe 08m
start:
if pin4=1 then goto program
read 0,b4
read 1,b2
read 2,b3
read 3,b5
if b4=1 then goto waitfor

program:
b1=150
do			;centre
pulsout 1,b1
pause 20
inc b0
loop until b0=5

do pulsout 1,b1	;left
pause 100
inc b1
loop until pin4=1
b2=b1
write 1,b2

do			;right
pulsout 1,b1
pause 100
dec b1
loop until pin3=1
b3=b1
write 2,b3

b4=1
write 0,b4

waitfor:
do
if pin4=1 and b5=0 then goto left
if pin3=1 and b5=1 then goto right
loop

left:
b5=1
write 3,b5
for b0 = b3 to b2
pulsout 1,b0
pause 30
next b0
goto waitfor

right:
b5=0
write 3,b5
for b0 = b2 to b3 step-1
pulsout 1,b0
pause 30
next b0
goto waitfor
The program is a lot simpler and the servo now works judder free, however........ the servo does display a couple of annoying traits
when the program is executing either the left or right labels
Code:
left:
b5=1
write 3,b5
for b0 = b3 to b2
pulsout 1,b0
pause 30
next b0
goto waitfor

right:
b5=0
write 3,b5
for b0 = b2 to b3 step-1
pulsout 1,b0
pause 30
next b0
goto waitfor
The servo firstly travels in the opposite direction ever so slightly and then moves in the correct direction ever so slightly too fast before slowing down and moving at the correct speed. In percentage terms I would say the first 10% of travel is faster than coded and the remaining 90% of travel is at the correct speed.
I deduce that there are four possible reasons for this....
1. My coding is flawed
2. My circuit is causing the servo to malfunction in the first instance when receiving a pulse
3. The servo has built in limitations
4. There is another issue that I don't know about (like the servo and input timing issue)

I would be grateful if anyone could advise
The circuit diagram remains the same as before
Rgds,
Sid
 

sid

Senior Member
Is there a command that can switch a pin/port off when not being used,
so that particular output can't send spurious data to a servo when the axe is doing something else ?
 

hippy

Ex-Staff (retired)
Is there a command that can switch a pin/port off when not being used,
so that particular output can't send spurious data to a servo when the axe is doing something else ?
Generally there is no way to isolate an output pin from the affects of what you do to it; you have to prevent spurious signals being generated.

It is possible to set a pin as an input and that will prevent "let pinsX=" commands affecting it but it won't stop other commands from doing so.
 

sid

Senior Member
Another question regarding servo's.
On start up my code points to a section within the program that sets b1 to 150 and then centres the servo
B1 then gets written to memory
After that the program then goes and defines a left and a right limit for the servo (b2 & b3) and again writes these values to memory

When the circuit is switched off and then back on again the servo should start from where it left off but it "always" moves to a completely random position until such time as the input switch is used and then it starts working within the defined limits again, why is this and more importantly how can I stop it from happening?
Rgds,
Sid

Code:
#picaxe 08m2	;scratchpad version
start:
if pinc.1 =1 then goto program
read 0,b4
read 1,b2
read 2,b3
read 3,b5
if b4=1 then goto waitfor
if b4=0 then goto program
goto start

program:
b1=150			
pulsout c.4,b1	;centre
pause 1000
high c.0

continue:
if pinc.1 =1 then goto progleft
goto continue

progleft:
pause 2000
do 
pulsout c.4,b1	;left
pause 200
inc b1
toggle c.0
loop until pinc.1=1
b2=b1
write 1,b2
low c.0
pause 2000


progright:
do			;right
pulsout c.4,b1
pause 200
dec b1
toggle c.0
loop until pinc.1=1
b3=b1
write 2,b3

b4=1
write 0,b4
high c.0
pause 2000
low c.0

waitfor:
do
if pinc.1=1 and b5=0 then goto left
if pinc.2=1 and b5=1 then goto right
loop

left:
b5=1
write 3,b5
for b0 = b3 to b2
pulsout c.4,b0
pause 200
next b0
goto waitfor

right:
b5=0
write 3,b5
for b0 = b2 to b3 step-1
pulsout c.4,b0
pause 200
next b0
goto waitfor
 

boriz

Senior Member
Is there a command that can switch a pin/port off when not being used,
so that particular output can't send spurious data to a servo when the axe is doing something else ?
It could depend on exactly what sort of noise is causing the servo to jiggle. I've had success just setting the pin HIGH. Try it. If that doesn't work, try setting it LOW.
 

sid

Senior Member
Thanks Boriz I will try that, but getting back to my previous question, why does the servo start in a different place each time the circuit is switched on even though the variable used to position it remains the same?
 

MartinM57

Moderator
You either have a code problem or an electrical problem.

I haven't studied the code as with no useful comments and raw variable names (suggest a few SYMBOLs would help a lot) it's too onerous to do so

Have you put sertxd commands throughout the code to check the values of the variables at appropriate times i.e. just before you write them to EEPROM, read them at startup etc?
 

hippy

Ex-Staff (retired)
why does the servo start in a different place each time the circuit is switched on even though the variable used to position it remains the same?
Is it that when not programming the servo limits the code jumps to 'waitfor' but you aren't controlling the servo in the 'waitfor' loop ?
 

sid

Senior Member
Is it that when not programming the servo limits the code jumps to 'waitfor' but you aren't controlling the servo in the 'waitfor' loop ?
That is an interesting point Hippy and I will now doubtless show my ignorance in this aspect in my reply.
As I understand it...... the "servo" command runs in the background constantly updating the servo
Whereas the "pulsout" command just pulses the servo at the time of carrying out the instruction and after that the servo receives no more pulses until the next "pulsout" command is acted upon by the axe.

If I understand you correctly what your saying is "even though the servo has been centred to 150 on the circuits initial start up and that value added to the variable b1 which then gets changed into whatever the values for b2 & b3 are (defining the limits of the servos movement from left-right), because there is no continuous command to the servo during the "waitfor" section of code the servo "loses count of where it is?"

Or
Having looked back through the code again, on subsequent start-ups I'm expecting the servo to know where centre is because I've given it the parameters of b2 & b3, when perhaps I should be centring the servo first on every start-up and then telling it to go to either b2 or b3?, which would be a shame as I'd like the servo to start from it's last position.

As an aside if I could get the thing to work using the servo command with out the constant random jitter then I would, but even with separate power supply's and decoupling capacitors of various types just about everywhere I can think to add one I still cant stop the random jittering. The pulsout command was an improvement but I still got random jitter but by replacing the 08m for the new 08m2 the jitter has finally succumbed, now I'm just left with the positioning issue

Thanks for the help though
Rgds,
Sid
 

hippy

Ex-Staff (retired)
If I understand you correctly what your saying is "even though the servo has been centred to 150 on the circuits initial start up and that value added to the variable b1 which then gets changed into whatever the values for b2 & b3 are (defining the limits of the servos movement from left-right), because there is no continuous command to the servo during the "waitfor" section of code the servo "loses count of where it is?"
More that, having originally positioned the servo, powered-off / restarted, when you do restart there is no PULSOUT or anything which sets the servo position ( nor sets pin 1 to an output even ) until the "waitfor" calls something else which does update pin 1.
 

sid

Senior Member
More that, having originally positioned the servo, powered-off / restarted, when you do restart there is no PULSOUT or anything which sets the servo position ( nor sets pin 1 to an output even ) until the "waitfor" calls something else which does update pin 1.
I thought about that after my last post and copied the centring code to the start of the program to centre the servo each time the circuit is switched on
But it would seem that position 150 is never quite in the same place
I'm coming to the conclusion that perhaps these cheap £4 servos are not that accurate?

Code:
#picaxe 08m2	;scratchpad version
start:
if pinc.1 =1 then goto program
read 0,b4
read 1,b2
read 2,b3
read 3,b5

b1=150			
pulsout c.4,b1	;centre

if b4=1 then goto waitfor
if b4=0 then goto program
goto start

program:
b1=150			
pulsout c.4,b1	;centre
pause 1000
high c.0

continue:
if pinc.1 =1 then goto progleft
goto continue

progleft:
pause 2000
do 
pulsout c.4,b1	;left
pause 200
inc b1
toggle c.0
loop until pinc.1=1
b2=b1
write 1,b2
low c.0
pause 2000


progright:
do			;right
pulsout c.4,b1
pause 200
dec b1
toggle c.0
loop until pinc.1=1
b3=b1
write 2,b3

b4=1
write 0,b4
high c.0
pause 2000
low c.0

waitfor:
do
if pinc.1=1 and b5=0 then goto left
if pinc.2=1 and b5=1 then goto right
loop

left:
b5=1
write 3,b5
for b0 = b3 to b2
pulsout c.4,b0
pause 100
next b0
goto waitfor

right:
b5=0
write 3,b5
for b0 = b2 to b3 step-1
pulsout c.4,b0
pause 100
next b0
goto waitfor
 

hippy

Ex-Staff (retired)
But it would seem that position 150 is never quite in the same place
With only one PULSOUT issued it could be that the servo doesn't get reliable enough information to set itself to where it should be.
 

SD70M

Senior Member
I'm using £2.95 turnigy 9g servos and they're right on every time. I am using the servo / servopos command though.

Angie
 

sid

Senior Member
Thanks Iron Jungle, I am using the latest version of PE downloaded only this week, I will take a look at your blog when I get back from work.

Further to my on going issue with random servo positions I have narrowed it down to servo start-up in that I made a new circuit on the breadboard with a duel power supply and wrote some new code and all works well, you can even switch the power to the picaxe on/off as many times as you like and the servo will continue from where you left it everytime, however..... when you switch the power to the servo off and then back on the servo on start-up moves to a different position. in fact if you take a just a servo and add a power supply to it and then keep switching the power on/off the servo will move to a different position everytime. This is what is causing my problem. Can anyone tell me how to stop the servo from doing this on power up
Rgds,
Sid

Code:
#picaxe 08m
start:
read 0,b0
read 1,b1
servo 4,b0
if b1=1 then goto left
if b1=2 then goto right


servo 4,85
b0=85
pause 2000



left:
b1=1
write 1,b1
do
servopos 4,b0
inc b0
write 0,b0
pause 100
toggle 2
loop until b0=215
pause 2000



right:
b1=2
write 1,b1
do
servopos 4,b0
dec b0
write 0,b0
pause 100
toggle 2
loop until b0=85
pause 2000
goto left
 

sid

Senior Member
Having read various blogs would I be right in thinking that servo twitch on start-up is inherent and can not be over come
 

SD70M

Senior Member
Having read various blogs would I be right in thinking that servo twitch on start-up is inherent and can not be over come
I've found that cheaper servos twitch on start up but should still go to the same place if the same value is sent to it.

I have a couple of metal geared servos and they don't twitch on startup. They're just way too expensive for what I need them for so the initial twitch I get is ok.

Angie
 

hippy

Ex-Staff (retired)
@ sid : Good point and you could be right.

I was testing everything power-off then on and I see the servo jump, then correct itself. With the PICAXE only being reset, power supply to the servo retained, everything works as it should, no twitch or jumps.

If the PICAXE is producing the servo pulses, disconnecting then applying power to the servo causes the twitch, so not sure how that could be solved.
 

ivydene25

New Member
I am doing something similar and I am switching the servo on and off using a darlington pair. Before I switch on the servo I set the servo command running with the position I require. When I then power up the servo the signal is already present and the servo moves to that location. If I then power down the servo and switch it on again it stays in the same location. I have had some jitter but infrequently.
I think that the servos jitter because it takes a finite amount of time for them to sync to the servo output from the picaxe.
I am using my servo as an analogue dial instrument and only need to update the position once every minute, so I am thinking that I may just powerdown the Servo between each update. More experimentation still to be done.
 

ivydene25

New Member
Just reread hippy' last and I appear to have the opposite behaviour. I wonder if the servos being used make a difference? I am using digital servos.
 

BruceNscale

New Member
Hi Sid,

You could replace the single "For Next" loop with several "For Next" loops using different pause rates to even out the movement. This would be easy to fiddle with until you get what you want. I'm using this approach to animate a construction crane on my layout.

Mechanically, you could replace the servo arm linkage with pulleys and belts to get a more linear motion. This would be harder to adjust, but would remove the tangential movement.

Happy modeling,

Bruce
 
Top