Shallow Thoughts : tags : raspberry pi
Akkana's Musings on Open Source Computing, Science, and Nature.
Sun, 12 May 2013
In my previous article about
modulation on Raspberry Pi, I mentioned that the reason I wanted
PWM on several pins at once was to drive several motors, for a robotic car.
But there's more to driving motors than just PWM. The GPIO output pins
of a Pi don't have either enough current or enough voltage to drive
a motor. So you need to use a separate power supply to drive the motors,
and do some sort of switching -- at minimum, a transistor or relay for
There are lots of motor driver chips. For Arduinos, "motor shields",
and such things are starting to become available for the Pi as well.
But motor shields are expensive, usually more than the Pi costs
itself. If you're trying to outfit a robotics class, or to help
low-income students build robots, it's not a great solution.
When I struggled with this problem for the Arduino, the solution I
eventually hit on was a
H-bridge chip. For under $2, you get bidirectional control of two
DC motors. For each motor, you send input to the chip via a PWM line
and two directional control lines.
The only problem is the snarl of wiring. One PWM and two direction
lines per motor is six wires, plus power for the chip's logic side,
power for the motors, and ground, and the three pins for a serial cable,
and you're talking a lot of wires to plug in.
Although this is all easy in comcept, it's also easy
to get a wire plugged in one spot over on the breadboard from where
it ought to be, and then nothing works.
I spent too much time making tables of what should get plugged into where.
I ended up with a table like this:
|Pi connector pin ||GPIO (BCM) ||SN754410 pin
|Pi 2 ||5V power ||Breadboard bottom V+ row
|Pi 18 ||24 ||1 (motor 1 PWM)
|Pi 15 ||22 ||1 (motor 0 PWM)
|Pi 24 ||8 (SPI CE0) ||4 (motor 1 direc 0)
|Pi 26 ||7 (SPI CE1) ||14 (motor 1 direc 1)
|Pi 25 ||Gnd ||Breadboard both grounds
|Pi 19 ||10 (MOS1) ||3 (motor 0 direc 0)
|Pi 21 ||9 (MOS0) ||13 (motor 0 direc 1)
|motor 0 || ||5, 11
|motor 1 || ||6, 12
... though, as you'll see, some of those pin assignments ended up
getting changed later.
One more thing: I found that I had to connect the chip's logic V+
(pin 2 on the SN754410) to the 5v pin on the RPi, not the 3.3V pin.
The SN754410 is okay with 3.3V logic signals, but it seems to need
a full 5V of power.
The software control is a little trickier than it ought to be, too,
because of the 2-wire control lines on each motor. With both lines high
or both lines low, nothing moves. (Some motor driver chips distinguish
between those two states: e.g. both low might be a brake, while both
high lets the motor freewheel; but I haven't seen anything indicating
the SN754410 makes any distinction.) Then set one line high, the other
low, and the motor spins one way; reverse the lines, and the motor
spins the other way. Assuming, of course, the PWM line is sending
Of course, you need RPI.GPIO version 0.5.2a or later to do any of this
PWM control. Get it via
pip install --upgrade RPi.GPIO
-- the RPI.GPIO in Raspbian mis-reports its version and is really 0.5.1a.
Simple enough in concept. Okay, now try explaining that to beginning
programmers. No, thanks! So I wrote a
PiMotor class in
Python that takes care of all those details. Initialize it with the pins
you want to use, then use calls like
stop(). It's on GitHub at
I put the H-bridge chip on a breadboard, wired up all the lines to the
Pi and a lithium-polymer airplane battery, and (after several hours of
head-banging while I found all the errors in my wiring), sure enough,
I could get the motors to spin.
But one thing I found while wiring was that I couldn't always use the
GPIO lines I'd intended to use. The RPi has seemingly a lot of GPIO
lines -- but
nearly all of
the GPIO lines have other purposes, except I haven't found any
good explanation of what those uses are and how to know when they're
in use. I found that quite frequently, I'd try a
GPIO.setup(pin, GPIO.OUT) and get
"This channel is already in use". Sometimes
helped, and sometimes it didn't. None of this stuff has much
documentation, and I haven't found any IRC channel or mailing list
for discussing RPi GPIO. And of course, there's no relation between
the pin number on the header and the GPIO pin number. So I spent a lot
of time counting breadboard rows and correlating to a printout I'd made
of the RPi's GPIO socket.
Putting the circuit on a proto-board
Once I got it working, I realized how much I didn't relish the
thought of ever doing it again -- like whenever I needed to unplug
the motors from the Pi and use it for something else.
Fortunately, at some point I'd bought an
Adafruit Pi Plate,
sort of the RPi equivalent of Adafruit's Arduino ProtoShield. I love
protoshields. I have a bunch of them, and I use them for all sorts of
Arduino projects, so I'd bought the Pi Plate thinking it might come in
handy some day. It's not quite like a protoshield, because it's
expensive and heavy, loaded up with lots of pointless screw terminals.
But you don't have to solder the screw terminals on; just solder the
headers and you have a protoshield for your RPi on which you can put
a mini breadboard and build your motor circuit.
I do wish, though, that Adafruit or someone made a simple, basic
proto board PCB with headers for the Pi. No screw terminals, no extra
parts, just the PCB and headers, to make it easy and cheap to swap
between different RPi projects. The
Slice of Pi looks intriguing, but the GPIO pins it exposes don't seem
to be the same ones exposed on the RPI's GPIO header. I'd be
interested in hearing from anyone who's tried one of these.
Anyway, with the Pi Plate shield, my motor circuit looks much neater,
and I can unplug it from my RPi without fear that it'll mean
another half hour if I ever want to get the motors hooked up again.
I did have to change some of the pin assignments yet again, because
the Pi Plate doesn't expose all the GPIO pins available on the RPi header.
I ended up using 25, 23, 24 for the first motor, and 17, 21, 22 for
I wanted to make a circuit diagram with Fritzing, but it turns out the
Fritzing I have can't import part definitions like the one for
Raspberry Pi, and the current Fritzing doesn't work on Debian Wheezy.
So that'll have to wait. But here's a photo of my
breadboarded circuit on the Pi Plate, and a link to my
breadboarded circuit using a cable to the GPIO.
Kevin Mark tipped me off that Fritzing is quite easy to build under
Debian, if you first
apt-get install qt4-qmake libqt4-dev libboost1.49-dev
I had to add one more package to Kevin's list,
or I got a lot of QSQLITE driver not loaded and other errors
on the terminal, and a dialog saying "Unable to find the following 114 parts"
followed by another dialog too big to fit on the screen with a list of
all the missing parts.
Once those packages are installed, download the Fritzing source tarball,
qmake, make, and sudo make install.
And my little car can go forward, spin around in both directions, and
then reverse! Now the trick will be to find some sensors I can use with
the pins remaining ...
[ 13:08 May 12, 2013
More hardware |
permalink to this entry |
Sat, 04 May 2013
I've written about how to
small DC motors with an Arduino, in order to
a little toy truck around.
But an Arduino, while great at talking to hardware, isn't very powerful.
It's easy to add simple sensors to the truck so it can stop before hitting
the wall; but if I wanted to do anything complicated -- like, say,
image processing with a camera -- the Arduino really isn't enough.
Enter Raspberry Pi. It isn't a super-fast processor either, but it's
fast enough to run Linux, Python, and image processing packages like
A Raspberry-Pi driven truck would be a lot more powerful: in theory,
I could make a little Mars Rover to drive around my backyard.
If, that is, I could get the RPi driving the car's motors.
Raspberry Pi, sadly, has a lot of limitations as a robotics platform.
It's picky about input voltages and power; it has no analog inputs,
and only one serial port (which you probably want to use for a console
if you're going to debug your robot reliably).
But my biggest concern was that it has only one pulse-width modulation
(PWM) output, while I needed two of them to control the car's two motors.
It's theoretically possible to do software PWM on any pin -- but
until recently, there were no libraries supporting that.
Until recently. I've been busy for the last month or two and haven't
been doing much RPi experimenting. As I got back into it this week, I
discovered something delightful: in the widely available python library
Software PWM is available starting with 0.5.2a.
Getting the right RPi.GPIO
Just what I'd been wanting! So I got an LED and resistor and plugged
them into a breadboard.
I ran a black wire from the RPi's pin 6, ground, to the short LED pin,
and connected the long pin via the resistor to the RPi's pin 18
(GPIO 24) (see the
peripherals for the official GPIO pin diagrams).
With the LED wired up, I
in my serial cable, powered up the RPi with its Raspbian SD card,
and connected to it with
screen /dev/ttyUSB0 115200.
I configured the network to work on my local net and typed
sudo apt-get install python-rpi.gpio
to get the latest version. It got 0.5.2a-1. Hooray!
I hurried to do a test:
pi@raspberrypi:~$ sudo python
Python 2.7.3 (default, Jan 13 2013, 11:20:46)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import RPi.GPIO as GPIO
>>> GPIO.setup(24, GPIO.OUT)
>>> led = GPIO.PWM(24, 100)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'PWM'
Whoops! But Raspbian said it was the right version ...
I checked again with
aptitude show python-rpi.gpio --
yep, 0.5.2a-1. Hmph!
After some poking around, I discovered that help(GPIO),
after printing out an interminable list of exception classes,
eventually gets to this:
VERSION = '0.5.1a'
In other words, Rapsbian is fibbing: that package that Raspbian says
is version 0.5.2a-1 is actually version 0.5.1a.
(This is the sort of thing that makes Raspberry Pi such a joy to work with.
Yes, that's sarcasm.)
Okay. Let's try removing that bogus Raspbian package and getting it from
apt-get remove python-rpi.gpio
pip install --upgrade RPi.GPIO
Then I tried the same test as before. Success!
And now I was able to set the LED to half brightness:
I was able to brighten and dim the LED at will:
I played with it a little while longer, then cleaned up:
If you're experimenting with RPi.GPIO's PWM, you'll want to check
out this useful 2-part tutorial:
What about motors?
So PWM works great for LEDs. But would it drive my little robotic car?
I unplugged my LED and wired up one of the
motor drivers circuits I'd wired up for the Arduino. And it worked
just as well! I was able to control the motor speed using ChangeDutyCycle().
I'll write that up separately, but I do have one caveat:
GPIO.cleanup(), for some reason, sets the pin output to HIGH.
So if you have your car plugged in and sitting on the ground when you
run cleanup(), it will take off at full speed.
I recommend testing with the car on a stand and the wheels off the ground.
Update: the motor post is up now, at
two DC motors with a Raspberry Pi.
[ 20:00 May 04, 2013
More hardware |
permalink to this entry |
Sat, 16 Mar 2013
I'm at PyCon, and I spent a lot of the afternoon in the Raspberry Pi lab.
Raspberry Pis are big at PyCon this year -- because everybody at
the conference got a free RPi! To encourage everyone to play, they
have a lab set up, well equipped with monitors, keyboards, power
and ethernet cables, plus a collection of breadboards, wires, LEDs,
switches and sensors.
I'm primarily interested in the RPi as a robotics controller,
one powerful enough to run a camera and do some minimal image processing
(which an Arduino can't do).
And on Thursday, I attended a PyCon tutorial on the Python image processing
It's a wrapper for OpenCV that makes it easy to access parts of images,
do basic transforms like greyscale, monochrome, blur, flip and rotate,
do edge and line detection, and even detect faces and other objects.
Sounded like just the ticket, if I could get it to work on a Raspberry Pi.
SimpleCV can be a bit tricky to install on Mac and Windows, apparently.
But the README on the SimpleCV
git repository gives an easy 2-line install for Ubuntu. It doesn't
run on Debian Squeeze (though it installs), because apparently it
depends on a recent version of pygame and Squeeze's is too old;
but Ubuntu Pangolin handled it just fine.
The question was, would it work on Raspbian Wheezy? Seemed like a
perfect project to try out in the PyCon RPi lab. Once my RPi was
set up and I'd run an
apt-get update, I used
used netsurf (the most modern of the lightweight browsers available
on the RPi) to browse to the
The first line,
sudo apt-get install ipython python-opencv python-scipy python-numpy python-pygame python-setuptools python-pip
was no problem. All those packages are available in the Raspbian repositories.
But the second line,
sudo pip install https://github.com/ingenuitas/SimpleCV/zipball/master
failed miserably. Seems that pip likes to put its large downloaded
files in /tmp; and on Raspbian, running off an SD card, /tmp quite
reasonably is a tmpfs, running in RAM. But that means it's quite small,
and programs that expect to be able to use it to store large files
are doomed to failure.
I tried a couple of simple Linux patches, with no success.
You can't rename /tmp to replace it with a symlink to a directory on the
SD card, because /tmp is always in use. And pip makes a new temp directory
name each time it's run, so you can't just symlink the pip location to
a place on the SD card.
I thought about rebooting after editing the tmpfs out of /etc/fstab,
but it turns out it's not set up there, and it wasn't obvious how to
disable the tmpfs. Searching later from home, the size is
set in /etc/default/tmpfs. As for disabling the tmpfs and using the
SD card instead, it's not clear. There's a block of code in
/etc/init.d/mountkernfs.sh that makes that decision; it looks like
symlinking /tmp to somewhere else might do it, or else commenting out
the code that sets RAMTMP="yes". But I haven't tested that.
Instead of rebooting, I downloaded the file to the SD card:
But it turned out it's not so easy to pip install from a local file.
After much fussing around I came up with this, which worked:
pip install http:///home/pi/master --download-cache /home/pi/tmp
That worked, and the resulting SimpleCV install worked nicely!
I typed some simple tests into the simplecv shell, playing around
with their built-in test image "lenna":
img = Image('lenna')
And, for something a little harder, some face feature detection:
let's find her eyes and outline them in yellow.
SimpleCV is lots of fun! And the edge detection was quite fast on the RPi --
this may well be usable by a robot, once I get the motors going.
[ 20:43 Mar 16, 2013
More linux/install |
permalink to this entry |
Sun, 06 Jan 2013
For a recent Raspberry Pi project, I decided to use the
Adafruit Pi Cobbler
to give me easy access to the RPi's GPIO pins.
My Cobbler arrived shortly before I had to leave for a short trip.
I was planning to take my RPi with me -- but not my soldering iron.
So the night before I left,
I hastily soldered together the Cobbler along with a few other parts I
wanted to play with. No problem -- it's an easy solder project, lots of
pins but no delicate parts or complicated circuitry.
Later, far from home, I opened up my hardware hack box, set up a breadboard and
started plugging in wires, following one of the tutorials mentioned below.
Except -- wait, the pins didn't seem to be in the place I expected them.
I quickly realized I'd soldered the ribbon cable connector on backward.
There's no way I could unsolder 26 pins all at once, even at home;
but away from home, without even a soldering iron, how could I possibly
(image courtesy of
The ribbon cable connector is basically symmetrical, two rows of 13 pins.
The connector on the cable is keyed -- it has a dingus sticking out of
it that's supposed to fit into the slot in the connector's plastic box.
If I could, say, cut another slot on the opposite side of the plastic
box, something big enough for the ribbon cable's sticky-out dingus
(sorry for the highly technical language!),
I could salvage this project and play with my RPi.
I was just about to dig in with the diagonal cutter when someone on IRC
suggested that I try to slide the plastic box (it turns out this is
called a "box header") up off the pins, turn it around and slide it back
on. They suggested that using a heat gun to soften the plastic might help.
I didn't have a heat gun where I was staying, but I did have a hairdryer.
I slipped a jeweler's screwdriver under the bottom of one side of the box,
levered against the circuit board to apply pressure upward, and hit it
with the hairdryer. It slid a few millimeters immediately.
I switched to the other side of the box and
repeated; that side obligingly slid too. About ten minutes of
alternating sides and occasional blasts from the hairdryer, and
the box was off! Sliding it back on was even easier. Project rescued!
(Incidentally, you may be thinking that the Cobbler is really just a
way to connect the Pi's header pins to a breadboard. I could have used
the backwards-soldered Cobbler and just kept track of which pins should
map to which other pins. True!
But all the pin numbers would have been mislabeled, and I know myself
well enough to know that eventually, I would have gotten the pin mapping
wrong and plugged something in to the wrong place. Having
destroyed an Adafruit Wave Shield earlier that day by doing just that,
connecting 5V to an I/O pin that it turned out wasn't expecting it
(who knew the SD reader chip was so sensitive?),
I didn't want to take the same risk with my only Raspberry Pi.)
[ 15:29 Jan 06, 2013
More hardware |
permalink to this entry |
Fri, 09 Nov 2012
I've been using my
Pi mostly headless -- I'm interested in using it to control hardware.
Most of my experimenting is at home, where I can plug the Pi's built-in
ethernet directly into the wired net.
But what about when I venture away from home, perhaps to a group
hacking session, or to give a talk? There's no wired net at most of
these places, and although you can buy USB wi-fi dongles, wi-fi is so
notoriously flaky that I'd never want to rely on it, especially as my
only way of talking to the Pi.
Once or twice I've carried a router along, so I could set up my own
subnet -- but that means an extra device, ten times as big as the Pi,
and needing its own power supply in a place where power plugs may be scarce.
The real solution is a crossover ethernet cable.
(My understanding is that you can't use a normal ethernet cable
between two computers; the data send and receive lines will end up crossed.
Though I may be wrong about that -- one person on #raspberrypi reported
using a normal ethernet cable without trouble.)
Buying a crossover cable at Fry's was entertaining. After several minutes
of staring at the dozens of bins of regular ethernet cables, I finally
found the one marked crossover, and grabbed it. Immediately, a Fry's
employee who had apparently been lurking in the wings rushed over to
warn me that this wasn't a normal cable, this wasn't what I wanted,
it was a weird special cable. I thanked him and assured him that was
exactly what I'd come to buy.
Once home, with my laptop connected to wi-fi, I plugged one end into
the Pi and the other end into my laptop ... and now what? How do I
configure the network so I can talk to the Pi from the laptop, and
the Pi can gateway through the laptop to the internet?
The answer is IP masquerading. Originally I'd hoped to give the
Pi a network address on the same networking (192.168.1) as the laptop.
When I use the Pi at home, it picks a network address on 192.168.1,
and it would be nice not to have to change that when I travel elsewhere.
But if that's possible, I couldn't find a way to do it.
Okay, plan B: the laptop is on 192.168.1 (or whatever network the wi-fi
happens to assign), while the Pi is on a diffferent network, 192.168.0.
That was relatively easy, with some help from the
Once I got it working, I wrote a script, since there are quite a few
lines to type and I knew I wouldn't remember them all.
Of course, the script has to be run as root.
Here's the script, on github:
I had to change one thing from the howto: at the end, when it sets
up security, this line is supposed to enable incoming
connections on all interfaces except wlan0:
iptables -A INPUT -m state --state NEW -i ! wlan0 -j ACCEPT
But that gave me an error,
Bad argument `wlan0'.
What worked instead was
iptables -A INPUT -m state --state NEW ! -i wlan0 -j ACCEPT
Only a tiny change: swap the order of -i and !. (I sent a correction
to the howto authors but haven't heard back yet.)
All set! It's a nice compact way to talk to your Pi anywhere.
Of course, don't forget to label your crossover cable, so you don't
accidentally try to use it as a regular ethernet cable.
Now please excuse me while I go label mine.
Update: Ed Davies has a great followup,
and Red Tape, that talks about how to set up a
subnet if you don't need the full masquerading setup, why
non-crossover cables might sometimes work, and a good convention for
labeling crossover cables: use red tape. I'm going to adopt that
convention too -- thanks, Ed!
[ 15:57 Nov 09, 2012
More hardware |
permalink to this entry |
Tue, 31 Jul 2012
Raspberry Pi, the tiny, cheap,
low-power Linux computer, dropped their order restrictions a few weeks
ago, and it finally became possible for anyone to order one. I
immediately (well, a day later, since the two sites that sell them
were slashdotted with people trying to order) put in an order with
Newark/element14. They said they were backordered six weeks, but
I wasn't in a hurry -- I just wanted to get in the queue.
Imagine my surprise when half a week later I got a notice that my
Pi had shipped! I got it yesterday. Thanks, Element14!
The Pi comes with no OS preloaded -- it boots off the SD card.
a download page where you can get an image of Debian Wheezy
their recommendation), Arch, or several other Linux distros.
I downloaded their latest Wheezy image and unzipped it.
But instructions on what to do from there are scanty, and tend to be
heavy on "click on this, then drag to here" directives that
make no sense if you're not using whatever desktop they assume you have.
So here's what ended up working.
Writing the SD card with dd
First, make sure you downloaded the image correctly:
sha1sum 2012-07-15-wheezy-raspbian.zip and compare the
sum it prints out with the one on the download page.
Then get an appropriate SD card. The image is sized for a 2G card, so
that's what I used, but you can use a larger card if needed ...
you'll only get 2G initially but you can resize the partition later.
Plug the SD card into a reader on your regular Linux desktop/laptop
machine, and figure out which device it is:
Then, assuming the SD card is in /dev/sdb (make sure of this! you don't
want to destroy your system disk by writing the wrong place!)
dd bs=1M if=2012-07-15-wheezy-raspbian.img of=/dev/sdb
Wait a while, make sure all the lights are off in your SD drive,
then remove the SD card from the reader. (Yes, even if you're about
to mount it to change something.)
Headless Raspberry Pi
Now you have an SD card that will probably boot your Pi.
If you want to run X on it and see a desktop, you'll need a USB keyboard
and mouse, some sort of monitor, and the appropriate cable.
That stopped me.
The Pi needs either an HDMI to DVI cable -- which I don't have, though
I will buy one as soon as I get a chance -- or an RCA composite video cable.
I think our old CRT TV can take composite video, but what I see
on the net suggests this is a poor solution for the Pi since
the resolution and image quality aren't really adequate.
But in any case, one of my main intended uses for the Pi involves using
it headless, as a robotics controller, in connection with an
Arduino or other
hardware for analog device control.
So the Pi needs to be able to boot without a monitor, taking commands
via its built-in ethernet interface, probably using ssh.
That means making some changes to the SD card.
Reinsert the card. (Why not just leave it in place? Because the image
you just wrote changed the partition table, and your computer won't
see the change unless you remove and reinsert the card.)
The card now has two partitions on it -- you can check that via
/proc/partitions. The first is the /boot partition,
where you shouldn't need to change anything. The second is the root
filesystem. Mount the second partition if your system didn't do that
mount /dev/sdb2 /mnt
Now specify a static IP address, so you'll always know how to
get to your Pi. Edit /mnt/etc/network/interfaces and change the
iface eth0 inet dhcp line to something like this,
using numbers that will work for your local network:
iface eth0 inet static
Now, if you google for other people who want to ssh in to their
Raspberry Pis or run them headless, you will find approximately
1,532,776 pages telling you that to enable sshd you'll need to
rename a file named boot_enable_ssh.rc somewhere on the /boot partition
Disregard this. There is no such file on the current
official wheezy pi images, and you will go crazy looking for it.
Happily, it turns out that the current images have the ssh server
enabled by default. You can verify that by looking at /mnt/etc/init.d/ssh
and seeing that it starts sshd. So after setting a static IP, you're
You're done! Remove the card, stick it in the Raspberry Pi,
plug in an ethernet cable, then power it with a micro USB cable.
Wait a minute or two (it's not the world's fastest booter,
and you should be able to ssh firstname.lastname@example.org or whatever
address you gave it. Log in with the password specified on the
Downloads page where you got the OS image ... and you're good to go.
Fun! Now I'm off to find an HDMI-DVI cable.
[ 20:26 Jul 31, 2012
More hardware |
permalink to this entry |