Source code for project Smart Alarm (Georgia Tech ECE 4180)

Dependencies:   SDFileSystem beep mbed

Fork of ADXL345_I2C by Peter Swanson

main.cpp

Committer:
ivygatech
Date:
2014-05-01
Revision:
2:13d5673286e2
Parent:
0:d0adb548714f

File content as of revision 2:13d5673286e2:

#include "ADXL345_I2C.h"
//#include "SDFileSystem.h"
#include "beep.h"
#include "string.h"
#include "time.h"
#include "mbed.h"

//SDFileSystem sd(p5, p6, p7, p8, "sd"); // the pinout on the mbed Cool Components workshop board
ADXL345_I2C accelerometer(p28, p27);
Serial bluetooth(p9, p10);
Serial pc(USBTX, USBRX);

// pin for load sensors
AnalogIn load1(p19);
AnalogIn load2(p20);

// pin for PowerSSRtail output
DigitalOut SSR(p21);
// pin for ZeroCross tail input // An external 1K pullup required
InterruptIn zerocross(p22);

// Beep with 1Khz for 0.5 seconds
Beep buzzer(p23);

PwmOut led_dim(LED1); // light dimmer
//DigitalOut led(LED2); // load detection
//DigitalOut led_r(LED3); // bluetooth readable
//DigitalOut led_w(LED4); // bluetooth writeable

//use timer interrupts to control dimming
Timeout SSRtriggerOn;

// dimmer value 0.0=off and 1.0=full on
volatile float dim;

// AC power line frequency
const float powerlinefrequency=60.000;

// this interrupt routine is activated after a time delay set by dim value
void triggerOn(){
    SSR = 1;
}

// this interrupt routine is activated by every AC line zero crossing
// it is needed to synchronize the SCR turnon time delay to the AC line
void dimmer()
{
    // turn off SSR at zero crossing
    SSR = 0;
    // compute time delay using dim value and set timer interrupt
    // triggers SSR after a small post zero crossing time delay
    SSRtriggerOn.attach(&triggerOn,(1.001-dim)/(2*powerlinefrequency));
}

int main() {
    char sysStart,sysAck;
    char readBuf[] = "00000";
    char writeBuf[] = "000.00T";
    
    int readings[3] = {0, 0, 0};
    int16_t offsetXsum = 0, offsetYsum = 0, offsetZsum = 0;
    double offsetX, offsetY, offsetZ;
    double moveCurr, moveAccu, moveMax, moveAve;
    int dataCount = 0;
    double wakeThresh = 15;
    char wakeDetect = 'F'; // set to 'T' if the user is already awake
    char loadDetect = 'F'; // set to 'T' if the user is still in bed
    
    int trackTime = 300;  // time duration of tracking sleep data. Default 6 hours (21600), should be set by Android.
    int intvTime = 5; // time interval of sending data to Android. Default is 60, here set to 5 for demo.
    int smartTime = 100; // time ahead of preset alarm time to determine the user is already in light-sleep. Default is 15 minutes (900 seconds), here set to 100 for demo.
    int snoozeTime = 15; // time to turn off the system after the user get out off bed for a certain period. Default 15 minutes (900 seconds), here set to 15 for demo.
    
    // set up timer to track system running time
    time_t tStart;
    set_time(1256729737);
    
// ====================================== HARDWARE SETUP ============================================================    
    pc.printf("\n\n\nStarting smart alarm...\n");
    wait(.001);
    
    // Get accelerometer device address
    pc.printf("ADXL345 Device ID is: 0x%02x\n", accelerometer.getDeviceID());
    wait(.001);
    
    // These are here to test whether any of the initialization fails. It will print the failure
    if (accelerometer.setPowerControl(0x00)){
         pc.printf("fail to intitialize power control\n"); 
         return 0;  }
    // Full resolution, +/-16g, 4mg/LSB.
    wait(.001);
    
    if(accelerometer.setDataFormatControl(0x0B)){
        pc.printf("fail to set data format\n");
        return 0;  }
    wait(.001);
     
    // 3.2kHz data rate.
    if(accelerometer.setDataRate(ADXL345_3200HZ)){
        pc.printf("fail to set data rate\n");
        return 0;    }
    wait(.001);
     
    // Measurement mode.
    
    if(accelerometer.setPowerControl(MeasurementMode)) {
        pc.printf("fail to set the power control to measurement\n"); 
        return 0;   } 
    
    // Calibrate the accelerometer
    for (int oi = 0; oi < 10; oi++) {
        accelerometer.getOutput(readings);
        pc.printf("Offset: %5i, %5i, %5i\n", (int16_t)readings[0], (int16_t)readings[1], (int16_t)readings[2]);
        offsetXsum += (int16_t)readings[0];
        offsetYsum += (int16_t)readings[1];
        offsetZsum += (int16_t)readings[2];
        wait(0.001);
    }
    offsetX = offsetXsum/10.0;
    offsetY = offsetYsum/10.0;
    offsetZ = offsetZsum/10.0;
    pc.printf("Average: %5.2f, %5.2f, %5.2f\n",offsetX,offsetY,offsetZ);
    
    // Bluetooth setup
    bluetooth.baud(115200);
    wait(0.05);
    
    // Set up interrupt routine to detect AC line zero crossings
    dim = 1.0; led_dim = dim;
    zerocross.mode(PullNone);
    wait(0.2);
    zerocross.rise(&dimmer);
       
// ====================================== SYSTEM START ==============================================================
    sysAck = 'A';
    while(1){
        if (!bluetooth.readable()){;}
        else{
            sysStart = bluetooth.getc(); // read start signal
            pc.printf("start? %c\n",sysStart);
            if (sysStart=='S'){
                time(&tStart); // record starting time
                wait(0.1);
                if (bluetooth.writeable()){//;}
                //else{
                    bluetooth.putc(sysAck); // send acknowledge signal
                    pc.printf("ack? %c\n",sysAck);
                    wait(1);
                    for (int ri=0;ri<5;ri++){ // read trackTime value (seconds - 5 bits)
                        if (bluetooth.readable()){//;}
                        //else{
                            readBuf[ri] = bluetooth.getc();
                            pc.printf("Bits received: %c\n",readBuf[ri]);
                            wait(0.01);
                        }   
                    }
                    break;
                }
            }
        }
    }
    sscanf (readBuf,"%d",&trackTime);
    pc.printf("Received tracking time: %5d\n\n",trackTime);
    if (trackTime==0) trackTime=100;
    
    // dim light
    for(dim = 1.0; dim >= 0.0; dim -= 0.02) {
        led_dim = dim;
        wait(0.1);
    }
    dim = 0.0; led_dim = dim;

// ====================================== SLEEP TRACKING ============================================================
//    mkdir("/sd/sleepdata", 0777);
    
//    FILE *fp = fopen("/sd/sleepdata/20140430.csv", "w");
//    if(fp == NULL) {
//        error("Could not open file for write\n");
//    }    

    while (time(NULL)-tStart<=trackTime) {
       //dim = 0.0;
       pc.printf("seconds elapsed: %5d of %5d; ",time(NULL)-tStart,trackTime);
       wakeDetect = 'F';
       //led_r = bluetooth.readable();
       //led_w = bluetooth.writeable();
       
       accelerometer.getOutput(readings); dataCount++;
       //pc.printf("%5i, %5i, %5i; ", (int16_t)readings[0], (int16_t)readings[1], (int16_t)readings[2]);
       moveCurr = sqrt(pow((int16_t)readings[0]-offsetX,2)+pow((int16_t)readings[1]-offsetY,2)+pow((int16_t)readings[2]-offsetZ,2));
       pc.printf("movement: %5.2f \n",moveCurr);
//       fprintf(fp,"%.2f\n",moveCurr);
       
       if (dataCount%intvTime != 0) {
           moveAccu += moveCurr;
           if (moveCurr > moveMax){
               moveMax = moveCurr;
            }
        }
        else {
            moveAve = moveAccu/intvTime;
            if ((time(NULL)-tStart+smartTime>trackTime) && (moveAve > wakeThresh)) wakeDetect = 'T';
            pc.printf("seconds elapsed: %5d, time diff: %5d; \n",time(NULL)-tStart,time(NULL)-tStart+smartTime-trackTime);
            
            sprintf(writeBuf, "%6.2f%c",moveMax,wakeDetect);
            pc.printf("Max: %.2f, Ave: %5.2f, Send: %s\n\n", moveMax, moveAve, writeBuf);

            for (int wi = 0; writeBuf[wi]!='\0'; wi++){
                if (bluetooth.writeable()){//;}
                //else {
                    bluetooth.putc(writeBuf[wi]);
                    pc.printf("Bits sent: %c\n",writeBuf[wi]);
                    wait(0.01);
                }
            }
            
            dataCount = 0;
            moveAccu = 0;
            moveMax = 0;
        }
       
       wait(1);
    }
//    fclose(fp);
    pc.printf("Tracking completed...\n\n\n");
    
    // turn on the light at pre-set alarm time
    for(dim = 0.0; dim <= 1.0; dim += 0.02) {
        led_dim = dim;
        wait(0.1);
    }
    dim = 1.0; led_dim = dim;


// ====================================== AUTO-SNOOZE ===============================================================
    wait(10);
    time(&tStart);
    loadDetect = 'F';
    while (time(NULL)-tStart<snoozeTime){
       dim = 1.0;
       
       pc.printf("%5.2f, %5.2f;  ",1-load1.read(),1-load2.read());
       if(load1.read() < 0.5 || load2.read() < 0.5) {
            loadDetect = 'T';
       } else {
            loadDetect = 'F';
       }
       pc.printf("load detected: %c\n",loadDetect);
       
       if (loadDetect=='T') {
           pc.printf("Oops...\n");
           buzzer.beep(rand()%740+260,0.5);
           dim = 0.5; led_dim = dim; wait(0.5);
           dim = 1.0; led_dim = dim; wait(0.5);
           time(&tStart);
        }
        else {
            pc.printf("Good job...don't fall back...%d seconds to go...\n",snoozeTime+tStart-time(NULL));
            wait(1);
        }
    }
    pc.printf("Congrats!LOL\n");
    
    // turn off light when user gets up or after snooze duration
    for(dim = 1.0; dim >= 0.0; dim -= 0.02) {
        led_dim = dim;
        wait(0.01);
    }
    dim = 0.0; led_dim = dim;
    pc.printf("Snoozing completed...System pause...\n\n\n");
    
}