Servo dances like crazy

mvn

New Member
[FIXED] Servo dances like crazy

English is not my first language, so please excuse me. I've tried my best to make sure most errors are eliminated so that you can understand my post in the clearest way possible. :)

Hi guys, I'm new to PICAXE so I'm wondering whether I could get some of your help.

At the moment, I've got a servo coupled with an 08M2 PICAXE chip which is connected to my desktop via serial to USB. The chip is connected to the download cable for getting commands from a C# program that I've written, while the servo is connected to the C.1 pin. I've setup the servo so that it looks similar to the layout from the manual, which means that it has its own batter pack (6 volts). My goal here is to achieve a stable servo movement that I can adjust from 0 to 90 degrees positioning.

servo layout.PNG

My main problem here is that whenever I use 'servopos' to send signal to my servo, the servo decides to move erratically. I've observed that at the beginning, it moves to the start where there is nearly 0 pulse, then it moves back to the angle/pulse it was specified. It repeats this several times until the signal stops (pause duration), and eventually the servo either stays at the specified point, or stops at the middle of nowhere.

In theory, I think that the servo is losing the pulse from the PICAXE and interprets this as an actual value. I do not have an oscilloscope to test this out as I'm also a little bit new to electronics. I also know that the PICAXE does not turn itself off when doing so, as the values (like 'b3') which were previously recorded can be recalled by other functions/variables.

I've read other threads around this forum but I can't seem to find an answer. The only ones I've seen were about the jittery movement of servos when moving, and none even state similar erratic behavior of the servo (so far).

Here is the PICAXE code that I use:
Code:
init:
    symbol pulse_pin = C.1    ' Servo signal pin
    symbol minServo = 84    ' 0 degrees pulse
    symbol maxServo = 169   ' 90 degrees pulse
    symbol stp = 16/2       ' step value pulse. inc/dec pulses by this amount
    symbol val = b9        ' Temporary value for FOR loops

    b1 = minServo        ' variable for calibrating b2 to correct position
    b2 = minServo        ' Used for setting the position of servo
    b3 = minServo        ' Used to record old position of b2 before setting a new value for it

    servo pulse_pin, 70    ' Initialise servo

main:
    do
        serrxd [5000, timeout], b0    ' Get data from download link and chuck it in 'b0'
                            ' If after 5secs, no command has been received,
                            ' go to timeout sub.
        ' PICAXE receives the data nicely.
        select case b0
            case "C"        ' Close
                b1 = 0
            case "1"        ' Open by 10%
                b1 = stp
            case "2"        ' Open by 20%
                b1 = stp * 2
            case "3"        ' Open by 30%
                b1 = stp * 3
            case "4"        ' Open by 40%
                b1 = stp * 4
            case "5"        ' Open by 50%
                b1 = stp * 5
            case "6"        ' Open by 60%
                b1 = stp * 6
            case "7"        ' Open by 70%
                b1 = stp * 7
            case "8"        ' Open by 80%
                b1 = stp * 8
            case "9"        ' Open by 90%
                b1 = stp * 9
            case "F"        ' Fully open
                b1 = maxServo - minServo
            case "A"        ' Auto
                gosub getTemp
            else
                gosub timeout
        endselect
        
        b3 = b2             ' Record old position
        b2 = b1 + minServo    ' Set b2 to desired position
        gosub driveServo
        
    loop
    goto main

' Sub for moving servo to a specific angle by pulse
driveServo:
    ' Smooth out the servo's transition to make it move slower
    if b3 > b2 then
        for val = b3 to b2 step -1
            servopos pulse_pin, val
            pause 50
        next val
    elseif b2 > b3 then
        for val = b3 to b2 step 1
            servopos pulse_pin, val
            pause 50
        next val
    endif

    ' Make sure servo stay at that position
    for val = 0 to 3
        servopos pulse_pin, b2
        pause 500
    next val

    sertxd("Servo moved!")    ' Send back to program
    return

getTemp:
    ' TODO:
    ' use readadc to read analogue voltage of temperature from sensor
    b1 = 17
    return

timeout:
    b3 = b2        ' Record old position
    if b0 = "A" then  ' If previous command is 'Auto', then use that instead
        gosub getTemp     ' set b1 & 2 variable from sensor
        b2 = b1 + minServo
    endif

    gosub driveServo
    goto main
    return
Hopefully you can understand what I'm doing in the code.

Before I end this, I heard that using serrxd/sertxd and servopos or any time dependent commands would cause bad things to happen as some PICAXE chips only have a single hardware timer. Doing so would have to make the commands share the single timer, thus the timer could become inaccurate to some commands.

I tried this without the serial commands, and I basically get the same problem. It shouldn't be the timer sharing that's causing this weird behavior. But I believe it might be how the pulses are changing too much in short intervals, which is something that I saw when the servo moves sometimes; when it is near the specified point, it moves there directly without any fuss, otherwise.
Code:
init:
    symbol pulse_pin = C.1 ' Motor 1
    b0 = 84     ' Left    (0 degrees)    
    b1 = 125    ' Center    (45 degrees)
    b2 = 169    ' Right     (90 degrees)
    servo pulse_pin, 85

main:
    do
        SERVOPOS pulse_pin, b0  ' Go to left
        pause 3000
        ' SERVOPOS pulse_pin, b1  ' Go to centre
        ' pause 2000
        SERVOPOS pulse_pin, b2  ' Go to right
        pause 3000
    loop
Do you think it's a busted servo, or is it a flaw in the PICAXE's internal hardware?
(Note: The servo I'm currently using is the GWS mini STD/BB
Link: http://www.gws.com.tw/english/product/servo/002.htm
Note 2: Current PICAXE firmware is PICAXE-08M2 v4.A)

-----

Other questions while I'm at it:

What do the other parameters in the serrxd command mean?
Code:
    disconnect
    serrxd [1000, timeout],@ptrinc,@ptrinc,@ptr
    reconnect
I can understand the square brackes, and @ptr parameter, but not the two @ptrinc. I usually use the command in this format as it's the only one I know:
Code:
serrxd [<timeout duration>, <timeout address>], <storage pointer>.
I tried using the qualifier bit of the command too, but I seem to be unable to receive anything when I send a command with the qualifier in it as well.
Eg:
-"c=" as qualifier (without quote marks)
-I write "c=F" from program to PICAXE
-The PICAXE does not understand the qualifier I've stated for it to have: "c="

The same goes with the sertxd command; I don't know what the last two parameters do.
Code:
main:    for b1 = 0 to 63                ; start a loop
      sertxd("The value of b1 is ",#b1,13,10)
      pause 1000
    next b1
Thank you for taking your time reading this. Suggestions are always welcome too.
 
Last edited:

westaust55

Moderator
Do you definitely have the 0V supply to the PICAXE connected to the 0V supply for the servo?

Is the servo signal connected directly to the PICAXE chip - not via a ULN2803 or similar interface chip?

Next is the fact that certain PICAXE commands such as SERIN and SERRXD are "blocking commands whereby nothing else happens while they are waiting for data and during that waiting time the interrupts to drive background signals such as servo pulses stops.

see Appendix 4 in PICAXE manual 2 for some information on command conflicts.
http://www.picaxe.com/docs/picaxe_manual2.pdf
 
Last edited:

westaust55

Moderator
The @PTRINC means that after saving (or fetching) data at the location the PTR is pointing at, the PTR is post save/fetch increments to point at the next location.

Otherwise you will keep saving data in the same memory location.


In the SERTDX command the values 13 and 10 are the ASCII codes for carriage return and line feed so the displayed output for the next SERTXD starts on a new line.

There are predefined constants in the Programming Editor as CR and LF that can be used and add a bit more "readability" to the data/code.

Finally,
Welcome to the PICAXE forum.
 

hippy

Technical Support
Staff member
I tried this without the serial commands, and I basically get the same problem.
That sounds like a hardware problem with the wiring or perhaps the supply. Get that working as it should before moving on to trying more complicated control.
 

AllyCat

Senior Member
Hi,

Welcome to the forum. Often the circuit diagram (or a photo) of the PICaxe is more important than of the servo:

Is there a decoupling capacitor connected between Legs 1 and 8 (of the 08M2)? Is the download circuit definitely correct? 6 volts is a little high for a PICaxe, it would be better to start with about 5 volts (3 x Alkaline AA or 4 x NiMH AA, etc.).

Also, it might be better to start by sending the command characters from the PICaxe Editor Terminal. Also put a command at the start of the Program such as SERTXD ("Starting",CR,LF), it can show if the PICaxe gets reset for any reason (e.g. noise on the power supply).

The 08M2 does not support the PTR commands, but is can use BPTR. @BPTR is an alternative way to access the memory, but @bptr has the advantage that it can read memory locations above the maximum b27 of an M2 PICaxe. So these two sections of code are exactly the same:

Code:
serrxd [1000, timeout],b10,b11,b12       ; Read bytes into 3 registers

bptr = 10                                          ; Set the byte pointer
serrxd [1000, timeout],@bptrinc,@bptrinc,@bptr   ; Read bytes into the same registers
Cheers, Alan.
 

mvn

New Member
Do you definitely have the 0V supply to the PICAXE connected to the 0V supply for the servo?
Yes, I have both grounds attached to each battery pack I'm using. (4.5V for PICAXE, and 6V for servo)

Is the servo signal connected directly to the PICAXE chip - not via a ULN2803 or similar interface chip?
It is. I do not have any ULN2803 at the moment, so I'm using the PICAXE chip to supply signals directly.

Next is the fact that certain PICAXE commands such as SERIN and SERRXD are "blocking commands whereby nothing else happens while they are waiting for data and during that waiting time the interrupts to drive background signals such as servo pulses stops.

see Appendix 4 in PICAXE manual 2 for some information on command conflicts.
http://www.picaxe.com/docs/picaxe_manual2.pdf
The 08M2 does not support the PTR commands, but is can use BPTR. @BPTR is an alternative way to access the memory, but @bptr has the advantage that it can read memory locations above the maximum b27 of an M2 PICaxe. So these two sections of code are exactly the same:

Code:
serrxd [1000, timeout],b10,b11,b12       ; Read bytes into 3 registers

bptr = 10                                          ; Set the byte pointer
serrxd [1000, timeout],@bptrinc,@bptrinc,@bptr   ; Read bytes into the same registers
Cheers, Alan.
I'll check those out. Thanks. And also, I think I'll assume that it is the same method that C uses to a string of characters as a pointer, correct?
Code:
// char can only store one character at a time
char * str = "String";
// but storing it as a pointer (* symbol), it can hold it as an address and use it as an actual string
The @PTRINC means that after saving (or fetching) data at the location the PTR is pointing at, the PTR is post save/fetch increments to point at the next location.

Otherwise you will keep saving data in the same memory location.

In the SERTDX command the values 13 and 10 are the ASCII codes for carriage return and line feed so the displayed output for the next SERTXD starts on a new line.
There are predefined constants in the Programming Editor as CR and LF that can be used and add a bit more "readability" to the data/code.

Finally,
Welcome to the PICAXE forum.
Ah, now I see. That took me a while to figure out, so I'll just chuck those in to my code. Thanks again.

Is there a decoupling capacitor connected between Legs 1 and 8 (of the 08M2)? Is the download circuit definitely correct? 6 volts is a little high for a PICaxe, it would be better to start with about 5 volts (3 x Alkaline AA or 4 x NiMH AA, etc.).
I'm supplying the chip with 4.5V; the 6V is for the servo.

Also, it might be better to start by sending the command characters from the PICaxe Editor Terminal. Also put a command at the start of the Program such as SERTXD ("Starting",CR,LF), it can show if the PICaxe gets reset for any reason (e.g. noise on the power supply).
I'll try that.

EDIT:
I think I've narrowed it down, thanks to AllyCat's suggestion:
restarting.PNG
When I switch on the PICAXE, I keep receiving the "Starting..." message from the chip. Like AllyCat said, it might be PICAXE chip resetting such as shown in my program's image above. I've also made sure that I attached a decoupling capacitor(0.1uF) to the positive and gnd leads of the PICAXE, but it still does the same thing.
Code:
init:
	symbol pulse_pin = C.1 ' Motor 1
	b0 = 84     ' Left	(0 degrees)	
	b1 = 125    ' Center    (45 degrees)
	b2 = 169    ' Right     (90 degrees)
	servo pulse_pin, 85

main:
	sertxd("Starting...", 13, 10)
	do
		SERVOPOS pulse_pin, b0  ' Go to left
		pause 3000
	loop
 
Last edited:

tony_g

Senior Member
have you tried it with initializing the pin first with the "servo" command at startup, page 212 in the 2nd manual.

maybe that can help a bit with the glitching.


tony
 

mvn

New Member
YES! It's functioning properly now! I re-wired everything from scratch, and somehow everything's working as it should. I've also included the extra decoupling capacitor for the PICAXE's pin 1 and 8, and made sure that the other one is on the servo. It might've been faulty wiring on the servo, which caused all the commotion, but who knows.

Thanks again guys! :D
 
Top