Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: MMA8452 N5110 PowerControl mbed
Diff: main.cpp
- Revision:
- 0:28fa9993bcf9
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon May 11 03:38:15 2015 +0000 @@ -0,0 +1,361 @@ +/** +@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); +} \ No newline at end of file