You are viewing an older revision! See the latest version

XBee Wireless Scoreboard

Table of Contents

  1. Overview
  2. Parts
  3. Software

by Jonathan Young, Digi International

Would you like to be able to keep tally of a score on a portable LCD screen with wireless pushbuttons? Then this is the project for you! This project uses an Arduino microcontroller, Mbed microcontroller, and a couple of Digi XBee radios.

Overview

Initially 0-0 /media/uploads/JonathanYoung22193/pic1.jpg

Push Home button /media/uploads/JonathanYoung22193/pic2.jpg

Now 1-0 /media/uploads/JonathanYoung22193/pic3.jpg

Push Home button 10 more times and Away button 3 times /media/uploads/JonathanYoung22193/pic4.jpg

Now 11-3 /media/uploads/JonathanYoung22193/pic5.jpg

Push Reset button /media/uploads/JonathanYoung22193/pic6.jpg

Back to 0-0 /media/uploads/JonathanYoung22193/pic7.jpg

Parts

  • Two solderless breadboards (MS MKKN2, AF 64, DK 438-1045-ND, SFE PRT-09567)
  • XBee radio (Series 2/ZB firmware) configured as a ZigBee Coordinator AT mode (Digi: XB24-27WIT-004, DK 602-1098-ND)
  • XBee radio (Series 2/ZB firmware) configured as a ZigBee Router AT mode (Digi: XB24-27WIT-004, DK 602-1098-ND)
  • One Arduino Uno board (MS MKSP4, SFE DEV-09950, AF 50)
  • Hookup wire or jumper wire kit (MS MKSEEED3, AF 153, DK 923351-ND, SFE PRT-00124)
  • USB A-to-B cable for Arduino (AF 62, DK 88732-9002, SFE CAB-00512)
  • XBee USB serial adapter (XBee Explorer or Digi Evaluation board) (AF 247, SFE WRL-08687)
  • Two XBee shields (Seeed Studio SLD01103P, Arduino A000065, SF WRL-10854)
  • Wire strippers (AF 147, DK PAL70057-ND, SFE TOL-08696)
  • One 16x2 character LCD display (with HD44780 parallel interface) (AF 181, DK 67-1758-ND, SFE LCD-00255)
  • One 10K ohm potentiometer (panel mount) (DK P3C3103-ND, RS 271-1715, SFE COM-09288)
  • Three 200 ohm resistor (DK P200BACT-ND)
  • 16-pin single-row male header (DK S1012E-36-ND, SFE PRT-00116)
  • Three momentary pushbutton switches (SPE COM-09190)
  • One Mbed Freedom board (Freescale FRDM-KL25Z)
  • Soldering tools (any hardware store)
  • An enthusiastic mind

Using the Arduino IDE

This project uses the Arduino software, known as the IDE, in order to program the Arduino Uno microcontroller. You can download it for free from the Arduino website software section at http://www.arduino.cc/en/Main/Software. There are many versions, so be sure to download the correct one. A basic guide to how to use it can be found at http://arduino.cc/en/Guide/HomePage

Using the Mbed Compiler

This project used the Mbed software, known as the online compiler, in order to program the Mbed microcontroller. You can sign up for a free account to access the online compiler at www.mbed.org. There are many versions of the Mbed, so make sure you select the correct platform. A basic guide to how to use it can be found at the same Mbed website.

Prepare and Configure your Coordinator Radio

1. Use X-CTU to set the designated coordinator radio in AT mode. 2. Configure the coordinator radio with a PAN ID (between 0x0 and 0xFFFFFFFFFFFFFFFF). Make sure you note this ID so that you can set up your router radio with the same one. 3. Enter in the High and Low destination addresses of your router radio.

Prepare and Configure your Router Radio

1. Use X-CTU to set the designated router radio in AT mode. 2. Configure the router radio with the PAN ID you set the coordinator radio with. 3. Set JV to 1 to ensure that your router attempts to rejoin the coordinator on startup. 4. Enter in the High and Low destination addresses of your coordinator radio.

The software to test the feasibility is kept simple; the objective is to observe all different elements of the project working together.

#include "mbed.h"
#include "USBMouse.h"
#include "ADXL345.h"
 
USBMouse mouse;
ADXL345 acc(p5, p6, p7, p8);
AnalogIn strength(p15);
 
int main() {
    //Initialize accelerometer
    acc.setPowerControl(0x00);
    acc.setDataFormatControl(0x0B);
    acc.setDataRate(ADXL345_3200HZ);
    acc.setPowerControl(0x08);
 
    while (1) {
        int readings[3];
        acc.getOutput(readings);        // test accelerometer
        printf("acc: %i, %i, %i\r\n", (int16_t)readings[0], (int16_t)readings[1], (int16_t)readings[2]);
 
        uint16_t str = strength.read_u16();        // test stretch sensor
        printf("strength: %d\r\n", str);
       
        mouse.move(10, 10);             // test USB relative mouse

        wait(0.1);
    }
}

Import programAngryBirdsFeasibility

Test Slingshot

Software

How does it all work ?

Import program

00001 /* mbed USB Slingshot, 
00002  *
00003  * Copyright (c) 2010-2011 mbed.org, MIT License
00004  * 
00005  * smokrani, sford
00006  *
00007  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00008  * and associated documentation files (the "Software"), to deal in the Software without
00009  * restriction, including without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
00011  * Software is furnished to do so, subject to the following conditions:
00012  * 
00013  *  The above copyright notice and this permission notice shall be included in all copies or
00014  * substantial portions of the Software.
00015  *
00016  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00017  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00018  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00019  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00020  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00021  */
00022 
00023 #include "mbed.h"
00024 #include "USBMouse.h"
00025 #include "ADXL345.h"
00026 
00027 // Physical interfaces
00028 USBMouse mouse;
00029 ADXL345 accelerometer(p5, p6, p7, p8);
00030 AnalogIn stretch_sensor(p15);
00031 BusOut leds(LED1, LED2, LED3, LED4);
00032 
00033 // Return slingshot angle in radians, up > 0 > down
00034 float get_angle() {
00035     int readings[3];
00036     accelerometer.getOutput(readings);
00037     float x = (int16_t)readings[0];
00038     float z = (int16_t)readings[2];
00039     return atan(z / x);    
00040 }
00041 
00042 // Return normalised stretch value based on bounds of all readings seen
00043 float get_stretch() {
00044     static float min_strength = 0.7;
00045     static float max_strength = 0.7;
00046     float current_strength = stretch_sensor.read();
00047     if(current_strength > max_strength) { max_strength = current_strength; }
00048     if(current_strength < min_strength) { min_strength = current_strength; }
00049     float stretch = (current_strength - min_strength) / (max_strength - min_strength);
00050     return 1.0 - stretch;
00051 }
00052 
00053 // move mouse to a location relative to the start point, stepping as needed
00054 void move_mouse(int x, int y) {
00055     const int STEP = 10;
00056     static int current_x = 0;
00057     static int current_y = 0;
00058     
00059     int move_x = x - current_x;
00060     int move_y = y - current_y; 
00061 
00062     // Move the mouse, in steps of max step size to ensure it is picked up by OS
00063     while(move_x > STEP) { mouse.move(STEP, 0); move_x -= STEP; }
00064     while(move_x < -STEP) { mouse.move(-STEP, 0); move_x += STEP; }
00065     while(move_y > STEP) { mouse.move(0, STEP); move_y -= STEP; }
00066     while(move_y < -STEP) { mouse.move(0, -STEP); move_y += STEP; }
00067     mouse.move(move_x, move_y);
00068     
00069     current_x = x;
00070     current_y = y;
00071 }
00072 
00073 template <class T>
00074 T filter(T* array, int len, T value) {
00075     T mean = 0.0;
00076     for(int i = 0; i<len - 1; i++) {
00077         mean += array[i + 1];
00078         array[i] = array[i + 1];
00079     }
00080     mean += value;
00081     array[len - 1] = value;
00082     return mean / (T)len;
00083 }
00084 
00085 typedef enum {
00086     WAITING = 2,
00087     AIMING = 4,
00088     FIRING = 8
00089 } state_t;
00090 
00091 int main() {
00092     leds = 1;
00093 
00094     // setup accelerometer
00095     accelerometer.setPowerControl(0x00);
00096     accelerometer.setDataFormatControl(0x0B);
00097     accelerometer.setDataRate(ADXL345_3200HZ);
00098     accelerometer.setPowerControl(0x08);
00099 
00100     state_t state = WAITING;    
00101     Timer timer;
00102 
00103     float angles[8] = {0};
00104     float stretches[8] = {0};
00105     
00106     while(1) {        
00107 
00108         // get the slingshot parameters
00109         float this_stretch = get_stretch();
00110         float this_angle = get_angle();
00111 
00112         // apply some filtering
00113         float stretch = filter(stretches, 8, this_stretch);
00114         float angle = filter(angles, 8, this_angle);
00115             
00116         leds = state;
00117                 
00118         // act based on the current state
00119         switch (state) {
00120             case WAITING:
00121                 if(stretch > 0.5) {             // significant stretch, considered starting 
00122                     mouse.press(MOUSE_LEFT);
00123                     state = AIMING;
00124                 }
00125                 break;
00126 
00127             case AIMING:
00128                 if(stretch - this_stretch > 0.1) { // rapid de-stretch, considered a fire
00129                     mouse.release(MOUSE_LEFT);
00130                     move_mouse(0, 0);
00131                     timer.start();
00132                     state = FIRING;
00133                 } else {
00134                     int x = 0.0 - cos(angle) * stretch * 200;
00135                     int y = sin(angle) * stretch * 200;
00136                     move_mouse(x, y);
00137                 }
00138                 break;
00139 
00140             case FIRING:
00141                 if(timer > 3.0) {
00142                     timer.stop();
00143                     timer.reset();
00144                     state = WAITING;
00145                 }        
00146                 break;
00147         };
00148         
00149         wait(0.01);
00150     }
00151 }

All wikipages