Project 1 Self-powered Health & Security Monitoring System USB device
Dependencies: C12832_lcd LM75B MMA7660 USBDevice mbed
main.cpp
- Committer:
- wane
- Date:
- 2014-03-28
- Revision:
- 0:88dc49222b35
- Child:
- 1:930838234048
File content as of revision 0:88dc49222b35:
// Project: Self-powered USB Health and Security Monitoring Device (HSMD) /* 241: Added temp alarm 251: Added motion alarm, sensitivity level Validated alarm status handling 252: Added lock, passcode control, mode (T-Testing; O-Operational) 261: Added non-blocking serial entry TO-DO: implement USB connection detection try record sound try gps add menu to LCD */ #include "mbed.h" #include "C12832_lcd.h" #include "LM75B.h" #include "MMA7660.h" #include "USBKeyboard.h" // Configure device as USBKeyboard USBKeyboard dev; #define UP 0x1 #define DOWN 0x2 #define LEFT 0x4 #define RIGHT 0x8 #define ON true #define OFF false // System configuration parameters #define YEAR 2014 #define MONTH 3 #define DATE 26 #define HOUR 17 #define MIN 35 #define DEF_LOWER_TEMP 72 // Lower bound of monitoring temperature #define DEF_UPPER_TEMP 89 // Upper bound of monitoring temperature #define LOW_SEN 0.7 // Low sensitivity #define MID_SEN 0.5 // Medium sensitivity #define HIGH_SEN 0.3 // High sensitivity #define BUZZ_POWER 0.5 // Buzz power level #define BUZZ_SPERIOD 0.2 // Security alarm buzz period #define BUZZ_TPERIOD 1 // Temperature alarm buzz period // System I/O C12832_LCD lcd; PwmOut alarm(p21); BusIn joy(p15,p12,p13,p16); InterruptIn IRQJoyUp(p15); InterruptIn IRQJoyDown(p12); InterruptIn IRQJoyLeft(p13); InterruptIn IRQJoyRight(p16); //DigitalIn fire(p14); InterruptIn IRQFire(p14); Serial pc(USBTX, USBRX); // tx, rx LM75B Ctmp(p28,p27); AnalogIn pot1(p19); AnalogIn pot2(p20); MMA7660 MMA(p28, p27); DigitalOut connectionLed(LED1); DigitalOut lockLed(LED2); //PwmOut Xaxis_p(LED2); //BusOut leds(LED3,LED4); //DigitalOut ledTAlarm(LED3); //DigitalOut ledSAlarm(LED4); PwmOut ledSAlarm(LED4); PwmOut ledTAlarm(LED3); // Gobal parameters float setUpperTemp; // Upper bound of temperature monitoring range float setLowerTemp; // Lower bound of temperature monitoring range bool sAlarmOn; // State of alarm int statusAlarm; // Status indicating whether health or/and security alarm is triggered bool sHealthFeatureActive; // State indicating temperature monitoring is activated bool sSecurityFeatureActive; // State indicating motion monitoring is activated bool sLockActive; // State indicating lock is active char sState; // security setting state char gState; // Global state int buzzPattern; float buzzPeriod; Ticker timer1; Ticker timer3; Ticker timer4; Timer timer2; Ticker ticAlarm; bool first; int count; bool activated; // for debounce fire time_t yet; time_t now; int alarmType; // 0 - Health; 1 - Security char senLevel; // Sensitivity level of motion alarm int mode; // Operation mode: // 0 = Test mode (for testing features) // 1 = Lock mode (lock and unlock device) int passcode; // 4-digit passcode for lock and unlock bool sPCOK; // state indicating a valid passcode is existing bool updateCurTempDisplay; bool updateJoyDisplay; bool tempOverride; float lowerTempBase; // For simulated lower bound temperature float upperTempBase; // For simulated upper bound temperature float temp; bool entryReady; // For tracking if user input is comlete unsigned char entryState; // State tracking input entry char inBuf[128]; // Input buffer char pos; // Gobal buffer index float timeElapsed; int tol; // Tolerance for hysteresis effect time_t seconds; float potBase1; float potBase2; #ifdef C #define deg 'C' #else #define deg 'F' #endif typedef struct { bool active; float factor; unsigned char sym[3]; } SENTYPE; const SENTYPE senParm[4] = { { false, LOW_SEN, " " }, { true, LOW_SEN, "S1" }, // Low sensitivity { true, MID_SEN, "S2" }, // Mid sensitivity { true, HIGH_SEN, "S3" }, // High sensitivity }; const char modeSym[2] = { 'T', 'O' }; /* enum FUNCTION_KEY { KEY_SCROLL_LOCK = 141, // Scroll lock KEY_CAPS_LOCK, // caps lock KEY_NUM_LOCK, // num lock }; */ // Function prototype void ISRFirePressed(); void ISRJoyUp(); void ISRJoyDown(); void ISRJoyLeft(); void ISRJoyRight(); void debounce(); void buzzOn(int pattern, float period); void buzzOff(); void buzzTest(); void peepEntry(); void calibratePot(); bool EnterTemp(); bool SetPasscode(); bool UnlockPasscode(); void USBConnCheck(); void SetTime(int year, int month, int date, int hour, int min, int sec); void TempMonitor(); void ReadTemp(); void MotionMonitor(); void DisplayLCD(); void AlarmCheck(); void FSM(void); // ISR for fire button void ISRFirePressed() { now = time(NULL); if (!activated && now > yet) { tempOverride = !tempOverride; //EnterTemp(); if (tempOverride) gState = 3; yet = now + 1; activated = true; } } /* now = time(NULL); if (!activated && now > yet) { sAlarmOn = !sAlarmOn; yet = now + 1; activated = true; //first = true; count++; //printf("sAlarmOn: %d\n\r", sAlarmOn); } */ // ISR for joystick up direction void ISRJoyUp() { now = time(NULL); if (!activated && now > yet) { //if (mode == 1 && sPCOK == false) // EnterPasscode(); senLevel = (senLevel + 1) % 4; sSecurityFeatureActive = senParm[senLevel].active; updateJoyDisplay = true; yet = now + 1; activated = true; } } // ISR for joystick down direction void ISRJoyDown() { now = time(NULL); if (!activated && now > yet) { mode = (mode + 1) % 2; updateJoyDisplay = true; yet = now + 1; activated = true; } } // ISR for joystick left direction void ISRJoyLeft() { now = time(NULL); if (!activated && now > yet) { sHealthFeatureActive = !sHealthFeatureActive; updateJoyDisplay = true; yet = now + 1; activated = true; } } // ISR for joystick right direction void ISRJoyRight() { now = time(NULL); if (!activated && now > yet) { if (mode == 1) { if (!sLockActive) gState = 1; else gState = 2; } yet = now + 1; activated = true; } } // Debouncer function void debounce() { if (activated) activated = false; } // Turn on buzz in different patterns void buzzOn(int pattern, float period) { switch (pattern) { case 0: // Temperature alarm = BUZZ_POWER; wait(0.2); alarm = 0; wait(period); /* for(float p=0; p<1.0; p += 0.1) { alarm = p; wait(period); } */ break; case 1: // Security alarm = BUZZ_POWER; wait(0.2); alarm = 0; wait(period); break; } /* led = led + 0.01; wait(0.2); if(led == 1.0) { led = 0; } */ } // Turn on led in different patterns void ledOn(int type, float period) { switch (type) { case 0: ledTAlarm = 1; wait(0.1); ledTAlarm = 0; wait(0.05); break; case 1: for(int p=0; p<10; p += 1) { ledSAlarm = 1; wait(0.02); ledSAlarm = 0; wait(0.02); } /* ledSAlarm = 1; wait(0.1); ledSAlarm = 0; wait(0.02); */ break; } /* for(float p=0; p<1.0; p += 0.1) { leds = statusAlarm; wait(period); } */ /* led = led + 0.01; wait(0.2); if(led == 1.0) { led = 0; } */ } // Turn off alarm void buzzOff() { alarm = 0; } void buzzTest() { sAlarmOn = OFF; timer1.attach(&debounce, 1); //IRQFire.rise(&ISRFirePressed); //IRQFire.fall(&ISRFireRelease); //IRQJoyUp.rise(&ISRJoyUp); //IRQJoyDown.rise(&ISRJoyDown); alarm.period(0.020); // servo requires a 20ms period printf("Test starts...\n\r"); while (1) { if (sAlarmOn) { buzzOn(buzzPattern, buzzPeriod); printf("%s: pattern: %d period: %.1f count: %d\n\r", sAlarmOn? "ON": "OFF", buzzPattern, buzzPeriod, count); } else { buzzOff(); buzzPattern = (buzzPattern + 1) % 2; count = 0; } wait(0.02); } } // Set date and time // Input: Year, month, date, hour, minute, second void SetTime(int year, int month, int date, int hour, int min, int sec) { struct tm Clock; Clock.tm_year = year - 1900; Clock.tm_mon = month - 1; Clock.tm_mday = date; Clock.tm_hour = hour; Clock.tm_min = min; Clock.tm_sec = sec; time_t epoch = mktime(&Clock); if (epoch == (time_t) -1) { error("Error: Invalid clock setting! Please try again.\n"); } set_time(epoch); } // Calibrate analog pot to allow tuning each pot for controlling upper and lower bound control temperature void calibratePot() { potBase1 = pot1.read(); potBase2 = pot2.read(); //tempBase = temp; lowerTempBase = setLowerTemp; upperTempBase = setUpperTemp; updateJoyDisplay = true; wait(0.5); } // Non-blockingly innput a simulated temperature // Input: None bool EnterTemp() { int i; bool done = false; switch (entryState) { case 0: break; case 1: pc.printf("\n\rEnter a simulated temperature: "); entryReady = false; entryState = 2; break; case 2: peepEntry(); if (!entryReady) break; else entryState = 3; case 3: sscanf(inBuf, "%d", &i); if (i < 0 || i >= 100) { printf("\n\rEnter a temperature between 0F and 100F: "); entryReady = false; entryState = 2; break; } else { temp = i; printf("Current temperature is now %dF.\n\r", i); updateCurTempDisplay = true; entryState = 1; done = true; calibratePot(); break; } } return done; } // Peep if serial data is received and read if so void peepEntry() { int i; char c; i = pc.readable(); if (i > 0) { //pc.printf("%d: ", i); while (i > 0) { c = pc.getc(); if (c == '\r') { pc.printf("\n\r"); inBuf[pos] = '\0'; //pc.printf("Return: %s\n\r", inBuf); pos = 0; entryReady = true; } else { //pc.printf("%c\n\r", c); pc.putc(c); inBuf[pos] = c; pos++; } i--; } } } // Non-blockingly set a passcode // Input: None bool SetPasscode() { int i; bool done = false; switch (entryState) { case 0: break; case 1: if (statusAlarm & 0x80000000) { if (!sPCOK) entryState = 2; else entryState = 5; } else { pc.printf("No USB connection detected. Check USB device being connected.\n\r"); } break; case 2: pc.printf("\n\rEnter a 4-digit passcode: "); entryReady = false; entryState = 3; break; case 3: peepEntry(); if (!entryReady) break; else entryState = 4; case 4: sscanf(inBuf, "%d", &i); if (i < 0000 || i > 9999) { pc.printf("\n\rEnter a passcode between 0000 and 9999: "); entryReady = false; entryState = 3; break; } else { passcode = i; pc.printf("\n\rPasscode is set (%d).\n\r", passcode); sPCOK = true; entryState = 5; } case 5: sLockActive = true; lockLed = 1; updateJoyDisplay = true; pc.printf("USB is now locked. Enter passcode to unlock.\n\r"); entryState = 1; done = true; break; } return done; } // Non-blockingly enter data to unlock passcode bool UnlockPasscode() { int i = 0; bool done = false; switch (entryState) { case 0: break; case 1: pc.printf("\n\rTo unlock, enter a 4-digit passcode: "); entryReady = false; entryState = 2; break; case 2: peepEntry(); if (!entryReady) break; else entryState = 3; case 3: sscanf(inBuf, "%d", &i); if (i < 0000 || i > 9999) { pc.printf("\n\rEnter a passcode between 0000 and 9999: "); entryReady = false; entryState = 3; } else { if (passcode == i) { pc.printf("\n\r====> Unlock successful. :-) \n\r"); sLockActive = false; statusAlarm &= 0xFFFFFFFD; lockLed = 0; updateJoyDisplay = true; } else { pc.printf("\n\r====> Incorrect passcode!\n\r"); } done = true; entryState = 1; } break; } return done; } // Check if USB is connected // To read lock status: bit0=NUM_LOCK bit1=CAP_LOCK bit2=SCROLL_LOCK void USBConnCheck() { char status = 0; char result; //if (!(statusAlarm & 0x80000000)) //{ // dev.keyCode(KEY_NUM_LOCK); if (dev.keyCode(KEY_CAPS_LOCK)) printf("\rSend KEY_CAPS_LOCK OK\n\r"); status = dev.lockStatus(); //printf("1: lockStatus = 0x%x statusAlarm = 0x%x\n\r", status, statusAlarm); if (!(statusAlarm & 0x80000000) && (status & 0x2)) { statusAlarm |= 0x80000000; result = true; } else if ((statusAlarm & 0x80000000) && !(status & 0x2)) { statusAlarm &= 0x7FFFFFFF; result = false; } //printf("2: lockStatus = 0x%x statusAlarm = 0x%x\n\r", status, statusAlarm); //return result; } // Turn on and off the alarm comparing the current temperature with and the set temperature // Input: None void TempMonitor() { // Record current state of relay switch int tempAlarm = statusAlarm & 0x1; if (((temp < (setLowerTemp - tol)) || (temp > (setUpperTemp + tol))) && sHealthFeatureActive) { statusAlarm |= 0x1; alarmType = 0; } else if (((temp >= setLowerTemp) && (temp <= setUpperTemp)) || !sHealthFeatureActive) { statusAlarm &= 0xFFFFFFFE; } // When alarm is turned on or off if (tempAlarm != (statusAlarm & 0x1)) { seconds = time(NULL); char buffer[32]; strftime(buffer, 32, "%T", localtime(&seconds)); if (statusAlarm & 0x1) { if (timer2.read()) { timer2.stop(); pc.printf("Temperature Alarm off for %.2f sec.\n\r", timer2.read()); } timer2.reset(); pc.printf("Temperature Alarm on.... %s\n\r", buffer); timer2.start(); } else { timer2.stop(); timeElapsed = timer2.read(); pc.printf("Temperature Alarm off... %s (Duration: %.2f sec)\n\r", buffer, timeElapsed); timer2.reset(); timer2.start(); } updateJoyDisplay = true; } } // Read temperature sensor // Input: None void ReadTemp() { //temp = Ctmp.read(); temp = Ctmp.read()*1.8+32; updateCurTempDisplay = true; } // Monitor accelerometer to detect motion and turn on and off the alarm after comparing the motion data with // preconfigurated motion factor. void MotionMonitor() { //Xaxis_p = MMA.x() || -MMA.x(); float xpos, ypos, zpos; float senNum = senParm[senLevel].factor; xpos = MMA.x(); ypos = MMA.y(); zpos = MMA.z(); if ((xpos > senNum || xpos < -(senNum) || ypos > senNum || ypos < -(senNum)) && sSecurityFeatureActive) { statusAlarm |= 0x2; pc.printf("Security Alarm ON 0x%x(senNum: %f Xpos: %6.3f Ypos: %6.3f Zpos: %6.3f)\n\r", statusAlarm, senNum, xpos, ypos, zpos); //updateJoyDisplay = true; } else { if ((statusAlarm & 0x2) && (mode == 0 || !sLockActive)) { statusAlarm &= 0xFFFFFFFD; pc.printf("Security Alarm OFF 0x%x(Xpos: %6.3f Ypos: %6.3f Zpos: %6.3f)\n\r", statusAlarm, xpos, ypos, zpos); } //else // pc.printf("Security Alarm %s (Xpos: %6.3f Ypos: %6.3f Zpos: %6.3f)\n\r", (statusAlarm & 0x2)? "sON": "sOFF", xpos, ypos, zpos); //updateJoyDisplay = true; } } // Display date, time, heater state, relay state, current and set temperature at LCD // Input: None void DisplayLCD() { seconds = time(NULL); char buffer[32]; strftime(buffer, 32, "%F %T", localtime(&seconds)); lcd.locate(0,3); lcd.printf("%s\n",buffer); if (updateCurTempDisplay || updateJoyDisplay) { lcd.printf("Now: %.1f%c L:%3.0f%c U: %3.1f%c\n", temp, deg, setLowerTemp, deg, setUpperTemp, deg); updateCurTempDisplay = false; } if (updateJoyDisplay) { lcd.printf("Mode: %c %1s%2s Status: %s%s\n", modeSym[mode], sHealthFeatureActive? "H": " ", senParm[senLevel].sym, sLockActive? "L":" ", sAlarmOn? "A": " "); updateJoyDisplay = false; } } // Check if alarm is to be triggered by either temp or security events // Do buzz for temperature and security alarm events accordingly void AlarmCheck() { bool prevState = sAlarmOn; if (statusAlarm & 0x1 || statusAlarm & 0x2) sAlarmOn = ON; else sAlarmOn = OFF; if (statusAlarm & 0x80000000) connectionLed = 1; else connectionLed = 0; if (prevState != sAlarmOn) updateJoyDisplay = true; //leds = statusAlarm; if ((statusAlarm & 0x2) && (statusAlarm & 0x1)) { buzzOn(1, BUZZ_SPERIOD); ledOn(1, BUZZ_SPERIOD); ledOn(0, BUZZ_TPERIOD); } // Security alarm else if (statusAlarm & 0x2) { buzzOn(1, BUZZ_SPERIOD); ledOn(1, BUZZ_SPERIOD); } // Temperature alarm else if (statusAlarm & 0x1) { buzzOn(0, BUZZ_TPERIOD); ledOn(0, BUZZ_TPERIOD); } } // Initialize settings void Init(void) { SetTime(YEAR, MONTH, DATE, HOUR, MIN, 0); IRQFire.rise(&ISRFirePressed); IRQJoyUp.rise(&ISRJoyUp); IRQJoyDown.rise(&ISRJoyDown); IRQJoyLeft.rise(&ISRJoyLeft); IRQJoyRight.rise(&ISRJoyRight); timer1.attach(&DisplayLCD, 1); timer3.attach(&debounce, 1); //timer4.attach(&USBConnCheck, 2); timer4.attach(&AlarmCheck, 1); //timer2.attach(&ReadTemp, 5); sHealthFeatureActive = OFF; sSecurityFeatureActive = OFF; sAlarmOn = OFF; statusAlarm = 0; sState = 0; setLowerTemp = DEF_LOWER_TEMP; setUpperTemp = DEF_UPPER_TEMP; tempOverride = false; senLevel = 0; buzzPattern = 0; buzzPeriod = 0.2; mode = 0; timeElapsed = 0; entryState = 1; lcd.cls(); lcd.locate(0,3); updateJoyDisplay = true; calibratePot(); pc.printf("\n\rHealth & Security Monitoring starts...\n\r"); } // Main loop in executing major temperature, motion monitoring tasks and alarm check task void FSM(void) { while(1) { //USBConnCheck(); // Override temperature read for testing. Use pot to control temperature if (!tempOverride) ReadTemp(); setLowerTemp = lowerTempBase + (pot1.read()-potBase1) * 12; setUpperTemp = upperTempBase + (pot2.read()-potBase2) * 12; updateCurTempDisplay = true; switch (gState) { case 0: break; case 1: if (SetPasscode()) gState = 0; break; case 2: if (UnlockPasscode()) gState = 0; break; case 3: if (EnterTemp()) gState = 0; break; } MotionMonitor(); TempMonitor(); //AlarmCheck(); /* Live check lockLed = 1; wait (0.1); lockLed = 0; wait(0.1); */ } } int main() { //buzzTest(); Init(); FSM(); }