Project of a Pedometer for the module ELEC 2645 in the University of Leeds

Dependencies:   MMA8452 N5110 PowerControl mbed

main.cpp

Committer:
ml13emds
Date:
2015-05-11
Revision:
1:edcb0cf0f3ac
Parent:
0:28fa9993bcf9

File content as of revision 1:edcb0cf0f3ac:

/**
@file main.cpp
 
@brief Pedometer implementation using the sensor Triple Axis Accelerometer Breakout - MMA8452Q
 
*/

#include "main.h"

int main()
{
    /// Finite State Machine that cotrols the whole system
    //Setting the initial state. Avoiding rubish values
    state = 0;
    I1_flag = 0;
    I2_flag = 0;
    
    // Adressing the rise of pin 15(which is connected to I1 of Sensor)to the interruption routine 1
    I1.rise(&Interrupt);
    
    // Adressing the rise of pin 16(which is connected to I2 of Sensor)to the interruption routine 2
    I2.rise(&Interrupt2);  

    while(1)
    {    
        // Main state machine 
        switch (state)
        {
            // Keep the device sleeping if no interruption is generated
            case 0:
            {
                    wait(0.7); 
                    // If an interruption is generated, check where it came from
                    if(I1_flag)
                    {
                        // Reading the cause of the interruption
                        Int_SourceSystem = mma8452.readByteFromRegister(INT_SOURCE);
                        // Checking if the Transient detection is the cause of the interruption generated
                        if ((Int_SourceSystem&0x20)==0x20) 
                        {
                            // Clearing the interrupt system for Transient Detection
                            Int_SourceTrans = mma8452.readByteFromRegister(TRANSIENT_SRC); 
                            // Clearing the interrupt system for Pulse Detection
                            Int_SourceTrans = mma8452.readByteFromRegister(PULSE_SRC); 
                            Int_SourceSystem = 0;
                            // Wait 200ms to make sure the intrrupt system is cleaned
                            wait(0.2); 
                            I1_flag = 0; 
                            I2_flag = 0; 
                            lcd.init();
                            // Choose the normal colour mode
                            lcd.normalMode();
                            // Set the LED backlight to 10%  
                            lcd.setBrightness(0.1);
                            // Clear the screen
                            lcd.clear();
                            // Starts the execution timer for next Menu
                            timer1.attach(&TimerExpired1,20.0);
                            timerFlag1 = 0;
                            // Going to the initial screen
                            state = 1;
                       
                        }
                    }
                    // If no interruption is generated, it keeps mbed sleeping and display turned off
                    else
                    {
                        lcd.turnOff();
                        // Standard initialisation used here due to different initialisations settings used through the code
                        // Sets the scale to 4g, 100Hz of ODR and set the Transient and Pulse Detection
                        mma8452.init();
                        timer1.detach();
                        timer2.detach();
                        timerFlag1 = 0;
                        timerFlag2 = 0;
                        Sleep();
                    }       
                break;
            }
            // Wait for an user command befor the timer counting ends
            case 1:
            {
                    lcd.printString("Welcome!",0,0);
                    lcd.printString("Tap for graph",0,2);
                    lcd.printString("Or",0,3);
                    lcd.printString("Shake for",0,4);
                    lcd.printString("Counting steps",0,5); 
                    wait(1); 

                    // Checking if an Transient Detection interrupt is generated (Countinuos shake)
                    if(I1_flag)
                    {
                        // Reading the cause of the interruption
                        Int_SourceSystem = mma8452.readByteFromRegister(INT_SOURCE);
                        // If the Transient detection is the cause of the interrupt generated
                        if ((Int_SourceSystem&0x20)==0x20)
                        {
                            // Goes to step counting screen
                            state = 2;
                        }
                    }

                    // Checking if an Pulse Detection interrupt is generated (Just a tap to left or right)                    
                    else if((I2_flag)&&(!I1_flag))
                    {
                        // Reading the cause of the interrupt
                        Int_SourceSystem = mma8452.readByteFromRegister(INT_SOURCE);
                        // If the Pulse detection is the cause of the interrupt generated
                        if ((Int_SourceSystem&0x08)==0x08) 
                        {
                            // Clearing the Transient interrupt system
                            Int_SourceTrans = mma8452.readByteFromRegister(TRANSIENT_SRC);
                            // Clearing the Transient interrupt system
                            Int_SourceTrans = mma8452.readByteFromRegister(PULSE_SRC);
                            Int_SourceSystem = 0;
                            // Wait 200ms to make sure the intrrupt system is cleaned
                            wait(0.2);
                            I1_flag = 0; 
                            I2_flag = 0;   
                            timer1.attach(&TimerExpired1,20.0);
                            timerFlag1 = 0;
                            lcd.clear();
                            // Going to the Km/day graph screen
                            state = 3;
                        }
                    }
                    // If no interrupt is generated and the timer finishes the counting, turn off the device again
                    else if(timerFlag1)
                    {
                        timerFlag1 = 0;
                        Int_SourceTrans = mma8452.readByteFromRegister(TRANSIENT_SRC); 
                        Int_SourceTrans = mma8452.readByteFromRegister(PULSE_SRC); 
                        Int_SourceSystem = 0;
                        wait(0.2);
                        I1_flag = 0;  
                        I2_flag = 0;  
                        state = 0;   
                    }   
                break;
            }
            // Steps counting Screen. Also save data.
            case 2:
            {
                    // Changes the scale to 2g, the ODR to 800Hz and set the output data to be read from the High Pass Filter
                    mma8452.transient_counting();                                                
                    lcd.clear();
                    buzzer = 0.5;
                    lcd.printString("Calibrating...",0,0);
                    wait(5);
                    // Take a average of the 50 values of the device before counting steps. Kind of calibration
                    acc_avg = mma8452.average();  
                    buzzer = 0;
                    step = 0; 
                    km = 0;
                    leds = 0x04; 
                    aux = 0; 
                    timerFlag2 = 0;
                    timer3.attach(&TimerExpired3,1);
                    // While the timer does not end, keep counting
                    while(!timerFlag2)
                    {    
                        acceleration = mma8452.readValues();   // read current values 
                        sub_x = acceleration.x - acc_avg.x;
                        sub_y = acceleration.y - acc_avg.y;
                        sub_z = acceleration.z - acc_avg.z;
                        acc_vector = (pow(sub_x,2.0)+pow(sub_y,2.0)+pow(sub_z,2.0)); 
                        acc_vector = sqrt(acc_vector);
                        // If the acceleration vector is greater than 0.15, add the steps
                        if(acc_vector > 0.15)
                        {
                             step = step + 2;
                             // Runing
                             if (acc_vector > 1.0)
                                km = km + 0.002;
                             // Walking
                             else
                                km = km + 0.001;     
                        }

                        lcd.clear(); 
                              
                        length = sprintf(buffer,"%6u steps",step); 
                        if (length <= 14)                 
                            lcd.printString(buffer,0,0);  
                        
                        length = sprintf(buffer,"%6.3f km",km); 
                        if (length <= 14)                 
                            lcd.printString(buffer,0,1); 
                        
                        length = sprintf(buffer,"%2u:%2u:%2u",hour, minute, second); 
                        if (length <= 14)                 
                            lcd.printString(buffer,0,2);                             
                              
                        // get current date    
                        time_t seconds = time(NULL);  
                        // Convert date to a string
                        strftime(buffer, 14 , "%a-%d/%m/%Y", localtime(&seconds));
                        lcd.printString(buffer,0,3);
                        
                        // Avoiding counting the same steps twice                                       
                        wait(0.65);
                        
                        // If one stops the activity, starts the timer
                        if ((acc_vector <0.15)&& (aux==0))
                        {
                            timer2.attach(&TimerExpired2,20.0);
                            aux = 1;
                        }
                        // If one walks again, reset the timer
                        else if ((acc_vector >0.15)&&(aux == 1))
                        {
                            timer2.detach();
                            aux = 0;
                        }

                    }   
                    buzzer = 0.5;
                    wait(3);
                    buzzer = 0;
                    Int_SourceTrans = mma8452.readByteFromRegister(TRANSIENT_SRC); 
                    Int_SourceTrans = mma8452.readByteFromRegister(PULSE_SRC);
                    Int_SourceSystem = 0;
                    wait(0.2);
                    timer3.detach();
                    second = 0;
                    minute = 0;
                    hour = 0;
                    I1_flag = 0;
                    timerFlag2 = 0;
                    // Saving data to local system File
                    writeDataToFile(buffer,step,km);
                    // Accumulating the steps per day value
                    time_t seconds = time(NULL);
                    strftime(buffer, 3 , "%u", localtime(&seconds));
                    int value = atoi(buffer);   
                    km_day[value]=km_day[value]+km;
                    state = 0;
                    break;
               }
               // Graph Km/day Screen 
               case 3:
               {
                        lcd.printString("Km/day",10,0);
                        lcd.printString("8",10,1);
                        lcd.printString("6",10,2);
                        lcd.printString("4",10,3);
                        lcd.printString("2",10,4);
                        lcd.printString("0",10,5);
                        lcd.drawRect(17,7,60,40,0);
                        // Logic to print the graph with all days
                        for (int x = 1; x < 30; x++) 
                        {
                            float n_pix = 8.0/36.0;
                            int last_point = ((8.0-km_day[x-1])/(n_pix));
                            int point = ((8.0-km_day[x])/(n_pix));
                            lcd.drawLine((x-1)+18,last_point+9,x+18,point+9,1);
                        }
                        lcd.refresh();
                        // If the system detects the tap again, it goes back to initial screen
                        if(I2_flag)
                        {
                            Int_SourceSystem = mma8452.readByteFromRegister(INT_SOURCE);
                            if ((Int_SourceSystem&0x08)==0x08)
                            {
                                Int_SourceTrans = mma8452.readByteFromRegister(TRANSIENT_SRC); 
                                Int_SourceTrans = mma8452.readByteFromRegister(PULSE_SRC);
                                Int_SourceSystem = 0;
                                wait(0.2);
                                I1_flag = 0; 
                                I2_flag = 0;   
                                timer1.attach(&TimerExpired1,20.0);
                                timerFlag1 = 0;
                                state = 1;
                            }
                        }
                        // If the user does not perform any action in 20 seconds, turn off the device
                        else if(timerFlag1)
                        {
                            timerFlag1 = 0;
                            Int_SourceTrans = mma8452.readByteFromRegister(TRANSIENT_SRC);
                            Int_SourceTrans = mma8452.readByteFromRegister(PULSE_SRC);
                            Int_SourceSystem = 0;
                            wait(0.2);
                            I1_flag = 0;  
                            I2_flag = 0;  
                            state = 0;   
                        }  
                        wait(1); 
                        lcd.clear();
                    break;
                }
               
               default:
                    //invalid state - call error routine
                    error();
                break;                   
        }
    }        
}

void Interrupt()
{
    /// Controls the Transient Detection Interrupt flag
    I1_flag = 1;
}

void Interrupt2()
{
    /// Controls the Pulse(Tap)Detection Interrupt flag
    I2_flag = 1;
}

void error() 
{
    /// Error function. In case of error of the state machine
    while(1) 
    { 
        lcd.clear();
        lcd.printString("FSM Error!",0,0);
    } 
}

void TimerExpired1()
{
    /// Timer 1 flag
    timerFlag1 = 1;
}

void TimerExpired2()
{
    /// Timer 2 Flag
    timerFlag2 = 1;
}

void TimerExpired3()
{
    /// Calculates the chronometer time
    second = second + 1;
    if (second > 60)
    {
        second = 0;
        minute = minute + 1;
        if (minute > 60)
        {
            hour = hour + 1;
            minute = 0;
        }
   
    }    
}

void writeDataToFile(char *date,int data1,float data2)
{
    /// Saves the km and steps data to flash disk
    FILE *fp = fopen("/local/log.txt", "a");
    // Create the txt file
    fprintf(fp,"Date: %s\n",date);
    fprintf(fp,"Steps = %6u\n",data1);
    fprintf(fp,"Km = %6.3f\n \n",data2);
    fclose(fp);
}