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
main.cpp
- Committer:
- groletter
- Date:
- 2013-09-03
- Revision:
- 4:04f83503d219
- Parent:
- 3:21245644a2e3
File content as of revision 4:04f83503d219:
// // 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(LED4); // 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("Motion detected - sending alert!\n"); 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; lcd.cls(); lcd.locate(0,3); lcd.printf("Connected to Host\n"); state = monCONNECTED; if (alertState.pendMotion) { alertState.pendMotion = false; send_alert(MOTION); motionLED = 0; } if (alertState.pendTempHi) { alertState.pendTempHi = false; send_alert(TEMP_HI); tempHiLED = 0; } if (alertState.pendTempLo) { alertState.pendTempLo = false; send_alert(TEMP_LOW); tempLoLED = 0; } } else { lcd.cls(); lcd.locate(0,3); lcd.printf("Not Connected to Host\n"); theTemp= get_temp(); lcd.printf("L=%.2f H=%.2f Temp=%.2f\n", myTemp.get_min(), myTemp.get_max(), theTemp); 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)) { lcd.cls(); lcd.locate(0,3); lcd.printf("TEMP ALERT %.2f over %.2f - sending alert!\n", theTemp, myTemp.get_max()); 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)) { lcd.cls(); lcd.locate(0,3); lcd.printf("TEMP ALERT %.2f under %.2f - sending alert!\n", theTemp, myTemp.get_min()); 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())) { // DEBUG 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); } }