The controller for a NERF turret, allowing it to track and fire at a human face with visual input gotten by polling a web server. This is part of the final project of the EE149 course of UC Berkeley. The project name is "Pew Pew".

Dependencies:   HTTPClient TSI cc3000_hostdriver_mbedsocket mbed

Files at this revision

API Documentation at this revision

Comitter:
impguard
Date:
Fri Dec 19 11:49:27 2014 +0000
Commit message:
Final version of the controller for the NERF turret.

Changed in this revision

HTTPClient.lib Show annotated file Show diff for this revision Revisions of this file
TSI.lib Show annotated file Show diff for this revision Revisions of this file
camera.h Show annotated file Show diff for this revision Revisions of this file
cc3000_hostdriver_mbedsocket.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 4a30986db2fb HTTPClient.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HTTPClient.lib	Fri Dec 19 11:49:27 2014 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/nebgnahz/code/HTTPClient/#25e3d3516a03
diff -r 000000000000 -r 4a30986db2fb TSI.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TSI.lib	Fri Dec 19 11:49:27 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/TSI/#1a60ef257879
diff -r 000000000000 -r 4a30986db2fb camera.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/camera.h	Fri Dec 19 11:49:27 2014 +0000
@@ -0,0 +1,111 @@
+/**
+*
+*   Code to get data from the camera by connecting to a web server via WiFi (using Adafruit CC3000).
+*
+*   author: Leo Kam
+*
+*
+*   The code to connect to the web via Adafruit is adapted from the code by Ben Zhang and Antonio Iannopollo, found at 
+*   http://developer.mbed.org/users/nebgnahz/code/CC3000_demo/
+*   The following libraries are used:
+*    - cc3000_hostdriver_mbedsocket
+*     (http://developer.mbed.org/users/Kojto/code/cc3000_hostdriver_mbedsocket/)
+*    - HTTPClient (http://developer.mbed.org/users/donatien/code/HTTPClient/)
+*
+**/
+
+
+#include "mbed.h"
+#include "cc3000.h"
+#include "HTTPClient.h"
+
+// KL25Z wifi connection
+// we need to define connection pins for:
+// - IRQ      => (pin D3)
+// - Enable   => (pin D5)
+// - SPI CS   => (pin D10)
+// - SPI MOSI => (pin D11)
+// - SPI MISO => (pin D12)
+// - SPI CLK  => (pin D13)
+// plus wifi network SSID, password, security level and smart-configuration flag.
+mbed_cc3000::cc3000 wifi(D3, D5, D10, SPI(D11, D12, D13),
+                         "EECS-PSK", "Thequickbrown", WPA2, false);
+
+// create an http instance
+HTTPClient http;
+
+// str is used to hold the response data
+char str[512];
+char * p;
+
+// setup the serial connection, and LEDs
+Serial pc(USBTX, USBRX);
+DigitalOut led_red(LED_RED);
+DigitalOut led_green(LED_GREEN);
+
+void initializeWiFi() {
+    // by default, it's red
+    led_red = 0;
+    led_green = 1;
+    
+    //print message to indicate the program has started
+    pc.printf("CC3000 Sample Program\r\n");
+    wifi.init();
+    pc.printf("Wifi Initialized\r\n");
+    
+    // check connection status
+    while(wifi.is_connected() == false) {
+        // try to connect
+        if (wifi.connect() == -1) {
+            pc.printf("Failed to connect."
+                      "Please verify connection details and try again.\r\n");
+            led_red = 0;
+            led_green = 1;
+        } else {
+            pc.printf("IP address: %s \r\n", wifi.getIPAddress());
+            
+            //once connected, turn green LED on and red LED off, and exit loop
+            led_red = 1;
+            led_green = 0;
+            break;
+        }
+    }
+}
+
+
+/* Get the x, y-coordinates and depth from camera. Return true if successfuly retrieve data from server, else return false and do not change parameters. */
+bool getCameraData(double &x, double &y, double &z, int timeout=2000) {
+    // check connection status
+    while(wifi.is_connected() == false) {
+        // try to connect
+        if (wifi.connect() == -1) {
+            pc.printf("Failed to connect."
+                      "Please verify connection details and try again.\r\n");
+            led_red = 0;
+            led_green = 1;
+        } else {
+            pc.printf("IP address: %s \r\n", wifi.getIPAddress());
+            
+            //once connected, turn green LED on and red LED off, and exit loop
+            led_red = 1;
+            led_green = 0;
+            break;
+        }
+    }
+    int ret = http.get("https://pew-pew-pew.herokuapp.com/position", str, 512);
+    if (!ret) {
+        p = strtok(str, " ");
+        x = atof(p);
+        p = strtok(NULL, " ");
+        y = atof(p);
+        p = strtok(NULL, " ");
+        z = atof(p);
+        pc.printf("Camera data: %f %f %f\r\n", x, y, z);
+        return true;
+    } else {
+        /*pc.printf("Error - ret = %d - HTTP return code = %d\r\n",
+                  ret,
+                  http.getHTTPResponseCode());*/
+        return false;
+    }
+} 
diff -r 000000000000 -r 4a30986db2fb cc3000_hostdriver_mbedsocket.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cc3000_hostdriver_mbedsocket.lib	Fri Dec 19 11:49:27 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/Kojto/code/cc3000_hostdriver_mbedsocket/#ca8c234997c0
diff -r 000000000000 -r 4a30986db2fb main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Fri Dec 19 11:49:27 2014 +0000
@@ -0,0 +1,264 @@
+/**
+*
+*   Controller for the NERF turret, allowing for tracking of target (human face) via visual input.
+*
+*   authors: Leo Kam
+**/
+
+#include "mbed.h"
+#include "camera.h"
+#include "TSISensor.h"
+
+//Relays for firing the NERF gun.
+DigitalOut flywheel(PTE5);
+DigitalOut trigger(PTE4);
+//Relays for turning the turret.
+DigitalOut step1(PTE2);
+DigitalOut step2(PTE3);
+//Relays for tilting the gun up and down.
+DigitalOut h_bridge1(PTB8);
+DigitalOut h_bridge2(PTB9);
+DigitalOut h_bridge3(PTB10);
+DigitalOut h_bridge4(PTB11);
+
+
+double x, y, z;                          //The coordinates of the target, relative to the barrel of the gun.
+double x_offset, y_offset, z_offset;     //The offsets to transform the camera data into a coordinate system relative to barrel of the gun.
+TSISensor tsi;                           //The touch sensor of the mbed.
+double eps = 40;                         //The error margin.
+double interval = 200;                   //The time between each poll of the server, in ms.
+bool safety = true;                      //Whether the safety of the NERF gun is on or off.
+
+void initialize();
+void calibrateCamera();
+bool getCoordinates(double&, double&, double&);
+bool onTarget(double);
+void stepMotorStates(int state);
+void turnLeft(double);
+void turnRight(double);
+void tiltUp(double);
+void tiltDown(double);
+void trackTarget();
+void safetyOn();
+void safetyOff();
+bool fire();
+
+int main() {
+    initialize();
+    double hysteresis = 0;
+    while(1) {
+        getCoordinates(x, y, z);
+        if(!onTarget(eps + hysteresis)) {
+            hysteresis = 0;
+            pc.printf("Tracking target...\r\n");
+            safetyOn();
+            trackTarget();  
+        } else {
+            pc.printf("Target acquired!\r\n");
+            if(safety) {
+                safetyOff();
+            }
+            fire();
+            wait(3);
+            hysteresis = 0.5 * eps;
+        }
+    }
+
+}
+
+/* All the initialization are done here. */
+void initialize() {
+    x = 0;
+    y = 0;
+    z = 0;
+    x_offset = 0;
+    y_offset = 0;
+    z_offset = 0;
+    initializeWiFi();
+    calibrateCamera();
+    
+    wait(3);
+    led_red = 0;
+    led_green = 1;
+    pc.printf("Tap when ready.\r\n");
+    while(1) {
+        if (tsi.readPercentage() > 0.001) {break;}
+    }
+    pc.printf("It's hunting season.\r\n");
+    led_red = 1;
+    led_green = 0;
+}
+
+/* Calibrate the camera to calculate the offsets for transforming the camera coordinates into gun coordinates. */
+void calibrateCamera() {
+    //Put someone's face right in front of the gun barrel.
+    
+    double x0, y0, z0;
+    x0 = 0;
+    y0 = 0;
+    z0 = 0;
+    wait(3);
+    pc.printf("Tap to start calibration of camera.\r\n");
+    while(1) {
+        //Wait for user to tap in order to start the calibration.
+        led_red = 0;
+        led_green = 1;
+        if (tsi.readPercentage() > 0.001) {break;}
+    }
+    led_red = 1;
+    led_green = 0;
+    wait(3);
+    pc.printf("Put face in front of gun barrel and tap when centered.\r\n");
+    while(1) {
+        //Continuously poll data from camera until mbed's slider is tapped.
+        getCameraData(x0, y0, z0);
+        led_red = 0;
+        led_green = 1;
+        if (tsi.readPercentage() > 0.001) {break;}
+    }
+    x_offset = -x0;
+    y_offset = -y0;
+    z_offset = -z0;
+    pc.printf("Offests: %f %f %f\r\n", x_offset, y_offset, z_offset);
+    //Green led on.
+    led_red = 1;
+    led_green = 0;
+}
+
+/* Get the coordinates of the target, relative to gun barrel. Return true if successfully retrieve data, else return false and do not change parameters. */
+bool getCoordinates(double &x, double &y, double &z) {
+    if (getCameraData(x, y, z)) {
+        x += x_offset;
+        y += y_offset;
+        z += z_offset;
+        pc.printf("Offsetted position: %f %f %f\r\n", x, y, z);
+        return true;   
+    } else {
+        //Fail to connect to server. Maybe track to last known target location?
+        return false;    
+    }
+}
+
+/* Check if the gun is aiming at a square area centered on the target, with TOLERANCE as the side length. */
+bool onTarget(double tolerance) {
+    //Ignore depth for now.
+    return abs(x) <= tolerance && abs(y) <= tolerance;
+}
+
+/* Helper function for using the stepper motor. */
+void stepMotorStates(int state) {
+    switch(state) {
+        case 0:
+            step1 = 0;
+            step2 = 0;
+            break;
+        case 1:
+            step1 = 1;
+            step2 = 0;
+            break;
+        case 2:
+            step1 = 1;
+            step2 = 1;
+            break;
+        case 3:
+            step1 = 0;
+            step2 = 1;
+            break;
+        default:
+            break;
+    }
+}
+
+/* Turn the turret left for the given milliseconds. */
+void turnLeft(double ms) {
+    stepMotorStates(3);
+    wait_ms(ms);
+    stepMotorStates(2);
+    wait_ms(ms);
+    stepMotorStates(1);
+    wait_ms(ms);
+    stepMotorStates(0);
+    wait_ms(ms);
+}
+
+/* Turn the turret left for the given milliseconds. */
+void turnRight(double ms) {
+    stepMotorStates(0);
+    wait_ms(ms);
+    stepMotorStates(1);
+    wait_ms(ms);
+    stepMotorStates(2);
+    wait_ms(ms);
+    stepMotorStates(3);
+    wait_ms(ms);
+}
+
+/* Tilt the gun up for the given milliseconds. */
+void tiltUp(double ms) {
+    h_bridge1 = 1;
+    h_bridge2 = 0;
+    h_bridge3 = 0;
+    h_bridge4 = 1;
+    wait_ms(ms);
+    h_bridge1 = 0;
+    h_bridge2 = 0;
+    h_bridge3 = 0;
+    h_bridge4 = 0;
+}
+
+/* Tilt the gun down for the given milliseconds. */
+void tiltDown(double ms) {
+    h_bridge1 = 0;
+    h_bridge2 = 1;
+    h_bridge3 = 1;
+    h_bridge4 = 0;
+    wait_ms(ms);
+    h_bridge1 = 0;
+    h_bridge2 = 0;
+    h_bridge3 = 0;
+    h_bridge4 = 0;
+}
+
+/* Move the turret to aim at the target. */
+void trackTarget() {
+    if (x < -eps) {
+        pc.printf("Turning left.\r\n");
+        turnLeft(200);
+    } else if(x >= eps) {
+        pc.printf("Turning right.\r\n");
+        turnRight(200);    
+    } else
+    if(y < -eps) {
+        pc.printf("Tilting down.\r\n");
+        tiltDown(500);        
+    } else if(y >= eps) {
+        pc.printf("Tilting up.\r\n");
+        tiltUp(1000);
+    }
+    
+    
+}
+
+/* Turn the safety of the NERF gun off (firewheel on). */
+void safetyOff() {
+    flywheel = 1;
+    safety = false;
+    wait(0.3);
+}
+
+/* Turn the safety on (firewheel off). */
+void safetyOn() {
+    flywheel = 0;
+    safety = true;
+}
+
+/* Fire the gun. Return true if successfully pull trigger, else false. */
+bool fire() {
+    if (!safety) {
+        trigger = 1;
+        wait(0.4);
+        trigger = 0;
+        return true;
+    }
+    return false;
+}
\ No newline at end of file
diff -r 000000000000 -r 4a30986db2fb mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Fri Dec 19 11:49:27 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/4fc01daae5a5
\ No newline at end of file