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
00001 // 00002 // Jerry Roletter - 9/1/13 00003 // UCSC Extension - USB Programming Class (Summer 2013) 00004 // 00005 // This code is for a simple home monitoring system that 00006 // detects temperature out of a programmed range, and any 00007 // motion of the mbed application board. If motion or out 00008 // of range temperature is detected it sends alerts to the 00009 // host if one is connected via a USB Serial device. Otherwise 00010 // it stores them until a host is connected. 00011 // 00012 // It keeps track of historic temperature and movement data. 00013 // The host can request those buffers for analysis. 00014 // 00015 // I build a protocol on top of the serial port. This allows 00016 // the host and device to communicate. As of 9/1/13 there still 00017 // seem to be some issues around the communication protocol 00018 // due to lost acks or improper error handling. Running out 00019 // of time to fully debug. 00020 // 00021 00022 #include "mbed.h" 00023 #include "MMA7660.h" 00024 #include "C12832_lcd.h" 00025 #include "LM75B.h" 00026 #include "USBSerial.h" 00027 #include <ctype.h> 00028 00029 // My specific classes for this assignment 00030 00031 #include "USBHomeMon.h" 00032 #include "Motion.h" 00033 #include "Temperature.h" 00034 #include "Communication.h" 00035 00036 // TODO: 00037 // - Add a command to allow host to disconnect 00038 // - Add a command to allow the host to ignore Alert messages 00039 // - Longer term allow host to change alert window period (collapse alerts) 00040 // - Clean up FIXME, printf(), etc. 00041 // - Add time to temperature information 00042 // 00043 00044 // LCD for debug 00045 C12832_LCD lcd; 00046 // Temperature Sensor 00047 LM75B tmp(p28,p27); 00048 // Accelerometer 00049 MMA7660 MMA(p28, p27); 00050 // USB Device 00051 USBSerial serial; 00052 00053 Timer sysMonTime; 00054 00055 DigitalOut connectionLED(LED1); 00056 DigitalOut motionLED(LED2); 00057 DigitalOut tempHiLED(LED3); 00058 DigitalOut tempLoLED(LED4); 00059 00060 // Global State 00061 int state; 00062 alert_state alertState; 00063 00064 double get_temp() { 00065 // Convert temperature to farenheit 00066 return tmp.read() * 9.0 / 5.0 + 32.0; 00067 } 00068 00069 bool detect_motion(motion_vec current_motion, motion_vec last_motion, Motion &myMotion) { 00070 motion_vec thresh = myMotion.get_motion_thresh(); 00071 motion_vec delta; 00072 delta.x = current_motion.x - last_motion.x; 00073 delta.y = current_motion.y - last_motion.y; 00074 delta.z = current_motion.z - last_motion.z; 00075 00076 if (last_motion.x > (current_motion.x+thresh.x) || last_motion.x < (current_motion.x-thresh.x) || 00077 last_motion.y > (current_motion.y+thresh.y) || last_motion.y < (current_motion.y-thresh.y) || 00078 last_motion.z > (current_motion.z+thresh.z) || last_motion.z < (current_motion.z-thresh.z)) { 00079 // FIXME - for debug 00080 lcd.cls(); 00081 lcd.locate(0,3); 00082 lcd.printf("Motion detected - sending alert!\n"); 00083 lcd.printf("x = %.2f y = %.2f z = %.2f\n", delta.x, delta.y, delta.z); 00084 return true; 00085 00086 } 00087 else { 00088 return false; 00089 } 00090 } 00091 00092 void store_alert(alert_type alert) { 00093 switch (alert) { 00094 case MOTION: 00095 alertState.pendMotion = true; 00096 break; 00097 case TEMP_LOW: 00098 alertState.pendTempLo = true; 00099 break; 00100 case TEMP_HI: 00101 alertState.pendTempHi = true; 00102 break; 00103 } 00104 } 00105 00106 #define MS_IN_SEC 1000.0 00107 00108 int main() { 00109 00110 alertState.pendMotion = false; 00111 alertState.pendTempHi = false; 00112 alertState.pendTempLo = false; 00113 00114 Motion myMotion; 00115 Temperature myTemp; 00116 double theTemp; 00117 double lastTimeMS, curTimeMS; 00118 double lastTempAlertSecs, lastMotionAlertSecs; 00119 double MotionAlertWaitSecs, TempAlertWaitSecs; 00120 00121 // Don't send too many alerts too quickly 00122 // These are just debug settings. A real system would 00123 // have much longer temperature settings 00124 00125 MotionAlertWaitSecs = 5.0; // Don't allow multiple alerts within 5.0 seconds 00126 TempAlertWaitSecs = 60.0; // Wait at least a minute between temp alerts 00127 00128 char host_cmd; 00129 msg_type msg; 00130 00131 motion_vec current_motion; 00132 motion_vec last_motion; 00133 00134 last_motion.x = MMA.x(); 00135 last_motion.y = MMA.y(); 00136 last_motion.z = MMA.z(); 00137 00138 sysMonTime.start(); 00139 lastTimeMS = sysMonTime.read_ms()/MS_IN_SEC; 00140 lastTempAlertSecs = sysMonTime.read(); 00141 lastMotionAlertSecs = lastTempAlertSecs; 00142 00143 // This method of setting the temperature is just for demo 00144 // purposes. I use the current temp to initialize the ranges. 00145 00146 theTemp = get_temp(); 00147 myTemp.set_min(theTemp - 1.0); 00148 myTemp.set_max(theTemp + 1.0); 00149 00150 state = monDISCONNECTED; 00151 00152 while(1) { 00153 if (state == monDISCONNECTED) { 00154 if (check_connection()) { 00155 connectionLED = 1; 00156 lcd.cls(); 00157 lcd.locate(0,3); 00158 lcd.printf("Connected to Host\n"); 00159 state = monCONNECTED; 00160 if (alertState.pendMotion) { 00161 alertState.pendMotion = false; 00162 send_alert(MOTION); 00163 motionLED = 0; 00164 } 00165 if (alertState.pendTempHi) { 00166 alertState.pendTempHi = false; 00167 send_alert(TEMP_HI); 00168 tempHiLED = 0; 00169 } 00170 if (alertState.pendTempLo) { 00171 alertState.pendTempLo = false; 00172 send_alert(TEMP_LOW); 00173 tempLoLED = 0; 00174 } 00175 } 00176 else { 00177 lcd.cls(); 00178 lcd.locate(0,3); 00179 lcd.printf("Not Connected to Host\n"); 00180 theTemp= get_temp(); 00181 lcd.printf("L=%.2f H=%.2f Temp=%.2f\n", myTemp.get_min(), myTemp.get_max(), theTemp); 00182 connectionLED = 0; 00183 } 00184 } 00185 // We are connected so listen for commands from 00186 // host. 00187 else { 00188 if (serial.available()) { 00189 host_cmd = rec_command(); 00190 msg = parse_msg(host_cmd); 00191 host_command_resp(msg, myTemp, myMotion); 00192 // FIXME - debug 00193 lcd.cls(); 00194 lcd.locate(0,3); 00195 lcd.printf("Received command %c\n", host_cmd); 00196 } 00197 } 00198 00199 // Detect if motion has occurred and handle it 00200 current_motion.x = MMA.x(); 00201 current_motion.y = MMA.y(); 00202 current_motion.z = MMA.z(); 00203 if(detect_motion(current_motion, last_motion, myMotion)) { 00204 // Only alert if last alert was outside window of alert time 00205 if (sysMonTime.read() > (lastMotionAlertSecs + MotionAlertWaitSecs)) { 00206 // moved 00207 motionLED = 1; 00208 // Adds the time of motion to the database of motion 00209 myMotion.add_sample(sysMonTime.read()); 00210 // Send it over serial port 00211 if (state == monCONNECTED) { 00212 send_alert(MOTION); 00213 // clear LED since host is connected 00214 motionLED = 0; 00215 } 00216 else { 00217 store_alert(MOTION); 00218 } 00219 lastMotionAlertSecs = sysMonTime.read(); 00220 } 00221 } 00222 00223 // Now check temperature and generate an alert 00224 theTemp = get_temp(); 00225 if (theTemp > myTemp.get_max()) { 00226 if (sysMonTime.read() > (lastTempAlertSecs + TempAlertWaitSecs)) { 00227 lcd.cls(); 00228 lcd.locate(0,3); 00229 lcd.printf("TEMP ALERT %.2f over %.2f - sending alert!\n", theTemp, myTemp.get_max()); 00230 tempHiLED = 1; 00231 if (state == monCONNECTED) { 00232 send_alert(TEMP_HI); 00233 // clear if connected 00234 tempHiLED = 0; 00235 } 00236 else { 00237 store_alert(TEMP_HI); 00238 } 00239 lastTempAlertSecs = sysMonTime.read(); 00240 } 00241 } 00242 else if (theTemp < myTemp.get_min()) { 00243 if (sysMonTime.read() > (lastTempAlertSecs + TempAlertWaitSecs)) { 00244 lcd.cls(); 00245 lcd.locate(0,3); 00246 lcd.printf("TEMP ALERT %.2f under %.2f - sending alert!\n", theTemp, myTemp.get_min()); 00247 tempLoLED = 1; 00248 if (state == monCONNECTED) { 00249 send_alert(TEMP_LOW); 00250 // clear if connected 00251 tempLoLED = 0; 00252 } 00253 else { 00254 store_alert(TEMP_LOW); 00255 } 00256 lastTempAlertSecs = sysMonTime.read(); 00257 } 00258 } 00259 00260 // See if it is time to store the temperature samples 00261 if (sysMonTime.read_ms()/MS_IN_SEC > (lastTimeMS + myTemp.get_period())) { 00262 // DEBUG lcd.printf("time to send temperature\n"); 00263 lastTimeMS = sysMonTime.read_ms()/MS_IN_SEC; 00264 myTemp.add_sample(get_temp()); 00265 } 00266 00267 //lcd.cls(); 00268 //lcd.locate(0,3); 00269 //lcd.printf("temp = %.2f\n", theTemp); 00270 00271 last_motion.x = current_motion.x; 00272 last_motion.y = current_motion.y; 00273 last_motion.z = current_motion.z; 00274 wait(0.3); 00275 } 00276 00277 }
Generated on Wed Jul 13 2022 20:30:35 by 1.7.2