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
main.cpp
- Committer:
- ml13emds
- Date:
- 2015-05-11
- Revision:
- 0:28fa9993bcf9
File content as of revision 0:28fa9993bcf9:
/**
@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);
}