This is my final project for UCSC Extension - USB Programming. It is a home monitoring program for motion and temperature and requires host-side code.

Dependencies:   C12832_lcd HomeMon LM75B MMA7660 USBDevice mbed

Revision:
0:977f7cf68014
Child:
2:f6a1f96dc3cd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Sep 01 23:35:50 2013 +0000
@@ -0,0 +1,259 @@
+//
+// Jerry Roletter - 9/1/13
+// UCSC Extension - USB Programming Class (Summer 2013)
+//
+// This code is for a simple home monitoring system that
+// detects temperature out of a programmed range, and any
+// motion of the mbed application board.  If motion or out
+// of range temperature is detected it sends alerts to the
+// host if one is connected via a USB Serial device.  Otherwise
+// it stores them until a host is connected.
+//
+// It keeps track of historic temperature and movement data.
+// The host can request those buffers for analysis.
+//
+// I build a protocol on top of the serial port.  This allows
+// the host and device to communicate.  As of 9/1/13 there still
+// seem to be some issues around the communication protocol
+// due to lost acks or improper error handling.  Running out
+// of time to fully debug.
+//
+
+#include "mbed.h"
+#include "MMA7660.h"
+#include "C12832_lcd.h"
+#include "LM75B.h"
+#include "USBSerial.h"
+#include <ctype.h>
+
+// My specific classes for this assignment
+
+#include "USBHomeMon.h"
+#include "Motion.h"
+#include "Temperature.h"
+#include "Communication.h"
+
+// TODO:
+//  - Add a command to allow host to disconnect
+//  - Add a command to allow the host to ignore Alert messages
+//  - Longer term allow host to change alert window period (collapse alerts)
+//  - Clean up FIXME, printf(), etc.
+//  - Add time to temperature information
+//
+
+// LCD for debug
+C12832_LCD lcd;
+// Temperature Sensor
+LM75B tmp(p28,p27);
+// Accelerometer
+MMA7660 MMA(p28, p27);
+// USB Device 
+USBSerial serial;
+
+Timer sysMonTime;
+
+DigitalOut connectionLED(LED1);
+DigitalOut motionLED(LED2);
+DigitalOut tempHiLED(LED3);
+DigitalOut tempLoLED(LED3);
+
+// Global State       
+int state;
+alert_state alertState; 
+
+double get_temp() {
+   // Convert temperature to farenheit
+   return tmp.read() * 9.0 / 5.0 + 32.0;
+}
+
+bool detect_motion(motion_vec current_motion, motion_vec last_motion, Motion &myMotion) { 
+    motion_vec thresh = myMotion.get_motion_thresh();
+    motion_vec delta;
+    delta.x = current_motion.x - last_motion.x;
+    delta.y = current_motion.y - last_motion.y;
+    delta.z = current_motion.z - last_motion.z;
+    
+    if (last_motion.x > (current_motion.x+thresh.x) || last_motion.x < (current_motion.x-thresh.x) || 
+      last_motion.y > (current_motion.y+thresh.y) || last_motion.y < (current_motion.y-thresh.y) || 
+      last_motion.z > (current_motion.z+thresh.z) || last_motion.z < (current_motion.z-thresh.z)) {
+        // FIXME - for debug 
+        lcd.cls();
+        lcd.locate(0,3);
+        lcd.printf("x = %.2f y = %.2f z = %.2f\n", delta.x, delta.y, delta.z);  
+        return true;  
+        
+    }
+    else {
+        return false;
+    }
+}
+
+void store_alert(alert_type alert) {
+    switch (alert) {
+        case MOTION:
+            alertState.pendMotion = true;
+            break;
+        case TEMP_LOW:
+            alertState.pendTempLo = true;
+            break;
+        case TEMP_HI:
+            alertState.pendTempHi = true;
+            break;
+    }
+}
+
+#define MS_IN_SEC 1000.0
+
+int main() {  
+    
+    alertState.pendMotion = false;
+    alertState.pendTempHi = false;
+    alertState.pendTempLo = false;
+    
+    Motion myMotion;
+    Temperature myTemp;
+    double theTemp;
+    double lastTimeMS, curTimeMS;
+    double lastTempAlertSecs, lastMotionAlertSecs;
+    double MotionAlertWaitSecs, TempAlertWaitSecs;
+    
+    // Don't send too many alerts too quickly
+    // These are just debug settings.  A real system would
+    // have much longer temperature settings
+    
+    MotionAlertWaitSecs = 5.0;  // Don't allow multiple alerts within 5.0 seconds
+    TempAlertWaitSecs = 60.0;   // Wait at least a minute between temp alerts
+    
+    char host_cmd;
+    msg_type msg;
+    
+    motion_vec current_motion;
+    motion_vec last_motion;
+
+    last_motion.x = MMA.x();
+    last_motion.y = MMA.y();
+    last_motion.z = MMA.z();    
+    
+    sysMonTime.start();
+    lastTimeMS = sysMonTime.read_ms()/MS_IN_SEC;
+    lastTempAlertSecs = sysMonTime.read();
+    lastMotionAlertSecs = lastTempAlertSecs;
+    
+    // This method of setting the temperature is just for demo
+    // purposes.  I use the current temp to initialize the ranges.
+    
+    theTemp = get_temp();
+    myTemp.set_min(theTemp - 1.0);
+    myTemp.set_max(theTemp + 1.0);
+    
+    state = monDISCONNECTED;
+    
+    while(1) {
+        if (state == monDISCONNECTED) {
+            if (check_connection()) {
+                connectionLED = 1;
+                state = monCONNECTED;
+                if (alertState.pendMotion) {
+                    alertState.pendMotion = false;
+                    send_alert(MOTION);
+                }
+                else if (alertState.pendTempHi) {
+                    alertState.pendTempHi = false;
+                    send_alert(MOTION);
+                }
+                else if (alertState.pendTempLo) {
+                    alertState.pendTempLo = false;
+                    send_alert(MOTION);
+                }
+            }
+            else {
+                connectionLED = 0;
+            }
+        }
+        // We are connected so listen for commands from
+        // host.
+        else {
+            if (serial.available()) {
+                host_cmd = rec_command();
+                msg = parse_msg(host_cmd);
+                host_command_resp(msg, myTemp, myMotion);
+                // FIXME - debug
+                lcd.cls();
+                lcd.locate(0,3);
+                lcd.printf("Received command %c\n", host_cmd); 
+            }
+        }
+        
+        // Detect if motion has occurred and handle it
+        current_motion.x = MMA.x();
+        current_motion.y = MMA.y();
+        current_motion.z = MMA.z();
+        if(detect_motion(current_motion, last_motion, myMotion)) { 
+          // Only alert if last alert was outside window of alert time
+          if (sysMonTime.read() > (lastMotionAlertSecs + MotionAlertWaitSecs)) {
+            // moved
+            motionLED = 1;
+            // Adds the time of motion to the database of motion
+            myMotion.add_sample(sysMonTime.read());
+            // Send it over serial port
+            if (state == monCONNECTED) {
+                send_alert(MOTION);
+                // clear LED since host is connected
+                motionLED = 0;
+            }
+            else {
+                store_alert(MOTION);
+            }
+            lastMotionAlertSecs = sysMonTime.read();
+          }
+        }
+                
+        // Now check temperature and generate an alert 
+        theTemp = get_temp();
+        if (theTemp > myTemp.get_max()) {
+          if (sysMonTime.read() > (lastTempAlertSecs + TempAlertWaitSecs)) {
+            tempHiLED = 1;
+            if (state == monCONNECTED) {
+                send_alert(TEMP_HI);
+                // clear if connected
+                tempHiLED = 0;
+            }
+            else {
+                store_alert(TEMP_HI);
+            }
+            lastTempAlertSecs = sysMonTime.read();
+          }
+        }
+        else if (theTemp < myTemp.get_min()) {
+          if (sysMonTime.read() > (lastTempAlertSecs + TempAlertWaitSecs)) {
+            tempLoLED = 1;
+            if (state == monCONNECTED) {
+                send_alert(TEMP_LOW);
+                // clear if connected
+                tempLoLED = 0;
+            }
+            else {
+                store_alert(TEMP_LOW);
+            }
+            lastTempAlertSecs = sysMonTime.read();
+          }
+        }   
+        
+        // See if it is time to store the temperature samples
+        if (sysMonTime.read_ms()/MS_IN_SEC > (lastTimeMS + myTemp.get_period())) {
+            lcd.printf("time to send temperature\n");
+            lastTimeMS = sysMonTime.read_ms()/MS_IN_SEC;
+            myTemp.add_sample(get_temp());
+        }
+         
+        //lcd.cls();
+        //lcd.locate(0,3);
+        //lcd.printf("temp = %.2f\n", theTemp);
+        
+        last_motion.x = current_motion.x;
+        last_motion.y = current_motion.y;
+        last_motion.z = current_motion.z;
+        wait(0.3);
+    }
+
+}