You are on page 1of 11

W HAT Y OU N EED

133

– — ™

š

˜

Figure 6.1: All the parts you need in this chapter

6.1 What You Need
1. A half-size breadboard or—even better—an Arduino Prototyping shield with a tiny breadboard 2. An ADXL335 accelerometer 3. A pushbutton 4. A 10kΩ resistor 5. Some wires 6. An Arduino board such as the Uno, Duemilanove, or Diecimila 7. A USB cable to connect the Arduino to your computer 8. A 6 pin 0.1" standard header

Report erratum

Download from Wow! eBook <www.wowebook.com>

this copy is (P1.0 printing, Janurary, 2011)

2: An ADXL335 sensor on a breakout board 6.analog. Z. you see a 6 pin 0. This not only makes it easier to attach the sensor to a breadboard but also stabilizes the sensor. we will have a quick look at the sensor’s specification and interpret the data. The sensor is the small black integrated circuit (IC).0 printing.wowebook.2. X. To use the sensor on a breadboard. you see a breakout board containing an ADXL335 sensor on the right. http://www. The sensor has six connectors labeled GND.1 In this section.com> this copy is (P1.W IRING U P THE A CCELEROMETER 134 Figure 6. so it 1. At that point. Y.2 Wiring Up the Accelerometer There are many different accelerometers. Janurary. differing mainly in the number of spacial axes they support (usually two or three). 3V. On the top. and TEST. 2011) . we’ll connect the ADXL335 to the Arduino and create a small demo program showing the raw data the sensor delivers. and the rest is just a carrier to allow connections.com/en/sensors/inertial-sensors/adxl335/products/product. In Figure 6.1" standard header.html Report erratum Download from Wow! eBook <www. solder the standard header to the connectors. We use the ADXL335 from Analog Devices—it’s easy to use and widely available.

Don’t worry if you’ve never soldered before. Learning How to Solder . let’s use it. X. and X to analog pin 2 (see Figure 6. and Z connectors have to be connected to three analog pins on the Arduino.3 Bringing Your Accelerometer to Life A pragmatic strategy to get familiar with a new device is to hook it up and see what data it delivers.begin(BAUD_RATE).3 volts power supply.println(analogRead(Z_AXIS_PIN)). void setup() { Serial.print(analogRead(X_AXIS_PIN)). the X.B RINGING Y OUR A CCELEROMETER TO L IFE 135 does not move accidentally. We connect Z to analog pin 0. on the following page. Increasing Precision Using a Temperature Sensor . } void loop() { Serial.0 printing. 6. on page 113. and the meaning of the remaining connectors should be obvious. } Report erratum Download from Wow! eBook <www. In Section A. Serial. BAUD_RATE = 9600. So. delay(100). Y_AXIS_PIN = 1. The following program reads input values for all three axes and outputs them to the serial port: Download MotionSensor/SensorTest/SensorTest.com> this copy is (P1. Z_AXIS_PIN = 0. 2011) . You can see the result on the left side of the photo (note that the breakout board on the left is not the same as on the right. Y to analog pin 1. Y.3. the ADXL335 is an analog device: it delivers results as voltages that have to be converted into acceleration values.4.2.pde const const const const unsigned unsigned unsigned unsigned int int int int X_AXIS_PIN = 2. Serial. Now that we’ve connected the ADXL335 to the Arduino. To power the sensor. Like the TMP36 temperature sensor we used in Section 5.wowebook.print(" "). but it’s very similar). and Z will then deliver acceleration data for the x-. Serial. Janurary. Y. You can ignore the connector labeled TEST. on page 241.print(analogRead(Y_AXIS_PIN)). and double-check the pin labels on the breakout board you’re using!). y-. connect GND to the Arduino’s ground pin and 3V to the Arduino’s 3. you can learn how to do it. Serial.print(" "). and z-axes.

Janurary. because that’s the default anyway.wowebook. 2011) . Open the serial monitor.0 printing.com> this copy is (P1. Note that we did not set the analog pins to INPUT explicitly.3: How to connect an ADXL335 sensor to an Arduino Our test program is as simple as it can be. and move the sensor around a bit—tilt it around the different axes. We define constants for the three analog pins and initialize the serial port in the setup( ) function. In the loop( ) function. we constantly output the values we read from the analog pins to the serial port.B RINGING Y OUR A CCELEROMETER TO L IFE 136 Figure 6. You should see an output similar to the following: 344 364 388 398 376 370 379 331 276 286 314 332 336 338 390 352 287 286 289 301 281 Report erratum Download from Wow! eBook <www.

print("/"). 2011) .pde const const const const unsigned unsigned unsigned unsigned int int int int X_AXIS_PIN = 2. min_y = min(y. int min_x. Serial. we’ll take a closer look at these values. min_z).print("x("). min_x = min(x. min_y). and z-axes. Y_AXIS_PIN = 1.wowebook. z = analogRead(Z_AXIS_PIN). In the next section. max_y = max(y. max_y. or they might not change their output values correctly. Serial. max_y). and accelerometers are no exception.0 printing.print(min_x). max_x = max(x. and we’ll flatten the jitter. min_x). min_z = min(z. Report erratum Download from Wow! eBook <www. Z_AXIS_PIN = 0. Janurary. Serial. Here’s a program that does the job: Download MotionSensor/SensorValues/SensorValues.F INDING AND P OLISHING E DGE VALUES 137 These values represent the data we get for the x-. min_x = min_y = min_z = 1000. They might change their output values even though you haven’t moved them. y-. } void loop() const int const int const int { x = analogRead(X_AXIS_PIN). y = analogRead(Y_AXIS_PIN). and they often jitter a bit. you can see that the first value changes accordingly. void setup() { Serial. int max_x. You have to constantly read the sensor’s output while moving it. They slightly vary in the minimum and maximum values they generate.com> this copy is (P1. max_z). we’ll determine the sensor’s minimum and maximum values. When you move the sensor only around the x-axis. for example. but it cannot be easily automated. max_z. BAUD_RATE = 9600.print(max_x). min_z. min_y. max_x). Finding the edge values of the sensor is easy.begin(BAUD_RATE). In this section. 6. Serial. That’s especially true for the data many sensors emit. max_z = max(z. max_x = max_y = max_z = -1000.4 Finding and Polishing Edge Values The physical world often is far from being perfect.

Serial. Serial. 2011) .print(min_y). because we need them later.print("). Serial.println(")"). then move the breadboard with the sensor in all directions. tilt it slowly. const unsigned int BUFFER_SIZE = 16.pde Line 1 5 10 - const unsigned int X_AXIS_PIN = 2. Serial. y(253/647).0 printing. } 138 We declare variables for the minimum and maximum values of all three axes. small changes will be ironed out. Instead of returning the acceleration data immediately. z("). y("). In principle. we collect the last readings and return their average.wowebook.F INDING AND P OLISHING E DGE VALUES Serial. int buffer[NUM_AXES][BUFFER_SIZE]. and you should get output like this: x(247/649). Janurary.print(min_z). const unsigned int Y_AXIS_PIN = 1. Now let’s see how to get rid of the jitter. and then tilt it around all axes.print("/"). move it fast.com> this copy is (P1. Serial.print("/"). Move it slowly. Compile and upload the sketch. Serial. Serial. and you’ll probably need them when you do your own sensor experiments. we permanently measure the acceleration of all three axes and adjust the minimum and maximum values accordingly. This way.print(max_z). const unsigned int NUM_AXES = 3. and tilt it fast. const unsigned int Z_AXIS_PIN = 0. and be careful when moving and rotating the breadboard so you do not accidentally loosen a connection.print(max_y). and we initialize them with numbers that are definitely out of the sensor’s range (-1000 and 1000). const unsigned int PINS[NUM_AXES] = { X_AXIS_PIN. The code looks as follows: Download MotionSensor/Buffering/Buffering. Z_AXIS_PIN }. Report erratum Download from Wow! eBook <www. it is simple. After a short while the minimum and maximum values will stabilize. int buffer_pos[NUM_AXES] = { 0 }. In the loop( ) function. Use long wires. Serial. z(278/658) Write down these values.print("). const unsigned int BAUD_RATE = 9600. Y_AXIS_PIN.

Serial. so we can calculate average values when we need them. Serial. we return the average value of the data we have gathered so far for the current axis. we also define a constant named NUM_AXES that contains the amount of axes we are measuring. long sum = 0. and the real action takes place in the get_axis( ) function.0 printing. buffer[axis][buffer_pos[axis]] = analogRead(PINS[axis]). we define some constants for the pins we use first. we define an array of buffer positions. In line 11. This time. so in line 12. Serial.begin(BAUD_RATE). It increases the buffer position and sets it back to zero when the end of the buffer has been reached. you might get bad data. Report erratum Download from Wow! eBook <www. } int get_x() { return get_axis(0). buffer_pos[axis] = (buffer_pos[axis] + 1) % BUFFER_SIZE. Serial. We have to store our current position in each buffer.print(get_y()).com> this copy is (P1. } void loop() { Serial. return round(sum / BUFFER_SIZE).print(get_x()). } int get_axis(const int axis) { delay(1). Finally. otherwise. They will be filled with the sensor data we measure. Then it reads the acceleration for the axis we have passed and stores it at the current buffer position belonging to the axis. setup( ) only initializes the serial port.print(" "). } As usual.F INDING AND P OLISHING E DGE VALUES 139 15 20 25 30 35 - void setup() { Serial. This helps us keep our code more generic later. } int get_z() { return get_axis(2). It starts with a small delay to give the Arduino some time to switch between analog pins. for (int i = 0. i++) sum += buffer[axis][i].print(" "). i < BUFFER_SIZE. Janurary. } int get_y() { return get_axis(1). 2011) . We also have an array named PINS that contains a list of the pins we use. we declare buffers for all axes.wowebook.println(get_z()).

Janurary. Report erratum Download from Wow! eBook <www.4. you will quickly see small changes. 6. you can see how to do it (please. In Figure 6. leave the sensor untouched on your desk. They will disappear as soon as the buffer is big enough. The acceleration data we measure now is sufficiently accurate. To see its effect.5 Building Your Own Game Controller To build a full-blown game controller. and we can finally build a game controller that will not annoy users because of unexpected movements. If you do not touch the sensor. we only need to add a button to our breadboard.com> this copy is (P1.0 printing. you would not expect the program’s output to change. doublecheck the pin labels on your breakout board!).wowebook.4: Game controller with accelerometer and pushbutton That’s the whole trick. and run the program with different buffer sizes. But if you set BUFFER_SIZE to 1. 2011) .B UILDING Y OUR O WN G AME C ONTROLLER 140 Figure 6.

Shields are a great way to enhance an Arduino’s capabilities. Janurary. Neat. but we still should think about ergonomics for a moment.6. and you can get shields for many different purposes such as adding Ethernet. Our current breadboard solution is rather fragile. and so on.5).0 printing.2 Using the Proto Shield our game controller looks as in Figure 6. The breadboard is surrounded by the Arduino’s pins. Sooner or later you will disconnect some wires. so you no longer need long wires. eh? 2. you could try to attach the breadboard to the Arduino using some rubber bands.5: An Arduino prototyping shield That’s how it looks inside a typical modern game controller. and you cannot really wave around the board when it’s connected to the Arduino.com> this copy is (P1. It is a pluggable breadboard that lets you quickly build circuit prototypes.B UILDING Y OUR O WN G AME C ONTROLLER 141 Figure 6. That works. A much better solution is to use an Arduino Prototyping shield (see Figure 6. To solve this problem. sound. and the controller will stop working. on the next page. displays.wowebook. you find a comprehensive list of Arduino shields. 2011) . We will not build a fancy housing for the controller. and it’s still hard to handle. Report erratum Download from Wow! eBook <www. but it does not look very pretty. At http://shieldlist.org/.

void setup() { Serial. It supports the button we have added.pde #include <Bounce.6: The complete game controller on a Proto shield Now that the hardware is complete. and it performs the anti-jittering we have created in Section 6. const unsigned int Y_AXIS_PIN = 1. Y_AXIS_PIN. int buffer_pos[NUM_AXES] = { 0 }. INPUT). const unsigned int X_AXIS_PIN = 2. const unsigned int PINS[NUM_AXES] = { X_AXIS_PIN. const unsigned int BUFFER_SIZE = 16.B UILDING Y OUR O WN G AME C ONTROLLER 142 Figure 6. Janurary.4. const unsigned int BAUD_RATE = 19200. on page 137: Download MotionSensor/Controller/Controller. const unsigned int Z_AXIS_PIN = 0. Z_AXIS_PIN }. } Report erratum Download from Wow! eBook <www. const unsigned int NUM_AXES = 3. we need a final version of the game controller software. 2011) . Bounce button(BUTTON_PIN. 20).wowebook. int buffer[NUM_AXES][BUFFER_SIZE]. pinMode(BUTTON_PIN.begin(BAUD_RATE).0 printing.h> const unsigned int BUTTON_PIN = 7.com> this copy is (P1. Finding and Polishing Edge Values.

Compile and upload the code.print(" "). The rest of the code is pretty much standard. Janurary. but wouldn’t it be even nicer if we also had a game that supports it? That’s what we will build in the next section. } int get_y() { return get_axis(1). on page 80. } As in Section 3.println("0").print(get_x()). } void loop() { Serial. } int get_x() { return get_axis(0). Serial.wowebook.println(button.print(" "). buffer_pos[axis] = (buffer_pos[axis] + 1) % BUFFER_SIZE.B UILDING Y OUR O WN G AME C ONTROLLER 143 int get_axis(const int axis) { delay(1). if (button.update()) Serial. for (int i = 0. we use the Bounce class to debounce the button. and it should output something like the following: 324 325 325 325 325 325 326 365 364 364 364 365 365 364 396 397 397 397 397 397 397 0 0 1 0 0 1 0 A homemade game controller is nice. Move it. else Serial.print(" "). } int get_z() { return get_axis(2).print(get_z()). open the serial terminal.read() == HIGH ? "1" : "0").com> this copy is (P1.print(get_y()). Serial. Serial. long sum = 0. Report erratum Download from Wow! eBook <www. Serial. press the button sometimes. i++) sum += buffer[axis][i]. return round(sum / BUFFER_SIZE). and play around with the controller. and the only thing worth mentioning is that we use a 19200 baud rate to transfer the controller data sufficiently fast. Building a Dice Game .7. buffer[axis][buffer_pos[axis]] = analogRead(PINS[axis]). Serial.0 printing. 2011) . i < BUFFER_SIZE.