ECE 4180 Fitbit Project / Mbed 2 deprecated 4180_Fitness_Tracker

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

Committer:
dyu2021
Date:
Thu Apr 16 01:36:01 2020 +0000
Revision:
20:adb9e6e1ad22
Parent:
7:fb47593628be
Child:
22:9442c37f793f
Added to main the RTOS version of Pedometer.cpp and will be the basis for our project

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dyu2021 0:ae05ad9e2610 1 #include "mbed.h"
dyu2021 20:adb9e6e1ad22 2 #include "rtos.h"
Richard_Xiong 7:fb47593628be 3 #include "LSM9DS1.h"
dyu2021 20:adb9e6e1ad22 4 #include "SCP1000.h"
dyu2021 20:adb9e6e1ad22 5 #include "MSCFileSystem.h"
dyu2021 20:adb9e6e1ad22 6 #include "PulseSensor.h"
dyu2021 20:adb9e6e1ad22 7 #include "PinDetect.h"
Richard_Xiong 7:fb47593628be 8 #include "uLCD_4DGL.h"
dyu2021 0:ae05ad9e2610 9
dyu2021 20:adb9e6e1ad22 10 SCP1000 scp1000(p5,p6,p7,p8);
dyu2021 20:adb9e6e1ad22 11 LSM9DS1 IMU(p9, p10, 0xD6, 0x3C);
dyu2021 20:adb9e6e1ad22 12 PulseSensor PPG(p20);
dyu2021 20:adb9e6e1ad22 13 uLCD_4DGL uLCD(p28,p27,p21);
dyu2021 20:adb9e6e1ad22 14 Serial pc(USBTX, USBRX);
dyu2021 20:adb9e6e1ad22 15 DigitalOut myled = LED1;
dyu2021 20:adb9e6e1ad22 16 DigitalOut led2(LED2);
dyu2021 20:adb9e6e1ad22 17 AnalogIn pot(p19);
dyu2021 20:adb9e6e1ad22 18 PinDetect pb(p29);
dyu2021 20:adb9e6e1ad22 19
dyu2021 20:adb9e6e1ad22 20 #define FSNAME "msc"
dyu2021 20:adb9e6e1ad22 21 MSCFileSystem msc(FSNAME);
dyu2021 20:adb9e6e1ad22 22
dyu2021 20:adb9e6e1ad22 23 volatile int bpm;
dyu2021 20:adb9e6e1ad22 24 volatile int steps = 0;
dyu2021 20:adb9e6e1ad22 25 volatile int flights = 0;
dyu2021 20:adb9e6e1ad22 26 volatile float distance = 0.0;
dyu2021 20:adb9e6e1ad22 27 volatile int calories = 0;
dyu2021 20:adb9e6e1ad22 28 //char stat_string[3];
dyu2021 20:adb9e6e1ad22 29
dyu2021 20:adb9e6e1ad22 30 volatile int mode = 1;
dyu2021 20:adb9e6e1ad22 31 volatile int oldMode = 1;
dyu2021 20:adb9e6e1ad22 32
dyu2021 20:adb9e6e1ad22 33 Thread thread1;
dyu2021 20:adb9e6e1ad22 34 Thread thread2;
dyu2021 20:adb9e6e1ad22 35 Thread thread3;
dyu2021 20:adb9e6e1ad22 36 Thread thread4;
dyu2021 20:adb9e6e1ad22 37 Thread thread5;
dyu2021 20:adb9e6e1ad22 38
dyu2021 20:adb9e6e1ad22 39 bool run = true;
dyu2021 20:adb9e6e1ad22 40
dyu2021 20:adb9e6e1ad22 41 // when the pushbotton is pressed the run flag is set to false and the main
dyu2021 20:adb9e6e1ad22 42 // function while loop exits so that the data file can be closed
dyu2021 20:adb9e6e1ad22 43 // so press the button when you're ready to be done collecting data
dyu2021 20:adb9e6e1ad22 44 void button (void) {
dyu2021 20:adb9e6e1ad22 45 run = false;
dyu2021 20:adb9e6e1ad22 46 }
Richard_Xiong 2:0c1c9795bfc4 47
dyu2021 20:adb9e6e1ad22 48 // Reads the value of the potentiometer and averages over 3 readings to get rid
dyu2021 20:adb9e6e1ad22 49 // of random spikes/zero values. Returns either a 1, 2 or 3 based on which 3rd
dyu2021 20:adb9e6e1ad22 50 // of its range the potentiometer is in and which screen should be displayed
dyu2021 20:adb9e6e1ad22 51 void read_pot() {
dyu2021 20:adb9e6e1ad22 52 float m1;
dyu2021 20:adb9e6e1ad22 53 float m2;
dyu2021 20:adb9e6e1ad22 54 float m3;
dyu2021 20:adb9e6e1ad22 55 while(1) {
dyu2021 20:adb9e6e1ad22 56 oldMode = mode;
dyu2021 20:adb9e6e1ad22 57 m1 = pot.read();
dyu2021 20:adb9e6e1ad22 58 m2 = pot.read();
dyu2021 20:adb9e6e1ad22 59 m3 = pot.read();
dyu2021 20:adb9e6e1ad22 60 if(m1 < 0.2 && m2 < 0.2 && m3 < 0.2) {
dyu2021 20:adb9e6e1ad22 61 mode = 1;
dyu2021 20:adb9e6e1ad22 62 } else if(m1 >= 0.2 && m1 < 0.4 && m2 >= 0.2 && m2 < 0.4 && m3 >= 0.2 && m3 < 0.4) {
dyu2021 20:adb9e6e1ad22 63 mode = 2;
dyu2021 20:adb9e6e1ad22 64 } else if(m1 >= 0.4 && m1 < 0.6 && m2 >= 0.4 && m2 < 0.6 && m3 >= 0.4 && m3 < 0.6) {
dyu2021 20:adb9e6e1ad22 65 mode = 3;
dyu2021 20:adb9e6e1ad22 66 } else if(m1 >= 0.6 && m1 < 0.8 && m2 >= 0.6 && m2 < 0.8 && m3 >= 0.6 && m3 < 0.8) {
dyu2021 20:adb9e6e1ad22 67 mode = 4;
dyu2021 20:adb9e6e1ad22 68 } else if(m1 >= 0.8 && m2 >= 0.8 && m3 >= 0.8) {
dyu2021 20:adb9e6e1ad22 69 mode = 5;
dyu2021 20:adb9e6e1ad22 70 }
dyu2021 20:adb9e6e1ad22 71 //when the mode changes, clear the screen
dyu2021 20:adb9e6e1ad22 72 if (oldMode != mode) {
dyu2021 20:adb9e6e1ad22 73 mtx.lock();
dyu2021 20:adb9e6e1ad22 74 uLCD.filled_rectangle(0,0, 128, 128, BLACK);
dyu2021 20:adb9e6e1ad22 75 mtx.unlock();
dyu2021 20:adb9e6e1ad22 76 }
dyu2021 20:adb9e6e1ad22 77 Thread::wait(200);
dyu2021 20:adb9e6e1ad22 78 }
dyu2021 20:adb9e6e1ad22 79 }
dyu2021 20:adb9e6e1ad22 80
dyu2021 20:adb9e6e1ad22 81 //Display the time on the top
dyu2021 20:adb9e6e1ad22 82 void display_time() {
dyu2021 20:adb9e6e1ad22 83 while(1) {
dyu2021 20:adb9e6e1ad22 84 mtx.lock();
dyu2021 20:adb9e6e1ad22 85 uLCD.locate(1, 1);
dyu2021 20:adb9e6e1ad22 86 uLCD.color(WHITE);
dyu2021 20:adb9e6e1ad22 87 uLCD.text_width(2);
dyu2021 20:adb9e6e1ad22 88 uLCD.text_height(3);
dyu2021 20:adb9e6e1ad22 89 time_t seconds = time(NULL);
dyu2021 20:adb9e6e1ad22 90 char timeBuffer[32];
dyu2021 20:adb9e6e1ad22 91 strftime(timeBuffer, 32, "%I:%M %p\r\n", localtime(&seconds));
dyu2021 20:adb9e6e1ad22 92 uLCD.printf("%s", timeBuffer);
dyu2021 20:adb9e6e1ad22 93 mtx.unlock();
dyu2021 20:adb9e6e1ad22 94 Thread::wait(500);
dyu2021 20:adb9e6e1ad22 95 }
dyu2021 20:adb9e6e1ad22 96 }
Richard_Xiong 2:0c1c9795bfc4 97
dyu2021 20:adb9e6e1ad22 98 /*
dyu2021 20:adb9e6e1ad22 99 //Make sure program still alive
dyu2021 20:adb9e6e1ad22 100 void blink_led() {
dyu2021 20:adb9e6e1ad22 101 while(1) {
dyu2021 20:adb9e6e1ad22 102 led2 = !led2;
dyu2021 20:adb9e6e1ad22 103 Thread::wait(1000);
dyu2021 20:adb9e6e1ad22 104 }
dyu2021 20:adb9e6e1ad22 105 }
dyu2021 20:adb9e6e1ad22 106 */
dyu2021 20:adb9e6e1ad22 107
dyu2021 20:adb9e6e1ad22 108 void update_screen(void) {
dyu2021 20:adb9e6e1ad22 109 while(1) {
dyu2021 20:adb9e6e1ad22 110 mtx.lock();
dyu2021 20:adb9e6e1ad22 111 // print the information to the LCD display
dyu2021 20:adb9e6e1ad22 112 switch(mode) {
dyu2021 20:adb9e6e1ad22 113 case 1:
dyu2021 20:adb9e6e1ad22 114 //Step count
dyu2021 20:adb9e6e1ad22 115 /*
dyu2021 20:adb9e6e1ad22 116 uLCD.media_init();
dyu2021 20:adb9e6e1ad22 117 uLCD.set_sector_address(0x0000, 0x0000);
dyu2021 20:adb9e6e1ad22 118 uLCD.display_image(0,0);
dyu2021 20:adb9e6e1ad22 119 */
dyu2021 20:adb9e6e1ad22 120 uLCD.filled_rectangle(10, 110, 118, 115, BLACK);
dyu2021 20:adb9e6e1ad22 121 uLCD.locate(3, 11);
dyu2021 20:adb9e6e1ad22 122 uLCD.text_height(1);
dyu2021 20:adb9e6e1ad22 123 uLCD.text_width(1);
dyu2021 20:adb9e6e1ad22 124 uLCD.color(WHITE);
dyu2021 20:adb9e6e1ad22 125 uLCD.printf("%4d steps",steps);
dyu2021 20:adb9e6e1ad22 126 uLCD.filled_rectangle(10, 110, 118, 115, WHITE);
dyu2021 20:adb9e6e1ad22 127 break;
dyu2021 20:adb9e6e1ad22 128 case 2:
dyu2021 20:adb9e6e1ad22 129 // Heart rate
dyu2021 20:adb9e6e1ad22 130 uLCD.locate(5, 11);
dyu2021 20:adb9e6e1ad22 131 uLCD.text_height(1);
dyu2021 20:adb9e6e1ad22 132 uLCD.text_width(1);
dyu2021 20:adb9e6e1ad22 133 uLCD.color(WHITE);
dyu2021 20:adb9e6e1ad22 134 uLCD.printf("%3d BPM", bpm);
dyu2021 20:adb9e6e1ad22 135 break;
dyu2021 20:adb9e6e1ad22 136 case 3:
dyu2021 20:adb9e6e1ad22 137 //Distance
dyu2021 20:adb9e6e1ad22 138 uLCD.locate(6, 11);
dyu2021 20:adb9e6e1ad22 139 uLCD.text_height(1);
dyu2021 20:adb9e6e1ad22 140 uLCD.text_width(1);
dyu2021 20:adb9e6e1ad22 141 uLCD.color(WHITE);
dyu2021 20:adb9e6e1ad22 142 uLCD.printf("%4.2f MI", distance);
dyu2021 20:adb9e6e1ad22 143 break;
dyu2021 20:adb9e6e1ad22 144 case 4:
dyu2021 20:adb9e6e1ad22 145 //Calories
dyu2021 20:adb9e6e1ad22 146 uLCD.locate(4, 11);
dyu2021 20:adb9e6e1ad22 147 uLCD.text_height(1);
dyu2021 20:adb9e6e1ad22 148 uLCD.text_width(1);
dyu2021 20:adb9e6e1ad22 149 uLCD.color(WHITE);
dyu2021 20:adb9e6e1ad22 150 uLCD.printf("%4d cal", calories);
dyu2021 20:adb9e6e1ad22 151 break;
dyu2021 20:adb9e6e1ad22 152 case 5:
dyu2021 20:adb9e6e1ad22 153 //Floors
dyu2021 20:adb9e6e1ad22 154 uLCD.locate(4, 11);
dyu2021 20:adb9e6e1ad22 155 uLCD.text_height(1);
dyu2021 20:adb9e6e1ad22 156 uLCD.text_width(1);
dyu2021 20:adb9e6e1ad22 157 uLCD.color(WHITE);
dyu2021 20:adb9e6e1ad22 158 uLCD.printf("%2d floors", flights);
dyu2021 20:adb9e6e1ad22 159 break;
dyu2021 20:adb9e6e1ad22 160 }
dyu2021 20:adb9e6e1ad22 161 mtx.unlock();
dyu2021 20:adb9e6e1ad22 162 Thread::wait(100);
dyu2021 20:adb9e6e1ad22 163 }
dyu2021 20:adb9e6e1ad22 164 }
dyu2021 20:adb9e6e1ad22 165
dyu2021 20:adb9e6e1ad22 166 //Read heart rate sensor, only want to read it if in heart rate mode
dyu2021 20:adb9e6e1ad22 167 void read_heartRate() {
dyu2021 20:adb9e6e1ad22 168 while(mode == 2 && run) {
dyu2021 20:adb9e6e1ad22 169 bpm = PPG.get_BPM();
dyu2021 20:adb9e6e1ad22 170 Thread::wait(400);
dyu2021 20:adb9e6e1ad22 171 }
dyu2021 20:adb9e6e1ad22 172 }
dyu2021 20:adb9e6e1ad22 173
dyu2021 20:adb9e6e1ad22 174 //Read barometer and count floors
dyu2021 20:adb9e6e1ad22 175 void read_baramoter() {
dyu2021 20:adb9e6e1ad22 176 unsigned long pressure;
dyu2021 20:adb9e6e1ad22 177 while(run) {
dyu2021 20:adb9e6e1ad22 178 pressure = scp1000.readPressure();
dyu2021 20:adb9e6e1ad22 179 //Floor counting algo here
dyu2021 20:adb9e6e1ad22 180 Thread::wait(200);
dyu2021 20:adb9e6e1ad22 181 }
dyu2021 20:adb9e6e1ad22 182 }
dyu2021 20:adb9e6e1ad22 183
dyu2021 0:ae05ad9e2610 184 int main() {
dyu2021 20:adb9e6e1ad22 185 // Off button
dyu2021 20:adb9e6e1ad22 186 pb.mode(PullUp);
dyu2021 20:adb9e6e1ad22 187 pb.attach_deasserted(&button);
dyu2021 20:adb9e6e1ad22 188 pb.setSampleFrequency();
dyu2021 20:adb9e6e1ad22 189
Richard_Xiong 6:29ccbdd09706 190 // set up the display
dyu2021 20:adb9e6e1ad22 191 uLCD.baudrate(3000000);
Richard_Xiong 2:0c1c9795bfc4 192 uLCD.background_color(BLACK);
Richard_Xiong 2:0c1c9795bfc4 193 uLCD.cls();
dyu2021 20:adb9e6e1ad22 194
dyu2021 20:adb9e6e1ad22 195 //Set RTC time
dyu2021 20:adb9e6e1ad22 196 set_time(1256729737);
Richard_Xiong 5:874e0af6fb50 197
dyu2021 20:adb9e6e1ad22 198 // LED indicates whether or not data is being collected
dyu2021 20:adb9e6e1ad22 199 myled = 0;
dyu2021 20:adb9e6e1ad22 200 // Start sensors
dyu2021 20:adb9e6e1ad22 201 int sample_num = 0;
dyu2021 20:adb9e6e1ad22 202 PPG.start();
dyu2021 20:adb9e6e1ad22 203 IMU.begin();
dyu2021 20:adb9e6e1ad22 204 IMU.calibrate(1);
dyu2021 20:adb9e6e1ad22 205 float ax;
dyu2021 20:adb9e6e1ad22 206 float ay;
dyu2021 20:adb9e6e1ad22 207 float az;
dyu2021 20:adb9e6e1ad22 208 float mag = 0;
dyu2021 20:adb9e6e1ad22 209 float buffer[2] = {0};
dyu2021 20:adb9e6e1ad22 210 float avg_buffer[2] = {0};
dyu2021 20:adb9e6e1ad22 211 float avg;
Richard_Xiong 5:874e0af6fb50 212
dyu2021 20:adb9e6e1ad22 213 // Initialize data file on usb flash drive
dyu2021 20:adb9e6e1ad22 214 FILE *fp = fopen( "/msc/data.txt", "w");
dyu2021 20:adb9e6e1ad22 215 if(fp == NULL) {
dyu2021 20:adb9e6e1ad22 216 error("Could not open file for write\n");
dyu2021 20:adb9e6e1ad22 217 }
dyu2021 20:adb9e6e1ad22 218 fprintf(fp, "sample number, pressure (Pa), ax (Gs), ay (Gs), az (Gs), lowpassed magnitude (Gs), heart rate (bpm)\n");
dyu2021 20:adb9e6e1ad22 219
dyu2021 20:adb9e6e1ad22 220 //Start threads
dyu2021 20:adb9e6e1ad22 221 thread1.start(update_screen);
dyu2021 20:adb9e6e1ad22 222 thread2.start(display_time);
dyu2021 20:adb9e6e1ad22 223 thread3.start(read_pot);
dyu2021 20:adb9e6e1ad22 224 thread4.start(read_heartRate);
dyu2021 20:adb9e6e1ad22 225 thread5.start(read_barometer);
Richard_Xiong 5:874e0af6fb50 226
dyu2021 20:adb9e6e1ad22 227 while(run) {
dyu2021 20:adb9e6e1ad22 228 // Read Sensors
dyu2021 20:adb9e6e1ad22 229 //bpm = PPG.get_BPM();
dyu2021 20:adb9e6e1ad22 230 //pressure = scp1000.readPressure();
dyu2021 20:adb9e6e1ad22 231 IMU.readAccel();
dyu2021 20:adb9e6e1ad22 232 ax = IMU.calcAccel(IMU.ax);
dyu2021 20:adb9e6e1ad22 233 ay = IMU.calcAccel(IMU.ay);
dyu2021 20:adb9e6e1ad22 234 az = IMU.calcAccel(IMU.az);
dyu2021 20:adb9e6e1ad22 235 // Calculate the 3 point moving average of the magnitude of the
dyu2021 20:adb9e6e1ad22 236 // acceleration vector
dyu2021 20:adb9e6e1ad22 237 mag = sqrt((ax*ax) + (ay*ay) + (az*az));
dyu2021 20:adb9e6e1ad22 238 avg = (buffer[0] + buffer[1] + mag) / 3;
dyu2021 20:adb9e6e1ad22 239 buffer[0] = buffer[1];
dyu2021 20:adb9e6e1ad22 240 buffer[1] = mag;
dyu2021 20:adb9e6e1ad22 241 // Count a step if the previous point was a maximum (greater than the
dyu2021 20:adb9e6e1ad22 242 // current point and 2 points back) and was greater than the threshold
dyu2021 20:adb9e6e1ad22 243 // value of 1.05
dyu2021 20:adb9e6e1ad22 244 if(sample_num > 1) {
dyu2021 20:adb9e6e1ad22 245 if((avg_buffer[1] > avg_buffer[0]) && (avg < avg_buffer[1]) && (avg_buffer[1] > 1.05)) {
dyu2021 20:adb9e6e1ad22 246 steps++;
dyu2021 20:adb9e6e1ad22 247 }
dyu2021 20:adb9e6e1ad22 248 }
dyu2021 20:adb9e6e1ad22 249 avg_buffer[0] = avg_buffer[1];
dyu2021 20:adb9e6e1ad22 250 avg_buffer[1] = avg;
dyu2021 20:adb9e6e1ad22 251 // Save the data to the usb flash drive and print to the terminal
dyu2021 20:adb9e6e1ad22 252 fprintf(fp, "%d, %lu, %f, %f, %f, %f, %d\r\n", sample_num, pressure, ax, ay, az, avg, bpm);
dyu2021 20:adb9e6e1ad22 253 pc.printf("%d, %lu, %f, %f, %f, %f, %d\r\n", sample_num, pressure, ax, ay, az, avg, bpm);
dyu2021 20:adb9e6e1ad22 254 sample_num++;
dyu2021 20:adb9e6e1ad22 255 myled = 1;
dyu2021 20:adb9e6e1ad22 256 // Sampling rate of ~200 Hz
dyu2021 20:adb9e6e1ad22 257 Thread::wait(50);
dyu2021 0:ae05ad9e2610 258 }
dyu2021 20:adb9e6e1ad22 259 fclose(fp);
dyu2021 20:adb9e6e1ad22 260 myled = 0;
dyu2021 20:adb9e6e1ad22 261 }