Driving multiple servos from the RaspberryPi


210 posts   Page 3 of 9   1, 2, 3, 4, 5, 6 ... 9
by rgh » Mon Oct 22, 2012 10:53 pm
rgh wrote:
Ph1lj2 wrote:Error could not insert module /usr/local/bin/servoblaster.ko: Invalid module format

That most likely means the servoblaster.ko module needs rebuilding to match the kernel you are running. I'll update the one on github to match the latest kernel in a day or two.

Actually, the servoblaster.ko on github seems to work with the current kernel. Have you run rpi-update recently? What does 'uname -a' report for you? Mine says
Code: Select all
richard@raspberrypi ~ $ uname -a
Linux raspberrypi 3.2.27+ #250 PREEMPT Thu Oct 18 19:03:02 BST 2012 armv6l GNU/Linux
Posts: 211
Joined: Fri Nov 25, 2011 3:53 pm
by Smcintosh » Tue Oct 23, 2012 6:57 am
Hmm I came up against in interesting problem when I tried to setup the servo after a restart. It did not work so I went through checking some things.

ls -l /dev/servoblaster
Returned
-rw-rw-rw- rather than crw-rw-rw-

so I deleted the /dev/servoblaster file and recreated it, but at this point it did not work any more. The servo just twitched about as it does when it gets no pulses.

So I got it work on a clean install but could not get it up and running after a RPi reboot, any idea what I am doing wrong?
Posts: 13
Joined: Tue Jul 31, 2012 11:37 am
by rgh » Tue Oct 23, 2012 7:24 am
Smcintosh wrote:Hmm I came up against in interesting problem when I tried to setup the servo after a restart. It did not work so I went through checking some things.

ls -l /dev/servoblaster
Returned
-rw-rw-rw- rather than crw-rw-rw-

so I deleted the /dev/servoblaster file and recreated it, but at this point it did not work any more. The servo just twitched about as it does when it gets no pulses.

So I got it work on a clean install but could not get it up and running after a RPi reboot, any idea what I am doing wrong?

If the file exists as -rw-rw-rw- rather than crw-rw-rw- it means it is a regular file, not a character device file. That in turn means you (or some script you ran) did "echo whatever > /dev/servoblaster" before you'd done the mknod command. I assume you've run through all the steps in my post here http://www.raspberrypi.org/phpBB3/viewtopic.php?f=37&t=15011&start=25#p193826 and all looks good, the major number from /proc/devices is the major number you see in the "ls -l" output, no error message when you do the echo command at the end of that sequence?
Posts: 211
Joined: Fri Nov 25, 2011 3:53 pm
by joan » Tue Oct 23, 2012 8:02 am
I have continued my experiments with PWM for motors/leds and servos.

I found memory <> memory DMA unreliable (memory <> peripheral memory seems fine) so abandoned that as a way of triggering servo pulses.

Currently I'm triggering the servo pulses using a timer tick (the pulse length is timed by DMA).

The PWM itself is still approx.400 Hz with 256 levels.

Short video http://www.youtube.com/watch?v=8ZvhRzZ7MLo
User avatar
Posts: 12702
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK
by Smcintosh » Tue Oct 23, 2012 8:07 am
rgh wrote:If the file exists as -rw-rw-rw- rather than crw-rw-rw- it means it is a regular file, not a character device file. That in turn means you (or some script you ran) did "echo whatever > /dev/servoblaster" before you'd done the mknod command. I assume you've run through all the steps in my post here http://www.raspberrypi.org/phpBB3/viewtopic.php?f=37&t=15011&start=25#p193826 and all looks good, the major number from /proc/devices is the major number you see in the "ls -l" output, no error message when you do the echo command at the end of that sequence?


Yes I did try to write to the file prior to mknod so then ran through the steps in your post http://www.raspberrypi.org/phpBB3/viewtopic.php?f=37&t=15011&start=25#p193826. It was then I spotted the missing "c" reported by ls-l.

This promted me to delete the file and recreate it with the mknod command but it still did'nt work. I will run through it again from startup and check each step again but what would the normal procedure be?

The file /dev/servoblaster already exists but not as a character device. If I try to mknod I get an error saying "file already exists". Do I delete and recreate or is there a simpler way to "get the c back".
Posts: 13
Joined: Tue Jul 31, 2012 11:37 am
by Ph1lj2 » Tue Oct 23, 2012 12:57 pm
ToddFerrante wrote:I've been working on getting the servoblaster drivers up and running. I also was unsuccessful getting the files to load automatically, so I had to improvise. To start with, I made simple bash scripts to load and unload the driver. "sbload" works great, but "sbunload" doesn't completely unload the driver. I put these in my /usr/local/bin directory along with a copy of servoblaster.ko. After executing "sudo sbload", using the "echo servo=width > /dev/servoblaster" command sets the PWM pulse. I used the command line to drive a Jaguar motor controller used in the FIRST robotics competition. Video can be found here: http://www.youtube.com/watch?v=Uj7IhPEe3b4

For a little more useful user interface, I wrote up a longer bash script which gives a live display of the pulse widths of the 8 servos and allows adjustment using the arrow keys, page up and down keys, and number keys. The user can set values for the min, max, and neutral pulse width for each channel. The program initializes with the servos at their neutral values, so you don't break anything it these are hooked up to hardware. Pressing the up/down arrow keys adjusts the pulse width by the step increment (initially 100 uS). The step increment is adjusted with the page up/down keys. Initially the active channel is 0. The left/right arrow keys change the channel by one, or you can go directly to any channel by pressing its number key. The screen displays all the current PWM channel pulse widths, with the currently selected channel shown in red. The second line of text displays the step value for the active channel. Finally, pressing "x" resets all the servos to their neutral value, unloads the driver and exits the script.

Code follows. (Sorry about the formatting. Apparently tabs don't copy and paste well from leafpad to the forum.)
Todd F.

/usr/local/bin/sbload
Code: Select all
#!/bin/bash

echo "servoblaster loading"
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
insmod $DIR/servoblaster.ko
major=$( sed -n 's/ servoblaster//p' /proc/devices )
[ "$major" ] && mknod -m 0666 /dev/servoblaster c $major 0
exit 0


/usr/local/bin/sbunload
Code: Select all
#!/bin/bash

echo "servoblaster unloading"
rm -f /dev/servoblaster
exit 0


/usr/local/bin/sbcontrol
Code: Select all
#!/bin/bash

#initialize arrays
min[0]=50
min[1]=50
min[2]=50
min[3]=50
min[4]=50
min[5]=50
min[6]=50
min[7]=50

max[0]=250
max[1]=250
max[2]=250
max[3]=250
max[4]=250
max[5]=250
max[6]=250
max[7]=250

neutral[0]=150
neutral[1]=150
neutral[2]=150
neutral[3]=150
neutral[4]=150
neutral[5]=150
neutral[6]=150
neutral[7]=150

inc[0]=10
inc[1]=10
inc[2]=10
inc[3]=10
inc[4]=10
inc[5]=10
inc[6]=10
inc[7]=10

red='\e[0;31m'
endColor='\e[0m'
active=0

#define functions

#display current pulse width values with active servo highlited
function prn_curr_pw {
active=$1
echo $active=${pw[$active]} > /dev/servoblaster
clear
for index in {0..7}
do
  if [ $index = $active ]; then
    echo -e ${red}$index":"${pw[$index]}0${endColor}" \c"
  else
    echo -e $index":"${pw[$index]}"0 \c"
  fi
done
echo " "
echo Servo $active pulse width increment ${inc[$active]}0 uS.
}

#main program
sudo sbload
clear
pw[0]=${neutral[0]}
echo 0=${pw[0]} > /dev/servoblaster
echo -e ${red}"0:"${pw[$active]}0${endColor}" \c"
for index in {1..7}
do
  pw[$index]=${neutral[$index]}         #set pulse width to neutral values
  echo $index=${pw[$index]} > /dev/servoblaster
  echo -e $index":"${pw[$index]}"0 \c"   #display initial values
done
echo " "
echo Servo $active pulse width increment ${inc[0]}0 uS.
while true            #read keypresses and act
do
  read -sn1 a
  case "$a" in            #number keypress sets active servo
    0)  prn_curr_pw $a
        active=$a;;
    1)  prn_curr_pw $a
        active=$a;;
    2)  prn_curr_pw $a
        active=$a;;
    3)  prn_curr_pw $a
        active=$a;;
    4)  prn_curr_pw $a
        active=$a;;
    5)  prn_curr_pw $a
        active=$a;;
    6)  prn_curr_pw $a
        active=$a;;
    7)  prn_curr_pw $a
        active=$a;;
    x)  clear
   for index in {0..7}
   do
       pw[$index]=${neutral[$index]}         #set pulse width to neutral values
       echo $index=${pw[$index]} > /dev/servoblaster
       echo -e $index":"${pw[$index]}"0 \c"   #display final values
   done
   echo " "   
   sudo sbunload
   exit
  esac
  test "$a" == `echo -en "\e"` || continue
  read -sn1 a
  test "$a" == "[" || continue
  read -sn1 a
  case "$a" in
    A)  let "new=${pw[$active]}+${inc[$active]}"    #keypress up arrow
   if [ "$new" -le "${max[$active]}" ]; then   #increase width
     let "pw[$active]=$new"
   fi
        prn_curr_pw $active;;
    B)  let "new=${pw[$active]}-${inc[$active]}"   #keypress up arrow
   if [ "$new" -ge "${min[$active]}" ]; then   #decrease width
     let "pw[$active]=$new"
   fi
        prn_curr_pw $active;;
    C)  let "active=$active+1"            #keypress left arrow
   if [ "$active" -eq 8 ]; then         #previous servo number
     active=0
   fi
   prn_curr_pw $active;;
    D)  let "active=$active-1"            #keypress right arrow
   if [ "$active" -eq -1 ]; then         #next servo number
     active=7
   fi
   prn_curr_pw $active;;
    5)  let "inc[$active]=${inc[$active]}+1"      #keypress pageup
   prn_curr_pw $active;;            #increase step
    6)  let "new=${inc[$active]}-1"         #keypress pageup
   if [ "$new" -ge 1 ]; then         #decrease width
     let "inc[$active]=$new"
   fi
        prn_curr_pw $active;;
  esac
done


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
Posts: 35
Joined: Sat Oct 20, 2012 9:21 pm
by rgh » Tue Oct 23, 2012 6:00 pm
Smcintosh wrote:Do I delete and recreate or is there a simpler way to "get the c back".

You need to delete it and recreate.
Posts: 211
Joined: Fri Nov 25, 2011 3:53 pm
by rgh » Tue Oct 23, 2012 6:18 pm
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.
Posts: 211
Joined: Fri Nov 25, 2011 3:53 pm
by JamesRonald » Wed Oct 24, 2012 2:28 am
by joan » Tue Oct 23, 2012 9:02 am
I have continued my experiments with PWM for motors/leds and servos.

I found memory <> memory DMA unreliable (memory <> peripheral memory seems fine) so abandoned that as a way of triggering servo pulses.

Currently I'm triggering the servo pulses using a timer tick (the pulse length is timed by DMA).

The PWM itself is still approx.400 Hz with 256 levels.

Short video http://www.youtube.com/watch?v=8ZvhRzZ7MLo


Very nice!! Do you plan to share your code via gethub or such?
Posts: 7
Joined: Fri Aug 31, 2012 8:55 pm
by Smcintosh » Sun Oct 28, 2012 7:51 am
rgh wrote:
Smcintosh wrote:Do I delete and recreate or is there a simpler way to "get the c back".

You need to delete it and recreate.


I have not been successful running servoblaster after installistion.

If I do a completely clean install on a new SD card (Wheezy) it works (I have done this 3 times), however after the pi is restarted it does not work at all. I have deleted the file in /dev/servoblaster and recreated with mknod but nothing.

I now have no idea what to do and am so frustrated with this now. What could possibly be happening?
Posts: 13
Joined: Tue Jul 31, 2012 11:37 am
by rgh » Sun Oct 28, 2012 11:56 am
Smcintosh wrote:What could possibly be happening?

I sent you a PM.
Posts: 211
Joined: Fri Nov 25, 2011 3:53 pm
by hexelpdkk » Sun Oct 28, 2012 8:06 pm
@rgh
Many thanks for servoblaster - whacked it on to a new install, worked a treat. I'm going to be using this as part of a work placement for my stepson - I'm going to have him writing the software for a serial interface using black and white marbles, believe it or not <evil stepfather cackle />
User avatar
Posts: 175
Joined: Fri Feb 24, 2012 4:40 pm
by bvo » Mon Oct 29, 2012 5:25 pm
Thak you for this usefull piece of code. :D I successfully compiled the module after modifying the source to only adress GPIO 23 and 24. All works fine, but sometimes the echo command hangs for about half a minute before execution. Someone has an idea whats the reason for this issue?

As i would like the servos to react to a target identified via a webcam and opencv, this delay woud be critical. I have an updated raspbian system, and i'm communicating over ssh and wlan dongle. I don't
know anything about kernel modules and sheduling / task priority, so I would appreciate some help here ;)
Posts: 6
Joined: Mon Oct 29, 2012 2:37 pm
by rgh » Mon Oct 29, 2012 6:07 pm
bvo wrote:... and i'm communicating over ssh and wlan dongle.

Could you connect a local USB keyboard and a monitor/tv and see if you still get the issue? There is nothing in the driver that should pause for 30 seconds, so I wonder if the effect you are seeing is actually down to lost packets and retries on your network connection.
Posts: 211
Joined: Fri Nov 25, 2011 3:53 pm
by bvo » Mon Oct 29, 2012 8:53 pm
rgh wrote:Could you connect a local USB keyboard and a monitor/tv and see if you still get the issue? There is nothing in the driver that should pause for 30 seconds, so I wonder if the effect you are seeing is actually down to lost packets and retries on your network connection.


thank you for your reply, but apparently this did not solve the problem. Even with the pi directly connected to a screen and keyboard (i don't have a usb keyboard, so i tryed it with a wireless keyboard, not sure if this is part of the issue), i get delays of sometimes more than a minute before execution. This happens every 5 or 6 commands issued to /dev/servoblaster. I can reproduce it when i send "echos" one after another. I will ask a buddy to borrow me a usb keyboard, and report if that solved the problem...
Posts: 6
Joined: Mon Oct 29, 2012 2:37 pm
by rew » Tue Oct 30, 2012 3:38 pm
Although in many cases the software only solution here is preferable, in other cases, a hardware solution might be in order.....
We have the SPI_SERVO or I2C_SERVO that allow you to control up to 7 servo motors through each board. (in theory up to 128 boards on each bus, at 2x SPI and 1x I2C...... :-) )
It is recommended to run the boards at 5V, so that it provides a full-swing 5V signal to the servo.

There is a simple program called "bw_tool" that allows you to set the servo values.... Something like
Code: Select all
 bw_tool -a 86 -w 20:40

will set the first servo output to 25%. 86 is the default address of the servo board. 20 is the register for setting the first output, and 40 is at 25% between 00 and 0xff.
We also sell the rpi_serial and cables to make things plug and play.
Check out our raspberry pi addons: http://www.bitwizard.nl/shop/
User avatar
Posts: 408
Joined: Fri Aug 26, 2011 3:25 pm
by rgh » Tue Oct 30, 2012 8:35 pm
bvo wrote:thank you for your reply, but apparently this did not solve the problem.

Can you confirm that the problem is really related to servoblaster, and not just down to something else odd with your system? You could try doing something a little different like
Code: Select all
echo "hello, world"

repeatedly; does that always respond immediately?
Posts: 211
Joined: Fri Nov 25, 2011 3:53 pm
by ame » Thu Nov 01, 2012 2:00 am
Thank you @rgh. I tried @JamesRonald's version of the servoblaster module and it works. I am driving two servos from the Pi GPIO pins.

In case anyone is interested in the details, I have two Futaba S3001 RC servos. I am using four AA Eneloop NiMH batteries to power them (nominal 4.8V). The GPIO pins are connected directly to the servo control lines. The -ve side of the battery pack is connected to the Pi GND pin. It's quite handy as the three pins are together on the GPIO header (pin 7:servo 0; pin 9:GND; pin 11:servo 1).
Posts: 3172
Joined: Sat Aug 18, 2012 1:21 am
Location: Korea
by ame » Fri Nov 02, 2012 12:00 am
I used the two servos to make a satellite tracker last night. I used KD2BD's "predict" program in server mode running on the Pi itself to calculate satellite positions (azimuth and elevation), and wrote a Python script to query the server for a specific satellite every second.

The script converts the az/el values into servo timing pulse widths (when el is above the horizon) and writes them to /dev/servoblaster

I ran it for a while and had no stuttering or stalling, so I am very happy with how it turned out. The Pi was doing nothing else at the time (no GUI or other tasks).
Posts: 3172
Joined: Sat Aug 18, 2012 1:21 am
Location: Korea
by JamesRonald » Fri Nov 02, 2012 12:23 am
@rgh, Thanks for sharing the ServoBlaster source. I'm using ServoBlaster, the IPGamePad Android application and a UDP server application that I wrote to control a small servo driven robot that I demoed for the Michigan Robot Club . I did create my own fork of ServoBlaster and added a parameter to specify the number of servo so that all of the GPIOs need not be dedicated to purpose of driving servos. I did see that you may add such additional features to ServoBlaster but with open source there is no need for me to wait. I do plan to make my UDP robot server application available but have not been able to come up with a meaningful and interesting name.

- Jim
MiRobotClub.org
Posts: 7
Joined: Fri Aug 31, 2012 8:55 pm
by tobrien81 » Fri Nov 02, 2012 7:09 am
OK, So I need a little help. I have connected my servo to RPi GPIO port 7, the driver loads fine and I get a character file in /dev called /dev/servoblaster. However when I type in echo 0=120 > /dev/servoblaster the servo does not move... Any ideas?
Posts: 17
Joined: Thu Aug 30, 2012 9:57 am
by ame » Fri Nov 02, 2012 7:33 am
tobrien81 wrote:OK, So I need a little help. I have connected my servo to RPi GPIO port 7, the driver loads fine and I get a character file in /dev called /dev/servoblaster. However when I type in echo 0=120 > /dev/servoblaster the servo does not move... Any ideas?


Apologies if these are simple-and-obvious points.

First, do you have a power supply for the servo? I used 4 NiMH cells, giving me about 5V. Battery positive to the red wire, and battery negative (or Ground, GND or 0V) to the black wire. I recommend that you don't use the 5V supply output from the Pi, because servos can draw a lot of current.

Second, is the 0V line on the servo connected to 0V or GND on the Pi? You must have a common ground between the Pi and the servo.

Finally, are you sure you have the correct pin? The first servo (servo 0) is on GPIO4, which is pin 7. It's the fourth from the left on the lower row. Next to that, pin 9, is GND.

I used this reference:
http://elinux.org/RPi_Low-level_periphe ... .28GPIO.29

Good luck.
Posts: 3172
Joined: Sat Aug 18, 2012 1:21 am
Location: Korea
by rgh » Fri Nov 02, 2012 8:28 am
@ame, @JamesRonald, thanks for sharing what you are doing with servoblaster, it's great to know you are having fun with it.
Posts: 211
Joined: Fri Nov 25, 2011 3:53 pm
by tobrien81 » Fri Nov 02, 2012 9:42 am
ame wrote:
tobrien81 wrote:OK, So I need a little help. I have connected my servo to RPi GPIO port 7, the driver loads fine and I get a character file in /dev called /dev/servoblaster. However when I type in echo 0=120 > /dev/servoblaster the servo does not move... Any ideas?


Apologies if these are simple-and-obvious points.

First, do you have a power supply for the servo? I used 4 NiMH cells, giving me about 5V. Battery positive to the red wire, and battery negative (or Ground, GND or 0V) to the black wire. I recommend that you don't use the 5V supply output from the Pi, because servos can draw a lot of current.

Second, is the 0V line on the servo connected to 0V or GND on the Pi? You must have a common ground between the Pi and the servo.

Finally, are you sure you have the correct pin? The first servo (servo 0) is on GPIO4, which is pin 7. It's the fourth from the left on the lower row. Next to that, pin 9, is GND.

I used this reference:
http://elinux.org/RPi_Low-level_periphe ... .28GPIO.29

Good luck.


Thanks so much for that. Yes I am using a 6V 1A power supply for the servos. I definitely plugging into the correct GPIO pin. When I plug it into GPIO4 it starts twitching, same with every other pin on the Pi... So could this be caused by the common GND issue you are talking about?

If so, does that mean I connect the black wire from the servo to the -'ve on the power supply and also to the Pi GND or just the Pi GND?
Posts: 17
Joined: Thu Aug 30, 2012 9:57 am
by ame » Fri Nov 02, 2012 2:05 pm
Ok, maybe this picture makes it clearer. It's for Arduino, but it's just a block diagram.

http://web.comporium.net/~shb/pix/servo-wire.jpg

In the picture you can see the +ve line from the external servo power is connected to the servo red wire. The -ve line from the external servo power is connected to the servo black wire and the Pi ground line (such as pin 9).

The servo control line (white or yellow, or some other colour) is connected to the GPIO signal pin (in our case, it's pin 7).

So, to answer your question, the black wire from the servo is connected to the to the -ve on the power supply and also to the Pi GND.

HTH
Posts: 3172
Joined: Sat Aug 18, 2012 1:21 am
Location: Korea