Shallow Thoughts : tags : arduino

Akkana's Musings on Open Source Computing, Science, and Nature.

Sun, 17 Feb 2013

Playing music or sound samples on Arduino

I've done a few experiments with playing music on an Arduino over the years -- the Arduino library has a tone() call that gives you a nice tinny monophonic "chiptunes" style noise. But for playing anything more complex, you need more processing power.

I had a silly little project in mind. I like some pink noise when I'm sleeping (in summer, I usually have a fan running). You can buy electronic devices called "sleep soothers" that have tracks of the ocean, rain, trains etc. but they often have annoying misfeatures (like foghorns or train whistles in the middle of a track). Wouldn't it be more fun to make my own, with sound samples of my choice?

Pink noise samples

Of course, I needed some sound samples, and I found a great resource: Laptop.org's list of Free sound samples. I downloaded a few sample collections that looked like they might have some nice ambient pink-noise sounds -- rain, ocean and so forth.

Some of the samples were usable right away. But others are only available at 44.1k, and the Adafruit Wave Shield, the hardware I was targeting first, will only play WAV audio at 16k. So they needed to be converted. A simple shell loop did that:

for fil in *.wav ; do
  avconv -i $fil -ar 16000 ../samples16/$fil
  echo $fil
done

Arduino hardware

There are several Arduino shields for playing sound files. The simplest (and probably cheapest) is the Adafruit Wave Shield, and that's what I started with. It comes as a kit that you solder together (an easy soldering project) and it has its own volume control and SD card reader. On the down side, it can only play .WAV files, not other formats like .MP3 or .OGG. But for my sleep soother project that was okay.

Getting basic sounds playing was easy, following Adafruit's tutorial and sample code. But for my project, I also needed some external buttons, to allow for jumping from one track to the next. I was a little confused about which pins are used by the shield, and I ended up wiring my button to one of the pins that the shield uses for talking to the SD card reader. Things didn't work at all. And then while I was fumbling with plugging/unplugging things, at some point I installed the shield onto the Arduino wrong, with the pins off by one. I'm not sure whether it was the miswired button or the off-by-one shield, but something got fried in the wave shield and it was never able to read an SD card again after that (yes, even after plugging it in properly).

I thought about ordering another Wave Shield. But I was leery -- if it's so delicate that a stray 5v signal in the wrong place can fry it permanently, how long did I expect a second one to last? Besides, I was tired of soldering things, and I happened to be putting in an Amazon order for some other things. So I ran a search and found that there was an MP3 player shield available through them, made by Seeed Studio. It even had buttons built in, so I wouldn't need any extra hardware. It was a little more expensive than the Wave shield, but it claimed to play MP3 and OGG as well as WAV, and it comes pre-assembled, no soldering needed.

The hardware arrived and looked nice. Two simple buttons plus a "multifunction" button you can press or rock left or right. I grabbed a micro SD card, put some MP3s on it, and went to Seeed's page on the Music Shield.

Hacking the Seeed library

I was a little worried when I discovered that they have three different demos there -- each of which comes with a different library, and you have to remove one set of libraries before you can try a different demo. Not a good sign.

And indeed, it wasn't. None of the demos worked at all. When I added some debug Serial.printlns, I found that it wasn't opening the SD card.

Much web searching found a couple of people saying they'd discovered that the Seeed shield only works with 2G or smaller microSD cards. Good luck finding one of those! The next day, I drove all over town looking for one, without success, and was on the verge of giving up when Dave remembered a little cheapie camera he'd bought a few years ago for taking airplane movies. It came with a microSD card. Success! It was a 2G card.

Back to trying the various demos and their incompatible libraries again. And this time, one of the demos, the first one (the one that comes with the Music v1 14.zip library), worked. I could play tracks, sequentially as they were loaded on the SD card.

Unfortunately, that wasn't what I wanted to do -- I wanted to play the same track over and over, jumping to the next track when the user presses a button. I tried the other demos. None of them worked at all.

Long story short, after struggling for the better part of a week and reverse-engineering a fair amount of the Music v1 14 library, I finally got my sketch working.

Sharing the changes

I come from the open-source world. I keep my Arduino sketches on GitHub (at least once they work well enough to be useful to anybody). So of course I wanted to share the work I'd put into fixing this library.

I had it all laid out and ready to commit, and was working on some documentation on how to use it, when I noticed the readme.txt in the library directory. It begins:

Copyright (c) 2010 Seedstudio.  All right reserved.

Pffft! So after finally getting things working, I can't share my working version of the library! What are they thinking? What on earth is the point of distributing a library for your hardware, one that you know doesn't work very well (or you wouldn't be distributing four different incompatible versions of it), and then not letting anyone fix it for you?

I posted a query in one of the many threads discussing problems with the Music Shield, asking if Seeed would consider releasing the library under a license that allowed redistribution. It's been a few weeks now, and no answer yet.

Incidentally, even posting the query wasn't easy. Seeed doesn't let you post in their forums unless you register -- and the registration process requires full name, address, and phone number! Fortunately, they have no way of knowing whether the info you give them is fake, so that's what I did.

Since I don't have permission to share the code directly, I've checked in a patch that updates their library so it can play arbitrary tracks, not just sequential ones, and can re-play the same track. It's here: Music Shield library on GitHub, along with my sample app, called play-repeat.

Conclusions

So my app is working now. Well, mostly; sometimes the volume randomly jumps in the middle of the night, which I think is a hardware glitch, but since it only happens after several hours of play, it's hard to debug.

But if you're looking for an Arduino sound project, I can't recommend either the Wave Shield or the Seeed Music Shield. The Wave Shield seems too fragile and its formats are limited, though the tutorials and support are great. And I'll certainly never buy anything from Seeed again.

If I had it to do over again, I'd spend the big bucks and buy the Sparkfun MP3 Player Shield. It's more expensive ($40) and doesn't have nice buttons like the Seeed shield, but it plays all the formats the Seeed shield does, and they offer tons of documentation and examples, including an open-source library and code contributed by users.

Tags: , ,
[ 11:37 Feb 17, 2013    More hardware | permalink to this entry | comments ]

Mon, 25 Jun 2012

Driving motors, CHEAPLY, with an Arduino

Some time ago, I wrote about my explorations into the options for driving motors from an Arduino.

Motor shields worked well -- but they cost around $50 each, more than the Arduino itself. That's fine for a single one, but I'm teaching an Arduino workshop (this Thursday!) for high school girls, and I needed something I could buy more cheaply so I could get more of them.

(Incidentally, if any women in the Bay Area want to help with the workshop this Thursday, June 28 2012, I could definitely use a few more helpers! Please drop me an email.)

What I found on the web and on the Arduino IRC channel was immensely confusing to someone who isn't an electronics expert -- most people recommended things like building custom H-bridge circuits out of zener diodes.

[Simple Arduino h-bridge (half-bridge) circuit] But it's not that complicated after all. I got the help I needed from ITP Physical Computing's DC Motor Control Using an H-Bridge. It turns out you can buy a chip called an SN754410 that implements an H-bridge circuit -- including routing a power source to the motors while keeping the Arduino's power supply isolated -- for under $2. I ordered my SN754410 chips from Jameco and they arrived the next day.

(Technically, the SN754410 is a "quad half-bridge" rather than an "dual h-bridge". In practice I'm not sure of the difference. There's another chip, the L298, which is a full h-bridge and is also cheap to buy -- but it's a bit harder to use because the pins are wonky and it doesn't plug in directly to a breadboard unless you bend the pins around. I decided to stick with the SN754410; but the L298 might be better for high-powered motors.)

Now, the SN754410 isn't as simple to use as a motor shield. It has a lot of wires -- for two motors, you'll need six Arduino output pins, plus a 5v reference and ground, the four wires to the two motors, and the two wires to the motor power supply. Here's the picture of the wiring, made with Fritzing.

[Half-bridge circuit on breadboard] With all those wires, I didn't want to make the girls wire them up themselves -- it's way too easy to make a mistake and connect the wrong pin (as I found when doing my own testing). So I've wired up several of them on mini-breadboards so they'll be more or less ready to use. They look like little white mutant spiders with all the wires going everywhere.

A simple library for half-bridge motor control

The programming for the SN754410 is a bit less simple than motor shields as well. For each motor, you need an enable pin on the Arduino -- the analog signal that controls the motor's speed, so it needs to be one of the Arduino's PWM output pins, 9, 10 or 11 -- plus two logic pins, which can be any of the digital output pins.

To spin the motor in one direction, set the first logic pin high and the second low; to spin in the other direction, reverse the pins, with the first one low and the second one high. That's simple enough to program -- but I didn't look forward to trying to explain it to a group of high school students with basically no programming experience.

To make it simpler for them, I wrote a drop-in library that simplifies the code quite a bit. It defines a Motor object that you can initialize with the pins you'll be using -- the enable pin first, then the two logic pins. Initialize them in setup() like this:

#include 

Motor motors[2] = { Motor(9, 2, 3), Motor(10, 4, 5) };

void setup()
{
    motors[0].init();
    motors[1].init();
}

Then from your loop() function, you can make calls like this:

    motors[0].setSpeed(128);
    motors[1].setSpeed(-85);
Setting a negative speed will tell the library to reverse the logic pins so the motor spins the opposite direction.

I hope this will make motors easier to deal with for the girls who choose to try them. (We'll be giving them a choice of projects, so some of them may prefer to make light shows with LEDs, or music with piezo buzzers.)

You can get the code for the HalfBridge library, and a sample sketch that uses it, at my Arduino github repository

Cheap and easy motor control -- and I have a fleet of toy cars to connect to them. I hope this ends up being a fun workshop!

Tags: , , ,
[ 21:32 Jun 25, 2012    More hardware | permalink to this entry | comments ]

Tue, 06 Mar 2012

Arduino Talk (with robotic shark) Wednesday night at SVLUG

[Linux controlled Air Swimmers flying robotic shark] I got a request from SVLUG to fill in at the last minute for a speaker with a health emergency. Fortunately, I'd been slated to give them my Arduino talk from SCALE in a few months, so I was happy to accept. I'm always glad for a chance to show off Bruce, my Arduino- and Linux-controlled 6-foot flying robotic shark.

And if anyone reading this happens to be in town for PyCon, Symantec isn't that far from Santa Clara, roughly a 10-minute drive ... and I promise there will be at least two interesting Python scripts presented.

It's free, of course, so come hear the talk! Here are the SVLUG meeting details and directions.

Tags: , , , ,
[ 18:25 Mar 06, 2012    More speaking | permalink to this entry | comments ]

Fri, 02 Mar 2012

Music with an Arduino

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: , ,
[ 18:54 Mar 02, 2012    More hardware | permalink to this entry | comments ]

Thu, 16 Feb 2012

Arduino Nano -- cute, but sensitive about USB cables

[Arduino Nano] 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: , ,
[ 15:24 Feb 16, 2012    More hardware | permalink to this entry | comments ]

Sat, 11 Feb 2012

Using motors with an Arduino

[Arduino-powered truck]

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

[Freeduino motor shield] 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.


[Pololu TB6612FNG Dual Motor Driver] 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.

Update: use a power transistor

It's been pointed out to me that an even cheaper way to run small motors, suitable for classrooms on a shoestring budged, is to use a transistor. Here's one circuit tutorial I found for that: Using a transistor to control high current loads with an Arduino.

Electronic Speed Controllers

[electronic speed controller]

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:

  1. 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.
  2. 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

Tags: , ,
[ 12:45 Feb 11, 2012    More hardware | permalink to this entry | comments ]

Tue, 07 Feb 2012

Tips on building an Ardweeny

[Ardweeny] 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: ,
[ 16:26 Feb 07, 2012    More hardware | permalink to this entry | comments ]

Fri, 27 Jan 2012

Arduino Air Swimmers Shark

[Air swimmers shark]

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

[Air Swimmers IR transmitter, front]

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!
[Air Swimmers IR transmitter, back]

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. [testing my transistor circuit]

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.
[Circuit for the Arduino-controlled Air Swimmers Shark]

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). [testing my transistor circuit]

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: , , ,
[ 13:02 Jan 27, 2012    More hardware | permalink to this entry | comments ]

Sat, 12 Nov 2011

Robot/Arduino Hackathon in Redwood City

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: , ,
[ 14:01 Nov 12, 2011    More hardware | permalink to this entry | comments ]

Sun, 16 Oct 2011

Monitor an Arduino's serial output from Python

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: , , ,
[ 19:27 Oct 16, 2011    More hardware | permalink to this entry | comments ]

Sun, 18 Sep 2011

Sonar / Echolocation with an Arduino

The first time I saw a Maxbotix Ultrasonic Rangefinder, I knew I had to have one. My mind filled with thoughts of bats and dolphins, echolocating. I'm the kind of geek-slash-animal-lover who, as a kid, used to swim underwater making noises trying to echolocate like a dolphin. (I probably shouldn't admit to that. And anyway, it never worked.)

Only in the last few years have I learned that some blind people actually do echolocate, though not underwater. But it takes a long time to learn, and not everyone can do it. Wouldn't it be great (especially if you were blind) if you could build something you attach to a hat or glasses? You could walk around hearing pings indicating whether you're about to walk into anything, or get walked into. How cool is that?

I already had a sonar rangefinder, which I used for a simple proximity webcam demo in a talk on plug computing.

With the demo over and the device known to work, I could finally try making a sonar device.

Clicks in earbuds

I wanted to use earbuds -- no reason everyone else should need to hear your sonar as you walk around. But how do you do that?

The obvious way works, as it turns out. Connect one earbud wire to one of the Arduino's digital outputs (via a resistor, to reduce the volume), the other to ground. Of course you can connect both earbuds to the same output, or to different outputs if you want to send different signals to each ear.

Then program the Arduino to set the line high, pause a short time, then set it low again, like this:

#define EARBUD       1    /* pin number */
#define clicklen    10    /* milliseconds */
#define timeout   2000    /* milliseconds */

void loop()
{
    while (1) {
        digitalWrite(EARBUD, 1);
        delay(clicklen);
        digitalWrite(EARBUD, 0);
        delay(timeout);
    }
}

This gives a short click ever 2 seconds. Once the rangefinder is hooked up, I'll make timeout a variable and adjust it according to the rangefinder signal.

I used cheap earbuds: the digital output is sending a square wave and probably isn't good for earbuds, so don't risk a set you care about.

I had to experiment to find a good resistor value to keep the volume audible but quiet enough not to be annoying. 10k was about right for my dollar-store earbuds. Of course, if you were actually building this device you'd want to use a potentiometer so you'll be able to adjust the volume as you walk, or use earbuds that come with one.

One sound-on-arduino page I found put a capacitor inline with the resistor ... to smooth out the waveform? I tried a 47 uF capacitor, but it didn't make any difference I could hear.

Adding the rangefinder

The rangefinder plugs in just like in my proximity webcam project: Power on the rangefinder to 5v on the Arduino, Gnd to ground, and AN (analog signal) to the Arduino's analog pin 1.

Then I just need to read the rangefinder output and map it to an appropriate delay between clicks. That took some tuning. Initially I just made the equation linear, for simplicity, and I experimented to see when I wanted to hear the clicks getting closer together. Something like this, added at the beginning of loop():

#define FACTOR       15
#define MINRANGE     20

    float range = analogRead(RANGEFINDER);
    int timeout = FACTOR * (range-MINRANGE);

Pretty cool -- now I could hear the clicks get really close together as I put my hand in front of the sensor.

But when I took the device outside, I found sometimes it would stop making noise for a long time, or even forever. Some of that was due to an earlier equation I used, where the values could sometimes be negative. (With the equation I showed above, they probably won't be -- I've never seen the rangefinder return single digits.) So I added a minimum:

#define MIN_TIMEOUT  5
    if (timeout < MIN_TIMEOUT) timeout = MIN_TIMEOUT;

That got rid of the "stops clicking and never starts again" problem. But I still had delays that were too long: if you face an open area, you might have a timeout of 6 seconds, and you could easily turn and walk into a tree before those 6 seconds are up. So I made a maximum timeout of 2 seconds: it will never go longer than that between checks.

#define MAX_TIMEOUT  2000
    if (timeout > MAX_TIMEOUT) timeout = MAX_TIMEOUT;

Much better! Now I could walk around and -- usually -- get warned before I got too close to obstacles.

You can grab the source and a Makefile for my test program program at sonarduino.

It's not perfect. Sometimes it gets a spurious reading from the rangefinder, and waits too long before warning you. It would really be better if it continued to check during those long timeouts.

And the rangefinder really doesn't give very reliable results much beyond a meter and a half. There are other models of rangefinder, and you'd probably want to experiment with several models before trying to use one of these gizmos to walk around at normal speed. You might even want to have two different types of

So this is just a start. I'm not going to give dolphins or bats any competition yet, and it's certainly not good enough that a blind person could use it to walk around at full speed. But it's a fun project, very easy to build, and I'm looking forward to playing with it further.

Tags: , , ,
[ 15:54 Sep 18, 2011    More hardware | permalink to this entry | comments ]

Sat, 11 Jun 2011

Wiring up a surplus-store LCD display to an Arduino

[Densitron LCD display with Arduino] Every now and then I think it might be handy to have some sort of display on the Arduino ... something a little more detailed than an LED that either blinks or doesn't.

Adafruit's 2-line LCD text display comes with a great Character LCD tutorial, but it's quite heavy, and includes a backlight I don't need. I wanted something more minimal.

The local surplus store always has lots of cheap LCDs, but they unfortunately tend to be unlabeled, so you can't tell which pin is which. But the other day I spied a very lightweight little display for $2.95 that actually had a label on it, so I grabbed it, figuring I'd be able to get the pinout from google. It said:

DENSITRON 2
617ASNG0441
0201 TAIWAN

Alas, googling produced no useful information for any of those numbers. Foiled again! It might as well have been unlabeled!

Wait -- let's not give up quite so quickly.

Adafruit's LCD Shield tutorial says most parallel displays have either 14 or 16 pins, while this one has 15. That's close, at least ... but comparing the two Ada tutorials, I could see that the pin assignments for the two displays were completely different even though both were 16-pin. I wasn't going to get pin assignments there.

Searching for just densitron 15-pin lcd found lots of displays that clearly weren't this one. But apparently a lot of them were similar to a display called an LM50. Perhaps mine used that pinout too.

So I tried it, and it worked with only a little experimentation. Here's the pinout:
LCD pin Function Arduino pin
1 Gnd Gnd
2 +5 V +5 V
3 Contrast pot
4 RS 7
5 EN 8
6 RW Gnd
7 D0  
8 D1  
9 D2  
10 D3  
11 D4 9
12 D5 10
13 D6 11
14 D7 12
15 (nonexistent backlight)

Or I can use the nice cable with the 8x2 connector that came with the display, which maps to these functions:
1 = Gnd Contrast RW D0 D2 D4 D6       
+5V RS EN D1 D3 D5 D7       

The Arduino LiquidCrystal library works just fine with it, using this initialization:

LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
in the Liquid Crystal Arduino sketch.

Works great! I went back and grabbed another $3 display. So the moral is, even a complete hardware klutz shouldn't give up too easily: with the right web search terms and a little fiddling, you might just get it to work after all.

Tags: , ,
[ 19:25 Jun 11, 2011    More hardware | permalink to this entry | comments ]

Mon, 30 May 2011

Command-line Arduino development

I've been doing more Arduino development lately. But I don't use the Arduino Java development environment -- programming is so much easier when you have a real editor, like emacs or vim, and key bindings to speed everything up.

I've found very little documentation on how to do command-line Arduino development, and most of the Makefiles out there are old and no longer work. So I've written up a tutorial. It ended up too long for a blog post, so I've made it a separate article:

Command-line Arduino development.

Tags: , , ,
[ 13:45 May 30, 2011    More programming | permalink to this entry | comments ]

Mon, 11 Apr 2011

Plug Computer + Arduino = Proximity Camera

In the last article, I wrote about how to get a very simple webcam demo running on a plug computer, also known as a Sheevaplug.

Okay, a webcam is sorta cool, but it's still a pretty easy thing to do from any laptop. I wanted to demonstrate some lower-level hardware control.

As I mentioned in the previous article, trying to run hardware directly from a plug computer is an exercise in frustration. So what do you do when you want to drive low-level hardware? Use an Arduino, of course!

Add the Arduino

[light sensor and Arduino] Happily, the sheeva.with-linux kernels include the FTDI driver you need to talk to an Arduino. So you can plug the Arduino to the plug computer, then let the Arduino read the sensor and write its value to the serial port, which you can read on the plug.

First I tried a simple light sensor from Adafruit, using the circuit from the LadyAda photocell tutorial.

I wrote a very simple Arduino sketch to read the analog output: lightsensor.pde. I'm allergic to Java IDEs, so I compiled the sketch from the commandline using this lightsensor Arduino Makefile. Edit the Makefile to point to wherever you've installed the Arduino software.

Now, on the plug, I needed a Python script to read the numbers coming in on the serial line. I ran apt-get install python-serial, then wrote this script: readsensor.py.

The script loops, reading the sensor and writing the output to an HTML file called arduino.html. Visit that in a browser from your desktop or laptop, and watch it reload and change the number as you wave your hand or a flashlight over the photocell.

Ultrasonic rangefinder for proximity detection

Pretty cool ... if you're extremely geeky and have no life. Otherwise, it's maybe a bit limited. But can we use this Arduino technique to do something useful in combination with the webcam exercise? How about an ultrasonic sonar rangefinder?

The rangefinder comes with a little PC board, and you have to solder wires to it. I wanted to be able to plug and unplug -- the rangefinger also has digital outputs and I may want to experiment with those some day. So I soldered an 8-pin header to the board. (The rangefinder board only has 7 holes, so I had to cut off the 8th pin on the header.)

I ran power and ground wires to 5v and Gnd on the Arduino, and a wire from the rangefinder's analog out to the Arduino's Analog In 2. A little heatshrink keeps the three wires together.

Then I rubber-banded the rangefinder to the front of the webcam, and I was ready to test.

[rangefinder and Arduino] [camera with rangefinder]

Use a sketch almost identical to the one for the light sensor: rangefinder.pde, and its rangefinder Arduino Makefile. I used pin 2 so I could leave the light sensor plugged in on Pin 1.

Now I ran that same readsensor.py script, paying attention to the numbers being printed out. I found that they generally read around 35-40 when I was sitting right in front of it (camera mounted on my laptop screen), and more like 150-250 when I got out of the way and pointed it across the room.

So I wrote a script, proximity.py, that basically does this:

  if data < 45 :
    if verbose :
      print "Snapping photo!"
    os.system("fswebcam --device /dev/video0 -S 1 output.jpg")
It also rewrites the HTML file to display the value it read from the rangefinder, though that part isn't so important.

Put it all together, and the proximity-sensitive camera snaps a photo any time something is right in front of it; otherwise, it keeps displaying the last photo and doesn't snap a new one. Sample uses: find out who's using your computer when you're away at lunch, or run a security camera at home, or set up a camera to snap shots of the exotic wildlife that's visiting your feeder or research station.

You could substitute an infra-red motion sensor and use it as a motion-operated security camera or bird feeder camera. I ordered one, but got bogged down trying to reverse-engineer the sensor (I should have just ordered one from Adafruit or Sparkfun).

I'm happy to say this all worked pretty well as a demo. But mostly, it's fun to know that I can plug in virtually any sensor and collect any sort of data I want. Adding the Arduino makes the plug computer much more fun and useful.

Tags: , , ,
[ 20:23 Apr 11, 2011    More tech | permalink to this entry | comments ]

Thu, 22 Jan 2009

LCA 2009: Thursday

The highlight of Thursday morning was a filler: one of the speakers had to cancel, so Paul Fenwick filled in with a combination of two short talks: "The Art of Klingon Programming" and "What's new in Perl 5.10?" I'm not a Perl programmer (at least not when I have a choice) but his talks were entertaining and even educational. What struck me most was that showmanship and humor don't have to detract from technical content. I'd had a discussion the previous day about the balance of offering lots of technical content versus entertaining the audience and not overwhelming them. Most technical talks are either dry, content heavy and so jam packed with information that you can't possibly remember everything, or lighter weight and glitzy but with not much real technical content and a "watered down" feeling. Paul's Klingon talk was one of the most content-full presentations I've seen at a conference, with lots of code examples, yet it kept the audence laughing, listening and grokking (to mix SF metaphors) all the way through. Showmanship can make it easier, not harder, to remember technical content.

In the afternoon, I'd been very much looking forward to the Arduino tutorial (Jonathan Oxer and Hugh Blemings) but it was a bit of a disappointment. The acoustics of the room and the handheld microphone, combined with the interactive nature of the presentation, meant that I could barely understand a word High Blemings said, and only some of what Jon Oxer said. (I've heard Jon Oxer talk before and never had trouble, so I primarily blame the room.)

Partway through, I skipped out to go check Donna Benjamin's "The Joy of Inkscape." It had been moved from its original lecture hall to a much smaller room with tables. The smaller room was Standing Room Only, a raucous and enthusiastic bunch who (the sitting ones, at least) were nearly all tapping away on laptops exploring either the demo Donna was showing or other Inkscape projects.

It was clearly a hugely successful and fun tutorial and I wanted to stay, but I couldn't find a place to sit where I could both see the screen and hear Donna, so I made my way back to Arduino. The second half, when they demoed various interesting sensors and a few unusual Arduino applications, was better than the first. But talking to folks later, a number of us were surprised because we expected a more interactive tutorial (the prep had encouraged us to bring or buy Arduino hardware).

The hot talk of the day was one I missed, after the tea break. I went to a talk on Spring, a robotics library (Clinton Roy), which was interesting enough and certainly popular (lots of people sitting by the door because all the seats were full) but afterward all I heard was people enthusing about Jeff Arnold's amazing Ksplice talk. He demonstrated a system of updating kernels in place, with no reboot required. People couldn't say enough about the talk, and I'm looking forward to downloading the video and seeing what I missed.

Tags: , , ,
[ 13:41 Jan 22, 2009    More conferences/lca2009 | permalink to this entry | comments ]

Mon, 27 Oct 2008

An Arduino battery timer

I wrote in my OSCON report a few months back that I came home from the conference with an Arduino microcontroller kit and just enough knowledge and software to make LEDs blink. And so it sat, for a month or two, while I tried to come up with some reason I desperately needed a programmable LED blinker (and time to play with it).

But it turned out I actually did have a practical need for a customizable programmable gizmo. One of the problems with R/C combat flying is that you're so focused on keeping track of which plane is yours that it's tough to keep track of how long you've gone on the current battery. You don't want to fly a lithium-polymer battery until it gets so weak you notice the drop in power -- that's really bad for the battery. So you need a timer.

My transmitter (a JR 6102) has a built-in timer, but it's hard to use. As long as you remember to reset it when you turn on the transmitter, it displays minutes and seconds since reset. Great -- so all I need is somebody standing next to me who can read it to me. Looking away from the sky long enough to read the timer is likely to result in flying into a tree, or worse. (The new uber-fancy transmitters have programmable beeping timers. Much more sensible. Maybe some day.)

I could buy a kitchen timer that dings after a set interval, but what's the fun of that? Besides, I could use some extra smarts that kitchen timers don't have. Like audible codes for how long I've flown, so I can make my own decision when to land based on how much throttle I've been using.

Enter the Arduino. Those digital outputs that can make an LED blink work just dandy for powering a little piezo beeper, and it turns out the Atmel ATmega168 has a built-in clock, which you can read by calling millis().

So I wired up the beeper to pin 8 (keeping an LED on pin 13 for debugging) and typed up a trivial timer program, battimer.pde. It gives a couple of short beeps when you turn it on (that's so you know it's on if you can't see it), then gives a short beep at 9 minutes, a long one at 10, shorter one at 11, and thereafter gives (minutes MOD 10) beeps, i.e. two for 12, three for 13 and so forth. Fun and easy, and it works fine at the field once I worked out a way to carry it (it's in a camera bag hanging on my belt, with the beeper outside the bag so I can hear it).

Fun! It could use better codes, and a pause switch (for when I land, fiddle with something then go back up on the same battery). Of course, in the long run I don't actually want to devote my only Arduino kit to being a glorified stopwatch forever. I have further plans to address that, but that's for a later posting ...

Tags: , ,
[ 12:10 Oct 27, 2008    More tech/hardware | permalink to this entry | comments ]

Syndicated on:
LinuxChix Live
Ubuntu Women
Women in Free Software
Graphics Planet
DevChix
Ubuntu California
Planet Openbox
Devchix
Planet LCA2009

Friends' Blogs:
Morris "Mojo" Jones
Jane Houston Jones
Dan Heller
Long Live the Village Green
Ups & Downs
DailyBBG

Other Blogs of Interest:
DevChix
Scott Adams
Dave Barry
BoingBoing

Powered by PyBlosxom.