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
Revision 37:c912fdde26fa, committed 2020-04-25
- 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