In 1978, I bought a wind-up donkey for my daughter, then an infant. The
donkey moved its head while playing “Donkey Serenade.” I figured that I could replicate that with an
Arduino, a motor, sound on an SD card, and a speaker. It took me 10 weeks, but I did it. Here’s the
story.
I got sidetracked for a while doing
my
Halloween Candy Cauldron, which came out of this one. While I was working
on the donkey, learning about playing sound with an Arduino, I began seeing
lots of Halloween projects on Adafruit shows, so I decided to try my hand on
Halloween sounds.
This was an incredibly rewarding project that was challenging, fun,
interesting, and educational—all the reasons I wanted to start with Arduino in
the first place!
Parts List (about $80 in parts
done this way, assuming you have all the tools and supplies)
Micro SD Card
Speaker (I used a 2” 8ohm speaker from an MFC printer I took apart)
Hook-up wire (I used 22 gauge solid wire to connect the speaker, and to
run from the terminal block on the PWM board to the power connector because
that was easier
Header pins (male, female, and right-angle)
Soldering iron and accessories
Heat Shrink tubing
Dremel or similar tool for cutting out the stand-offs on the enclosure
Drill and bits for making holes in the enclosure (1 for the power jack
and 1 for the wires to the speaker and servo)
Electrician’s tape to keep stuffing out of the wire hole
Needle and thread
Step 1: play music
Step 2:
operate servo
Step 3: put it together
Step 4: getting small
I asked Becky Stern, Director of Wearable Technology
at Adafruit, for some advice on getting all this in a donkey. She
answered my question on Wearable Wednesday (~21:30)! I also needed to change some components.
First I swapped out the Arduino Uno for a Pro Mini 5V (I thought). Next I bought a microSD breakout to replace
the shield. The Micro SD runs on 3.3V, so I thought I needed a voltage
regulator and maybe something else (http://forums.adafruit.com/viewtopic.php?f=19&t=60813 ). In the process
I found out that the 5V pro mini was really a 3.3V, and figured out that that
was really what I wanted (power the Pro Mini, the amplifier, the PWM board, and
the servo from the battery, and power the SD from the Mini).
Step 5: refine
I figured out how to play the song in a loop without
resetting the Arduino (TMRpcm.loop(1)). In the process of doing all this I
cooked my Mini—it won’t put out 3.3V anymore (more like .9V) so I’m back on the
Uno until my 3V Pro Trinket comes next week.
I also decided to go with a 6V coin cell holder with switch (https://www.adafruit.com/product/783 ) for power. I
gave up on the amplifier and put in an LM386 circuit. It works OK, but I also ordered an amplifier
breakout (https://www.adafruit.com/product/2130) just in case I can’t get the sound I want out of a smaller
speaker.
Step 6: construction
Donkey arrived 10/4/2014. It will accommodate a small project box,
servo, speaker, and battery holder. Now I need to be sure I can get the whole
circuit on a board small enough to fit into the enclosure. The Altoids tin will
fit in the donkey, but I also have a project box if I can’t get the circuit in
the Altoids tin.
Programming the Pro Trinket was somewhat flaky at
first. I needed to install the hardware updates for the Arduino IDE so it would
recognize the board. Also, had to set the programmer to USBTinyUSB. When that
didn’t work (“can’t find USBTiny”) I discovered I needed the Windows
drivers. After I got that all done I was
able to upload the example blink program, so I’m in business, I think. Now I
need to solder the headers so I can test the circuit. I have another Pro
Trinket coming tomorrow, so I will use that for the real thing, soldering
directly, but I’ll need this one with the headers anyway. UPDATE: there may be an issue with the ProTrinket and
device recognition on Windows (or at least my Windows systems). I got it to work with Ubuntu, and in the
process discovered that the upload took longer than the bootloader was active,
so I have to wait to press the reset button to activate the bootloader, but
leave enough time in the compile process for it to initialize. Kind of a pain, but it’s working. I never did
get it working on Windows 7 (that may be my fault), but it’s working OK on
Windows 8 and Ubuntu.
Step 7: more construction
I tested the 6V coin cell battery, and the power
lights on the boards come on but no music and no motion. I need find another power source. I’m
considering a 9V with a voltage regulator to bring it to 5V. A 4bXAA works (6V)
but it’s big. Also I got the Adafruit mono amp, and it puts out more volume
than the LM386. I also takes up a lot less space. Next, I got some SMT breakout
boards (https://www.adafruit.com/product/1208) so I’ll see if I can solder the TSSOP-28 PCA9685 to it
and save more space. That didn’t work—not skilled enough. I will try to make a
DIY breakout. I shorted something and cooked my amp, just got new amps today
and will try again. The servo moves but no music…hopefully the new amp will get
me back where I was. The new amp fixed the problem. I decided to stick with the
Adafruit PCA9685 PWM board because my surface mount skills are not there yet.
Step 9: The enclosure
I got a 4x2x1
enclosure from Radio Shack.
I fixed an Adafruit 1/8 size Perma-Proto Board to the enclosure with a
screw, and drilled a ½” hole for a power receptacle and a 3/8” hole for the
servo and speaker wires. In another 3V Pro Trinket, I soldered female headers
to A4&A5 and Adafruit silicone coated flexible wires to the pins I need for
the circuit. I put right angle headers on the I2C pins of the PWM board, so I
can slide those into the female headers and have the bigger board flat with the
Trinket on its side perpendicular to the PWM board. All the power and ground
connections will go to the Perma-Proto Board + and - rails, with the power
connector supplying those rails. The
power supply will be an Adafruit 4xAA battery pack with switch so there is an
external switch access to batteries for
changing without opening the donkey, and less space to take up inside.
Step 10: new Trinket
I tried wiring up the circuit with the new, newly soldered
Trinket. It powers up, and puts out 3.3V on that
Rail, but it does not play sound or move the motor.
Either I did not wire it correctly or there is something wrong with my
soldering. More testing tomorrow.
The next week:
I wired it up again. After some
fussing with connections I got the whole thing to work. I spent some design
time on the enclosure, so on to soldering/enclosing.
Step 11: The enclosure, part 2
Day 1: I
discovered that I could not fit the Perma-Proto board and the other components
in the enclosure. The next size larger
is too big for the donkey. Also, the
internal stand-offs in the enclosure were in the way, so it was redesign
time. I moved the power
connector/receptacle from the end to the side to give more room. I used my
Dremel knock-off tool to cut out the internal standoffs. Now everything
fits. Without the Perma-Proto Board, I
will need to connect the wires for power and ground directly to the connector. Next
I got to soldering:
1.
I connected a
2.1mm jack (to plug into the power receptacle) to the battery pack and covered
the splices with heat shrink tubing.
2.
I soldered
new, solid core wire leads to the speaker.
Solid core works better in the terminal blocks.
3.
I connected
solid core wire to the external power terminal block on the PWM board, and ran them
under the board to the power connections.
4.
I removed the
jumper wires from the amplifier, and soldered wires directly to the header
pins. The A- and GND wires to go to GND,
the Vin to go to power, and the A+ pin is soldered to the wire going to digital
pin 9 on the Trinket (SpeakerPin).
So far, so good. Tomorrow I’ll replace the six jumper
wires on the SD card with direct soldered connections, and test the audio.
Assuming that works, I’ll do the 4 remaining wires on the PWM board.
Step 11: The enclosure, part 3
It works!
Without the circuit board there was a lot of soldering. I soldered all
the power leads together, two at a time, adding the next one in turn until I
had one lead to connect to the power connector + lead, then did the same with
the grounds, to the – lead. I left the
jumper wires on the SD board because they’re pretty secure and didn’t want to
risk cross-connections due to sloppy soldering.
I did solder leads to the headers for Vcc and GND on the PWM board. For the SD board, I cut and stripped the
jumpers and connected them to the correct leads:
·
GND to the
GND complex
·
3.3V to the
3.3V pin on the Trinket
·
SPI pins to
the leads I already had soldered to Trinket pins 10-13
I used heat shrink tubing on the splices to protect
the connections from touching.
Everything fits—I can close up the enclosure and
secure it with screws. The music plays and the servo moves.
Tomorrow: open up the donkey.
Step 12: the donkey 1
I used an x-acto knife to cut the donkey’s belly
along a seam, and took out some stuffing.
I got the servo in the neck, and it will turn the head, but I need to
fix it to something solid so the horn of the servo turns the donkey instead of
the donkey holding the horn while the servo turns. Meanwhile, I stripped the
plastic gears on the servo. This is the
second servo I’ve ruined. So, I ordered
two new servos, one micro and one standard, both with metal gears from
Adafruit. Hopefully one of them will do the trick.
Step 13: the donkey 2
I used the standard servo. It’s substantial, and it
does the trick. I was able to close up the enclosure and screw on the cover
with only one mishap: the ground lead on to the power connector broke and I had
to de-solder/re-solder it. I pulled more
stuffing out of the head to get the servo in closer. It moves a little, but
with more stuffing, it should be even better than it is now. There’s a little interference from the servo
(actually I think it’s from the PWM board) but it’s OK.
Next: sew on the Velcro and re-stuff.
Step 14: the donkey 3
First, I sewed on strips of Velcro that I had cut to
the length of the slit in the donkey’s belly.
I’m not great at sewing, so it was a little frustrating, but I got
through it. Next, I tried different
positions for the servo to get it to move the head. I re-stuffed the neck to
try to keep the servo in position, placed the speaker, re-stuffed the rest of
the donkey put the enclosure in and closed the Velcro. After one more iteration to get the servo
better positioned, it’s done. I’d like
more range of motion on the head, but it does move.
Step 15: futures
1.
I’d like to
get more movement from the Servo. I have to experiment with different horns,
different positions, and different programming.
I was time-limited on this one—I needed to have it ready for
Thanksgiving Dinner, so I haven’t been able to pursue more options yet.
2.
I would
shorten the wires inside the enclosure, and probably move the power connector
to the end of the box (rather than coming up from the bottom).
3.
I’d also like
to find a box that fits the components a little better, and to fasten the
boards to the enclosure (right now, they’re loose, and any jostling by
grandchildren may disconnect something). I think I could put standoffs on the
end of the enclosure for the Trinket and the bottom for the PWM Board.
4.
Rather than
connect the Pro Trinket to the PWM board via right-angle headers, I might want
to solder wires directly from the holes on the Trinket to the holes on the PWM
board.
5.
To accomplish
#3 and other improvements, I would need to hold off on soldering header pins to
any components until I know how I really want to wire up and solder the whole
project. I soldered the headers first thinking generically, then when I got
inside I found that some of the pins were in the way.
6.
I’d like to
see if I can make a PCA9685 breakout on my own to save space. New Year’s
Resloution #1: get some SMT soldering
skills.
7.
Investigate
60MHz vs 50MHz on the Servo (see comment in sketch)
Circuit as laid out on a
breadboard
Resources
Presentation
on Adafruit Show-and-Tell
In-Process https://www.youtube.com/watch?v=Y8tFcF2-klw about minute 13 to 16:30
Finished http://www.adafruit.com/blog/2014/11/26/show-and-tell-google-live-hangout-wednesday-night-at-730pm-et-112614-video/ about 4:50 to 6:45
Discussion on Wearable Wednesday
http://www.adafruit.com/blog/2014/09/17/wearable-electronics-with-becky-stern-9172014-live-2pm-et/
Donkey:
Sound:
Tutorial:
Sound from SD:
Micro SD:
TMRpcm library
Power servo
PWM/Servo Breakout
Amplifier
Increase volume (LM386)
Amplifier I used
Servo I finally used
Arduino Sketch
/*September-November
2014
THE HEAD MOVE DONKEY
Uses TMRpcm library to
play music from and SD card, and Adafruit_PWMServoDriver library to drive the
servo.
Some comments are from
example code that came with those libraries
Objective is to move the
donkey's head with the servo while playing "Donkey Serenade.
When I was on the Uno
and had the serial monitor, I used an led to prove that I was moving through
the loop. That is now commented.
Circuit uses the
Adafruit Class D mono amp, Adafruit PWM servo board driving a micro servo, a
micro SD card board, an 8 ohm speaker, and a 4xAA batter holder
It now runs on an
Adafruit 3V Pro Trinket, feeding 3V to the SD card and using battery power for
the Trinket, Servo, PWM board, and amp
*/
/*includes*/
#include <Wire.h>
#include
<Adafruit_PWMServoDriver.h>
// called this way, it
uses the default address 0x40
Adafruit_PWMServoDriver
pwm = Adafruit_PWMServoDriver();
// you can also call it
with a different address you want
//Adafruit_PWMServoDriver
pwm = Adafruit_PWMServoDriver(0x41);
#include <SD.h> //
need to include the SD library
#include
<TMRpcm.h> // also need to include this library...
/*constants*/
// Depending on your
servo make, the pulse width min and max may vary, you
// want these to be as
small/large as possible without hitting the hard stop
// for max range. You'll
have to tweak them as necessary to match the servos you
// have!
#define SERVOMIN 200 // this is the 'minimum' pulse length
count (out of 4096)
#define SERVOMAX 350 // this is the 'maximum' pulse length
count (out of 4096)
/*SERVOMAX reduced from
600 in example to 500 to save the servo (I stripped the gears on one
already). That gave me ~160
degrees.
I reduced it again to
350, so it goes ~90 degrees: 45 to left and 45 to right if I have the motor and
horn positioned properly. That's what I want
*/
// our servo # counter
#define SD_ChipSelectPin
10 //using digital pin 4 on arduino nano
328 2014-09-03 changed to 10 to match datalogger
//#define ledPin 5 //pin to control led 2014-10-25 testing
/*variables*/
int angle = 0; // servo position in degrees
uint8_t servonum = 0;
/*objects*/
TMRpcm speaker; // create an object for use in this sketch
void setup(){
speaker.speakerPin = 9; //11 on Mega, 9 on
Uno, Nano, etc
speaker.loop(1); //2014-10-03 play repeatedly
Serial.begin(9600);
if (!SD.begin(SD_ChipSelectPin))
{
// see if the card is present and can be initialized:
Serial.println("SD not
initialized");
return;
// don't do anything more if not
}
else
{
Serial.println("SD
initialized");
}
speaker.volume(1);
speaker.play("hmd.wav"); //play
Donkey Serenade each time the arduino powers up, or is reset (as of 2014-10-03,
plays repeatedly)
pwm.begin();
pwm.setPWMFreq(50); // Analog servos run at ~60 Hz updates (says
Adafruit--I found that 50 worked better with my servo from Radio Shack—never
set it back for the Adafruit servo)
}
void loop()
{
//blink led to show
arduino is looping through this whether servo moves or not
// digitalWrite(ledPin, LOW); // 2014-10-25
testing only
delay(1000);
// digitalWrite(ledPin, HIGH); //testing
for (uint16_t pulselen = SERVOMIN; pulselen
< SERVOMAX; pulselen++) {
pwm.setPWM(servonum, 0, pulselen);
delay (100); //was 50, doubling the delay
to move the head more slowly
}
delay(1000); //pause when limit is reached
for (uint16_t pulselen = SERVOMAX; pulselen
> SERVOMIN; pulselen--) {
pwm.setPWM(servonum, 0, pulselen);
delay (100);
}
delay(1000); //pause when limit is reached
}