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); }