You are viewing an older revision! See the latest version
XBee Wireless Scoreboard
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
Push Home button
Now 1-0
Push Home button 10 more times and Away button 3 times
Now 11-3
Push Reset button
Back to 0-0
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 }
