![](/media/cache/profiles/1d7c91037101cce725efa1fe469232a5.50x50_q85.jpg)
DreamForce 2013 Mini-Hack Challenge Project
Dependencies: ADXL345 USBDevice mbed filter
Diff: main.cpp
- Revision:
- 0:a2c33a8eded1
- Child:
- 1:d9d593d4ea39
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed Oct 30 19:07:09 2013 +0000 @@ -0,0 +1,169 @@ +/* mbed USB Slingshot, + * + * Copyright (c) 2010-2011 mbed.org, MIT License + * + * smokrani, sford, danson, sgrove + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "mbed.h" +#include "USBMouse.h" +#include "ADXL345.h" + +// Physical interfaces +USBMouse mouse; +ADXL345 accelerometer(p5, p6, p7, p8); +AnalogIn stretch_sensor(p15); +BusOut leds(LED1, LED2, LED3, LED4); + +// +// DreamForce 2013 Challenge: +// - Adjust the resultant slingshot angle for the difference between the accelerometer angle and the relative angle of the sling to the slingshot body. +// - Result should be in radians: up > 0 > down just like with get_angle() below - except adjusted! +// - Note: You may need to add some filters to optimize (and stabilize) the readings from the potentiometers +// +float adjust_for_sling_angle(float slingshot_body_angle) { + float modified_angle = slingshot_body_angle; // default + + // innovate!!! + + // return the modified angle taking into account the sling angle relative to the slingshot body + return modified_angle; +} + +// Return slingshot angle in radians, up > 0 > down +float get_angle() { + int readings[3]; + accelerometer.getOutput(readings); + float x = (int16_t)readings[0]; + float z = (int16_t)readings[2]; + return atan(z / x); +} + +// Return normalised stretch value based on bounds of all readings seen +float get_stretch() { + static float min_strength = 0.7; + static float max_strength = 0.7; + float current_strength = stretch_sensor.read(); + if(current_strength > max_strength) { max_strength = current_strength; } + if(current_strength < min_strength) { min_strength = current_strength; } + float stretch = (current_strength - min_strength) / (max_strength - min_strength); + return 1.0 - stretch; +} + +// move mouse to a location relative to the start point, stepping as needed +void move_mouse(int x, int y) { + const int STEP = 10; + static int current_x = 0; + static int current_y = 0; + + int move_x = x - current_x; + int move_y = y - current_y; + + // Move the mouse, in steps of max step size to ensure it is picked up by OS + while(move_x > STEP) { mouse.move(STEP, 0); move_x -= STEP; } + while(move_x < -STEP) { mouse.move(-STEP, 0); move_x += STEP; } + while(move_y > STEP) { mouse.move(0, STEP); move_y -= STEP; } + while(move_y < -STEP) { mouse.move(0, -STEP); move_y += STEP; } + mouse.move(move_x, move_y); + + current_x = x; + current_y = y; +} + +template <class T> +T filter(T* array, int len, T value) { + T mean = 0.0; + for(int i = 0; i<len - 1; i++) { + mean += array[i + 1]; + array[i] = array[i + 1]; + } + mean += value; + array[len - 1] = value; + return mean / (T)len; +} + +typedef enum { + WAITING = 2, + AIMING = 4, + FIRING = 8 +} state_t; + +int main() { + leds = 1; + + // setup accelerometer + accelerometer.setPowerControl(0x00); + accelerometer.setDataFormatControl(0x0B); + accelerometer.setDataRate(ADXL345_3200HZ); + accelerometer.setPowerControl(0x08); + + state_t state = WAITING; + Timer timer; + + float angles[8] = {0}; + float stretches[8] = {0}; + + while(1) { + + // get the slingshot parameters + float this_stretch = get_stretch(); + float this_angle = get_angle(); + + // apply some filtering + float stretch = filter(stretches, 8, this_stretch); + float angle = filter(angles, 8, this_angle); + + // DreamForce 2013 Challenge: Adjust the angle to account for the relative angle between the sling and the slingshot body + angle = adjust_for_sling_angle(angle); + + leds = state; + + // act based on the current state + switch (state) { + case WAITING: + if(stretch > 0.5) { // significant stretch, considered starting + mouse.press(MOUSE_LEFT); + state = AIMING; + } + break; + + case AIMING: + if(stretch - this_stretch > 0.1) { // rapid de-stretch, considered a fire + mouse.release(MOUSE_LEFT); + move_mouse(0, 0); + timer.start(); + state = FIRING; + } else { + int x = 0.0 - cos(angle) * stretch * 200; + int y = sin(angle) * stretch * 200; + move_mouse(x, y); + } + break; + + case FIRING: + if(timer > 3.0) { + timer.stop(); + timer.reset(); + state = WAITING; + } + break; + }; + + wait(0.01); + } +}