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
Revision 0:4a30986db2fb, committed 2014-12-19
- 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
--- /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
--- /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
--- /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;
+ }
+}
--- /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
--- /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
--- /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