Shallow Thoughts
Akkana's Musings on Open Source Computing, Science, and Nature.
Sat, 18 May 2013
In my post about
Controlling
a toy car with a Raspberry Pi, I skipped over one important detail:
the battery. How do you power the RPi while it's driving around the room?
Most RPi sites warn that you shouldn't use the Pi with a power supply
drawing less than an amp. I suspect that's overstated, and it probably
doesn't draw more than half of that most of the time; but add the draw
of two motors and we're talking a fairly beefy battery, not a couple
of AAs or a 9V.
Luckily, as an R/C plane pilot,
I have a fridge full of small 2- and 3-cell lithium-polymer batteries
(and a li-po charger to go with them). The problem is:
the Pi is rather picky about its input voltage. It wants 5V and nothing
else. A 2-cell li-po is 7.4V. So I needed some sort of voltage regulator.
It's easy enough to get a simple
5V
voltage regulator (pictured at right) -- 30c at Jameco, not much
more locally. But they're apparently fairly inefficient, and need a
heat sink for high current loads.
So I decided to blow the big bucks ($15) for a
5V step-down power
converter (left) that claims to be 94% efficient with no need for
a heat sink.
Unlike most of Adafruit's products, this one comes with no tutorials
and no hints as to pinouts, but after a little searching, I determined
that the pins worked the same way as the cheap voltage regulators.
With the red logo facing you, the left pin (your left) is input power
from the battery; middle is ground (connect this to the battery's
ground which is shared with the Pi's ground); the right pin is the
regulated 5V output, which goes to pin 2 on the Pi's GPIO connector.
I was able to run both the RPi and the motor drive circuit off the
same 7.4 volt 2-cell li-po battery (which almost certainly wouldn't
work with 4 AAs, though it might work with 8). A 500 mAh battery seems
to be plenty to drive the RPi and the car, though I don't know how long
the battery life will be. I'll probably be using 610 mAh batteries for
most of my testing, since I have a collection of them for the aerial
combat planes.
Here's a wiring diagram made with Fritzing
showing how to hook up the battery to power a RPi. If you're driving motors,
you can run a line from the battery's + terminal (the left pin of the
voltage regulator) as your motor voltage source, and use the right pin
as your 5V logic source for whatever motor controller chip you're using.
Tags: hardware, raspberry pi, robots
[
16:50 May 18, 2013
More hardware |
permalink to this entry |
comments
]
Wed, 15 May 2013
Checking versions in Debian-based systems is a bit of a pain.
This happens to me a couple of times a month: for some reason I need
to know what version of something I'm currently running -- often a
library, like libgtk. aptitude show
will tell you all about a package -- but only if you know its exact name.
You can't do aptitude show libgtk or even
aptitude show '*libgtk*' -- you have to know that the
package name is libgtk2.0-0. Why is it libgtk2.0-0? I have no idea,
and it makes no sense to me.
So I always have to do something like
aptitude search libgtk | egrep '^i' to find out what
packages I have installed that matches the name libgtk, find the
package I want, then copy and paste that name after typing
aptitude show.
But it turns out it's super easy in Python to query Debian packages using the
Python
apt package. In fact, this is all the code you need:
import sys
import apt
cache = apt.cache.Cache()
pat = sys.argv[1]
for pkgname in cache.keys():
if pat in pkgname:
pkg = cache[pkgname]
instver = pkg.installed
if instver:
print pkg.name, instver.version
Then run
aptver libgtk and you're all set.
In practice, I wanted nicer formatting, with columns that lined up, so
the actual script is a little longer. I also added a -u flag to show
uninstalled packages as well as installed ones. Amusingly, the code to
format the columns took about twice as many lines as the code that does the
actual work. There doesn't seem to be a standard way of formatting
columns in Python, though there are lots of different implementations
on the web. Now there's one more -- in my
aptver
on github.
Tags: linux, debian, ubuntu, python, programming
[
15:07 May 15, 2013
More linux |
permalink to this entry |
comments
]
Sun, 12 May 2013
In my previous article about
pulse-width
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
each motor.
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
SN754410
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.
Programming it
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
a signal.
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 set_speed(s)
and stop(). It's on GitHub at
pimotors.py.
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 GPIO.cleanup()
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
HobbyTronics
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
the second.
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
motor
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, libqt4-sql-sqlite,
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 ...
Tags: hardware, raspberry pi, robots
[
13:08 May 12, 2013
More hardware |
permalink to this entry |
comments
]
Wed, 08 May 2013
A couple of months ago I wrote about
watching
an eclipse of Europa by Jupiter's shadow. It's a game I call
"Whac-a-Moon", where a moon comes out from behind Jupiter, but stays there
for only a short time then disappears into eclipse. If you aren't ready
for it, it's gone.
This can only happen when Jupiter's shadow is offset from Jupiter that
there's a gap between the planet and the shadow as seen from Earth.
Jupiter is getting low in the west, and soon we'll lose it behind the
sun, but tonight, Wednesday May 8, there's a decent Ganymede Whac-a-Moon
opportunity for those of us on the US west coast.
Ganymede disappears behind Jupiter at 6:45 pm PDT, still during daylight.
Some time around 9:43 Ganymede reappears from behind Jupiter,
but it only stays visible for a couple of minutes before entering
Jupiter's eclipse. Don't trust these times I'm giving you: set up at
least five minutes early, preferably more than that. And set up
somewhere with a good western horizon, because Jupiter will be very
low, less than 8 degrees above the horizon.
You can simulate the event on my
Javascript Jupiter.
When the G goes blue, that means Ganymede is in eclipse.
But the simulation won't show you the interesting part:
how gradual the eclipse is, as the moon slides through the edge
of Jupiter's shadow. During the Europa eclipse a few months ago,
I wanted to record the time of disappearance so I could adjust
my code accordingly, but I found I couldn't pin it down at all --
Europa started dimming almost as soon as it emerged from behind
Jupiter, and kept dimming until I couldn't convince myself I saw
it any more.
So far, I've only watched Europa as it slid into eclipse by
Jupiter's shadow; I haven't whacked Ganymede. But Ganymede is so much
larger that I suspect the slow dimming effect will be even more
obvious. Unfortunately, I'm not optimistic about being able to see it
myself; we've had cloudy skies here for the last few nights, and that
combined with the low western horizon may do me in. I may have to wait
until autumn, when Jupiter will next be visible in our evening skies.
But I hope someone reading this gets a chance to see this month's eclipse.
Tags: astronomy, science
[
10:46 May 08, 2013
More science/astro |
permalink to this entry |
comments
]
Sat, 04 May 2013
I've written about how to
drive
small DC motors with an Arduino, in order to
drive
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
SimpleCV.
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
RPi.GPIO,
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
RPi Low-level
peripherals for the official GPIO pin diagrams).
With the LED wired up, I
plugged
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.setmode(GPIO.BCM)
>>> 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
pypi instead:
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:
led.start(50)
I was able to brighten and dim the LED at will:
led.ChangeDutyCycle(90)
led.ChangeDutyCycle(25)
I played with it a little while longer, then cleaned up:
led.stop()
GPIO.cleanup()
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
SN754410
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
Driving
two DC motors with a Raspberry Pi.
Tags: raspberry pi, hardware, electronics, robots
[
20:00 May 04, 2013
More hardware |
permalink to this entry |
comments
]
Sat, 13 Apr 2013
We've been considering the possibility of moving out of the Bay Area
to somewhere less crowded, somewhere in the desert southwest we so
love to visit. But that also means moving to somewhere
with much harsher weather.
How harsh? It's pretty easy to search for a specific location and get
average temperatures. But what if I want to make a table to compare
several different locations? I couldn't find any site that made
that easy.
No problem, I say. Surely there's a Python library, I say.
Well, no, as it turns out. There are Python APIs to get the current
weather anywhere; but if you want historical weather data, or weather
data averaged over many years, you're out of luck.
NOAA purports to have historical climate data, but the only dataset I
found was spotty and hard to use. There's an
FTP site containing
directories by year; inside are gzipped files with names like
723710-03162-2012.op.gz. The first two numbers are station numbers,
and there's a file at the top level called ish-history.txt
with a list of the station codes and corresponding numbers.
Not obvious!
Once you figure out the station codes, the files themselves are easy to
parse, with lines like
STN--- WBAN YEARMODA TEMP DEWP SLP STP VISIB WDSP MXSPD GUST MAX MIN PRCP SNDP FRSHTT
724945 23293 20120101 49.5 24 38.8 24 1021.1 24 1019.5 24 9.9 24 1.5 24 4.1 999.9 68.0 37.0 0.00G 999.9 000000
Each line represents one day (20120101 is January 1st, 2012),
and the codes are explained in another file called
GSOD_DESC.txt.
For instance, MAX is the daily high temperature, and SNDP is snow depth.
So all I needed was to decode the station names, download the right files
and parse them. That took about a day to write (including a lot of
time wasted futzing with mysterious incantations for matplotlib).
Little accessibility refresher: I showed it to Dave -- "Neat, look at
this, San Jose is the blue pair, Flagstaff is green and Page is red."
His reaction:
"This makes no sense. They all look the same to me. I have no idea
which is which."
Oops -- right. Don't use color as your only visual indicator. I knew that,
supposedly! So I added markers in different shapes for each site.
(I wish somebody would teach that lesson to Google Maps, which uses
color as its only indicator on the traffic layer, so it's useless
for red-green colorblind people.)
Back to the data --
it turns out NOAA doesn't actually have that much historical data
available for download. If you search on most of these locations,
you'll find sites that claim to have historical temperatures dating
back 50 years or more, sometimes back to the 1800s. But NOAA typically
only has files starting at about 2005 or 2006. I don't know where
sites are getting this older data, or how reliable it is.
Still, averages since 2006 are still interesting to compare.
Here's a run of noaatemps.py KSJC KFLG KSAF KLAM KCEZ KPGA KCNY.
It's striking how moderate California weather is compared
to any of these inland sites. No surprise there. Another surprise
was that Los Alamos, despite its high elevation, has more moderate weather
than most of the others -- lower highs, higher lows. I was a bit
disappointed at how sparse the site list was -- no site in Moab?
Really? So I used Canyonlands Field instead.
Anyway, it's fun for a data junkie to play around with, and it prints
data on other weather factors, like precipitation and snowpack, although
it doesn't plot them yet.
The code is on my
GitHub
scripts page, under Weather.
Anyone found a better source for historical weather information?
I'd love to have something that went back far enough to do some
climate research, see what sites are getting warmer, colder, or
seeing greater or lesser spreads between their extreme temperatures.
The NOAA dataset obviously can't do that, so there must be something
else that weather researchers use. Data on other countries would be
interesting, too. Is there anything that's available to the public?
Tags: python, programming, weather, data
[
21:57 Apr 13, 2013
More programming |
permalink to this entry |
comments
]
Fri, 05 Apr 2013
Watching people weave into and out of our lane while they texted
on the freeway (where are all the cops who are supposed to be cracking
down on that this week?),
Dave came up with an idea: a competition where you drive
some sort of course -- start with an autocross course, or maybe add
twists like parallel parking -- while simultaneously texting.
Your score is a combination of your time through the course,
fewest pylons hit, and the accuracy of your texted replies.
He was thinking of a show we used to see at a pizza place we
frequented a few years ago, "Cash Cab". The premise: there's a special
taxi that drives around New York City rigged with video gear, and if
it picks you up, you get a chance to play a "Who wants to be a
millionaire" style quiz show in the time till the driver gets you
to your destination.
I have to admit, although Dave's combination of Cash Cab and autocross
sounded intriguing, it didn't sound like something I'd actually want
to do. Although I see plenty of drivers who seem to love the challenge
of parallel parking or negotiating rush-hour traffic with one hand
(or no hands!), it's not my thing.
But here's a modification that did sound fun to me:
you wear a hands-free headset, and while you negotiate the course,
someone asks you quiz-show type questions and you have to
answer while you're driving the course. You can still use both
hands to drive; just not your whole brain.
It's an exercise in concentration and filtering distractions. Can you
figure out what part of the course needs your fullest attention, and
which parts you might be able to take nearly as fast while thinking
about the quiz question? It's a biathlon for motorheads.
The scientifically minded part of me wants to take a little extra time
and add a free run through the course for each contestant at the
beginning and end of the event, with no quiz questions.
That way everybody gets a baseline time for the
course, and it's easy to find out how much the distraction hurts
our driving. Some studies say that a hands-free phone is
just as distracting as a handheld one. Wouldn't you love to find
out exactly how true that is for you?
I know it'll never happen -- it's hard enough to reserve autocross
sites without the additional complications of an untried event format.
But I'd sure love to try it. If any researchers with funding for
distracted-driving studies are reading this and want to use the idea,
count me in as either a helper or a study subject.
I'm calling it QuizCross. You heard it here first.
Tags: autocross, games
[
19:55 Apr 05, 2013
More misc |
permalink to this entry |
comments
]
Sun, 31 Mar 2013
Happy Easter! In keeping with the season, here's a dinosaur egg I
spotted on a recent hike.
Okay, or maybe it's just a vaguely egg-shaped rock. But there's been a lot
going on this spring now that the weather is turning.
First, we seem to have Eurasian collared doves nesting somewhere near
our house. There's a dove up on the power pole, cooing, most of the day.
I know I've heard lots of reports of collared doves around the south bay
in past years, particularly down around Morgan Hill, but this is the first
time I'd seen more than a glimpse of them here at home in San Jose.
It's fun to see new species, though I hope these European interlopers
don't push out the native mourning doves entirely.
In addition, the wildflowers have been great out on the trails, especially
around the south end of Windy Hill OSP and Coal Mine Ridge. A hike up
there last week revealed nearly every wildflower on my
wildflower page
that could be in flower now -- California poppy, wild cucumber
(intriguingly also called manroot), giant trillium, hound's tongue,
milkmaids, the most impressive profusion of Indian warrior I've seen,
blue larkspur, miner's lettuce, Sierra suncup,
vetch (it's pretty despite the unfortunate name), red maid,
wild radish, wood sorrel, broom, and my favorite, shooting star.
Dave had to keep waiting for me while I argued with the camera
over macro focus distances. So if you like wildflowers, get out there
and take a look!
Tags: nature, birds, wildflowers
[
16:22 Mar 31, 2013
More nature |
permalink to this entry |
comments
]