Need help with PIC and servo

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 **************************************************************************
Add pictures here
<% if( /^image/.test(type) ){ %>
<% } %>
<%-name%>
Add image file
Upload
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:

Add pictures here
<% if( /^image/.test(type) ){ %>
<% } %>
<%-name%>
Add image file
Upload
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

Add pictures here
<% if( /^image/.test(type) ){ %>
<% } %>
<%-name%>
Add image file
Upload
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:

Add pictures here
<% if( /^image/.test(type) ){ %>
<% } %>
<%-name%>
Add image file
Upload
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

Add pictures here
<% if( /^image/.test(type) ){ %>
<% } %>
<%-name%>
Add image file
Upload
Buddy wrote:

...
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
Add pictures here
<% if( /^image/.test(type) ){ %>
<% } %>
<%-name%>
Add image file
Upload
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

Add pictures here
<% if( /^image/.test(type) ){ %>
<% } %>
<%-name%>
Add image file
Upload

Polytechforum.com is a website by engineers for engineers. It is not affiliated with any of manufacturers or vendors discussed here. All logos and trade names are the property of their respective owners.