Simon Ford
/
Slingshot
mbed USB Slingshot code
Embed:
(wiki syntax)
Show/hide line numbers
main.cpp
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 }
Generated on Tue Jul 12 2022 13:23:58 by 1.7.2