DSC_0044

John: My son is in Cub Scouts, and for years we’ve been building Pinewood Derby cars. It’s always … interesting to see how much involvement the scouts have, versus their parents, in making their cars. For the most part, I’ve let my son do what he wants: cut the car, sand it, paint it, and so on. But after watching one parent spend hours painstakingly cutting, sanding, and grinding his kid’s car, my son and I decided we’d kick it up a notch this year — his last year in Cub Scouts.

August: My dad and I had an idea that our last Pinewood Derby car should be really cool. My dad is a geek and really good with electronics so he did most of the coding. I did most of the design. I thought it was a lot of fun because I got to spend more time with my dad, and got to do a lot of things that I like. I couldn’t wait until the race to see how fast it was. It did not win a single race — but we did win the most unique car design. It was the best Cub Scout experience I’ve ever had.

Figure 1. A boy and his Arduino-powered Pinewood Derby car.
Figure 1. A boy and his Arduino-powered Pinewood Derby car.

John: Even though I have a pretty nice wood shop, I’m more of a programmer type (I’ve written 6 books on mobile development). I’d wanted to do something with Arduino, so this seemed like the perfect opportunity to do so while at the same time providing me with a chance to teach my son how to wire things together, solder, and write code.

In this project, we’ll show you how to create a Pinewood Derby car that uses an Arduino compatible microcontroller board and an accelerometer to flash a set of LEDs in response to the orientation of the car. When the car sits flat in the pits, it flashes the lights in a certain pattern. When it’s at the starting gate and on the angled portion of the track, the light pattern changes and becomes much more active. Knowing that the car may jump off the track, we added special “danger” patterns when the car is tipped on its left or right side.

Since everything is done in code, it’s super easy to completely change the light patterns and orientation settings in the software. You and your kid can spend hours trying out different patterns to get the right, and potentially unique, ones for your car.

COMPONENTS
For this project, we used the following components:

Arduino Board
The Arduino is a programmable microcontroller that’s open-source, so there are a lot of different boards available. The Arduino team has designed some, while others in the community have implemented their own designs. Check out the Maker Shed and you’ll find a bevy of devices of all sizes and capabilities.

You can use any Arduino-compatible board with at least 10 digital outputs and 3 analog inputs, but since the Pinewood Derby car has specific requirements for length, width, and weight, your choices will be limited based on what will actually fit on (or in) your car. We prototyped our solution using a breadboard and the Arduino Micro (Maker Shed #MKSP20). This allowed me to teach my son breadboarding and get him involved in wiring the solution before we started soldering things together. When it came time to mount it on the car, I looked for an even smaller board and selected the Teensy 3.0 (pjrc.com/teensy). Since then, a 3.1 version was released and I’m sure there are other, suitably sized alternatives. The LiPo battery I chose outputs 3.7V, so I had to make sure the board I selected could operate on less than 5V.

Power
We wired an alkaline battery pack into our prototype and it worked great. But with the car’s 5oz weight limitation, this wasn’t optimal. My son’s a smartphone fanatic (even though he’s too young to actually have a smartphone), so I started thinking about using a smartphone battery. A quick search pointed me to Adafruit’s 3.7v 1200mAh LiPo battery. It has enough juice to power the Arduino and LEDs for several hours.

A Pinewood Derby car performs best when its weight is as close to 5oz as possible. With this battery and the other parts I selected, the car’s total weight was 4.8oz, so we needed to add very little weight to bring it up to the limit. If you select a smaller battery, you’ll need to add more weight.

My original plan was to disconnect the battery for charging. My son and I started thinking how cool it would be to have the car itself be rechargeable, so we decided on Adafruit’s #259 USB charging module. With the battery embedded in the bottom of the car and the charging module mounted on the back, you can charge the car using a standard cellphone charger. (The #259 module uses a USB Mini-B connector so I had to dig out an old BlackBerry charger.)

Adafruit now offers an even smaller charging module (#1904) with a Micro USB connector, so this may be a better choice for your project. It looks to be the same size as the power switch (described in the next section), so it would be easy to stack them together and take up very little space on the back of the car.

If you don’t want to go the rechargeable route, you can use the Maker Shed 9V Battery Case for Arduino. It should fit within the base of the car (although you’ll have to make a taller car) and it has a built-in power switch.

Power Switch
To switch our LiPo battery on and off, I selected the Push-button Power Switch Breakout (#1400). It has mounting holes, so it’s easily mounted on the car, and it’s got an LED indicator underneath so it’s easy to tell whether the car is powered or not (just in case something else isn’t working) and the red glow just looks cool. You can also use the Tactile On/Off Switch with Leads (Maker Shed #MKAD81) but it doesn’t have an indicator light and you’ll have to figure out a way to mount it on/in the car.

Accelerometer
To allow the Arduino to measure the car’s orientation, I selected the Adafruit ADXL335 5V ready triple-axis accelerometer. Even though it’s rated at 5V, it will operate at the lower voltages provided by the 3.7V battery I selected. It has a small form factor and easily mounts on the front of the car.

Lighting
In our prototype, we simply wired in 5 white LEDs, but we were looking for something more. I tried the Adafruit 8 LED NeoPixel Stick — it’s simple, mounts cleanly on the car, and uses only a few wires. It’s also multi-colored, so that’s pretty cool. But it wasn’t bright enough for our purposes and I had some issues getting the sample code to work correctly, so I discarded it as an option.

Instead we decided to just wire up 10 LEDs. I purchased three sets of 3.7V LEDs: yellow and blue to match the Cub Scouts colors, and orange simply because my son and I both like orange. I selected clear capsules so that the LEDs all look the same until they illuminate. You’ll also need the appropriate resistors to use with the LEDs you select. I purchased LED/resistor bundles from Amazon (blue: amzn.com/B004UZCADG, yellow: amzn.com/B004UZB9WO & orange: amzn.com/B004UZ3FNU).

Wiring
To connect the 10 LEDs to the Arduino board, I purchased some 10-wire ribbon cable. The battery connects directly to its charging module, but I also needed to connect the charging module to the switch and from there to the Arduino board, so I needed black and red hookup wire too.

Project Steps

Make the Car

You can pretty much make your car any way you want — the Scouts are supposed to make it themselves (with your help, of course) — but you’ll need to look at the components you’ll be wiring together and carefully plan your car to accommodate the configuration you implement.

NOTE: Check your pack’s Pinewood Derby race rules to make sure your car complies. Our pack, for example, has specific rules for width, height, and weight, plus a rule about components being solidly mounted on the car.

Figure 2 shows the car we created. The battery is underneath the car and all the electronics are mounted on top. You don’t have to do it this way, we just selected this approach as it highlighted the electronics — it was important that our car looked like it had a bunch of hardware on it.

Figure 2. The Arduino-Powered Pinewood Derby Car.
Figure 2. The Arduino-Powered Pinewood Derby Car.

For your car, you may want to hide everything. You could carve out a cavity for all of the components and only show the charging connector and LEDs. For our race, I was concerned that someone would complain about potential cheating, so I made sure everything (except the battery wires) was easily visible. If any complaint was made, I could simply unscrew 12 screws and the whole thing could be easily inspected before being reattached for a race.

1. Cut the Battery Cavity

Before you make any profile cuts to the car body, first make a space for the battery underneath. That way, the car’s top can rest flat against your work surface without rocking or slipping as you cut the battery cavity. To start, turn the car body upside down and decide where you want to put the battery. Conventional wisdom, feel free to disagree, is that you want the car’s center of gravity to be right in front of the rear wheels. You’ll soon be mounting electronic components to the car body, so put the battery somewhere that mounting screws won’t pierce it. We put ours right in front of the rear axle.

NOTE: In the official Pinewood Derby kit, the rear axle slot is closer to the back of the car than the front axle slot is to the front of the car. Many cars are made backwards, with the car facing the wrong way – the front wheels using the rear axle slots.

Mark the battery’s position with a pencil, then use a ruler to mark out the complete battery cavity. Leave a little extra space around the battery (you’ll use epoxy to cement the battery in place and it will need some room) and also at the top of the battery (for the power cable). Figure 3 shows the results of this step on our car. The X in the figure marks the area of the car body that will be chiseled out.

Figure 3. Marking the battery position.
Figure 3. Marking the battery position.

Using an X-Acto or other hobby knife, trace the edges of the battery compartment you just marked. Make multiple passes and cut down to the approximate thickness of the battery.

Using a chisel, cut away the wood within the cavity lines to the thickness of the battery as shown in Figure 4. Carve away from the rear axle. If you carve toward the axle, you risk undercutting the material between the cavity and the axle, popping off a chunk of wood between the two. If this happens, there won’t be solid wood to hold the axle in place, so the car body will be ruined.

Figure 4. Finished battery cavity.
Figure 4. Finished battery cavity.

Sand the cavity to smooth out any rough spots. Test-fit the battery and make sure it’s flush with the bottom of the car.
With the battery in place, mark the location of the battery wires then remove the battery.

NOTE: If your battery came with a connector at the end, cut it off so you have 2 unfinished wires coming out of the battery. Cut each wire separately to avoid shorting out the battery while you cut it.

Drill a small hole (big enough to feed the battery wires through) from the bottom of the car where you marked the battery wire location, to the top of the car where the other components will be mounted. Make sure the hole is small enough for just the battery wires and that it goes straight through to where the other components will be.

When finished, you should be able to feed the wires through to the top of the car and insert the battery flush within the battery cavity.

2. Cut the Car’s Profile

We cut the body into the traditional Pinewood Derby wedge profile. Many car kits already come in this profile, so it’s a pretty popular design for Cub Scouts; all they need to do is paint it, put on the wheels and they’re ready to go. We made our wedge slightly thicker in order to accommodate the ½” screws we used to attach the electronics.

Using a pencil, mark the side of the car with the wedge profile, making sure the thickness doesn’t fall below ½” at the front, as shown in Figure 5. In the figure, the back of the car is to the left of the image. To make this easy, I marked the front of the car at ½” and drew a line to an arbitrary point on the back of the car, high enough to accommodate the battery height and length of the mounting screws.

Figure 5. Marking the wedge.
Figure 5. Marking the wedge.

CAUTION: I do not recommend you allow your son to make the cut – you should make it, using the appropriate safety precautions and safety gear. I let my son cut his Pinewood Derby car on my band saw, but only under my direct supervision. Whether or not you let your son use power tools is up to you (not me).

Cut the car profile with a saw. Be sure to wear safety glasses. Then use a bench sander (or sanding block) to smooth and flatten the car’s top.
To route the wires connecting the different components, we cut a trough in the top of the car about 3/8″ wide and ¼” deep. I used my table saw, but you could easily do this with a Dremel, router, or chisel.

One of the things we didn’t do, but you should, is round out the front of the car to make it more aerodynamic going down the track (and cooler looking too). Be careful to not shorten the car by cutting material off the front of the car — your pack’s rules may not allow it.
At this point, the car body is ready; sand and smooth the remaining edges then paint the car and put it aside to dry.

3. Mount the Wheels

Over the years, I’ve always made my son put the wheels on his car at the last minute, right before we headed to the race. Why? Wheel placement is critical to car performance, and if I put the wheels on too early, my son would play with the car and whack the wheels out of alignment, ruining his car’s chances in the race.

When we built this car the same rule applied, and the night before the race we were putting the wheels on — and struggling. We needed to hold the car pretty tight to manhandle the axles into place, but electronic components can be fragile, and I knew I might smash something or break a connection if I held the car too tight.

I realize now we should have put the wheels on early, before mounting the electronics. But how to protect the wheels after they’re on the car? I came up with an excellent solution (one I wish I’d thought of years ago). When you buy your car kit, pick up a couple of extra ones, in case you make mistakes. Once the wheels are on, take an extra car body blank and keep it under the car (you can see an example if you look closely at Figure 2) at all times. It’s the exact same size as the car you’re working with and it’s flat on top and bottom. You can even tack small pieces of wood on the front and back of the blank to keep the production car in place on top.

Connect the Electronics

It’s time to assemble the electronic components. Figure 6 shows the logic of how everything connects; the numbers indicate (roughly) the sequence of steps in the connection process.

The charging module is smart enough that you can simply plug a rechargeable battery into it and wire the module to the electronic components that need electricity. When the charging module is plugged into a cellphone charger or USB cable, it will charge the battery and pass the appropriate voltage on to the electronic components. When you disconnect the charger, the battery provides voltage to the electronic components.

Figure 6. Logical connection diagram.
Figure 6. Logical connection diagram.

NOTE: Use the shortest possible wires in order to minimize chaos on top of the car. You don’t have a lot of space to work with, so things will likely be a little tight.

1. Connect the Battery and Charger

Pass the battery wires up through the hole you drilled in the bottom of the car and connect them to the BATT input pads on the charging module (indicated in the red box in Figure 7). Solder the red wire to the positive (+) BATT pad, and the black wire to the negative (–) BATT pad.

Figure 7. Charging module.
Figure 7. Charging module.

2. Connect the Pushbutton

Solder the pushbutton to the switch module shown in Figure 8. The 4 top and bottom connectors on the pushbutton (left) solder into the 4 top and bottom connections in the middle of the module (right).

Figure 8. Power switch module.
Figure 8. Power switch module.

The power switch module has input/output connectors on both sides. For this step, pick one side of the module and make both connections to the same side: Solder a red wire from the charging module’s positive (+) LOAD connector (Figure 7) to the switch’s In connector. Solder a black wire from the charging module’s negative (–) LOAD connector to the switch’s G (ground) connector.

3. Wire up the Arduino

The pin layout for the Teensy 3.0 microcontroller is shown in Figure 9; for this project, we’ll be connecting a bunch of stuff to it.

Figure 9. Teensy 3.0 pin configuration.
Figure 9. Teensy 3.0 pin configuration.

We positioned the accelerometer at the front of the car, and the block of LEDs between it and the Arduino board. In Figure 6 you can see that both the accelerometer and the LED block have one common connection: the (black) ground wire. To simplify the wiring, I decided to use a single ground wire shared across both the accelerometer and the LED block. Cut a black wire long enough to reach from the Arduino GND pin on the middle-right side of the board (Figure 9) to the front of the car. Strip one end and solder the wire to the Arduino GND pin.

For the LED connections, measure out 2 lengths of 10-wire ribbon cable that will reach from the Arduino board to the front of the car. You’ll trim them back as you wire together the rest of the car. Strip both ends of one of the ribbon cables and solder the 10 wires to pins 0 through 9 on the bottom of the Arduino board (Figure 9). These wires will connect to the LED block as shown in Figure 12.

On the other section of ribbon cable, remove 6 wires, leaving only 4: the red wire and 3 other colors. You’ll use the red wire to provide power to the accelerometer (you might as well keep the color convention used so far). Strip the ends of the 4-wire ribbon cable and solder the red wire to the 3.3V pin shown on the right side of the Arduino in Figure 9. Solder the remaining 3 wires to Arduino pins 14 (A0), 15 (A1), and 16 (A2).

At this point, you’ve got one black ground wire and 2 ribbon cables (a 10-wire and a 4-wire) connected to the Arduino board.

4. Build the LED Block

Now you’ll assemble the block of LEDs. Cut a piece of proto board or perfboard sized to fit the top of the car body and accommodate all 10 LEDs and their associated resistors as shown in Figure 10. This was about 14×20 holes in our case. I positioned the LEDs on the outside of the board, and the resistors in the middle. The black ground wire connects all 10 resistors to ground underneath the board, while the ribbon cable travels across the top of the board and each wire splits off to connect to the positive (+) lead of each LED.

Figure 10. Completed LED block.
Figure 10. Completed LED block.
Figure 11. LED color placement.
Figure 11. LED color placement.

For our car, we used 3 different colors of LEDs: 4 blue at front and rear, 4 yellow just inside the blue, and 2 orange in the middle as shown in Figure 11. Our LEDs are clear so when the car is off, you can’t tell what colors are used. Use whatever colors and patterns you want for your car.

Figure 12 is a logical wiring diagram that shows how the different components are connected.

Figure 12. LED block wiring diagram.
Figure 12. LED block wiring diagram.

On the bottom of the board, solder each LED’s negative lead (shorter wire) to the nearest resistor lead. Use a knife to strip all the insulation off the ground wire between the first and last resistors. Then wrap each resistor’s remaning lead around the ground wire and solder them in place. (This was the easiest way for me to use a single ground wire for all the LEDs as well as the accelerometer.)

Stick the ribbon cable to the top of the board with double-sided tape, then split off each wire and solder it to its individual LED’s positive (+) lead (the longer wire) as shown Figures 9, 10, and 12. The pin numbers in Figure 12 correspond to the connections shown in Figure 9. If you wire yours differently, you’ll have to make some minor changes to the application source code shown later in the article.

5. Connect the Accelerometer

Trim the remaining length of the black ground wire to reach the accelerometer on the car, then strip and solder it to the ground connection (GND) on the accelerometer shown in Figure 13.

Figure 13. Accelerometer module.
Figure 13. Accelerometer module.

Cut the 4-wire ribbon cable to length, then strip the ends. Solder the red wire to the voltage input (Vin), and the remaining wires to the Xout (Arduino pin 14), Yout (pin 15), and Zout (pin 16) connectors. (If you wire yours differently, you’ll have to make minor changes to the Arduino code.)

Mount the Hardware

With everything wired up, you could go ahead and mount all the components to your car body, but then you’ll be jinxing things (I never screw a PC case cover on until after I’m certain everything works, otherwise I know I’ll just be taking it off again to troubleshoot). We used the #2 screws to mount everything but the Teensy Arduino board. Add nylon spacers under components as needed to ensure there’s enough space to route wires between components without pinching.

There aren’t any mounting holes on the Teensy, but the ribbon cable pretty much holds the board in place. You could use brads or even hot glue, but that didn’t seem to be necessary.

I used epoxy to hold the battery securely in its cavity in the bottom of the car. You could use double-sided tape, velcro, or even duct tape; I went for the permanent solution so I would never have to worry about it falling out in a crash.

NOTE: Once the battery is epoxied in there, it’s not coming out without destroying the car, so plan carefully.

Set up the Arduino

In order to program an Arduino board, you need to use the free Arduino IDE. The Teensy board I used for this project requires some extra software, Teensyduino and the Teensy Loader, in order to be able to download applications onto the board. Unfortunately, as I write this, the latest version of the Teensy Loader is not compatible with the latest version of the Arduino IDE; it can only work with Arduino IDE version 1.06. So, point your browser of choice to http://arduino.cc/en/Main/OldSoftwareReleases then download and install Arduino IDE version 1.06.

1. Install Teensyduino

Now install Teensyduino from https://www.pjrc.com/teensy/teensyduino.html to enable the IDE to see the Teensy board. Next, download and install the latest version of the Teensy Loader from https://www.pjrc.com/teensy/loader.html.

With all the software installed, open the Arduino IDE. First you’ll configure the IDE so it knows what board you’re working with. Open the Tools→Board menu and select the appropriate Teensy board as shown in Figure 14.

Figure 14. Configuring the Arduino IDE for the Teensy board.
Figure 14. Configuring the Arduino IDE for the Teensy board.

Now you’ll tell the IDE how to communicate with the board. Open the Tools menu again and make sure USB Type: Serial is selected as shown in Figure 15.

Figure 15. Configuring the Arduino IDE for serial connection.
Figure 15. Configuring the Arduino IDE for serial connection.

With the software in place, download this project’s code from https://github.com/johnwargo/Arduino-Pinewood-Derby. Go back to the Arduino IDE, select File→Open, and open the downloaded project file, called pinewood1.ino.

2. Connect to Teensy

Connect a USB cable from your computer to the micro USB jack on the Arduino board (shown in Figure 9).

Figure 16. Arduino IDE and Teensy Loader.
Figure 16. Arduino IDE and Teensy Loader.

Now compile the project code and upload it to the Teensy board. You can do this by clicking the checkmark button (Verify) in the upper left corner of Figure 16, then clicking the right arrow button (Upload) to the right of the checkmark button.

When you do this, the Teensy Loader window will open (Figure 16). The first time you to this, you’ll need to press the small black button on your Teensy board to reset the board and initialize the loader. Once you’ve done that, the code should upload to the board every time you click the deploy button in the IDE.

If everything went well with your assembly, the LEDs should start blinking away!

DSC_0044
DSC_0024

Set the car flat, then tip it forward and back, and side to side, to see the different light patterns. You can customize these patterns by tweaking the project code – read the next section to see how it all works.

NOTE: If you wired the LEDs or the accelerometer into different pins, you’ll need to change the code before you can run the application. Read the next section for a detailed analysis of the application code and what you’ll need to change.

The Arduino Code

Let’s walk through the project’s Arduino source code so you can understand exactly how it works. Again, the project code can be found at https://github.com/johnwargo/Arduino-Pinewood-Derby.

1. Define Constants

The code starts by defining some constants used by the application:

//Number of lights the car has
const int numLights = 10;
//====================================================
// Constants used to define the accelerometer input
// pins
//====================================================
const int xPin = 14;
const int yPin = 15;
const int zPin = 16;
//====================================================
// Constants used to identify the device's orientation
//====================================================
const int IS_FLAT = 0;
const int IS_LEFT = 1;
const int IS_RIGHT = 2;
const int IS_SLANT = 3;
//====================================================
// Orientation thresholds
//====================================================
const int T_RIGHT = 400;
const int T_LEFT = 525;
const int T_SLANT = 470;
int blueLights[4] = {0,4,5,9};
int orangeLights[2] = {2,7};
int yellowLights[4] = {1,3,6,8};
int i = 0;

The numLights constant is used to manage the process of looping through all of the lights. Whenever the application needs to do something to all of the lights, to turn them all on or all off for example, you’ll see something like this:

for (i = 0; i < numLights; i++) {
//do something here
}

For my code, I wired the LEDs to the Arduino’s digital output pins beginning with pin 0, this is what allows me to easily loop through all of the lights using this code. It’s important that the lights are wired sequentially beginning with pin 0, as shown in Figure 12, in order for this code to work. If you wired the lights to a different starting pin, you’ll need to change the affected for loops everywhere so that the loop begins with the first digital output pin you used.

In order to make the code more readable, I defined constants for each of the accelerometer inputs:

// Constants used to define the accelerometer input
// pins
//====================================================
const int xPin = 14;
const int yPin = 15;
const int zPin = 16;

If you connected the accelerometer Xout, Yout, or Zout pins differently than is described earlier in this article, you’ll need to change the values here to align with how your device is wired.

I defined constants for the different orientations the application will react to:

//====================================================
// Constants used to identify the device's orientation
//====================================================
const int IS_FLAT = 0;
const int IS_LEFT = 1;
const int IS_RIGHT = 2;
const int IS_SLANT = 3;

This makes the code a little more readable and allowed me to implement a simple switch statement to branch on the different orientations.

As I tweaked the car so that the program could react to different orientation thresholds, I defined the threshold values as constants at thebeginning of the application so that I wouldn’t have to hunt for them when I needed to make changes.

//====================================================
// Orientation thresholds
//====================================================
const int T_RIGHT = 400;
const int T_LEFT = 525;
const int T_SLANT = 470;

Change the values here to affect what accelerometer reading switches the car from flat mode to left, right or slant mode.

I also defined arrays for each of the light groupings (blue, yellow, and orange) so that the application would have an easy way to affect all lights of the same color simultaneously:

int blueLights[4] = {0,4,5,9};
int orangeLights[2] = {2,7};
int yellowLights[4] = {1,3,6,8};

When you look later in the code, you’ll see that I made separate functions for affecting each light grouping. I know I could just pass an array to a function and have the function affect all lights defined by the array, but I was trying to keep the code simple for my son and not try to get into array passing (which seems to be challenging to do in Arduino C).

2. The Code

With all of the application’s constants defined, it’s time to jump into the code.

The setup function initializes the application and the car’s hardware:

void setup() {
//Set all of the pins to output mode
for (i = 0; i < numLights; i++) {
pinMode(i, OUTPUT);
}
//make sure all of the lights are off
doAll(LOW);
//Grab the initial value off of the accelerometer
//this will be disgarded. Eliminates a quick light
//lighting issue when the device is first turned on
int tempInt = getOrientation();
//Do a short delay before doing anything else
delay(500);
//Flash all of the lights (twice)
doBlinkBlink();
}

The code starts by setting all of the pins used by the LEDs to OUTPUT mode. These statements instruct the Arduino on how to deal with those 10 pins.

Next the application calls a simple function called doAll to make sure that the output voltage for all of the LED pins is LOW (0). I found that the Teensy board automatically turned one of the pins on, so I had to add this call to setup to make sure that the car started with all lights off.

Another thing I noticed is that the accelerometer would sometimes start with rogue values for the X, Y, and/or Z axes, so during setup I had the application read all initial values from the accelerometer then discard them. If I didn’t do this, the car would often start by displaying one of the light patterns when in reality the car was sitting flat.

Just for fun, I then had the code wait for half a second (500 milliseconds) then flash the lights twice to get everyone’s attention before doing its light thing.

After setup executes, the Arduino will repeatedly execute the loop function. Anything the car needs to do has to be coded here:

void loop() {
//make sure all of the lights are off
doAll(LOW);
//Read the accelerometer
int orientation = getOrientation();
//Now do something based on the orientation
switch (orientation) {
case IS_LEFT:
doAllRight(100);
break;
case IS_RIGHT:
doAllLeft(100);
break;
case IS_FLAT:
doCycle(125);
break;
case IS_SLANT:
doBlend(75);
break;
default:
//This should never execute
//make sure all of the lights are off
doAll(LOW);
}
}

The function first sets all lights to off, something I probably didn’t need to do, but I learned a long time ago never to assume any state within an application. Next, the code reads the accelerometer then fires off a function to blink the lights in a certain pattern depending on the car’s orientation. If you want to make your own patterns, simply code the function that implements it and change the loop function so your function (or functions) are called when the car is in a particular orientation.

You can also add additional orientations by adding the appropriate constants at the beginning of the code, add the appropriate case statement to the loop function and modify the getOrientation function (described below) so it can determine the orientation you want the car to react to.

In the application’s getOrientation function, the code reads the accelerometer then uses the different threshold constants to determine the car’s current orientation:

int getOrientation(){
int x = analogRead(xPin);
int y = analogRead(yPin);
int z = analogRead(zPin);
//Are we flat in the X direction?
if (y > T_SLANT) {
//Are we on our right side?
if (x < T_RIGHT) {
return IS_RIGHT;
}
//Are we on our left side?
else if (x > T_LEFT) {
return IS_LEFT;
}
else {
//We must be flat
return IS_FLAT;
}
}
else {
//We're slanted
return IS_SLANT;
}
}

The code compares X or Y accelerometer values to determine whether any of the thresholds have been crossed then returns the appropriate constant to the loop function so it can execute the appropriate function based on the orientation. I could have put all of this code into the loop function, but that would have complicated things and made it harder to read. It was easier to demonstrate the code’s functions in smaller chunks so my son could more easily understand what was going on.

How did I know what threshold values to use? When I had everything wired up and working, I wrote some code that simply output the accelerometer values back to the Arduino IDE. In the setup function, I added the following code:

Serial.begin(9600);

This told the application to open the serial port for output. Next, in my getOrientation function I added code that outputted the axis and value using the following:

Serial.print("X: ");
Serial.println(x);
Serial.print("Y: ");
Serial.println(y);
Serial.print("Z: ");
Serial.println(z);

I then moved the car around and watched the different values on the screen. That’s how I was able to determine which accelerometer value (xy, or z) was being affected and what threshold value to use. Once I had all the numbers I needed, I removed that code and was all ready to go.

That’s it; at this point, the car knows how to turn the lights on/off and is able to determine its orientation via the accelerometer. All that’s left is to fire the lights.

To simplify things, I made some helper functions I could use different ways in the code. The setLightStatus allows me to set a range of lights to a particular state (on or off). In the following example, I’m setting lights 5 through 9 to on (HIGH):

setLightStatus(5, 10, HIGH);
//====================================================
// Turn on/off a range of lights
//====================================================
void setLightStatus(int theStart, int theEnd, int theStatus) {
for (i = theStart; i < theEnd; i++) {
digitalWrite(i, theStatus);
}
}

As described previously, I can affect all lights using:

doAll(LOW); //turns all lights off
doAll(HIGH); //turns all lights on
//====================================================
// Turn on/off all of the lights
//====================================================
void doAll(int status){
setLightStatus(0, 10, status);
}

When the application first runs, it blinks all of the lights twice using:

//====================================================
// Flash all of the lights twice
//====================================================
void doBlinkBlink(){
doAll(HIGH);
delay(200);
doAll(LOW);
delay(100);
doAll(HIGH);
delay(200);
doAll(LOW);
}

This is, I know, very low tech, but it was a nice simple example for my son to comprehend.

When the car is flat on a surface, it cycles through all of its lights in sequence using:

//====================================================
// Loop through the lights
// timeDel controls how long the each light stays on
//====================================================
void doCycle(int timeDel){
for (i = 0; i < numLights; i++) {
//Loop through all of the pins and turn the light on
digitalWrite(i, HIGH);
//Then wait for timeDel miliseconds
delay(timeDel);
//Then turn the light off
digitalWrite(i, LOW);
}
}

This is an example of where starting my digital output pins at pin 0 allowed me to create a simple for loop to process all lights in sequence. In this function, I pass in a timeDel variable that tells the function how long to keep each light on (in milliseconds). You could modify this so that the light spends an equal amount of time off by adding another delay after turning the light off.

I made separate functions for turning each light group on:

//====================================================
// Turn on all of the Blue lights
// then wait a little bit
//====================================================
void doAllBlue(int timeDel){
for (i = 0; i < 4; i++) {
digitalWrite(blueLights[i], HIGH);
}
delay(timeDel);
}

//====================================================
// Turn on all of the Orange lights
// then wait a little bit
//====================================================
void doAllOrange(int timeDel){
for (i = 0; i < 2; i++) {
digitalWrite(orangeLights[i], HIGH);
}
delay(timeDel);
}

//====================================================
// Turn on all of the Yellow lights
// then wait a little bit
//====================================================
void doAllYellow(int timeDel){
for (i = 0; i < 4; i++) {
digitalWrite(yellowLights[i], HIGH);
}
delay(timeDel);
}

Then I cycled through each light group using the following:

//====================================================
// Light the lights in bands, blue first, then
// yellow, to orange and back again.
//====================================================
void doBlend(int timeDel){
doAllBlue(timeDel);
doAll(LOW);
doAllYellow(timeDel);
doAll(LOW);
doAllOrange(timeDel);
doAll(LOW);
doAllYellow(timeDel);
doAll(LOW);
doAllBlue(timeDel);
}

This code lights each light group for a certain amount of time (passed in the timeDel variable): Blue then yellow, then orange, then yellow, and finally blue again. This is the frenetic pattern I used when the car is sitting in the starting gate.

Going Further

The cool thing about this project is that there’s so much more that you can do with it. You can make your own light patterns and pair the electronics with the fanciest (or simplest) car your imagination can come up with.

You can use an accelerometer and/or gyroscope to determine whether the car is in motion – since my son and were just getting into this, I focused on orientation rather than motion. A cool enhancement would be to flash the lights in an even more frenetic pattern while the car is in motion.

I’m sure you can write much cleaner and more concise C code for your project. What I did here was more for educating my son than showing how well I can write code.

I’d like to maintain a public gallery of the different cars you create from this article, so when you have your car running, share it in the Comments below, and send me a tweet with a picture or video link to @johnwargo and I’ll publish them somewhere.