DreamForce 2013 Mini-Hack Challenge Project

Dependencies:   ADXL345 USBDevice filter mbed

Fork of df-minihack-slingshot by Doug Anson

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);
+    }
+}