Driving multiple servos from the RaspberryPi


198 posts   Page 4 of 8   1, 2, 3, 4, 5, 6, 7, 8
by tobrien81 » Sat Nov 03, 2012 9:34 am
Perfect. Thanks for that :-) I am new to servos and electronics. Programming is my forte :-)
Posts: 17
Joined: Thu Aug 30, 2012 9:57 am
by tobrien81 » Tue Nov 06, 2012 5:46 am
Hey

So now I am confused. I have connected everything together. 6V power supply 1A, 1 x Servo to GPIO4, I have the servoblaster char file in /dev and in /dev/procs with an id of 251, however when I run the command "echo 0=12 > /dev/servoblaster" and I have tried 0 - 7 in the command I do not get any movement on my servo... What am I missing.

BTW, sorry for the newbie-ness, as forementioned, I am new to electronics of this type...

Tom
Posts: 17
Joined: Thu Aug 30, 2012 9:57 am
by ame » Tue Nov 06, 2012 6:45 am
tobrien81 wrote:Hey

So now I am confused. I have connected everything together. 6V power supply 1A, 1 x Servo to GPIO4, I have the servoblaster char file in /dev and in /dev/procs with an id of 251, however when I run the command "echo 0=12 > /dev/servoblaster" and I have tried 0 - 7 in the command I do not get any movement on my servo... What am I missing.

BTW, sorry for the newbie-ness, as forementioned, I am new to electronics of this type...

Tom


Dare I ask, have you loaded the driver?

sudo insmod servoblaster

And check it's there using "lsmod"

Can you take a picture of your wiring and post it somewhere for us to see?

Do you have access to any test equipment, such as a multimeter or an oscilloscope?

If you like, I can write down every step I made to make it work, but I think it was this:

1. Make new SDCard image of Debian Wheezy (I didn't have an up-to-date one)
2. Download jronald's files from here:
https://github.com/jronald/PiBits/downloads
I did this on another PC and then extracted servoblaster.ko
3. Copy servoblaster.ko to Pi
4. Issue "sudo insmod servoblaster" on Pi (can't remember if I used sudo)
I then ran the commands listed in the source file to create the node:
5. Issue "sed -n 's/ servoblaster//p' /proc/device"
This gave me the answer 251
6. Issue "mknod -m 0666 /dev/servoblaster c 251 0"
7. Issue "echo 0=150 > /dev/servoblaster"
..and my servo twitched into life. It's on GPIO4 (pin 7) and GND (pin 9).

I'd be happy to shut it all down and redo it to check the sequence of events.

Lastly, "12" is a rather low number (is it a typo?). The servo might be hitting its end stop. Try "echo 0=150 > /dev/servoblaster". This should give you 1500us or 1.5ms, which is the nominal mid-point of a servo's range.
Posts: 967
Joined: Sat Aug 18, 2012 1:21 am
Location: Japan
by ame » Tue Nov 06, 2012 8:20 am
I just checked on the Pi at home. What I did is pretty much as I described, but I had to use 'sudo' with 'mknod...'
Posts: 967
Joined: Sat Aug 18, 2012 1:21 am
Location: Japan
by joan » Tue Nov 06, 2012 8:24 am
It's not clear from your post as to whether you have got it working or not. Have you connected the servo ground to the Pi's ground as well as the ground of the power source?
User avatar
Posts: 5982
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK
by tobrien81 » Tue Nov 06, 2012 9:56 am
Ok, so I started fresh on my Pi and now it works. I must have had a hardware addressing conflict somewhere in linux.

Thank you so much for your time :-)
Posts: 17
Joined: Thu Aug 30, 2012 9:57 am
by JamesRonald » Mon Nov 12, 2012 12:49 am
@ame, I added the change that you requested to handle larger count values based on the number of servos specified. The new limit is (cycle_ticks / num_servos - 1) although values > ~300 will not be useful and may damage your servos. I have not yet had a chance to test the changes so let me know if there are any issues. The updated kernel module is available from my repository at https://github.com/jronald/PiBits
Posts: 7
Joined: Fri Aug 31, 2012 8:55 pm
by ame » Mon Nov 12, 2012 1:07 am
Thanks @JamesRonald.

One of my servos has a low limit of 610us, below which it goes a little mad. I am not sure what the high limit is because I can only write 2490us. I have the feeling it will accept pulses a little higher, so I'd like to try. I will try the new driver later (not until Wednesday I am afraid).

Are either you or @rgh considering an option to invert the sense of the output pulse? I mentioned this before, and it would allow the use of a single transistor inverter to buffer the 3V3 output of the Pi to a 5V signal for the servo. Personally I haven't found it necessary, but there probably should be a buffer there...
Posts: 967
Joined: Sat Aug 18, 2012 1:21 am
Location: Japan
by Smcintosh » Mon Nov 12, 2012 10:39 am
rgh wrote: I don't know why only one person apparently had that issue but if you can get a 'scope on the GPIO pin you should see a 1.2ms pulse repeating every 20ms. If you see something other than that, let us know. Unfortunately I'm a long way from Hull or I'd happily call round to give you a hand.


While trying to solve the problems I have been having I pot a scope on the GPIO and did get some discrepancies with the timings.

0=200 gave me a 1.38ms pulse
0=150 gave 1ms
and 0=100 gave 0.7ms
Posts: 13
Joined: Tue Jul 31, 2012 11:37 am
by ame » Wed Nov 14, 2012 11:57 am
JamesRonald wrote:@ame, I added the change that you requested to handle larger count values based on the number of servos specified. The new limit is (cycle_ticks / num_servos - 1) although values > ~300 will not be useful and may damage your servos. I have not yet had a chance to test the changes so let me know if there are any issues. The updated kernel module is available from my repository at https://github.com/jronald/PiBits


Thanks! I just tried it. Indeed I can write larger values to /dev/servoblaster and my servo will travel a little further. One goes slightly mad at the high end at 2580us, the other at 2530us.

I agree that values of > 300 would be generally useless, and in fact a limit of 250 (or 249) is entirely reasonable. Four of my servos have a maximum value which is much less than 250. The other two are barely useful beyond that limit.

One thing I noticed: With num_servos set to 2 I occasionally get long pauses when writing to /dev/servoblaster. This is quite rare, but never happens when num_servos is not specified.
Posts: 967
Joined: Sat Aug 18, 2012 1:21 am
Location: Japan
by adentse » Fri Nov 16, 2012 12:05 am
I think this might render my card quite useless :)

http://electronics.chroma.se/rpisb.php

Anyway, modified my card a bit and replaced the Attiny with a buffer-IC and
connected it to the IO-pins that the kernel-module use.

Hope I'll get theese cards soon :)

Best regards
Mikael
Posts: 6
Joined: Thu Nov 15, 2012 11:33 pm
by Rodney Wertz » Sat Nov 17, 2012 7:31 pm
rgh wrote:
Ph1lj2 wrote:So after a lot more trying, my hang-up appears to with Sbcontrol script, when I execute the command I get back the following error message :-

/usr/local/bin/sbcontrol: line 53: syntax errot neat unexpected token 'then'
/usr/local/bin/sbcontrol: line 53: ' if [ $index = $active ]; then'


previous to that I run the sudo sbload with no issues

As far as I can see my code matches that above (I simply copied it - not typed)

Any help would be appreciated

Did you typo the error message above, or did it really say "errot neat" rather than "error near"?

Anyway, I just cut and pasted the script to a file (I used vim as my editor), and I get:
Code: Select all
richard@bugsy:~$ wc /tmp/sbcontrol
 141  358 3211 /tmp/sbcontrol
richard@bugsy:~$ md5sum /tmp/sbcontrol
33eab45cdb423df0123f16dcbfa45d76  /tmp/sbcontrol
richard@bugsy:~$

'wc' shows the number of lines, words, and characters in my file, 'md5sum' shows a sort of checksum for the file content. Do you get the same wc and md5sum, output for your file? I don't have any blank lines at the end of my file btw, the last line is "done". I didn't try to run the script this time, but when it was first posted I copy and pasted it and it ran ok. If your md5sum is different and you can't figure out what is going on, you could run "od -x /usr/local/bin/sbcontrol" and sending me the output in a private message.


I have been getting exactly the same error. My values for wc and md5sum were way out. I figured it was possibly a problem with the copying of the text. I downloaded a copy of Notepad++ and copied the text to that and saved it as a txt file. I then transfered it to the RPi on a USB thumb drive and copied and pasted it into nano and saved it. WC and md5sum were identical to yours and the file gave no errors. There is probably a simplier and more elegant way to do it but this worked for me.
Rodney
Posts: 24
Joined: Sun Jun 03, 2012 12:22 am
Location: Wolfforth, Texas
by rgh » Sat Nov 17, 2012 8:15 pm
This explains the problem with cutting and pasting code from the forum: http://www.raspberrypi.org/phpBB3/viewtopic.php?f=37&t=19346&p=204341&hilit=nbsp#p204341. In the next post on that thread joan has a suggestion for using 'tr' to strip the problem characters.
Posts: 220
Joined: Fri Nov 25, 2011 3:53 pm
by ToddFerrante » Sun Nov 18, 2012 9:56 pm
I just discovered a nifty way to use servoblaster over a wireless (or wired) network link. Both computers need to be on the same network.

First, install netcat onto both the robot controller and the control station using:
Code: Select all
sudo apt-get install netcat

Keep in mind that I have "robotcontroller" and "controlstation" defined in my hosts file with the static ip addresses of my two Pis.

On the robotcontroller (connected to the motors) do:
Code: Select all
sudo sbload
nc -v -lp 5000 > /dev/servoblaster

The second command activates netcat in listen mode, listening to port 5000 and sending any input to servoblaster.

On the controlstation do:
Code: Select all
nc -v robotcontroller 5000

This activates netcat and sends any typed input directly to port 5000 on robotcontroller.
Now, on controlstation type servoblaster commands, such as:
Code: Select all
1=170
1=190
1=210
1=180
1=150

This series of commands moves servo number 1. When finished, hit crtl-c on each machine to stop netcat.

Todd F.
Posts: 19
Joined: Sun Sep 30, 2012 8:00 pm
by rgh » Fri Nov 23, 2012 11:24 pm
I just updated https://github.com/richardghirst/PiBits/tree/master/ServoBlaster. Significant changes are:

You can now "cat /dev/servoblaster" to read back the current settings. This is intended primarily as a debug feature, as it'll let you confirm that the driver is really seeing commands you think you are sending. It does also let you capture all servo positions (via "cat /dev/servoblaster > some.file") and later restore them (via "cat some.file > /dev/servoblaster").

You can now do "make install" which will create the udev rules so that later you can just do "sudo insmod servoblaster.ko" and /dev/servoblaster should be created for you automatically.

You can do "make install_autostart" which will arrange for the module to be loaded and /dev/servoblaster created automatically on subsequent reboots. Use this with care, as it means the eight GPIO pins will be reconfigured as outputs on every reboot in future (not a good idea if you might have other hardware driving them sometimes). You can disable the autoloading of the module later by removing the relevant line from /etc/modules. This works on Raspbian, at least.

Finally, the driver now copes with you sending multiple commands in one write (e.g. echo -ne "0=100\n1=200\n2=150\n" > /dev/servoblaster).

Thanks go to Robin for most of this work.
Posts: 220
Joined: Fri Nov 25, 2011 3:53 pm
by box » Sat Nov 24, 2012 10:58 pm
rgh wrote:I just updated https://github.com/richardghirst/PiBits/tree/master/ServoBlaster. Significant changes are:

You can now "cat /dev/servoblaster" to read back the current settings. This is intended primarily as a debug feature, as it'll let you confirm that the driver is really seeing commands you think you are
...


Hello folks.

Kernel module is not working for me :?
I have the same problem with /dev/servoblaster file (no such file after loading module), like "Smcintosh" had (on page2). I installed latest kernel and servoblaster versions.
Here is listing:
Code: Select all
root@pi ServoBlaster # uname -a
Linux pi 3.2.27+ #1 PREEMPT Sat Nov 24 05:35:07 EST 2012 armv6l GNU/Linux
root@pi ServoBlaster # insmod ./servoblaster.ko
root@pi ServoBlaster # lsmod
Module                  Size  Used by
servoblaster            4906  0
snd_bcm2835            12732  0
...
root@pi ServoBlaster # ls -la /dev/se*
ls: cannot access /dev/se*: No such file or directory
root@pi ServoBlaster # cat /proc/devices
Character devices:
...
189 usb_device
204 ttyAMA
251 servoblaster
252 vchiq
253 vc-mem
254 rtc
...
root@pi ServoBlaster # mknod -m 0666 /dev/servoblaster c 251 0
root@pi ServoBlaster # ls -la /dev/se*
crw-rw-rw- 1 root root 251, 0 Nov 24 17:19 /dev/servoblaster
root@pi ServoBlaster # cat /dev/servoblaster
0=0
1=0
2=0
3=0
4=0
5=0
6=0
7=0
root@pi ServoBlaster # echo 0=150 > /dev/servoblaster
root@pi ServoBlaster # echo 7=100 > /dev/servoblaster
root@pi ServoBlaster # cat /dev/servoblaster
0=150
1=0
2=0
3=0
4=0
5=0
6=0
7=100
root@pi ServoBlaster #


Servo connected to 7 (GPIO 25 pin). I tried all (0-7) and I'm sure that connection is OK, because servo is working in single PWM mode (without this module) on (GPIO pin 12)
I've got the same problem two days ago (on previous servoblaster version), and now (new version).
Any ideas? :roll:
Posts: 19
Joined: Thu Nov 22, 2012 8:08 pm
by rgh » Sun Nov 25, 2012 12:46 am
@box, @Smcintosh,
I've just added a debug utility to the git repository, can you grab https://github.com/richardghirst/PiBits/blob/master/ServoBlaster/servodebug.c, then set one of the servo outputs and compile and run it like this:

Code: Select all
$ echo 2=100 > /dev/servoblaster
$ gcc -Wall -O2 -o servodebug servodebug.c
$ sudo chrt 1 ./servodebug
This code should be compiled with the command:

  gcc -Wall -O2 -o servodebug servodebug.c

It should be run with the command:

  sudo chrt 1 ./servodebug


Good, DMA controller is running

Timing 1M cycles of system tick, should take 1000000us
but small variations are to be expected

1M increments of system tick measured at 999997us

Monitoring for the first 20 transitions on servo control lines

    time   outputs
    (us)   76543210
        0  00000100
      999  00000000
    19999  00000100
    20999  00000000
    39999  00000100
    40999  00000000
    59999  00000100
    60999  00000000
    79999  00000100
    80999  00000000
    99998  00000100
   100998  00000000
   119998  00000100
   120998  00000000
   139998  00000100
   140998  00000000
   159998  00000100
   160998  00000000
   179998  00000100
   180998  00000000



You can see in the example output above that servo output 2 goes high at time 0, then low at 999us, then high at 19999us, low at 20999us, etc. That means the output is on for approximately 1ms in every 20ms, as expected for a command of "2=100".

I'm interested to see your output. Does it even get as far as showing a list of transition times, or does it error before that? Does the pattern repeat every 20ms for you, or is it running at a different speed for some reason? Does it run at a consistent speed for you, or does the pattern repeat at irregular intervals? If it is running at the wrong speed consistently, there are a couple of module parameters you can try to adjust that, see the README for details.

This debug code can be disturbed by interrupt processing or scheduling, so you might get the occasional odd result, but if you run it a few times it should give fairly consistent results. The GPIO pins are obviously configured as outputs by servoblaster; this debug code reads the GPIO level input register to report what is actually driven on to the pins by servoblaster.


Richard
Posts: 220
Joined: Fri Nov 25, 2011 3:53 pm
by box » Sun Nov 25, 2012 1:54 am
Here is my output:
Code: Select all
root@pi ServoBlaster # gcc -Wall -O2 -o servodebug servodebug.c
root@pi ServoBlaster # chrt 1 ./servodebug
This code should be compiled with the command:

 gcc -Wall -O2 -o servodebug servodebug.c

It should be run with the command:

 sudo chrt 1 ./servodebug


Good, DMA controller is running

Timing 1M cycles of system tick, should take 1000000us
but small variations are to be expected

1M increments of system tick measured at 999963us

Monitoring for the first 20 transitions on servo control lines

 time outputs
 (us) 76543210
      0 10000000
   1000 00000000
  20000 10000000
  21000 00000000
  40000 10000000
  41000 00000000
  60000 10000000
  61000 00000000
  79999 10000000
  80999 00000000
  99999 10000000
 100999 00000000
 119999 10000000
 120999 00000000
 139999 10000000
 140999 00000000
 159999 10000000
 160998 00000000
 179998 10000000
 180998 00000000

root@pi ServoBlaster #
Posts: 19
Joined: Thu Nov 22, 2012 8:08 pm
by rgh » Sun Nov 25, 2012 11:18 am
@box, Thanks... that didn't help much did it. So apparently your servo output is doing exactly what it should. You are using servo 7, which is GPIO 25, which is on P1 pin 22. If you use a separate power source for your servo, the 0v of that source should be tied to the 0v (GND) on the Pi. I don't know what servo you are using, but I am assuming you are providing it with sufficient power, and that it is happy with a control signal that switches between 0v and 3v, or there abouts. If you have extra electronics between P1-22 and the servo control input to buffer the signal I assume that circuit is not inverting the control (which would give you a 19ms pulse from the servo's point of view, which is invalid).

Here's another test you can do if you have a multimeter. I set mine to measure DC voltage and measured the voltage on P1-22. If I "echo 7=0 > /dev/servoblaster" I measure 0v, "7=125" gives me about 0.2v, "7=249" gives me about 0.4v. That seems reasonable because 249 is 2.49ms, which is one eighth of 20ms, and 0.4v is about one eighth of 3.3v (the GPIO high level). You should do this first with no servo connected, and then again with the servo connected, in case the servo is somehow overloading the GPIO output. I did this with a cheap meter that cost about £7; it's possible others might not average a pulsing signal in the same way. Of course, if you have an oscilloscope you can use that to check the pulses, or if you have a second Pi you could use Panalyzer on that to monitor the first Pi.

Another idea would be to make my debug code set up another GPIO pin as an input and monitor that one, then you could link it to P1-22 and be sure you were genuinely monitoring the control signal that was being sent to the servo.

Finally, when you say it doesn't work, what actually happens if you "echo 7=100" and then "echo 7=200"? Does the servo not move at all? Does it twitch a bit?
Posts: 220
Joined: Fri Nov 25, 2011 3:53 pm
by box » Sun Nov 25, 2012 10:17 pm
Now it is working. My mistake. I used pin25 instead of GPIO25 (pin22). :oops:
I think it will be good idea to add to README.txt list of servo outputs like:
-----------------
Servo Pin GPIO
0 7 4
1 11 17
2 5(12) 1(18)*
3 13 21
4 15 22
5 16 23
6 18 24
7 22 25

* Your description about PWM0_ON_GPIO18
------------------
... to avoid many mistakes and questions.
It will be very helpful for idiots like me :lol:
Thank you Richard.
Posts: 19
Joined: Thu Nov 22, 2012 8:08 pm
by rgh » Mon Nov 26, 2012 7:14 pm
@box, yeah, with three different ways to number gpio pins there is plenty of scope for confusion :) I'll update the README.
Posts: 220
Joined: Fri Nov 25, 2011 3:53 pm
by rgh » Sun Dec 02, 2012 10:29 am
I noticed the code in servoblaster that configured the PWM clock was unreliable - if I repeatedly unloaded and reloaded the driver it didn't always start up properly, and if I played some PWM audio before loading servoblaster, then servoblaster rarely worked. I've made some changes and uploaded a new module, which is more robust.

ServoBlaster currently uses the PWM hardware for timing purposes, so cannot be used at the same time as PWM audio on the 3.5mm jack, and if you play PWM audio after loading servoblaster.ko, you'll need to unload and reload servoblaster.ko in order to recover. I should perhaps investigate using some other hardware for timing purposes (such as PCM, maybe), which is less likely to cause a conflict.
Posts: 220
Joined: Fri Nov 25, 2011 3:53 pm
by aasdf » Sun Dec 02, 2012 11:25 pm
The latest Arch kernel includes the realtime PREEMPT patches, if you included support for this you could probably get much more accurate timing without having to suspend interrupts
Posts: 2
Joined: Sun Dec 02, 2012 11:24 pm
by rgh » Mon Dec 03, 2012 8:33 am
aasdf wrote:The latest Arch kernel includes the realtime PREEMPT patches, if you included support for this you could probably get much more accurate timing without having to suspend interrupts

Ummm, the timing is generated in hardware (via the DMA controller, and using the PWM FIFO clock to generate delays); why would PREEMPT_RT have any impact at all on that? The code does disable interrupts, but only so it can adjust multiple DMA control blocks in a well defined time window.

Have you tried the code and found the timing to be inaccurate, or is this just a random "Arch is better at everything" post ;-)
Posts: 220
Joined: Fri Nov 25, 2011 3:53 pm
by adentse » Tue Dec 04, 2012 11:16 pm
Hello!

I tried to layout a board to get nice connectors and a buffer for the RPi. Arrived today and got
it working after updating the kernel. It got a a 74HC541 to make the 3.3V-signal 5V. It also protects the RPi from the servos/ESC and the servos can be powered via ESC or RPI, and RPI can be powered via micro-usb or ESC. Since i had some room on the PCB i broke out the serial port.

Image

http://electronics.chroma.se/rpiswsb.php

Best regards
Mikael
Posts: 6
Joined: Thu Nov 15, 2012 11:33 pm