Shallow Thoughts : : hardware
Akkana's Musings on Open Source Computing, Science, and Nature.
Fri, 02 Mar 2012
Working on projects that might be fun for a proposed Arduino high school
workshop, I realized I hadn't done much with Arduinos and sound.
I'd made clicking noise for my
sonar
echolocation device, but nothing more than that.
But the Arduino library has a nice function to control a speaker:
tone(int pin,
int frequency, int length).
tone() works much better than trying to make your own
square wave, because it uses interrupts and doesn't glitch when
the processor gets busy doing other things. You can leave off the
length parameter and the tone will continue until you
tell it to stop or change frequency.
Random tones
So you can produce random tones like this (SPEAKER is the pin the
speaker is plugged into):
uint8_t SPEAKER = 8;
void setup()
{
pinMode(SPEAKER, OUTPUT);
// Seed the random number generator from floating analog pin 0:
randomSeed(analogRead(0));
}
void loop()
{
// Random frequency between 20 and 1400 (Hz).
unsigned long freq = random(20, 1400);
long duration = random(5, 50);
tone(SPEAKER, freq, duration);
delay(random(100, 300));
}
Light theremin
Purely random tones aren't very interesting to listen to, though, as
it turns out.
How about taking input from a photo-resistor, to make
a light theremin that wails as I move my hand up and down above the
sensor? The photoresistor I was using typically reads, on the Arduino,
between 110 (with my hand over the sensor) and 800. So I wanted
to map that range to audible frequencies the speaker could handle,
between about 20 Hz and 5000.
uint8_t LIGHTSENSOR = 0;
void loop()
{
// Set the frequency according to the light value read off analog pin 0.
#define MAX_SIGNAL 800
#define MAX_FREQ 5000
#define MIN_SIGNAL 380
#define MIN_FREQ 20
int lightsensor = analogRead(LIGHTSENSOR);
int freq = (lightsensor - MIN_SIGNAL)
* (float)(MAX_FREQ - MIN_FREQ)
/ (MAX_SIGNAL - MIN_SIGNAL)
+ MIN_FREQ;
tone(SPEAKER, freq);
}
Random music (chiptunes)
That was fun, but
I still wanted to try some random music that actually sounded ... musical.
So how about programming the standard scale, and choosing frequencies from
that list?
I looked up the frequency for Middle C, then used fractions to
calculate the rest of the
"just" diatonic
scale for C major:
float middle_c = 262.626;
float just[] = { 1., 9./8, 5./4, 4./3, 3./2, 5./3, 15./8 };
#define NUMNOTES (sizeof(just)/sizeof(*just))
float cur_octave = 1.;
Multiplying the frequency by 2 transposes a note up one octave;
dividing by two, down one octave. cur_octave will keep track
of that.
Now if whichnote is a number from 0 to 7,
cur_octave * just[whichnote] * middle_c
will give the next frequency to play.
Just choosing notes from this list wasn't all that interesting either.
So I adjusted the code to make it more likely to choose a note just one
step up or down from the current note, so you'd get more runs.
rand = random(0, 6);
if (rand == 0)
whichnote = (whichnote + 1) % NUMNOTES;
else if (rand == 1)
whichnote = (whichnote + 1) % NUMNOTES;
else
whichnote = random(0, NUMNOTES);
float freq = middle_c * just[whichnote];
// Change octave?
rand = random(0, 10);
if (rand == 1 && cur_octave <= 3) {
cur_octave *= 2.;
} else if (rand == 2 && cur_octave >= 1) {
cur_octave /= 2.;
}
freq *= cur_octave;
It's still not great music, but it's a fun experiment and I'm looking
forward to adding more rules and seeing how the music improves.
Bach
But this left me hungry for real music. What if I wanted to play
a real piece of music? Certainly I wouldn't want to type in an array
of frequency numbers, or even fractions. I'd like to be able to say
A, Ab (for A-flat), Cs (for C-sharp), etc.
So I defined the frequency for each of the notes in the scale:
#define NOTE_Ab 207.652
#define NOTE_A 220.000
#define NOTE_As 233.082
#define NOTE_Bb NOTE_As
#define NOTE_B 246.942
#define NOTE_C 261.626
#define NOTE_Cs 277.183
#define NOTE_Db NOTE_Cs
#define NOTE_D 293.665
#define NOTE_Ds 311.127
#define NOTE_Eb NOTE_Ds
#define NOTE_E 329.628
#define NOTE_F 349.228
#define NOTE_Fs 369.994
#define NOTE_Gb NOTE_Fs
#define NOTE_G 391.995
#define NOTE_Gs 415.305
#define NOTE_REST 0.0
#define NOTE_SUSTAIN -1.0
Then the first part of Bach's 2-part invention #4 in D minor
looks like this:
float composition[] = {
NOTE_D, NOTE_E, NOTE_F, NOTE_G, NOTE_A*2, NOTE_As*2,
NOTE_Db, NOTE_As*2, NOTE_A*2, NOTE_G, NOTE_F, NOTE_E,
NOTE_F, NOTE_REST, NOTE_A*2, NOTE_REST, NOTE_D*2, NOTE_REST,
NOTE_G, NOTE_REST, NOTE_Cs*2, NOTE_REST, NOTE_E*2, NOTE_REST,
NOTE_D*2, NOTE_E*2, NOTE_F*2, NOTE_G*2, NOTE_A*4, NOTE_As*4,
NOTE_Db*2, NOTE_As*4, NOTE_A*4, NOTE_G*2, NOTE_F*2, NOTE_E*2,
};
And the code to play it looks like:
unsigned long note = composition[i++];
if (note == NOTE_REST)
noTone(SPEAKER);
else if (note == NOTE_SUSTAIN)
; // Don't do anything, just let the current tone continue
else
tone(SPEAKER, note);
It's a bit tedious to type in the notes one by one like that, which
is why I stopped when I did. And as far as I know, the Arduino can
only emit one tone at once -- to play the real 2-part invention,
you either need a second Arduino, or extra hardware like a
wave shield.
Anyway, it was a fun series of experiments, even if none of it
produces great music. You can see the source at
github:
akkana/arduino/music.
Tags: arduino, hardware, music
[
18:54 Mar 02, 2012
More hardware |
permalink to this entry |
comments
]
Thu, 16 Feb 2012
I just got an Arduino
Nano. Cute little thing -- I'm looking forward to
using it in portable projects. But I had one problem when first plugging
it in. It was getting power just fine, and blinking its LED -- but it
wasn't showing up as a USB serial port in Linux. dmesg said things like:
usb 1-3.4: new full speed USB device number 7 using ehci_hcd
usb 1-3.4: device descriptor read/64, error -32
usb 1-3.4: device descriptor read/64, error -32
with several different device numbers each time, and an occasional
unable to enumerate USB device on port 4 thrown in.
A web search found a few other people seeing this problem on Linux
or Linux-based devices, with some people saying that pressing the RESET
button multiple times helps. It didn't for me. What solved the problem
for me was switching cables. The mini-USB cable I'd been using -- which
has worked fine for other purposes, including programming other Arduinos
through an FTDI Friend -- apparently was missing something the
Nano needs for downloading. With a different cable,
dmesg showed a much more civilized
usb 1-3.4: new full speed USB device number 20 using ehci_hcd
ftdi_sio 1-3.4:1.0: FTDI USB Serial Device converter detected
usb 1-3.4: Detected FT232RL
usb 1-3.4: Number of endpoints 2
usb 1-3.4: Endpoint 1 MaxPacketSize 64
usb 1-3.4: Endpoint 2 MaxPacketSize 64
usb 1-3.4: Setting MaxPacketSize 64
usb 1-3.4: FTDI USB Serial Device converter now attached to ttyUSB0
What was wrong with the cable? I did some testing with a multimeter versus a
pinout
diagram. Didn't get a definitive answer, but I did find that on the
cable that doesn't work for the Nano, it was hard to get a solid
connection on the D- (#2) pin inside the Type A connector. But since
that's the connector that goes to the computer end (in my case, a powered
hub), if it wasn't making good contact, I would expect it to show up
everywhere, not just with the Nano. Maybe the Nano is more sensitive to
a good solid D- connection than other devices.
I'm not really convinced. But Arduino's
Troubleshooting
Guide suggests:
"Try a different USB cable; sometimes they don't work."
So I guess they don't know what's special about some cables either.
So if your Arduino Nano doesn't initially connect properly, don't panic.
Try a few different cables (everybody has about a zillion mini-USB
cables lying around, right? If not, here, have five of mine).
The Nano is happily composing random chiptunes as I write this.
Tags: hardware, arduino, usb
[
15:24 Feb 16, 2012
More hardware |
permalink to this entry |
comments
]
Sat, 11 Feb 2012
This is the story of my adventures learning to drive a little toy truck
from an Arduino: specifically, how to drive the motors.
Motor control turned out to be trickier than I expected, and I don't
see a lot of "Arduino motor control for dummies" pages on the web,
so I'm writing one.
My truck is from a thrift shop. It has two brushed motors (about 280-350
size, in R/C plane parlance). It was originally radio controlled.
It has space for 4 AA batteries, nominal 6v, which I thought should be perfect
for the Arduino.
Connecting directly to the Arduino (don't)
First, you can drive a small motor directly by plugging one lead into
ground and the other into an Arduino digital or analog output line.
(Analog output isn't real analog output -- it uses PWM, pulse width modulation.)
Don't do this. You risk damaging your Arduino, either by putting
too much current through it (the Arduino maxes out at 40ma per pin, 200ma
total; a small motor can pull several amps), or from
back-EMF when
the motor stops.
Motor shields
Lots of Arduino-oriented shops sell "motor shields". I bought a
Freeduino
motor shield because I could get it from Amazon and it was cheap.
It's a kit you have to solder together, but it's a very easy soldering job.
The demo code is easy, too. I wired it up to the Arduino, loaded the demo
code, hooked up my Arduino to the truck's onboard batteries, and ...
nothing. Sometimes the motor would twitch a bit, or hum, but the truck
didn't move.
I wondered if maybe it was something about the batteries (though they
were brand new). I tried plugging the Arduino in to the universal AC
power supply I use for testing. No improvement.
At first I suspected that the motor shield was junk because its 1 amp
maximum wasn't enough. But I was wrong -- the problem was the batteries.
Neither the truck's 4xAA batteries nor the (supposedly) 1 amp AC adaptor could
put out enough current to drive motors.
When it finally occurred to me to try
a lithium-polymer model airplane battery (2 cells, 7.4 volts, 500 mAh),
the truck immediately zipped across the floor and smashed into a chair leg.
So motor shields work fine, and they're very easy to use -- but don't
underestimate the importance of your power supply. You need a battery
capable of supplying a fairly beefy current.
But why is that, when the truck was designed for 4xAA batteries?
Well, the 4xAAs can drive the motors, but they can't drive the motors,
the Arduino and the shield all at the same time. If I power the
Arduino separately off a 9v battery, the truck will move. It doesn't zip
across the room like with the li-po battery, but at least it moves.
Motor Driver
So I had a solution. Except I wanted something a little cheaper. A
$20-30 motor shield is fine for a one-time project, but I was also
shopping for parts to teach a summer camp class in robotics. We're on
a shoestring budget, and an additional $20 per team is a little too much.
On a recommendation from Eugene at
Linux Astronomy, who's been
teaching wonderful robotics classes for several years, I discovered
Pololu as a source of robotics
equipment. Poking around their site, I found the
TB6612FNG Dual
Motor Driver Carrier, which is under $8 in quantity. Sounded like
a much better deal, so I ordered one to try it out.
The TB6612FNG comes with headers not yet soldered. I substituted female
headers, so it would be easier to plug in jumper wires to the Arduino
and the male leads from the motors.
Writing an Arduino program for the TB6612FNG is a little more
complicated than for the motor shield. It has two direction pins for
each motor, plus a STDBY pin you have to keep high. So there
are a lot more pins to manage, and when you change motor direction
you have to toggle two pins, not just one.
That'll make it more confusing for the students (who are
beginning programmers), but I've written wrappers like
drive(int whichmotor, int direc, int speed) to make it simpler.
The motor driver has the same power supply issue as the motor shield did:
I can't power it, the Arduino and the motors all from the 4xAA batteries.
Like the shield, it works okay with the Arduino on 9v, and great with
one li-po powering everything.
Electronic Speed Controllers
I also tried using ESCs, the electronic speed controllers I've used
with radio controlled airplanes. You can talk to them using the Arduino
Servo library (there are lots of examples online). That works,
but there are two issues:
- ESCs all have wierd proprietary arming sequences,
so you have to figure out what they are (e.g. run the voltage up to maximum,
hold there for two seconds, then down to zero, then hold for two seconds,
then you're ready to drive) and write that into your code. If you switch
ESCs, you may have to rewrite the arming code.
- ESCs only go in one direction -- fine for driving a truck forward,
not so good if you need to drive a steering motor both ways.
I'm sure ESCs have the same battery issue as the other two options,
but I didn't even try running one off the AAs.
Anyone who has ESCs sitting around probably has beefy batteries too.
Custom H-bridges
All the cool robotics hipsters (cHipsters?) buy H-bridge chips
and build their own circuits around them, rather than using things like
motor shields or motor drivers.
This
H-bridge
circuit by Bob Blick is one popular example.
(Those double-transistor-in-a-circle things are Darlington transistors.)
But a web search like arduino h-bridge circuit turns
up other options.
For driving big motors, you definitely need your own H-bridge circuit
(or an ESC), since all the available motor shields and drivers are
limited to 2 amps or less. For small motors like my toy truck,
I'm not sure what the advantage is. Except being one of the cool cats.
Summary
- For any sort of motor, either use a beefy battery (lithium polymer
is idea, but you need a special charger and safety precautions for them),
or use separate batteries for the Arduino and the motors.
- Motor shields are the easiest and most turnkey option.
- A motor driver is cheaper and smaller, but slightly more hassle to use.
- Use an ESC for big motors that only need to go in one direction,
or if you're already a model airplane junkie and have some lying around.
- Use a custom H-bridge circuit if you're a cHipster or you have a
really big motor project.
Tags: arduino, hardware, robots
[
12:45 Feb 11, 2012
More hardware |
permalink to this entry |
comments
]
Tue, 07 Feb 2012
I've wanted an
Ardweeny
for a long time. It's just so cute -- it's an Arduino compatible
that's barely bigger than the Atmega 328 chip driving it. Plus, it's cheap:
$10 including the chip.
Like most small or low-cost Arduino clones, the Ardweeny doesn't have its
own USB connection; instead, you use an adaptor such as an
FTDI Friend,
which slides onto a 6-pin header on the Ardweeny.
I knew that ahead of time.
One thing I hadn't realized was that the Ardweeny gets its only power
from the USB adaptor. So if you want to use an Ardweeny by itself
with no computer connection, you need a regulated 5v power supply.
Those are easy enough to build (see the
Breadboard
Arduino), but don't forget to allow for that when designing projects.
The Ardweeny comes as a kit that needs soldering -- something that
isn't made clear in the sales literature, though for the price, it didn't
surprise me. I downloaded the Ardweeny
soldering steps (PDF) and got to work.
Easy initial build
The PDF estimates 15 minutes for the construction. The first part,
soldering the 10 components, was a snap, and took maybe 10 minutes.
At this point you can take the Ardweeny and nestle it down over the
Atmega chip, and test it to check your soldering work.
I plugged in my FTDI Friend and the LED immediately started blinking.
Success! (It's nice of them to pre-program the chip with blink code,
so it's easy to tell it's working.) Downloading my own version
of the blink sketch (use the Duemilanove w/Atmega 238 setting,
or atmega328 if you use my Makefile) also worked fine.
The last step: soldering the legs
Except that I wasn't done. The next step of the build is to solder all
28 legs of the Ardweeny directly to the Atmega chip's legs. Scary idea
-- won't all that heat kill the chip? But the instructions didn't have
any warnings about that. I took a deep breath and forged ahead.
This part put me way over the 15-minute estimate -- 28 pins is a lot
of pins, and I took it slowly, careful to be sparing with heat and solder.
When I was finally done, I plugged the FTDI Friend back in and
... nothing. Not a blink. And when I checked voltage on one of the V+
pins versus the ground pin, it measured around 1.5v, not the 5v I
expected to see.
So I'd messed something up. Somehow, even though it worked without
soldering the legs, that additional soldering had broken it.
I went through all the pins with a voltmeter checking for shorts,
and tested everything I could. Nothing obviously wrong.
It might have been nice to inspect my solder joints on the Ardweeny --
but once the Ardweeny is soldered to the chip, the solder is all inside
and you can't see it. But anyway, I'd tested it and it had worked fine.
Detaching the backpack from the chip
So I figured I must have destroyed the chip with heat or static during that
soldering process. My Ardweeny was a brick. Nothing salvageable at all.
Unless -- if I could somehow de-solder the legs and pull the two apart,
I could use the Ardweeny with another chip.
But how do you de-solder 28 legs? I tried a solder sucker (a
pen-shaped vacuum pump) and de-soldering braid, but neither one
broke the bond between the two sets of legs.
I tried sliding an X-acto knife in between the Ardweeny's legs and the
chip's while heating the leg with solder; no luck, the knife blade was
too good a heat sink and the solder never melted.
Dave finally found a solution. With my assurance that the chip was
probably dead anyway, he rolled the Ardweeny on its back, and used
the tip of the heated soldering iron to bend each chip leg inward away
from the Ardweeny leg. When he was done, the chip looked bent and sad,
like a squashed millipede -- but the pieces were separated.
Testing to find the problem
And now I could take the Ardweeny and stick it on an Atmega 328 I
pulled out of another Arduino. Plugged in the FTDI Friend and -- nothing.
Wait, it was the backpack that was bad? But I tested it before doing that
last soldering phase!
I took the sad squashed-millipede Atmega and carefully bent all the pins
back into shape, or at least close enough that I could plug it into a socket
in my Diecimila. And, amazingly -- that poor abused overheated
squashed bent 328 still worked just fine.
Okay, so the problem is definitely in the Ardweeny backpack.
Now that the solder joints were exposed again, I examined them all
and found two that looked questionable. I re-soldered them -- and
everything worked.
Lessons for the Ardweeny
I still don't know why my board worked the first time, then failed after
the step of soldering the legs. But it makes me nervous about repeating
that leg-soldering step. What if something else, something that's
working now, stops working?
For now, I'll probably solder just a few pins -- maybe the
four outermost ones -- and rely on pressure for the other contacts.
Of course, in a real environment where the Ardweeny might be subject
to vibration and temperature changes, that might not be good enough.
But until then, it seems the safest option.
Tags: arduino, hardware
[
16:26 Feb 07, 2012
More hardware |
permalink to this entry |
comments
]
Fri, 27 Jan 2012
When SCALE approved my talk proposal,
Fun
with Linux and Devices, I had a challenge: I needed some good,
visual Arduino demos that would work in front of an audience.
In particular, I wanted something that moved. A little toy truck?
A moving penguin? A rotating sunflower? I fiddled with this and that,
not fully satisfied with anything. And then suddenly I realized what I needed.
Something cool. Something BIG.
Something I'd been wanting an excuse to buy anyway.
An Air Swimmers Shark.
I'd seen these things on video, but never in person. They're available
all over, even on Amazon, so I put in an order there and got a shark
in a few days.
These things are ridiculous and cool. It's huge, about 5 feet long,
and filled with helium. It takes maybe half an hour to assemble.
It has a small motor to beat the tail, an infrared transmitter,
and a weighted receiver that moves back and forth on a track to tilt
the fish up or down as it swims.
Once it's assembled, you can get it filled with helium at a party
store (which costs $3 to $6 depending on where you go).
Once the shark is filled, you add clay as ballast until the shark is
neutrally buoyant, neither rising nor sinking. It's quite sensitive:
you'll find yourself needing to add or remove pea-sized chunks of clay
as the temperature in the room changes, but being a little over- or
under-ballasted doesn't hurt it much.
With its tail beating, the shark really does look like it's swimming
through the air.
My shark is named Bruce, after the mechanical shark used for the movie
"Jaws". My Bruce, I'm happy to say, has been much more tractable than
his famously intemperate namesake.
Okay, now how do we turn this ridiculous-but-cool thing into an Arduino
project?
Hacking the transmitter
There were two possible approaches. First, mount an Arduino directly
on the shark, and let it be totally self-directed. Second, patch the
Arduino into the shark's transmitter and control it from Linux.
I chose the second option, for several reasons. First, I was fairly
sure it would be easier, and less invasive (the shark would still be
usable with manual control). I also liked the idea of keeping the
transmitter as a manual override, in case my control program didn't
work right. Finally, I liked the idea of keeping a Linux machine in the
loop -- the shark would actually be controlled by Linux, not just by
the Arduino.
So the first thing I did was take the transmitter apart (4 Philips screws).
Inside are 4 pushbuttons, for right, left, up, and down, and the circuit
board is nice and simple. Whew -- this might be doable!
Four more screws and I had access to the back of the board, which was
equally simple. Now I could get my voltmeter on the contacts while I
pushed buttons.
It turned out the contacts (indicated with arrows on the photo) on the
downstream side of each switch were normally high (4.5 volts -- the transmitter
uses 3 AAA batteries). When I pushed the button, the contact went to ground.
Okay, so what I needed was some way for the Arduino to ground those
contacts at will.
First I needed to solder some wires to the contacts.
(How do you tell which side of the pushbutton is the one you need to solder?
Well, one side changes voltage when you press the button, and the other
side stays constant. The one that changes is the one you need to connect
to the Arduino, so the Arduino can change it too.)
I figured I needed 6 wires: ground, power, and one for each switch.
(It turned out I didn't need the power wire, but I figured it didn't
hurt to include it just in case.)
I wanted to have a nice small connector on the side of the transmitter,
but I couldn't find any 6-pin connectors that didn't look big and bulky,
so I gave up and decided I'd just let my ribbon cable dangle from the
transmitter. If I got a nice multi-colored one, maybe it would look festive.
I couldn't find any 6-conductor ribbon cable, so I got a
wider one and separated 6 wires from the rest. Then I soldered the
six wires to the appropriate places (marked by arrows in the photo).
On the other end, I tinned the six wires with solder so I could plug
the stranded wires into my breadboard.
Simulating button presses
I've done enough reading to know of three ways to simulate a button press.
You can put a relay between the two contacts of the switch; you can do
the same thing, but with an optocoupler (opto-isolator) instead of a relay;
or you can do some magic with a transistor. I was fuzzy on the
transistor magic bit, so a relay sounded easiest.
I played around with a relay and a spare switch and convinced myself I
knew how to wire them up. Then it was off to my local parts store to
buy four matched relays small enough to fit on my little mini breadboard.
There followed a several-day fiasco wherein I bought lots of relays
that turned out not to be suitable, and got increasingly frustrated at
how large and clunky all the available relays were.
There are smaller ones, but I couldn't get them to work.
And I learned that relays mostly come without documentation on which
pin does which, so there's a lot of experimenting with each new type.
Frustrated, I tried some optocouplers I'd bought on a whim last year.
No dice ... couldn't get them to work either.
Desperate, I turned to IRC, #arduino on Freenode. The folks there are
mostly electronics wizards, and I'm sure my questions must have seemed
very dumb, but they were patient with me, and pointed me toward
a very simple circuit,
LED4dummies,
that was just what I needed. (They also suggested
Wikipedia's Open
collector article, but I found that less clear.)
It took me some
experimenting with a transistor, an LED and a couple of resistors
(I blew out a couple of transistors before I realized I had the R2 resistor
in the wrong place) but eventually I got it working, and felt confident
enough to try it with the real shark transmitter. The key was to simplify
the circuit so it had no extra parts, then once it was working, add more
parts to build it up to what I needed.
At left, the circuit I ended up with. For each button, I have one
transistor and one resistor (I don't need the second resistor from the
LED4dummies circuit, since that was just to keep the LED from burning out).
At right is the circuit assembled on a mini-breadboard on top of the
proto-shield.
Note that the ends of the ribbon cable are plugged in to a spare header I had
lying around; a header makes a passable connector, so I can plug it in
fairly easily right before a talk. The green and blue wires in the back
are going to Arduino digital output pins 3 through 6 (leaving 0 and 1
for serial I/O). The red wires go from the transistors back to the
ribbon cable wires that go to the shark's transmitter buttons.
The software side
Now I could make the shark think I'd pressed a button on its transmitter.
How do I control that from Linux?
On the Arduino side, I wrote a simple program that reads and parses
commands coming over the USB cable. So from the computer, I might send
a line like L 300, and the Arduino would "press" the Left
button for 300 milliseconds. I had already written something like this
for a couple of other Arduino programs. That program is
shark.pde.
On the Linux side, first I needed something that established a serial
connection and sent commands to the Arduino. I wrote a Python class
for that,
shark.py.
That let me send commands from the Python console to test the shark.
Then I needed something more visual, something I could show during a talk.
In particular, the shark doesn't swim unless someone's pressing left,
right, left, right buttons over and over. Of course I wanted the computer
to handle that part.
So I wrote a little Python-GTK application that keeps the shark swimming,
and lets me drag a mouse around to adjust its left/right up/down direction:
sharkwindow.
Purely by coincidence, the week before SCALE, Scott Adams introduced a
roboshark character:
Dilbert, Jan 11 2012.
Nice timing for the debut of my own roboshark!
Sadly, I don't have any photos or video of the shark in action.
But if you're a LWN subscriber, there's an article on my talk
with a couple of great pictures:
Robots rampage (in a
friendly way) at SCALE 10X.
And you can see my slides and notes at
Arduino notes.
Tags: arduino, hardware, robots, radio control
[
13:02 Jan 27, 2012
More hardware |
permalink to this entry |
comments
]
Sat, 12 Nov 2011
Yesterday Dave and I attended a "Robot Hackathon" in Redwood City,
part of a "nerd new year" 11/11/11 celebration.
What a fun event! O'Reilly/Make
generously sponsored hardware, so everybody got an Arduino Uno
as well as a Grid Kit, a couple of sheets of cardboard pre-scored
in a grid to encourage cutting and bending into various robot shapes,
and a couple of motors. Tools were provided -- there were big bins
of wire, soldering irons, glue guns, box cutters and other odds and ends.
People of all ages were there having fun -- lots of kids there with
their parents, as well as adults of all ages and experience levels.
The adults were mostly fiddling with the Arduinos; the younger kids
mostly eschewed the electronics and concentrated on building cool
monsters and vehicles with the cardboard kits. I saw some great models
-- penguins, squid, tanks, cherrypickers, many-legged bugs.
Wish I'd thought to take a camera along.
No instructions were provided, but I didn't see many people looking
lost; there were enough people there with experience in Arduino,
soldering and the other tools who were happy to help others.
I was able to help some folks with their Arduino projects
while I worked on copying a grid penguin model from a nearby table.
There were lots of friendly volunteers (I think they were from Robotics
for Fun) wandering around offering advice, in between building a
cardboard city out of GridKits.
There was even pizza, from host Pizza & Pipes.
I had to leave before finishing my penguin, but it does have me
inspired to do more with Arduinos and motors. I had a blast, both
fiddling with my own projects and helping other people get started
with Arduinos, and I'm pretty sure everybody else in the room was
having an equally good time.
Thanks, sponsors O'Reilly/Make,
Robotics for Fun,
The Grid Kit,
Mozilla,
MS and
Andreessen Horowitz!
Controlling motors from an Arduino
One point of confusion: everybody got their Arduino LEDs blinking quickly,
but then how do you control a motor? I wasn't sure about that either,
but one of the volunteers found a printout of sample code, and it
turned out to be simplicity itself: just plug in to one of the digital
outputs, and set it to HIGH when you want the motor to spin.
There was much discussion at my table over how to reverse a motor.
I suggested you could plug the two motor leads into two digital pins,
then set one HIGH and the other LOW; then to reverse the motor, just
swap the HIGH and LOW pin. Nobody believed me, and there were a lot
of fervent assertions that there was some magic difference between
a pin being LOW and a real ground. I should have coded it up then
to demonstrate ... I wish I had, rather than spending so much time
hot-gluing penguin parts.
Now that I'm home and it's too late, here's an example of how to
reverse a motor by plugging in to two digital outputs.
// Arduino basic motor control
#define DELAYTIME 1000 // milliseconds
int motorPins[2] = { 5, 6 }; // plug the motor leads into these pins
int direction = 0; // toggle between 0 and 1
void setup()
{
pinMode(motorPins[0], OUTPUT);
digitalWrite(motorPins[0], LOW);
pinMode(motorPins[1], OUTPUT);
digitalWrite(motorPins[1], LOW);
}
// Alternate between two directions and motionless.
// Assume we start with both pins low, motor motionless.
void loop()
{
delay(DELAYTIME);
digitalWrite(motorPins[direction], HIGH);
delay(DELAYTIME);
digitalWrite(motorPins[direction], LOW);
direction = !direction;
}
Incidentally, powering robot motors directly from an Arduino is
generally a bad idea. It's okay for testing or for small servos, but
if you're going to be driving a truck with the motors or otherwise
pulling a lot of current, it's better to use a
separate power
supply for the motors rather than trying to power them from the Arduino.
The easy way is to buy something like this
Motor/Stepper/Servo Shield
that plugs in to the top of your Arduino and has its own power supply.
Arduino Uno on the command line
As I've written before, I prefer to do my
Arduino
hacking from the command line ... but I didn't know the settings
needed for an Uno, and avrdude is quite particular about settings
and can't auto-configure anything.
So I ended up using the standard Arduino IDE while I was at the event ...
there was theoretically wifi at the site, but it wasn't working for me
so I had to wait 'til I got home to search for solutions.
Now I've uploaded a new, more flexible version of my Arduino Makefile
with presets for the Uno, Duemilanove and Diecimila models:
Makefile-0022-v3.
Tags: hardware, arduino, robots
[
14:01 Nov 12, 2011
More hardware |
permalink to this entry |
comments
]
Sun, 16 Oct 2011
Debugging Arduino sensors can sometimes be tricky.
While working on my Arduino sonar
project, I found myself wanting to know what values
the Arduino was reading from its analog port.
It's easy enough to print from the Arduino to its USB-serial line.
First add some code like this in setup():
Serial.begin(9600);
Then in loop(), if you just read the value "val":
Serial.println(val);
Serial output from Python
That's all straightforward --
but then you need something that reads it on the PC side.
When you're using the Arduino Java development environment, you can
set it up to display serial output in a few lines at the bottom of
the window. But it's not terrifically easy to read there, and I
don't want to be tied to the Java IDE -- I'm much happier doing my
Arduino
development from the command line. But then how do you read serial
output when you're debugging?
In general, you can use the screen program to talk to serial
ports -- it's the tool of choice to log in to plug computers.
For the Arduino, you can do something like this:
screen /dev/ttyUSB0 9600
But I found that a bit fiddly for various reasons. And I discovered
that it's easy to write something like this in Python, using
the serial module.
You can start with something as simple as this:
import serial
ser = serial.Serial("/dev/ttyUSB0", 9600)
while True:
print ser.readline()
Serial input as well as output
That worked great for debugging purposes.
But I had another project (which I will write up separately)
where I needed to be able to send commands to the Arduino as well
as reading output it printed. How do you do both at once?
With the select module, you can monitor several file descriptors
at once. If the user has typed something, send it over the serial line
to the Arduino; if the Arduino has printed something, read it and
display it for the user to see.
That loop looks like this:
while True :
# Check whether the user has typed anything (timeout of .2 sec):
inp, outp, err = select.select([sys.stdin, self.ser], [], [], .2)
# If the user has typed anything, send it to the Arduino:
if sys.stdin in inp :
line = sys.stdin.readline()
self.ser.write(line)
# If the Arduino has printed anything, display it:
if self.ser in inp :
line = self.ser.readline().strip()
print "Arduino:", line
Add in a loop to find the right serial port (the Arduino doesn't always
show up on /dev/ttyUSB0) and a little error and exception handling,
and I had a useful script that met all my Arduino communication needs:
ardmonitor.
Tags: arduino, hardware, programming, python
[
19:27 Oct 16, 2011
More hardware |
permalink to this entry |
comments
]
Sun, 02 Oct 2011
A recent Jon Carroll column
got me thinking about Making and Fixing.
This was the passage that got me started:
... I took it to Dave up at the repair place. "You need a new
battery," he said. Looked like a fine battery to me, but what do I
know? I had a second opinion from the guy who wanted to sell me a
battery. What could go wrong?
I brooded about this on the way. I realized how much we are at the
mercy of the repair people in our lives, and how much we do not know
about, well, most things.
At their mercy
That took me back. I grew up with the idea that mechanical things
like cars were a little scary, something one doesn't really muck with.
This despite the many happy afternons I spent building little
balsa-wood gliders with my father. Later, I learned a little
electronics, and built little things like a switchbox so my mom could
switch between cable and VCR without unplugging anything.
But knowing I could handle an X-Acto knife and soldering iron somehow
didn't translate to the notion that I could work on anything as
scarily mechanical as a car or a home appliance.
When I was just getting out on my own, my car -- a 200SX turbo, my
pride and joy -- developed a terrible ticking sound. When I got on the
gas hard, it would make this loud tick tick tick tickticktick.
I took it to the mechanic. He listened to the noise and said "Lady,
it's your turbo." He said it needed replacement.
I was pretty sure that wasn't right. I had read the turbo spun at something
like 100,000 RPM. This sound was more like -- I don't know, a few
ticks a second, maybe a few hundred RPM? Shouldn't something spinning
at a hundred thousand RPM (let's see, that's ... divide by 60 ... 1667 Hz),
shouldn't that make a sort of a whine, not ticks?
I asked the mechanic that. He shook his head. "Lady, it's your turbo.
You have to replace it."
I was pretty sure I was being lied to. But what could I do?
As Jon Carroll says, "we are at the mercy of the repair people in our lives."
I arranged for a replacement. The warranty covered part of it; I still had
to pay quite a bit.
And when it was over, the tick-tick-ticking noise was still there.
I'd been right -- the noise wasn't coming from the turbo.
Somehow that didn't make me feel better.
Becoming Kaylee
I saw a movie some time around then -- some awful movie involving
motorcycles, I forget the details -- that had a character I liked.
You've probably seen the archetype -- she's been in other movies.
You know, the girl-mechanic with the grease smudge on one cheek and the
bright eyes. Think Kaylee from Firefly, only this was long before Firefly.
I wanted to be that girl -- the one who never had to put up with
mechanics lying to her, the one who'd never get stuck somewhere.
She had control over her life. She understood the machines.
But how do you even get started learning something like that?
All the guys I knew who knew how to work on cars had grown up in a
culture where they learned it from their father or brothers.
I set a goal: I'd do my own oil change. I found instructions somewhere.
I bought a crescent wrench -- one of those adjustable things --
and an oil pan to catch the oil, and a new filter.
I lay down in the dirt and slid under the car and got the wrench on the
bolt and ... it kept sliding off. I couldn't get the bolt loose,
and I was rounding off the corners so maybe no one could ever get
it loose. Oh no! The instructions didn't say what to do if that happened.
I got in the car, drove to the local mechanics' shop (not the same one
that had lied to me about the turbo) and threw myself on their mercy.
I said I'd be happy to pay whatever an oil change cost, but I didn't
want them to do it -- just please show me how to get the bolt loose.
They were super nice about it. They broke it loose (they said whoever
did it last way over-tightened it). They took a look at my crescent
wrench and told me never to use it again -- that I should stop at Napa
on the way home and buy a 14mm box-end wrench. I don't think they even
charged me anything.
Back at home, armed with my new 14mm wrench, I got the drain plug off,
and the rest of the oil change went smoothly. I changed the filter and
put the new oil in and closed up. My hands were shaking as I drove off --
surely all the oil was going to fall out right away, trashing my
engine forever. But it didn't.
When I got back, one of my housemates was home. He said "You look adorable."
Apparently I had that grease smudge on my cheek -- you know, just like
the girl mechanic in the movie. Maybe there was hope!
And you know what? Once I knew how to do an oil change, I found it took less
time to do it myself than it did to drive to the shop, drop off the
car, arrange a ride home, and all the other hassle associated with
having someone else do it.
Beyond oil changes
Doing my own oil change boosted my confidence incredibly. But I wanted
to learn more. I wanted to be able to fix things when they broke down.
It was around this time that I took up autocross racing. Of course,
a lot of the guys at the autocrosses were great mechanics. I started
asking them questions, picking their brains.
My car still made that tick-tick-tick sound -- I'd pretty much learned
to live with it since it seemed to be this mysterious thing no one
knew how to fix. I asked one of my autocrosser friends.
He said "Yeah, I've noticed you have an exhaust leak. You
should fix that" He said it like, duh, doesn't everybody recognize the
sound of an exhaust leak when they hear it?
What's an exhaust leak? How would I fix it? Turns out it means the gasket
between the exhaust manifold and the head is bad. You have to unbolt
the manifold and pull it back so you can slip a new gasket in. (He showed
me what all those things were so I'd know what he was talking about.)
Normally that would be pretty easy, but on a turbo car it meant
disconnecting all the turbo plumbing and moving the turbo out of the
way. Eesh!
Another autocrosser, an expert mechanic, offered to help.
We did the job. It turned out to be harder than expected.
Seems that previous mechanics, probably the nim-nuts who replaced the
turbo, had messed up the threads in the aluminum head -- and instead
of fixing it right, they'd just taken a stud with different threads
and jammed it in. I learned all about taps, and Heli-coils, and
other techniques that weren't part of the original plan.
And the noise went away. We fixed it right. Not like the shop
that was only interested in screwing another ignorant customer out of
whatever they could get.
Books
I still wanted to learn more, and not be so dependent on helpful guys.
I looked around for books.
Shop manuals and Haynes and Chilton and Clymer manuals all assume you're
already pretty comfortable working on cars. I needed something that
explained things.
I'd been kicking around the idea of getting a car just for autocross --
some older, simpler car that would be easy to learn on. One option
I was considering was a Scirocco, and that put me on to Poor
Richard's Rabbit Book: How to Keep Your VW Rabbit/Scirocco Alive.
It was fabulous. It explained everything from the beginning -- what the
various parts do, how to find them in a Rabbit/Scirocco -- but it was
clear enough that it worked for any car, not just a VW. I inhaled that
book. It was my bible for years, even after I gave up on the Scirocco
idea. I chose a Fiat X1/9 instead.
Colibri
Everyone knows Fiat's reputation. The joke is that it stands for "Fix
It Again, Tony" (though I always preferred "Fix It Alla Time").
A Fiat would surely force me to learn, fast.
My new baby, Colibri (Italian for "hummingbird") was a mess of a car.
It had been in several accidents. Just about everything needed some
amount of work. It was perfect. I loved it.
My first big job was a brake job in the parking lot of a San Diego Pep Boys,
Poor Richard's and the Haynes manual in hand, the store handy
so I could go in and buy tools I discovered I needed, a pay phone
nearby so I could make long-distance calls to my boyfriend when I hit snags.
(We were in the process of moving, but the brake job couldn't wait
until he was there in person -- and besides, I wanted to learn how to
do things myself!)
I was there for hours, and used the pay phone several times. But I emerged
triumphant -- covered in grime, but with brakes that worked great.
Over the next few years of driving and racing Fiats, I learned how to
re-jet a carburetor (and how to do it really fast when a bit of
fluff from your sketchy aftermarket performance air filter clogs a
carburetor jet when you're stuck in traffic on 101 and the car
suddenly isn't getting any power from the primary). I got good at
replacing the alternator,
doing alignments,
working on suspension; I replaced the exhaust system a few times,
and eventually the head.
We don't have to be at the mercy of the repair people in our lives.
Fixing and Making
And that brings me to the Maker movement -- because fixing things,
very often, is making,
and that's something I hadn't realized at first.
I remember watching my master mechanic boyfriend (the one who'd helped
me with the 200SX) faced with
the problem of a pop-up headlight that rattled. The link that held the
light in place was worn from so many years of rattling along potholed
roads. The part was available -- but look at it, he said. This will
just wear out again in a couple of years. There's no lubrication, no
adjustment, no compensation for how the angle changes as the headlight
goes up and down.
He redesigned it using a
rod end --
a lovely piece of hardware that has a threaded rod (adjustable!) at
one end and a nylon-encased ball bearing at the other. It came out
far more solid and adjustable than the original ever was. No more bouncing!
Later, when I got more confidence in my own automotive ability, I
could do some of that myself. My proudest accomplishment was a set of
adjustable spring perches made out of a toilet part from the hardware
store. They cost about a tenth as much as the custom spring perches
the top-flight autocrossers were using, and worked almost as well. I only
wish I'd been prescient enough to have taken photos for a future website.
When you take your car to a mediocre mechanic, like the one who lied
to me about my turbo because he was too inept to recognize the real
problem, you get the wrong idea.
You come away thinking that fixing things is all about
replacing one part after another until the customer stops coming back.
But real fixers aren't like that. They look at a design
and ponder how to make it better. They fiddle with things, and try out
new ideas. If they're not sure what's wrong, they set up experiments,
just like a programmer does chasing a bug, or a scientist testing a new theory.
In today's world,
being a Maker is hot now,
while being a mere fixer isn't held in such high regard. But it should be.
People who fix old stuff -- who can figure out how to take
something broken and make it better than it was to begin with -- not only
are creative Makers, they're also environmental heroes. They're our
best hope to keep us from drowning in a sea of discarded junk.
I'm still not that good at it. I try to fix my computer stuff when it
breaks. I've learned a little
woodworking,
painting, plumbing and other home-maintenance skills from my husband,
who grew up in a culture where most people worked on things like that.
(That definitely wasn't true where I grew up.)
I don't work on the car nearly as often as I used to in the Fiat days --
I have more money and less energy and free time -- but I try to do
enough that I know what does and doesn't need fixing. When I don't
know something (which is still most of the time), I google for help,
and fiddle with things, and invent solutions, and sometimes I succeed,
sometimes not. When I do go to a repair person, I can ask the right
questions, and I can tell if I'm being lied to.
Jon Carroll is right, of course. There's so "much we do not know about,
well, most things." None of us has time to know everything about
everything we own. But that isn't going to stop me from trying. Fixing
is just as cool as making ... and maybe they're the same thing, really.
And I still want to be Kaylee. Maybe I'm making progress.
Tags: hardware, cars, autocross
[
20:34 Oct 02, 2011
More hardware |
permalink to this entry |
comments
]