Slingshot Controller

Dependencies:   ADXL345 DebounceIn USBDevice mbed

Committer:
Brandon
Date:
Wed Oct 17 16:33:04 2012 +0000
Revision:
1:2721dc2acc2c
Parent:
0:cf17ea89fd09
Updated comments, added names, cleaned old code.

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 1:2721dc2acc2c 21
Brandon 1:2721dc2acc2c 22 Edited to use slider/pushbutton input instead of stretch sensor by Joshua Schrader and Brandon Yee, 2012
Brandon 1:2721dc2acc2c 23
Brandon 0:cf17ea89fd09 24 */
Brandon 0:cf17ea89fd09 25
Brandon 0:cf17ea89fd09 26 #include "DebounceIn.h"
Brandon 0:cf17ea89fd09 27 #include "mbed.h"
Brandon 0:cf17ea89fd09 28 #include "USBMouse.h"
Brandon 0:cf17ea89fd09 29 #include "ADXL345.h"
Brandon 0:cf17ea89fd09 30
Brandon 0:cf17ea89fd09 31 USBMouse mouse;
Brandon 0:cf17ea89fd09 32 ADXL345 accelerometer(p5, p6, p7, p8);
Brandon 0:cf17ea89fd09 33 AnalogIn stretch_sensor(p15);
Brandon 0:cf17ea89fd09 34 DebounceIn button(p13);
Brandon 0:cf17ea89fd09 35 float str;
Brandon 0:cf17ea89fd09 36 int push;
Brandon 0:cf17ea89fd09 37 BusOut leds(LED1, LED2, LED3, LED4);
Brandon 0:cf17ea89fd09 38
Brandon 0:cf17ea89fd09 39 // Return slingshot angle in radians, up > 0 > down
Brandon 0:cf17ea89fd09 40 float get_angle() {
Brandon 0:cf17ea89fd09 41 int readings[3];
Brandon 0:cf17ea89fd09 42 accelerometer.getOutput(readings);
Brandon 0:cf17ea89fd09 43 float x = (int16_t)readings[0];
Brandon 0:cf17ea89fd09 44 float z = (int16_t)readings[2];
Brandon 0:cf17ea89fd09 45 return atan(z / x);
Brandon 0:cf17ea89fd09 46 }
Brandon 0:cf17ea89fd09 47
Brandon 0:cf17ea89fd09 48 // Return normalised stretch value based on bounds of all readings seen
Brandon 0:cf17ea89fd09 49 float get_stretch() {
Brandon 0:cf17ea89fd09 50 static float min_strength = 0.7;
Brandon 0:cf17ea89fd09 51 static float max_strength = 0.7;
Brandon 0:cf17ea89fd09 52 float current_strength = stretch_sensor.read();
Brandon 0:cf17ea89fd09 53 if(current_strength > max_strength) { max_strength = current_strength; }
Brandon 0:cf17ea89fd09 54 if(current_strength < min_strength) { min_strength = current_strength; }
Brandon 0:cf17ea89fd09 55 float stretch = (current_strength - min_strength) / (max_strength - min_strength);
Brandon 0:cf17ea89fd09 56 return 1.0 - stretch;
Brandon 0:cf17ea89fd09 57 }
Brandon 0:cf17ea89fd09 58
Brandon 0:cf17ea89fd09 59 // move mouse to a location relative to the start point, stepping as needed
Brandon 0:cf17ea89fd09 60 void move_mouse(int x, int y) {
Brandon 0:cf17ea89fd09 61 const int STEP = 10;
Brandon 0:cf17ea89fd09 62 static int current_x = 0;
Brandon 0:cf17ea89fd09 63 static int current_y = 0;
Brandon 0:cf17ea89fd09 64
Brandon 0:cf17ea89fd09 65 int move_x = x - current_x;
Brandon 0:cf17ea89fd09 66 int move_y = y - current_y;
Brandon 0:cf17ea89fd09 67
Brandon 0:cf17ea89fd09 68 // Move the mouse, in steps of max step size to ensure it is picked up by OS
Brandon 0:cf17ea89fd09 69 while(move_x > STEP) { mouse.move(STEP, 0); move_x -= STEP; }
Brandon 0:cf17ea89fd09 70 while(move_x < -STEP) { mouse.move(-STEP, 0); move_x += STEP; }
Brandon 0:cf17ea89fd09 71 while(move_y > STEP) { mouse.move(0, STEP); move_y -= STEP; }
Brandon 0:cf17ea89fd09 72 while(move_y < -STEP) { mouse.move(0, -STEP); move_y += STEP; }
Brandon 0:cf17ea89fd09 73 mouse.move(move_x, move_y);
Brandon 0:cf17ea89fd09 74
Brandon 0:cf17ea89fd09 75 current_x = x;
Brandon 0:cf17ea89fd09 76 current_y = y;
Brandon 0:cf17ea89fd09 77 }
Brandon 0:cf17ea89fd09 78
Brandon 0:cf17ea89fd09 79 template <class T>
Brandon 0:cf17ea89fd09 80 T filter(T* array, int len, T value) {
Brandon 0:cf17ea89fd09 81 T mean = 0.0;
Brandon 0:cf17ea89fd09 82 for(int i = 0; i<len - 1; i++) {
Brandon 0:cf17ea89fd09 83 mean += array[i + 1];
Brandon 0:cf17ea89fd09 84 array[i] = array[i + 1];
Brandon 0:cf17ea89fd09 85 }
Brandon 0:cf17ea89fd09 86 mean += value;
Brandon 0:cf17ea89fd09 87 array[len - 1] = value;
Brandon 0:cf17ea89fd09 88 return mean / (T)len;
Brandon 0:cf17ea89fd09 89 }
Brandon 0:cf17ea89fd09 90
Brandon 0:cf17ea89fd09 91 typedef enum {
Brandon 0:cf17ea89fd09 92 WAITING = 2,
Brandon 0:cf17ea89fd09 93 AIMING = 4,
Brandon 0:cf17ea89fd09 94 FIRING = 8
Brandon 0:cf17ea89fd09 95 } state_t;
Brandon 0:cf17ea89fd09 96
Brandon 0:cf17ea89fd09 97 int main() {
Brandon 0:cf17ea89fd09 98 leds = 1;
Brandon 0:cf17ea89fd09 99
Brandon 0:cf17ea89fd09 100 // setup accelerometer
Brandon 0:cf17ea89fd09 101 accelerometer.setPowerControl(0x00);
Brandon 0:cf17ea89fd09 102 accelerometer.setDataFormatControl(0x0B);
Brandon 0:cf17ea89fd09 103 accelerometer.setDataRate(ADXL345_3200HZ);
Brandon 0:cf17ea89fd09 104 accelerometer.setPowerControl(0x08);
Brandon 0:cf17ea89fd09 105
Brandon 0:cf17ea89fd09 106 state_t state = WAITING;
Brandon 0:cf17ea89fd09 107 Timer timer;
Brandon 0:cf17ea89fd09 108
Brandon 0:cf17ea89fd09 109 float angles[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 angle = filter(angles, 8, this_angle);
Brandon 0:cf17ea89fd09 122
Brandon 0:cf17ea89fd09 123 leds = state;
Brandon 0:cf17ea89fd09 124
Brandon 0:cf17ea89fd09 125 // act based on the current state
Brandon 0:cf17ea89fd09 126 switch (state) {
Brandon 0:cf17ea89fd09 127 case WAITING:
Brandon 0:cf17ea89fd09 128 if(stretch > 0.2) { // significant stretch, considered starting
Brandon 0:cf17ea89fd09 129 mouse.press(MOUSE_LEFT);
Brandon 0:cf17ea89fd09 130 state = AIMING;
Brandon 0:cf17ea89fd09 131 }
Brandon 0:cf17ea89fd09 132 break;
Brandon 0:cf17ea89fd09 133
Brandon 0:cf17ea89fd09 134 case AIMING:
Brandon 1:2721dc2acc2c 135 if(push) { // push button while aiming, considered a fire
Brandon 0:cf17ea89fd09 136 mouse.release(MOUSE_LEFT);
Brandon 0:cf17ea89fd09 137 move_mouse(0, 0);
Brandon 0:cf17ea89fd09 138 timer.start();
Brandon 0:cf17ea89fd09 139 wait(1);
Brandon 0:cf17ea89fd09 140 state = FIRING;
Brandon 1:2721dc2acc2c 141 } else { //incrementally move mouse
Brandon 0:cf17ea89fd09 142 int x = 0.0 - cos(angle) * stretch * 40;
Brandon 0:cf17ea89fd09 143 int y = sin(angle) * stretch * 40;
Brandon 0:cf17ea89fd09 144 move_mouse(x, y);
Brandon 0:cf17ea89fd09 145 }
Brandon 0:cf17ea89fd09 146 break;
Brandon 0:cf17ea89fd09 147
Brandon 0:cf17ea89fd09 148 case FIRING:
Brandon 1:2721dc2acc2c 149 push = !button; //update button
Brandon 1:2721dc2acc2c 150 if(push) { // if pushed, return to ready
Brandon 0:cf17ea89fd09 151 timer.stop();
Brandon 0:cf17ea89fd09 152 timer.reset();
Brandon 0:cf17ea89fd09 153 state = WAITING;
Brandon 0:cf17ea89fd09 154 wait(.5);
Brandon 0:cf17ea89fd09 155 }
Brandon 0:cf17ea89fd09 156 break;
Brandon 0:cf17ea89fd09 157 };
Brandon 0:cf17ea89fd09 158
Brandon 0:cf17ea89fd09 159 wait(0.01);
Brandon 0:cf17ea89fd09 160 }
Brandon 0:cf17ea89fd09 161 }