mbed USB Slingshot code

Dependencies:   mbed ADXL345

Committer:
simon
Date:
Sun Feb 26 02:51:40 2012 +0000
Revision:
0:6fef570fcbc4
Lots of cleanup, simpler logic

Who changed what in which revision?

UserRevisionLine numberNew contents of line
simon 0:6fef570fcbc4 1 /* mbed USB Slingshot,
simon 0:6fef570fcbc4 2 *
simon 0:6fef570fcbc4 3 * Copyright (c) 2010-2011 mbed.org, MIT License
simon 0:6fef570fcbc4 4 *
simon 0:6fef570fcbc4 5 * smokrani, sford
simon 0:6fef570fcbc4 6 *
simon 0:6fef570fcbc4 7 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
simon 0:6fef570fcbc4 8 * and associated documentation files (the "Software"), to deal in the Software without
simon 0:6fef570fcbc4 9 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
simon 0:6fef570fcbc4 10 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
simon 0:6fef570fcbc4 11 * Software is furnished to do so, subject to the following conditions:
simon 0:6fef570fcbc4 12 *
simon 0:6fef570fcbc4 13 * The above copyright notice and this permission notice shall be included in all copies or
simon 0:6fef570fcbc4 14 * substantial portions of the Software.
simon 0:6fef570fcbc4 15 *
simon 0:6fef570fcbc4 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
simon 0:6fef570fcbc4 17 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
simon 0:6fef570fcbc4 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
simon 0:6fef570fcbc4 19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
simon 0:6fef570fcbc4 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
simon 0:6fef570fcbc4 21 */
simon 0:6fef570fcbc4 22
simon 0:6fef570fcbc4 23 #include "mbed.h"
simon 0:6fef570fcbc4 24 #include "USBMouse.h"
simon 0:6fef570fcbc4 25 #include "ADXL345.h"
simon 0:6fef570fcbc4 26
simon 0:6fef570fcbc4 27 // Physical interfaces
simon 0:6fef570fcbc4 28 USBMouse mouse;
simon 0:6fef570fcbc4 29 ADXL345 accelerometer(p5, p6, p7, p8);
simon 0:6fef570fcbc4 30 AnalogIn stretch_sensor(p15);
simon 0:6fef570fcbc4 31 BusOut leds(LED1, LED2, LED3, LED4);
simon 0:6fef570fcbc4 32
simon 0:6fef570fcbc4 33 // Return slingshot angle in radians, up > 0 > down
simon 0:6fef570fcbc4 34 float get_angle() {
simon 0:6fef570fcbc4 35 int readings[3];
simon 0:6fef570fcbc4 36 accelerometer.getOutput(readings);
simon 0:6fef570fcbc4 37 float x = (int16_t)readings[0];
simon 0:6fef570fcbc4 38 float z = (int16_t)readings[2];
simon 0:6fef570fcbc4 39 return atan(z / x);
simon 0:6fef570fcbc4 40 }
simon 0:6fef570fcbc4 41
simon 0:6fef570fcbc4 42 // Return normalised stretch value based on bounds of all readings seen
simon 0:6fef570fcbc4 43 float get_stretch() {
simon 0:6fef570fcbc4 44 static float min_strength = 0.7;
simon 0:6fef570fcbc4 45 static float max_strength = 0.7;
simon 0:6fef570fcbc4 46 float current_strength = stretch_sensor.read();
simon 0:6fef570fcbc4 47 if(current_strength > max_strength) { max_strength = current_strength; }
simon 0:6fef570fcbc4 48 if(current_strength < min_strength) { min_strength = current_strength; }
simon 0:6fef570fcbc4 49 float stretch = (current_strength - min_strength) / (max_strength - min_strength);
simon 0:6fef570fcbc4 50 return 1.0 - stretch;
simon 0:6fef570fcbc4 51 }
simon 0:6fef570fcbc4 52
simon 0:6fef570fcbc4 53 // move mouse to a location relative to the start point, stepping as needed
simon 0:6fef570fcbc4 54 void move_mouse(int x, int y) {
simon 0:6fef570fcbc4 55 const int STEP = 10;
simon 0:6fef570fcbc4 56 static int current_x = 0;
simon 0:6fef570fcbc4 57 static int current_y = 0;
simon 0:6fef570fcbc4 58
simon 0:6fef570fcbc4 59 int move_x = x - current_x;
simon 0:6fef570fcbc4 60 int move_y = y - current_y;
simon 0:6fef570fcbc4 61
simon 0:6fef570fcbc4 62 // Move the mouse, in steps of max step size to ensure it is picked up by OS
simon 0:6fef570fcbc4 63 while(move_x > STEP) { mouse.move(STEP, 0); move_x -= STEP; }
simon 0:6fef570fcbc4 64 while(move_x < -STEP) { mouse.move(-STEP, 0); move_x += STEP; }
simon 0:6fef570fcbc4 65 while(move_y > STEP) { mouse.move(0, STEP); move_y -= STEP; }
simon 0:6fef570fcbc4 66 while(move_y < -STEP) { mouse.move(0, -STEP); move_y += STEP; }
simon 0:6fef570fcbc4 67 mouse.move(move_x, move_y);
simon 0:6fef570fcbc4 68
simon 0:6fef570fcbc4 69 current_x = x;
simon 0:6fef570fcbc4 70 current_y = y;
simon 0:6fef570fcbc4 71 }
simon 0:6fef570fcbc4 72
simon 0:6fef570fcbc4 73 template <class T>
simon 0:6fef570fcbc4 74 T filter(T* array, int len, T value) {
simon 0:6fef570fcbc4 75 T mean = 0.0;
simon 0:6fef570fcbc4 76 for(int i = 0; i<len - 1; i++) {
simon 0:6fef570fcbc4 77 mean += array[i + 1];
simon 0:6fef570fcbc4 78 array[i] = array[i + 1];
simon 0:6fef570fcbc4 79 }
simon 0:6fef570fcbc4 80 mean += value;
simon 0:6fef570fcbc4 81 array[len - 1] = value;
simon 0:6fef570fcbc4 82 return mean / (T)len;
simon 0:6fef570fcbc4 83 }
simon 0:6fef570fcbc4 84
simon 0:6fef570fcbc4 85 typedef enum {
simon 0:6fef570fcbc4 86 WAITING = 2,
simon 0:6fef570fcbc4 87 AIMING = 4,
simon 0:6fef570fcbc4 88 FIRING = 8
simon 0:6fef570fcbc4 89 } state_t;
simon 0:6fef570fcbc4 90
simon 0:6fef570fcbc4 91 int main() {
simon 0:6fef570fcbc4 92 leds = 1;
simon 0:6fef570fcbc4 93
simon 0:6fef570fcbc4 94 // setup accelerometer
simon 0:6fef570fcbc4 95 accelerometer.setPowerControl(0x00);
simon 0:6fef570fcbc4 96 accelerometer.setDataFormatControl(0x0B);
simon 0:6fef570fcbc4 97 accelerometer.setDataRate(ADXL345_3200HZ);
simon 0:6fef570fcbc4 98 accelerometer.setPowerControl(0x08);
simon 0:6fef570fcbc4 99
simon 0:6fef570fcbc4 100 state_t state = WAITING;
simon 0:6fef570fcbc4 101 Timer timer;
simon 0:6fef570fcbc4 102
simon 0:6fef570fcbc4 103 float angles[8] = {0};
simon 0:6fef570fcbc4 104 float stretches[8] = {0};
simon 0:6fef570fcbc4 105
simon 0:6fef570fcbc4 106 while(1) {
simon 0:6fef570fcbc4 107
simon 0:6fef570fcbc4 108 // get the slingshot parameters
simon 0:6fef570fcbc4 109 float this_stretch = get_stretch();
simon 0:6fef570fcbc4 110 float this_angle = get_angle();
simon 0:6fef570fcbc4 111
simon 0:6fef570fcbc4 112 // apply some filtering
simon 0:6fef570fcbc4 113 float stretch = filter(stretches, 8, this_stretch);
simon 0:6fef570fcbc4 114 float angle = filter(angles, 8, this_angle);
simon 0:6fef570fcbc4 115
simon 0:6fef570fcbc4 116 leds = state;
simon 0:6fef570fcbc4 117
simon 0:6fef570fcbc4 118 // act based on the current state
simon 0:6fef570fcbc4 119 switch (state) {
simon 0:6fef570fcbc4 120 case WAITING:
simon 0:6fef570fcbc4 121 if(stretch > 0.5) { // significant stretch, considered starting
simon 0:6fef570fcbc4 122 mouse.press(MOUSE_LEFT);
simon 0:6fef570fcbc4 123 state = AIMING;
simon 0:6fef570fcbc4 124 }
simon 0:6fef570fcbc4 125 break;
simon 0:6fef570fcbc4 126
simon 0:6fef570fcbc4 127 case AIMING:
simon 0:6fef570fcbc4 128 if(stretch - this_stretch > 0.1) { // rapid de-stretch, considered a fire
simon 0:6fef570fcbc4 129 mouse.release(MOUSE_LEFT);
simon 0:6fef570fcbc4 130 move_mouse(0, 0);
simon 0:6fef570fcbc4 131 timer.start();
simon 0:6fef570fcbc4 132 state = FIRING;
simon 0:6fef570fcbc4 133 } else {
simon 0:6fef570fcbc4 134 int x = 0.0 - cos(angle) * stretch * 200;
simon 0:6fef570fcbc4 135 int y = sin(angle) * stretch * 200;
simon 0:6fef570fcbc4 136 move_mouse(x, y);
simon 0:6fef570fcbc4 137 }
simon 0:6fef570fcbc4 138 break;
simon 0:6fef570fcbc4 139
simon 0:6fef570fcbc4 140 case FIRING:
simon 0:6fef570fcbc4 141 if(timer > 3.0) {
simon 0:6fef570fcbc4 142 timer.stop();
simon 0:6fef570fcbc4 143 timer.reset();
simon 0:6fef570fcbc4 144 state = WAITING;
simon 0:6fef570fcbc4 145 }
simon 0:6fef570fcbc4 146 break;
simon 0:6fef570fcbc4 147 };
simon 0:6fef570fcbc4 148
simon 0:6fef570fcbc4 149 wait(0.01);
simon 0:6fef570fcbc4 150 }
simon 0:6fef570fcbc4 151 }