Need help with PIC and servo

Translate This Thread From English to

Threaded View
I found the post from "Eriswerks" in this group on February 12th that
described my problem exactly: my Futaba 3004 servo turns clockwise 90-180
degrees when pulsed by my PIC 16F84A (code attached below).  I've selected
pulse widths from 0-1000 counts, which is supposedly 0-10ms with my 4MHz
crystal.  I've also varied the low part of each pulse from 10 to 1800, which
is supposed to be in milliseconds in the PICBasic Pro PULSOUT command.
Regardless of these values the result is about the same: the servo rotates
90-180 degrees clockwise (viewed from the top) per set of cycles.  I'd
really appreciate any help.  --Buddy

Here's the latest version of my servo calibration routine with the shortest
pulse widths I've tested (it's supposed to work with 100-200 counts per
pulse but did not):

***************************************************************************
Include "modedefs.bas"                     ' Include serial modes

trisa = %00000000                         ' set porta to outputs
trisb = %00000000                         ' set portb to outputs

lcd         var PORTA.3                     'lcd signal on 16F84A pin 2
piezo       var PORTB.4
left_led    var PORTB.0
right_led   var PORTB.1
servo       var PORTB.7                           'servo signal on 16F84A
pin 13
baud        con N2400
timer       var Byte
width       var byte
width_init  var byte

high left_led                    ' turn on left LED
low right_led                    ' turn off right LED

Serout lcd,baud,[254,1]               ' clear lcd screen

pause 1000                        ' give time to initialize lcd

Serout lcd,baud,[254,128,"- Servo cal -"]    ' display program title on the
LCD

Serout lcd,baud,[254,192,"Pulse: "]               ' set up the LCD display

pause 5000                        ' wait for 5 seconds

low left_led                    ' turn off left LED
high right_led                    ' turn on right LED
sound piezo,[125,50]
low piezo

width_init = 0                                    ' set initial pulse width
width = width_init                                ' initial pulse width
variable
low servo                                         ' initialize servo pin

main:

    Serout lcd,baud,[254,200,#width,"     "]    ' display the pulse width in
counts

    for timer = 1 to 20                           ' send pulses to servo
        pulsout servo,width
        pause 15
    next timer

    pause 4000

    toggle left_led                ' toggle left LED
    toggle right_led               ' toggle right LED

    if width < 100 then                           ' increase width through
max then repeat
        width = width + 10
    else
        width = width_init
        sound piezo,[125,50]
        low piezo
    endif

Goto main

end
**************************************************************************



Re: Need help with PIC and servo

I don't know PICBasic, but I know with the BASIC Stamp pulsout is NOT
milliseconds, it's the minimum timing amount for the particular chip, in
MICROseconds. So, with the BS2, which has a minimum 2 microsecond
granularity, a value of 750 is 1500 microseconds.

Try something simpler. All you need is a pulsout command, a pin number,
and a value. Keep setting values in your code, and re-download your code
to try different values. After you get this code to work you can create
a more fancy program that sweeps the servo, updates an LCD, etc.

Provide ONLY pulses in the range of 1000 to 2000 microseconds (1 to 2
milliseconds). The servo should center at 1500 microseconds (1.5
milliseconds). If the servo is unmodified, using longer or shorter
pulses may *permanently damage* the servo, because it will case the
servo to hit its stops. Even if the servo is modified for contiunuous
rotation, values much shorter or longer than 1000-2000 microseconds may
put the servo electronics into an unknown state.

You may, after determining your programming timing is correct,
experiment with SLIGHTLY longer or shorter values. This will allow you
to achieve close to 180 degree rotation of the servo. However, start
with the safe 1000-2000 microsecond range.

-- Gordon


Buddy wrote:


Re: Need help with PIC and servo

Gordon -- Thanks for responding.  You're right: I said "PULSOUT" used
milliseconds when I should have said PAUSE.  As I mentioned elsewhere in the
post, PULSOUT counts supposedly equal 10us for this PIC when using a 4MHz
crystal.

I agree also that a shorter routine would have been quicker to write, but
now that this one's done it seems it should actually help solve this problem
by telling me what pulse width is being sent to the servo while I watch it
respond.  The LCD commands work OK and don't require any attention when I
change the code to try new pulse widths.

Finally, I tried to say in the original post that I had varied the pulse
widths from 0 to 1000 counts, which should be about 0-10ms.  This includes
1000-2000 microseconds, as you suggest, which is where I started.  As I
mentioned, all non-zero pulse widths produce essentially the same results,
including 1us, 100us, 1000us, 1500us, 2000us, 5000us and 10000us, plus many
others between the extremes.

Thanks again for your thoughts.  What do you think I should try next?

Buddy



Re: Need help with PIC and servo

As I noted with some (many?) servos giving them a pulse that's
significantly shorter than the designed 1000-2000 microseconds can put
them into an unstable/unknown state. Your code shouldn't be going below
1000 microseconds, or above 2000 microseconds. Some servo models are
known to deadlock in this condition, and the only way to get them
working again is to unplug them (remove power).

You CAN go slightly higher or lower, depending on the servo, but again,
emphasis on *slightly*.

-- Gordon


Buddy wrote:


Re: Need help with PIC and servo

Gordon -- Thanks again.  My first run used PULSOUT commands that varied
between 100 and 200 counts, which is what every source I've found
recommends.  Every group of ten (in that version) pulses drove the servo
90-180 degrees clockwise.  I then moved the boundaries a little at a time
after removing power from everything each time, but the performance never
changed.  It took a lot of tries before I sent the 1us and 10000us pulses
but the servo never acted differently.  Incidentally, I tried another servo
with the "nominal" code values, hoping that I had a bad one, but it behaved
the same way.

As soon as I hit "Send" I'm going to build a little servo control circuit
with a pot and a 555 timer.  Depending on the results I may also download a
sound-card oscilloscope and see if I can find out what these pulses look
like.

Thanks again, and please share any other thoughts or comments.  --Buddy



Re: Need help with PIC and servo



Nobody mentioned it, but is also important that you don't send more than
50 pulses per second. As gordon said, some servos can deal with a higher
rate, but 50 samples per second (one every 20 ms) is the safe way to go

Re: Need help with PIC and servo

Thanks, Matthias.  This issue turned out to be caused by not having the
grounds from my servo power supply and my logic circuit power supply tied
together.  Gordon's book mentions this but I didn't appreciate its
importance until afterwards.  One 1/2" (12mm) wire on my breadboard took
care of everything!  --BR



Site Timeline