This is a repository for code relating to mbed Fitness Tracker

Dependencies:   mbed PulseSensor2 SCP1000 mbed-rtos 4DGL-uLCD-SE LSM9DS1_Library_cal PinDetect FatFileSystemCpp GP-20U7

Files at this revision

API Documentation at this revision

Comitter:
dyu2021
Date:
Sat Apr 25 17:37:42 2020 +0000
Parent:
35:c14c5059f5b7
Child:
38:d20bdc0a670d
Commit message:
Finalized code

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/main.cpp	Sat Apr 25 02:42:39 2020 +0000
+++ b/main.cpp	Sat Apr 25 17:37:42 2020 +0000
@@ -20,7 +20,6 @@
 AnalogIn pot(p20);
 PinDetect pb(p21);
 GPS gps(p13, p14);
-DigitalIn pb2(p19, PullUp);
 
 #define FSNAME "msc"
 MSCFileSystem msc(FSNAME); 
@@ -37,8 +36,6 @@
 unsigned long pressure;
 float latitude = 0;
 float longitude = 0;
-float old_lat = 0;
-float old_lon = 0;
 #define PI 3.14159
 unsigned long p_buff[4];
 int count = 0;
@@ -69,36 +66,58 @@
 Mutex usb_mtx;
 
 //Saves current configuration in a text file
+//Saved in format gender, age, weight and step goal separated by tabs
 void save_config() {
     usb_mtx.lock();
+    two = 1;
     FILE *fp = fopen( "/msc/config.txt", "w");
     if(fp == NULL) {
-        error("Could not open file for write\n");
+        pc.printf("Could not open file for write\n");
+    } else {
+        fprintf(fp, "%d\t%d\t%d\t%d\n\r", gender, age, weight, stepGoal);
+        //pc.printf("Config saved\r\n");
+        fclose(fp);
     }
-    fprintf(fp, "%d\t%d\t%d\t%d\n\r", gender, age, weight, stepGoal);
-    //pc.printf("Config saved\r\n");
-    fclose(fp);
+    two = 0;
     usb_mtx.unlock();
 }
 
-//Reads configuration file and sets up all the values
-void read_config() {
+//Reads configuration file and sets up user specific values and the last saved 
+//activity date
+//If files don't exist or are empty, will return false, else returns true
+bool read_config() {
     usb_mtx.lock();
+    three = 1;
     FILE *fp1 = fopen( "/msc/config.txt", "r");
     FILE *fp2 = fopen("/msc/data.txt", "r");
     if(fp1 == NULL || fp2 == NULL) {
-        error("Could not open file for read\n");
+        pc.printf("Could not open file for read\n");
+        //Go back to first setup screen if files don't exist
+        screen = 1;
+        usb_mtx.unlock();
+        return false;
+    } else {
+        char buf[128];
+        //Read config file to setup user specific values and data file to load last
+        //stored data. If config file empty, then go back to setup screen
+        if (fscanf(fp1, "%d\t%d\t%d\t%d", &gender, &age, &weight, &stepGoal) != EOF) {
+            fscanf(fp2, "%s\t%d\t%d\t%f\t%f", buf, &steps, &flights, &calories, &distance);
+            //pc.printf("Data loaded\r\n");
+        } else {
+            //files empty, go back to setup screen
+            screen = 1;
+            fclose(fp1);
+            fclose(fp2);
+            three = 0;
+            usb_mtx.unlock();
+            return false;
+        }
+        fclose(fp1);
+        fclose(fp2);
+        three = 0;
+        usb_mtx.unlock();
+        return true;
     }
-    char buf[128];
-    pc.printf("Starting Config loaded\r\n");
-    fscanf(fp1, "%d\t%d\t%d\t%d", &gender, &age, &weight, &stepGoal);
-    pc.printf("Config loaded\r\n");
-    //Check if data file is empty
-    fscanf(fp2, "%s\t%d\t%d\t%f\t%f", buf, &steps, &flights, &calories, &distance);
-    pc.printf("Data loaded\r\n");
-    fclose(fp1);
-    fclose(fp2);
-    usb_mtx.unlock();
 }
 
 // when the pushbotton is pressed the run flag is set to false and the main 
@@ -108,21 +127,19 @@
     run = false;
 }
 
+//Switches to next screen in setup mode with a button press
 void next() {
-    //pc.printf("Button pressed\r\n");
     oldScreen = screen;
     screen++;
-    //pc.printf("asdfsf\r\n");
     if (usePrev) {
-        //pc.printf("Entering read config\r\n");
         readConfig = true;
     } else if(screen == 6) {
         setup_state = false;
     }
 }
 // Reads the value of the potentiometer and averages over 3 readings to get rid 
-// of random spikes/zero values. Returns either a 1, 2 or 3 based on which 3rd 
-// of its range the potentiometer is in and which screen should be displayed
+// of random spikes/zero values. Returns either a number 1-5 that indicates
+// which screen should be displayed
 void read_pot() {
     float m1; 
     float m2;
@@ -142,10 +159,9 @@
     } else if(m1 >= 0.8 && m2 >= 0.8 && m3 >= 0.8) {
         mode = 5;
     }
-    //when the mode changes, clear the screen
 }    
  
-//Display the time on the top
+//Display the time on the top of the screen
 void display_time() {
     while(1) {
         serial_mtx.lock();
@@ -162,22 +178,22 @@
     }
 }
 
+//Setup mode where user enters their gender, age, weight, and daily step goal
 void setup_screen(void) {
     while(1) {
         serial_mtx.lock();
+        //when chnage in screen, clear the LCD screen
         if (oldScreen != screen) {
             uLCD.filled_rectangle(0,0, 128, 128, BLACK);
             oldScreen++;
         }
         switch(screen) {
-            //Add additional case for Use Previous setup
-            //If yes, then set set_up to false and call read_config()
-            //If no, then continue. After setup, save_config() is called
+            //Checks if user wants to enter new configuration or use previous one
             case 1: 
-                uLCD.locate(2, 1);
+                uLCD.locate(1, 1);
                 uLCD.text_width(1);
                 uLCD.text_height(1);
-                uLCD.puts("Use Previous Configuration?");
+                uLCD.puts("Use Previous \nConfiguration?");
                 uLCD.text_width(3);
                 uLCD.text_height(3);
                 uLCD.locate(1, 3);
@@ -269,7 +285,7 @@
                 uLCD.puts("Daily Step Goal");
                 char step_string[5];
                 if(pot.read() < 0.2) {
-                    stepGoal = 500;
+                    stepGoal = 100;
                     sprintf(step_string, "  %d", stepGoal);
                 }else if(pot.read() < 0.4) {
                     stepGoal = 1000;
@@ -296,15 +312,16 @@
         Thread::wait(100);
     }
 }
- 
+
+//Displays live activity data on LCD Display
 void update_screen(void) {
     while(1) {
         read_pot();
         serial_mtx.lock();
+        //If change in mode, clear screen
         if (oldMode != mode) {
             uLCD.filled_rectangle(0,0, 128, 128, BLACK);
         }
-        // print the information to the LCD display
         switch(mode) {
             case 1:
                 //Step count
@@ -369,13 +386,13 @@
     }
 }
 
+//Read heart rate sensor and calculates calories burned
 void readHR(){
     while(1) {
         bpm = PPG.get_BPM();
-        //calories = calories + (.0083)*.239*(gender*(-55.0969+.6309*bpm+.1988*weight+.2017*age)+(1-gender)*(-20.4022+.4472*bpm-.1263*weight+.074*age));
+        //Formula that calculates calories based off heart rate and user data
         calories = calories + (.0083)*0.239*(gender*(-55.0969+.6309*bpm+.1988*0.453592*weight
-                                             +.2017*age)+(1-gender)*(-20.4022+.4472*bpm-.1263*0.453592*weight+.074*age));
-        //converted weight from lbs to kilograms
+                +.2017*age)+(1-gender)*(-20.4022+.4472*bpm-.1263*0.453592*weight+.074*age));
 
         //Alternate way to calculate distance (likely more accurate)
         //distance = distance + (steps - oldSteps)* stride_length;
@@ -384,6 +401,7 @@
     }
 }
 
+//Reads barometer and detects floors climbed
 void readBarometer()
 {
     while(1) {
@@ -406,8 +424,11 @@
         Thread::wait(2000);
     }
 }
-        
+
+//Read GPS to get current longitude and latitude and also calculate distance traveled
 void readGPS(){
+    float old_lat = 0;
+    float old_lon = 0;
     while(1) {
         serial_mtx.lock();
         if(gps.connected()) {
@@ -437,9 +458,13 @@
     }
 }
 
+//Saves current activity data to data.txt
+//Data saved in the format date, steps, flights, calories, and distance separated by tabs
+//Prev_data.txt stores the daily activity data over the past week
 void save_data() {
     // Save the data to the usb flash drive and print to the terminal
     usb_mtx.lock();
+    two = 1;
     FILE *fp = fopen( "/msc/data.txt", "w");
     if(fp == NULL) {
         error("Could not open file for write\n");
@@ -447,11 +472,13 @@
     time_t seconds = time(NULL);
     char temp_date[32];
     strftime(temp_date, 32, "%m/%d/%y", localtime(&seconds));
-    //pc.printf("Temp: %s\r\n", temp_date);
+    
+    //If the date has changed, indicating new day, then append current data to prev_data.txt
+    //Reset all activity data to zero
     if (strcmp(temp_date, date) != 0) {
         FILE *fp2 = fopen("/msc/prev_data.txt", "a");
         if(fp2 == NULL) {
-        error("Could not open file for append\n");
+            error("Could not open file for append\n");
         }
         //pc.printf("Writing to prev_data.txt\r\n");
         fprintf(fp2, "%s\t%d\t%d\t%0.2f\t%0.2f\n", date, steps, flights, calories, distance);
@@ -463,12 +490,13 @@
         distance = 0;
     } else if (strcmp(temp_date, date) == 0) {
         fprintf(fp, "%s\t%d\t%d\t%0.2f\t%0.2f\n", date, steps, flights, calories, distance);
-        //pc.printf("%s\t%d\t%d\t%0.2f\t%0.2f\n\r", date, steps, flights, calories, distance);
     }
     fclose(fp);
     usb_mtx.unlock();
 }
 
+//Waits for command from GUI and once command received, transfer all the data stored
+//in prev_data.txt to the GUI which will be plotted
 void serial_USB() {
     float buf_distance[2], buf_calories[2];
     int buf_steps[2],buf_flights[2];
@@ -493,7 +521,7 @@
             }
         }
         usb_mtx.unlock();
-        Thread::wait(100);
+        Thread::yield();
     }
 }
     
@@ -501,8 +529,8 @@
     //Set RTC time
     set_time(1256729737);
     time_t seconds = time(NULL);
+    //Keep track of the date mbed Fitbit was first turned on
     strftime(date, 32, "%m/%d/%y", localtime(&seconds));
-    //pc.printf("%s\r\n", date);
     
     // Next screen button
     pb.mode(PullUp);
@@ -513,15 +541,20 @@
     uLCD.baudrate(3000000);
     uLCD.background_color(BLACK);
     uLCD.cls();
+    //Thread to display setup screens
     thread1.start(setup_screen);
     
     while(setup_state) {
         if (readConfig) {
-            read_config();
-            setup_state = false;
+            if (read_config()) {
+                setup_state = false;
+            } else {
+                setup_state = true;
+                usePrev = false;
+                readConfig = false;
+            }
         }
         Thread::yield();
-        //pc.printf("%d\r\n", screen);
     }
     thread1.terminate();
     save_config();
@@ -529,7 +562,7 @@
     // Off button
     pb.attach_deasserted(&button);
     
-    // set up the display
+    // set up the display for displaying real time data and clock
     uLCD.cls();
     thread1.start(update_screen);
     thread2.start(display_time);
@@ -544,14 +577,15 @@
     PPG.start();
     IMU.begin();
     IMU.calibrate(1);
-    float ax;
-    float ay;
-    float az;
+    float ax, ay, az;
     float mag = 0;
     float buffer[2] = {0};
     float avg_buffer[2] = {0};
     float avg;
+    //float max = 1.0;
+    //float min = 1.0;
     
+    //Start threads for sensors and serial command
     thread3.start(readBarometer);
     thread4.start(readGPS);
     thread5.start(readHR);
@@ -560,7 +594,7 @@
     usb_timer.start();
 
     while(run) {
-        // Read Sensors
+        // Read IMU and get acceleration in all three axis
         IMU.readAccel();
         ax = IMU.calcAccel(IMU.ax);
         ay = IMU.calcAccel(IMU.ay);
@@ -571,29 +605,37 @@
         avg = (buffer[0] + buffer[1] + mag) / 3;
         buffer[0] = buffer[1];
         buffer[1] = mag;
-        // Count a step if the previous point was a maximum (greater than the 
-        // current point and 2 points back) and was greater than the threshold 
-        // value of 1.05
+        // Count a step if the difference between the current and previous avg
+        // point crosses a threshold
         if(sample_num > 1) {
             float dif1 = avg_buffer[1] - avg_buffer[0];
             float dif2 = avg_buffer[1] - avg;
             float peak_prominence = 0.01;
             if(dif1 > peak_prominence && dif2 > peak_prominence) {
                 steps++;
+                //Dynamic stride length calculation using max and min values of
+                //z acceleration
+                //stride_length = K * pow((double)(max - min), 0.25) * 3.28084;
+                //max = 1.0;
+                //min = 1.0;
             }
         }
         avg_buffer[0] = avg_buffer[1];
         avg_buffer[1] = avg;
         
+        //if (az > max) { max = az;}
+        //else if (az < min) {min = az;}
+        
         sample_num++;
-        one = !one;
-        // Sampling rate of ~200 Hz
+        one = !one; //led indicating if main is still running
+        
+        //Every minute, save current activity data to data.txt
         if(usb_timer.read() >= 5) {
-            //pc.printf("Starting USB Write\r\n");
             save_data();
             usb_timer.stop();
             usb_timer.reset();
             usb_timer.start();
+            two = 0;
         }
         Thread::wait(200);
     }
@@ -607,11 +649,11 @@
     usb_timer.reset();
     
     save_data();
-    two = 1;
-    //Append data from data.txt to prev_data.txt
+    //For demo
     usb_mtx.lock();
     FILE *fp1 = fopen("/msc/prev_data.txt", "a");
-    FILE *fp2 = fopen("/msc/data.txt", "r");
-    two = 0;
+    fprintf(fp1, "%s\t%d\t%d\t%0.2f\t%0.2f\n", date, steps, flights, calories, distance);
+    fclose(fp1);
+    usb_mtx.unlock();
     return 0;
 }
\ No newline at end of file