Another take on a Pinewood Derby car with lights, this time with an Atmel ATtiny2313
microcontroller inside (along with a mess of wires). I haven't verified this, but a rough
calculation suggests that the lights should run for about 4 hours on two CR2016 batteries,
which is sufficient for a weigh-in and race.
The goal was to add front, back and roof LEDs to the car. My son wanted the roof lights to
flash in an alternating pattern (that is, one on when the other is off, and vice versa). The
simplest solution that I could see was to use a microcontroller. I could have used flashing
LEDs, but they wouldn't be synchronized. I could have used a 555 timer and an inverter,
but this would increase the part count. I also wanted to strobe the LEDs to lengthen
battery life and use the duty cycle to equalize brightness in some way. So, it just had to
be a microcontroller. Besides, a Pinewood Derby car with a computer inside - how cool
The total cost of parts for this project probably amounts to less than $10 or so. However,
you need to be familiar with programming a microcontroller (the wonderful ATtiny2313).
I use the avrdude/avr-gcc toolchain on Linux with a USBtinyISP programmer from
http://ladyada.net . I used a programming cradle (see https://www.instructables.com/id/Ghetto-Development-Environment/ for example) to connect the programmer to the microcontroller.
The electronic parts used in the car were:
1x ATtiny2313 ($2.88)
2x 5mm white LED ($1.72)
2x 5mm yellow LED ($0.64)
2x 5mm red LED (don't remember, probably $0.10 or less)
wirewrap hookup wire (two colors so the LEDs are connected with correct polarity)
ShapeLock (aka Friendly Plastic) to fashion a battery holder
2x ring connectors for battery terminals
2x CR2016 coin batteries ($1.17)
2x 20 pin DIP sockets (one split in half to simplify hooking up the ground connections)
1x tiny switch (I used a SPDT, $0.75)
1x diode to drop supply voltage below 5.5V (I used a zener in the 'wrong' direction)
The total of the known prices is less than $8.00, but it would be a bit misleading to characterize
this as a $10 project! I used the 20 pin DIP ATtiny2313 because I had it in my box. There
are many alternatives, the only consideration is space. If my soldering skills were up to it
(they're not), a SMD version would be cool.
The code is written in C, and is fairly straightforward. Working with interrupts is often a
bit delicate for timing reasons, but in this case a 1mS interrupt rate gives plenty of
time to perform the tasks at hand. Most of my coding time was spent figuring out the
correct timer/interrupt setup. (However, I should point out that I have been coding for
many years, and have a lot of experience dealing with this sort of project.)
Among other things, you will need a programmer for the ATtiny2313. Fast debugging was
helped significantly by my prehistoric (but functional) 4 channel 300Mhz Tektronix scope.
Soldering iron, solder, wire snips, wire stripper, solder sucker, wire of various sorts and
a breadboard for experiments all help too. A good tweezers and double sided Scotch
mounting tape (I like the mounting squares) are almost indispensable.
I am no expert in woodworking, so I have no contribution in this regard. I am, however,
an expert in finding overly complex solutions to simple problems, and in using delicate
and intensely complicated solution techniques. In this regard I can be of great help.
The project took a lot longer than I intended, mainly because (1) the hookup wire I used
(wire wrap) was very brittle and (2) soldering the connections in the spaghetti mess of
wires stretched my limited soldering skills.
Most of the relevant instructable information is contained in the image notes on the
pictures. I split the steps into the woodworking part, the (electronics) hardware, the
software and the assembly (by far the hardest part for me).
Hopefully we will win some category of the Pinewood Derby :-). (See the end of the
last step for the conclusion of this story.)
Step 1: Preparing the Car
He then used a Dremel tool to do some sanding. His focus was more on removing wood
than on producing a smooth surface. But he had fun.
I quickly realised during this that I had to let my son drive the process. My initial tendency
was to aim for perfection of some sort (not that I could achieve it), which would have
spoiled the fun. Luckily I got sense and chilled out.
I used a 1/2" wood chisel to hollow out space for the wires, battery and microcontroller. I was
lucky with my size guess. This was a little challenging for me (see picture) as the pine kept
splitting unexpectedly. Take care not to get too close to the sides or the axle slots. Patience
works here, remove small slivers of wood at a time rather than going for big chunks.
Then I drilled holes for the 6 (5mm diameter) LEDs. Two from the top, the back and the
front. I drilled a small hole first, then widened it with a larger bit. Again be careful, the
pine splits easily. Make sure your holes end up in the chiseled out space! No magic here,
just careful aim.
My son then applied one coat wood primer, and the sprayed the car with metallic paint.
More primer coats and more (lighter) layers of spray would probably produce a better finish
(and take much longer). My main concern here, however, was making sure my son pointed
the spray can towards the car and not his face! Also, he was more concerned with process
Step 2: The Hardware
an obvious choice. Since the white LEDs have a turn-on of about 3.2V, and coin batteries
mostly come in multiples of 1.5V this meant that we needed at least 4.5V. This would mean
3 batteries, which was getting messy. So, I decided that two 3V batteries would do.
The Wiki entry http://en.wikipedia.org/wiki/List_of_battery_sizes has some useful
information (assuming its correct!). A CR2016 is exactly half the thickness of a CR2032,
so I decided on using 2xCR2016. I initially thought I could use a sewable CR2032 coin
battery holder (from http://www.sparkfun.com ) and double-up the batteries, but when it
arrived I realized that it would short out one of the batteries. So, I settled on the less-than-
satisfactory method of fashioning our own. I used two ring terminals (with insulation
removed) and ShapeLock wrapped around the two cells. This worked fine. The CR2016
has about 90mAh according to the Wiki.
Another issue was that the microcontroller has a maximum operating voltage of 6V (see
http://www.atmel.com/dyn/resources/prod_documents/doc2543.pdf ) and lithium cells
have a higher than nominal open circuit voltage (see the Wiki entry above ), so it seemed
prudent to lower the operating voltage slightly. I used a diode in series with the supply to
get a 0.7V drop or so. (A quick worst case computation shows that the maximum current
would be around 100mA, so the diode must be rated for at about 100mW, which is not
an issue unless you are using really tiny diodes.) I used a Zener in the 'wrong' direction
since I have lots of them.
The Atmel spec. (see link above) is pretty clear as specs. go. The ATtiny2313 has fuses
that allow you to choose some operating characteristics such as using an internal clock
and operating frequency. The next section shows how to program the fuses with the avr
I chose to run the ATtiny2313 at 1Mhz, which is more than fast enough for our needs,
and at this frequency the active supply current is about 2mA, which is pretty negligible
compared to the LED draw. Other relevant ATtiny2313 characteristics are (1) the maximum
DC current per I/O pin (40mA), (2) the maximum DC current through power and ground
(200mA) and (3) the I/O pin HI voltage at the relevant LED current (4.5V @ 20mA, 4.8V @
A quick sanity check shows that there are no gross violations of the spec: The white and
yellow LEDs are rated at 20mA, the red LED is rated at 10mA. So, the worst case current is
about (4*20+2*10) mA for LEDS, and about 2mA for the ATtiny2313, so a worst case of
about 102mA. So all seems fine from a spec. point of view.
However, at a draw of 102mA, the CR2016s will last less than an hour. This is not sufficient
as there may be an hour or more delay between Pinecar Derby weigh-in and the actual race.
So I decided to schedule the LEDs to use less current (using a lower duty cycle) and to switch
on at different times. This will be dealt with in the next section.
A current limiting resistor should be used so the LEDs operate at the appropriate point.
The appropriate resistor value can be computed using the formula below. The relevant LED
characteristics are the forward (on) voltage, V_f_min, and the on current, I_on. Below V_f_min,
the LED is not turned on, and there is no point in driving more current than I_on (it won't get
much brighter, battery power is wasted and the LED life is cut short, not that the latter is a
big consideration here). V_HI is the I/O pin output HI voltage when sourcing current I_on.
The resistor value doesn't need to be exact, of course, and the final choice will depend on
what you have in your box (I have a resistor kit that has gazillions of different values), and
what the actual brightness looks like (remember, the car just has to light up for a few
hours, we're not manufacturing a million units!). Furthermore, since the duty cycle will
be less than 100%, smaller resistor values can work. I made a mistake when I looked up
the yellow forward voltage on the spec. and used a resistor value of 100 ohms instead of
the 'correct' 135 ohms. Not a big deal, just a bit sloppy on my part (since I've gone to the
bother of computing the value in the first place!). The second picture below shows the
relevant numbers for the LEDs and the I/O pin HI voltage vs. source current.
I used a bread board (see third picture below) to make sure all was well, and to let me
test the software before assembly. One minor thing to watch out for: I choose to use
PORTB (don't remember exactly why, it might have been so I could verify the internal
clock frequency on another pin), which overlaps with the programming pins. So, you
will need to disconnect one of the LEDs (pin 17, I think) when programming the unit,
or you may hit some odd programming errors. You can see the ugly battery holder
Step 3: The Software
I have included the code below, as well as a syntax highlighted version which I find easier
I decided to use a timer to generate an interrupt every 1mS or so. This gives about a thousand
cycles (the compiler will save/restore registers on interrupt, so there are less than a thousand)
between interrupts. This should be adequate for any reasonable light flashing schedule!
You need to read the spec. carefully to setup the timer and interrupts. Remember to enable
interrupts in the main loop. The spec. link is http://www.atmel.com/dyn/resources/prod_documents/doc2543.pdf .
The first image below shows the staggered turn-on times for each LED and the duty cycles
for each. To make life simple, I decided to use a 16mS period, so the duty cycle can be set
to any of the values n/16, with n=1,...,16. A variable count_ms is incremented every time
the interrupt routine finished. I chose 16 because I can just mask off the bottom 4 bits
of count_ms to figure out where we are in the duty cycle period. The data structure Led
(see the .h files below) indicates the staggered start time for each LED, and how long it
should remain on.
I have some additional code to alternate the yellow LEDs, so at most one yellow LED
is on at any time. The variable slow_count toggles every 256mS, about a quarter of a
Using the first picture below, you can figure out the maximum and average total LED current.
The average draw (including the microcontroller) is about 22mA, which gives about 4 hours
of light. Since the maximum draw is only 42mA, there is no need for a capacitor across the
power supply (to suppress switching transients).
I adjusted the on-times so the brightness of each LED was about the same. The yellow
and red LEDs have diffusers, the white LED has a lens, which works out somewhat like
a real car. The white LEDs were very bright. There is a slightly visible flicker (at 1000/16 Hz),
but it is tolerable, and draws attention when the car moves.
A multi-channel scope makes easy work of debugging. I'm not sure how I would have found
my bugs otherwise. There is actually a subtle bug in the code, but it doesn't matter in that
it is a corner case that is irrelevant. If the pulse_on_time is set to 0, then the corresponding
LED will stay on all the time! The fix is to also check that a LED is turned on only if the
value of pulse_on_time is non-zero. However, this lengthens the code unnecessarily, if you
want an on-time of 0, just comment out that LED!
The ATtiny2313 fuses must be set appropriately to select the internal clock of 1Mhz. The
following link http://www.engbedded.com/fusecalc/ is useful to simplify the slightly confusing
reverse logic used for fuse programming. The fuse.txt file below shows the command I used
to program the microcontroller.
The build instructions are in the file build.txt below. (Just for a sanity check, I print out the
code sizes and the variable map.)
Step 4: Assembly
anticipated. I used wire wrap wire which was the smallest insulated wire I could find. It is
very brittle and makes soldering leads very time consuming (for me). (I might have been
better off actually wire wrapping instead of soldering.)
Inspired by 'Blinkenlights' (https://www.instructables.com/id/Ghetto-Development-Environment ),
I soldered the relevant resistors onto the cathode of the LED (doesn't matter, just helps if
you are consistent so you don't get mixed up later). I soldered the wire-wrap wire onto the
suitable trimmed anode and resistor leads. Then I used heat shrink tubing (of different sizes)
to cover the exposed metal and add some strength. Then I inserted the leads and threaded
them through to the inside cavity. I used some polystyrene glue to fix the LEDs in position.
The result was a spaghetti mess of brittle leads.
Next I soldered the anode leads to the appropriate pin on a 20 pin DIP socket. This was
tough, as the socket plastic melts readily, and the neighboring pin tends to heat fast,
undoing your previous work. I connected the switch to the batteries, and added the voltage
dropping diode wrapped in heat shrink tube.
In the previous step, I managed to ruin one DIP socket with too much heat. I was able to
salvage one side of it to serve as a 'ground plane'. I wired all the pins together, and soldered
the LED, microcontroller and battery ground leads into the socket side. This used up some
precious space, but saved my sanity (what little I have).
Then I crammed all the stuff into the cavity. I broke a few connections doing this, so I
resoldered and was more careful the next time. I used a small square of double sided
Scotch mounting tape to attach the switch to the side. The attachment is a bit spongy,
epoxy would have been better, but its sufficient. (See the second picture below.)
At this stage I was able to test the close to final car. See the third picture, you can see the
white & red LEDs and one of the alternating yellow LEDs. (You can also see my copy of
Hungerford's Algebra which is pretty incomprehensible to my engineering mind :-)).
To keep the guts from falling out, I cut some tin from the bottom of a chocolate box we
got as a present. This was pretty difficult, I went through a few Dremel cutting disks before
I finished. You need to smooth the edges carefully so that little hands don't get cut. You
need to remember to make some room for the switch. I cut mine in the wrong place, but
the switch is easy to reposition. I drilled two holes and attached the bottom with two tiny
wood screws I found. I printed out a piece of paper indicating on/off to make the bottom
look a little prettier.
I used Gorilla super glue to add some washers. The car weighs about 4.5 oz. after adding
the washers. Still a little light, but that will be fine. Yes, I know the ratio of air drag to gravity
is not optimal, but as my brother says, "the enemy of good is better". And he knows.
Finally, and by far the most important step, we added some decals. The dry transfer decals
were expensive (about $3.50), but worked amazingly well. (Shown in the first picture of
We're both very proud of our car :-). Even if we don't win (but we might).
Feel free to ask questions, I would be happy to elaborate (if I can).
P.S. We won the Coolest Car in the Pack trophy! And there were lots of really cool cars
there. Thanks to the amazing folks who ran the event. We added a few more washers
that brought our weight up to 4.95 oz, and a friend gave us some graphite so we could
put it on our tire sidewalls. But we didn't win any heat. But we are happy :-).