Slingshot Controller

Dependencies:   ADXL345 DebounceIn USBDevice mbed

Committer:
Brandon
Date:
Sun Oct 14 18:58:38 2012 +0000
Revision:
0:cf17ea89fd09
Child:
1:2721dc2acc2c
lab3

Who changed what in which revision?

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