Fitbit code using RTOS

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

Committer:
dyu2021
Date:
Wed Apr 22 17:22:42 2020 +0000
Revision:
4:158ea0c5531c
Parent:
3:f3e1ee4aa5ec
Updated GPS distance calculation and fixed saving dates

Who changed what in which revision?

UserRevisionLine numberNew contents of line
memig3 0:bcfec522ef98 1 #include "mbed.h"
dyu2021 2:f96f7a311486 2 #include "rtos.h"
memig3 0:bcfec522ef98 3 #include "LSM9DS1.h"
memig3 0:bcfec522ef98 4 #include "SCP1000.h"
memig3 0:bcfec522ef98 5 #include "PulseSensor.h"
memig3 0:bcfec522ef98 6 #include "PinDetect.h"
memig3 0:bcfec522ef98 7 #include "uLCD_4DGL.h"
memig3 0:bcfec522ef98 8 #include "GPS.h"
memig3 0:bcfec522ef98 9 #include "MSCFileSystem.h"
memig3 0:bcfec522ef98 10
memig3 0:bcfec522ef98 11 SCP1000 scp1000(p5,p6,p7,p8);
memig3 0:bcfec522ef98 12 LSM9DS1 IMU(p9, p10, 0xD6, 0x3C);
memig3 0:bcfec522ef98 13 PulseSensor PPG(p17);
memig3 0:bcfec522ef98 14 uLCD_4DGL uLCD(p28,p27,p29);
memig3 0:bcfec522ef98 15 Serial pc(USBTX, USBRX);
memig3 0:bcfec522ef98 16 DigitalOut one = LED1;
memig3 0:bcfec522ef98 17 DigitalOut two = LED2;
memig3 0:bcfec522ef98 18 DigitalOut three = LED3;
memig3 0:bcfec522ef98 19 DigitalOut four = LED4;
memig3 0:bcfec522ef98 20 AnalogIn pot(p20);
memig3 0:bcfec522ef98 21 PinDetect pb(p21);
memig3 0:bcfec522ef98 22 GPS gps(p13, p14);
memig3 0:bcfec522ef98 23
memig3 0:bcfec522ef98 24 #define FSNAME "msc"
memig3 0:bcfec522ef98 25 MSCFileSystem msc(FSNAME);
memig3 0:bcfec522ef98 26
memig3 0:bcfec522ef98 27 int bpm;
memig3 0:bcfec522ef98 28 int steps = 0;
memig3 0:bcfec522ef98 29 int flights = 0;
memig3 0:bcfec522ef98 30 float distance = 0.0;
memig3 0:bcfec522ef98 31 float calories = 0;
dyu2021 2:f96f7a311486 32 int oldSteps = 0;
dyu2021 2:f96f7a311486 33 const int stepGoal = 100;
dyu2021 2:f96f7a311486 34 float stride_length = 0.0;
memig3 0:bcfec522ef98 35
memig3 0:bcfec522ef98 36 unsigned long pressure;
memig3 0:bcfec522ef98 37 float latitude = 0;
memig3 0:bcfec522ef98 38 float longitude = 0;
memig3 0:bcfec522ef98 39 float old_lat = 0;
memig3 0:bcfec522ef98 40 float old_lon = 0;
memig3 0:bcfec522ef98 41 #define PI 3.14159
memig3 0:bcfec522ef98 42 unsigned long p_buff[4];
memig3 0:bcfec522ef98 43 int count = 0;
memig3 0:bcfec522ef98 44
memig3 0:bcfec522ef98 45 int mode = 1;
memig3 0:bcfec522ef98 46 int oldMode = 1;
memig3 0:bcfec522ef98 47
memig3 0:bcfec522ef98 48 bool run = true;
memig3 0:bcfec522ef98 49
memig3 0:bcfec522ef98 50 int gender;
memig3 0:bcfec522ef98 51 int weight;
memig3 0:bcfec522ef98 52 int age;
memig3 0:bcfec522ef98 53 int screen = 1;
memig3 0:bcfec522ef98 54 int oldScreen = 1;
memig3 0:bcfec522ef98 55 bool setup_state = true;
dyu2021 2:f96f7a311486 56
dyu2021 3:f3e1ee4aa5ec 57 Timer usb_timer;
dyu2021 3:f3e1ee4aa5ec 58
dyu2021 2:f96f7a311486 59 Thread thread1;
dyu2021 2:f96f7a311486 60 Thread thread2;
dyu2021 2:f96f7a311486 61 Thread thread3;
dyu2021 2:f96f7a311486 62 Thread thread4;
dyu2021 2:f96f7a311486 63 Thread thread5;
dyu2021 4:158ea0c5531c 64 Mutex serial_mtx;
dyu2021 3:f3e1ee4aa5ec 65 Mutex usb_mtx;
memig3 0:bcfec522ef98 66
memig3 0:bcfec522ef98 67 // when the pushbotton is pressed the run flag is set to false and the main
memig3 0:bcfec522ef98 68 // function while loop exits so that the data file can be closed
memig3 0:bcfec522ef98 69 // so press the button when you're ready to be done collecting data
memig3 0:bcfec522ef98 70 void button (void) {
memig3 0:bcfec522ef98 71 run = false;
memig3 0:bcfec522ef98 72 }
memig3 0:bcfec522ef98 73
memig3 0:bcfec522ef98 74 void next() {
memig3 0:bcfec522ef98 75 oldScreen = screen;
memig3 0:bcfec522ef98 76 screen++;
memig3 0:bcfec522ef98 77 if(screen == 4) {
memig3 0:bcfec522ef98 78 setup_state = false;
memig3 0:bcfec522ef98 79 }
memig3 0:bcfec522ef98 80 }
memig3 0:bcfec522ef98 81
memig3 0:bcfec522ef98 82 // Reads the value of the potentiometer and averages over 3 readings to get rid
memig3 0:bcfec522ef98 83 // of random spikes/zero values. Returns either a 1, 2 or 3 based on which 3rd
memig3 0:bcfec522ef98 84 // of its range the potentiometer is in and which screen should be displayed
memig3 0:bcfec522ef98 85 void read_pot() {
memig3 0:bcfec522ef98 86 float m1;
memig3 0:bcfec522ef98 87 float m2;
memig3 0:bcfec522ef98 88 float m3;
memig3 0:bcfec522ef98 89 oldMode = mode;
memig3 0:bcfec522ef98 90 m1 = pot.read();
memig3 0:bcfec522ef98 91 m2 = pot.read();
memig3 0:bcfec522ef98 92 m3 = pot.read();
memig3 0:bcfec522ef98 93 if(m1 < 0.2 && m2 < 0.2 && m3 < 0.2) {
memig3 0:bcfec522ef98 94 mode = 1;
memig3 0:bcfec522ef98 95 } else if(m1 >= 0.2 && m1 < 0.4 && m2 >= 0.2 && m2 < 0.4 && m3 >= 0.2 && m3 < 0.4) {
memig3 0:bcfec522ef98 96 mode = 2;
memig3 0:bcfec522ef98 97 } else if(m1 >= 0.4 && m1 < 0.6 && m2 >= 0.4 && m2 < 0.6 && m3 >= 0.4 && m3 < 0.6) {
memig3 0:bcfec522ef98 98 mode = 3;
memig3 0:bcfec522ef98 99 } else if(m1 >= 0.6 && m1 < 0.8 && m2 >= 0.6 && m2 < 0.8 && m3 >= 0.6 && m3 < 0.8) {
memig3 0:bcfec522ef98 100 mode = 4;
memig3 0:bcfec522ef98 101 } else if(m1 >= 0.8 && m2 >= 0.8 && m3 >= 0.8) {
memig3 0:bcfec522ef98 102 mode = 5;
memig3 0:bcfec522ef98 103 }
memig3 0:bcfec522ef98 104 //when the mode changes, clear the screen
memig3 0:bcfec522ef98 105 }
memig3 0:bcfec522ef98 106
memig3 0:bcfec522ef98 107 //Display the time on the top
memig3 0:bcfec522ef98 108 void display_time() {
dyu2021 2:f96f7a311486 109 while(1) {
dyu2021 4:158ea0c5531c 110 serial_mtx.lock();
dyu2021 2:f96f7a311486 111 uLCD.locate(1, 1);
dyu2021 2:f96f7a311486 112 uLCD.color(WHITE);
dyu2021 2:f96f7a311486 113 uLCD.text_width(2);
dyu2021 2:f96f7a311486 114 uLCD.text_height(3);
dyu2021 2:f96f7a311486 115 time_t seconds = time(NULL);
dyu2021 2:f96f7a311486 116 char timeBuffer[32];
dyu2021 2:f96f7a311486 117 strftime(timeBuffer, 32, "%I:%M %p\r\n", localtime(&seconds));
dyu2021 2:f96f7a311486 118 uLCD.printf("%s", timeBuffer);
dyu2021 4:158ea0c5531c 119 serial_mtx.unlock();
dyu2021 2:f96f7a311486 120 Thread::wait(700);
dyu2021 2:f96f7a311486 121 }
memig3 0:bcfec522ef98 122 }
memig3 0:bcfec522ef98 123
memig3 0:bcfec522ef98 124 void setup_screen(void) {
dyu2021 2:f96f7a311486 125 while(1) {
dyu2021 4:158ea0c5531c 126 serial_mtx.lock();
dyu2021 2:f96f7a311486 127 if (oldScreen != screen) {
dyu2021 2:f96f7a311486 128 uLCD.filled_rectangle(0,0, 128, 128, BLACK);
dyu2021 2:f96f7a311486 129 oldScreen++;
dyu2021 2:f96f7a311486 130 }
dyu2021 2:f96f7a311486 131 switch(screen) {
dyu2021 2:f96f7a311486 132 case 1:
dyu2021 2:f96f7a311486 133 //Gender
dyu2021 2:f96f7a311486 134 uLCD.locate(2, 1);
dyu2021 2:f96f7a311486 135 uLCD.text_width(2);
dyu2021 2:f96f7a311486 136 uLCD.text_height(2);
dyu2021 2:f96f7a311486 137 uLCD.puts("Gender");
dyu2021 2:f96f7a311486 138 uLCD.text_width(3);
dyu2021 2:f96f7a311486 139 uLCD.text_height(3);
dyu2021 2:f96f7a311486 140 uLCD.locate(1, 3);
dyu2021 2:f96f7a311486 141 uLCD.putc('M');
dyu2021 2:f96f7a311486 142 uLCD.locate(4, 3);
dyu2021 2:f96f7a311486 143 uLCD.putc('F');
dyu2021 2:f96f7a311486 144 if(pot.read() > 0.5) {
dyu2021 2:f96f7a311486 145 gender = 0;
dyu2021 2:f96f7a311486 146 uLCD.rectangle(13, 60, 48, 100, BLACK);
dyu2021 2:f96f7a311486 147 uLCD.rectangle(75, 60, 110, 100, GREEN);
dyu2021 2:f96f7a311486 148 } else {
dyu2021 2:f96f7a311486 149 gender = 1;
dyu2021 2:f96f7a311486 150 uLCD.rectangle(75, 60, 110, 100, BLACK);
dyu2021 2:f96f7a311486 151 uLCD.rectangle(13, 60, 48, 100, GREEN);
dyu2021 2:f96f7a311486 152 }
dyu2021 2:f96f7a311486 153 break;
dyu2021 2:f96f7a311486 154 case 2:
dyu2021 2:f96f7a311486 155 //Weight
dyu2021 2:f96f7a311486 156 uLCD.color(WHITE);
dyu2021 2:f96f7a311486 157 uLCD.locate(9, 14);
dyu2021 2:f96f7a311486 158 uLCD.text_width(1);
dyu2021 2:f96f7a311486 159 uLCD.text_height(1);
dyu2021 2:f96f7a311486 160 uLCD.puts("lbs");
dyu2021 2:f96f7a311486 161 uLCD.locate(2, 1);
dyu2021 2:f96f7a311486 162 uLCD.text_width(2);
dyu2021 2:f96f7a311486 163 uLCD.text_height(2);
dyu2021 2:f96f7a311486 164 uLCD.puts("Weight");
dyu2021 2:f96f7a311486 165 weight = 0.45 * (90 + pot.read() * 210);
dyu2021 2:f96f7a311486 166 char weight_string[3];
dyu2021 2:f96f7a311486 167 if(weight < 100) {
dyu2021 2:f96f7a311486 168 sprintf(weight_string, " %d", weight);
dyu2021 2:f96f7a311486 169 } else {
dyu2021 2:f96f7a311486 170 sprintf(weight_string, "%d", weight);
dyu2021 2:f96f7a311486 171 }
dyu2021 2:f96f7a311486 172 uLCD.text_width(3);
dyu2021 2:f96f7a311486 173 uLCD.text_height(3);
dyu2021 2:f96f7a311486 174 uLCD.locate(2, 3);
dyu2021 2:f96f7a311486 175 uLCD.color(GREEN);
dyu2021 2:f96f7a311486 176 uLCD.puts(weight_string);
dyu2021 2:f96f7a311486 177 uLCD.line(35, 100, 110, 100, WHITE);
dyu2021 2:f96f7a311486 178 break;
dyu2021 2:f96f7a311486 179 case 3:
dyu2021 2:f96f7a311486 180 //Age
dyu2021 2:f96f7a311486 181 uLCD.color(WHITE);
dyu2021 2:f96f7a311486 182 uLCD.locate(3, 1);
dyu2021 2:f96f7a311486 183 uLCD.text_width(2);
dyu2021 2:f96f7a311486 184 uLCD.text_height(2);
dyu2021 2:f96f7a311486 185 uLCD.puts("Age");
dyu2021 2:f96f7a311486 186 age = (int) (10 + pot.read() * 89);
dyu2021 2:f96f7a311486 187 char age_string[2];
dyu2021 2:f96f7a311486 188 sprintf(age_string, "%d", age);
dyu2021 2:f96f7a311486 189 uLCD.text_width(3);
dyu2021 2:f96f7a311486 190 uLCD.text_height(3);
dyu2021 2:f96f7a311486 191 uLCD.locate(2, 3);
dyu2021 2:f96f7a311486 192 uLCD.color(GREEN);
dyu2021 2:f96f7a311486 193 uLCD.puts(age_string);
dyu2021 2:f96f7a311486 194 uLCD.line(40, 100, 90, 100, WHITE);
dyu2021 2:f96f7a311486 195 break;
dyu2021 2:f96f7a311486 196 }
dyu2021 4:158ea0c5531c 197 serial_mtx.unlock();
dyu2021 2:f96f7a311486 198 Thread::wait(100);
memig3 0:bcfec522ef98 199 }
memig3 0:bcfec522ef98 200 }
memig3 0:bcfec522ef98 201
memig3 0:bcfec522ef98 202 void update_screen(void) {
dyu2021 2:f96f7a311486 203 while(1) {
dyu2021 2:f96f7a311486 204 read_pot();
dyu2021 4:158ea0c5531c 205 serial_mtx.lock();
dyu2021 2:f96f7a311486 206 if (oldMode != mode) {
dyu2021 2:f96f7a311486 207 uLCD.filled_rectangle(0,0, 128, 128, BLACK);
dyu2021 2:f96f7a311486 208 }
dyu2021 2:f96f7a311486 209 // print the information to the LCD display
dyu2021 2:f96f7a311486 210 switch(mode) {
dyu2021 2:f96f7a311486 211 case 1:
dyu2021 2:f96f7a311486 212 //Step count
dyu2021 2:f96f7a311486 213 //uLCD.media_init();
dyu2021 2:f96f7a311486 214 //uLCD.set_sector_address(0x0000, 0x0005);
dyu2021 2:f96f7a311486 215 //uLCD.display_image(50, 45);
dyu2021 2:f96f7a311486 216 uLCD.filled_rectangle(10, 110, 118, 115, BLACK);
dyu2021 2:f96f7a311486 217 uLCD.locate(3, 11);
dyu2021 2:f96f7a311486 218 uLCD.text_height(1);
dyu2021 2:f96f7a311486 219 uLCD.text_width(1);
dyu2021 2:f96f7a311486 220 uLCD.color(WHITE);
dyu2021 2:f96f7a311486 221 uLCD.printf("%4d steps",steps);
dyu2021 2:f96f7a311486 222 uLCD.filled_rectangle(10, 110, 10 + int(steps * (110/stepGoal)), 115, WHITE);
dyu2021 2:f96f7a311486 223 break;
dyu2021 2:f96f7a311486 224 case 2:
dyu2021 2:f96f7a311486 225 // Heart rate
dyu2021 2:f96f7a311486 226 //uLCD.media_init();
dyu2021 2:f96f7a311486 227 //uLCD.set_sector_address(0x0000, 0x000A);
dyu2021 2:f96f7a311486 228 //uLCD.display_image(50, 45);
dyu2021 2:f96f7a311486 229 uLCD.locate(5, 11);
dyu2021 2:f96f7a311486 230 uLCD.text_height(1);
dyu2021 2:f96f7a311486 231 uLCD.text_width(1);
dyu2021 2:f96f7a311486 232 uLCD.color(WHITE);
dyu2021 2:f96f7a311486 233 uLCD.printf("%3d BPM", bpm);
dyu2021 2:f96f7a311486 234 break;
dyu2021 2:f96f7a311486 235 case 3:
dyu2021 2:f96f7a311486 236 //Distance
dyu2021 2:f96f7a311486 237 //uLCD.media_init();
dyu2021 2:f96f7a311486 238 //uLCD.set_sector_address(0x0000, 0x000F);
dyu2021 2:f96f7a311486 239 //uLCD.display_image(50, 45);
dyu2021 2:f96f7a311486 240 uLCD.locate(6, 11);
dyu2021 2:f96f7a311486 241 uLCD.text_height(1);
dyu2021 2:f96f7a311486 242 uLCD.text_width(1);
dyu2021 2:f96f7a311486 243 uLCD.color(WHITE);
dyu2021 2:f96f7a311486 244 uLCD.printf("%4.2f ft", distance);
dyu2021 2:f96f7a311486 245 break;
dyu2021 2:f96f7a311486 246 case 4:
dyu2021 2:f96f7a311486 247 //Calories
dyu2021 2:f96f7a311486 248 //uLCD.media_init();
dyu2021 2:f96f7a311486 249 //uLCD.set_sector_address(0x0000, 0x0000);
dyu2021 2:f96f7a311486 250 //uLCD.display_image(50, 45);
dyu2021 2:f96f7a311486 251 uLCD.locate(4, 11);
dyu2021 2:f96f7a311486 252 uLCD.text_height(1);
dyu2021 2:f96f7a311486 253 uLCD.text_width(1);
dyu2021 2:f96f7a311486 254 uLCD.color(WHITE);
dyu2021 2:f96f7a311486 255 uLCD.printf("%4d cal", (int)calories);
dyu2021 2:f96f7a311486 256 break;
dyu2021 2:f96f7a311486 257 case 5:
dyu2021 2:f96f7a311486 258 //Floors
dyu2021 2:f96f7a311486 259 //uLCD.media_init();
dyu2021 2:f96f7a311486 260 //uLCD.set_sector_address(0x0000, 0x0014);
dyu2021 2:f96f7a311486 261 //uLCD.display_image(50, 45);
dyu2021 2:f96f7a311486 262 uLCD.locate(4, 11);
dyu2021 2:f96f7a311486 263 uLCD.text_height(1);
dyu2021 2:f96f7a311486 264 uLCD.text_width(1);
dyu2021 2:f96f7a311486 265 uLCD.color(WHITE);
dyu2021 2:f96f7a311486 266 uLCD.printf("%2d floors", flights);
dyu2021 2:f96f7a311486 267 break;
dyu2021 2:f96f7a311486 268 }
dyu2021 4:158ea0c5531c 269 serial_mtx.unlock();
dyu2021 2:f96f7a311486 270 Thread::wait(100);
memig3 0:bcfec522ef98 271 }
memig3 0:bcfec522ef98 272 }
memig3 0:bcfec522ef98 273
memig3 0:bcfec522ef98 274 void readHR(){
dyu2021 2:f96f7a311486 275 while(1) {
dyu2021 2:f96f7a311486 276 bpm = PPG.get_BPM();
dyu2021 2:f96f7a311486 277 //calories = calories + (.0083)*.239*(gender*(-55.0969+.6309*bpm+.1988*weight+.2017*age)+(1-gender)*(-20.4022+.4472*bpm-.1263*weight+.074*age));
dyu2021 2:f96f7a311486 278 calories = calories + (.0083)*0.239*(gender*(-55.0969+.6309*bpm+.1988*0.453592*weight
dyu2021 2:f96f7a311486 279 +.2017*age)+(1-gender)*(-20.4022+.4472*bpm-.1263*0.453592*weight+.074*age));
dyu2021 2:f96f7a311486 280 //converted weight from lbs to kilograms
dyu2021 2:f96f7a311486 281
dyu2021 2:f96f7a311486 282 //Alternate way to calculate distance (likely more accurate)
dyu2021 2:f96f7a311486 283 //distance = distance + (steps - oldSteps)* stride_length;
dyu2021 2:f96f7a311486 284 //oldSteps = steps;
dyu2021 2:f96f7a311486 285 Thread::wait(500);
dyu2021 2:f96f7a311486 286 }
memig3 0:bcfec522ef98 287 }
memig3 0:bcfec522ef98 288
dyu2021 2:f96f7a311486 289 void readBarometer()
dyu2021 2:f96f7a311486 290 {
dyu2021 2:f96f7a311486 291 while(1) {
dyu2021 2:f96f7a311486 292 pressure = scp1000.readPressure();
dyu2021 2:f96f7a311486 293 if(count >= 0) count--;
dyu2021 2:f96f7a311486 294 unsigned long dif;
dyu2021 2:f96f7a311486 295 if(pressure < p_buff[0]) {
dyu2021 2:f96f7a311486 296 dif = p_buff[0] - pressure;
dyu2021 2:f96f7a311486 297 } else {
dyu2021 2:f96f7a311486 298 dif = 0;
dyu2021 2:f96f7a311486 299 }
dyu2021 2:f96f7a311486 300 if(pressure != 0 && p_buff[0] != 0 && dif > 40 && dif < 60 && count < 0) {
dyu2021 2:f96f7a311486 301 flights++;
dyu2021 2:f96f7a311486 302 count = 2;
dyu2021 2:f96f7a311486 303 }
dyu2021 2:f96f7a311486 304 p_buff[0] = p_buff[1];
dyu2021 2:f96f7a311486 305 p_buff[1] = p_buff[2];
dyu2021 2:f96f7a311486 306 p_buff[2] = p_buff[3];
dyu2021 2:f96f7a311486 307 p_buff[3] = pressure;
dyu2021 2:f96f7a311486 308 Thread::wait(2000);
memig3 0:bcfec522ef98 309 }
memig3 0:bcfec522ef98 310 }
memig3 0:bcfec522ef98 311
memig3 0:bcfec522ef98 312 void readGPS(){
dyu2021 2:f96f7a311486 313 while(1) {
dyu2021 4:158ea0c5531c 314 serial_mtx.lock();
dyu2021 2:f96f7a311486 315 if(gps.connected()) {
dyu2021 2:f96f7a311486 316 if(gps.sample()) {
dyu2021 2:f96f7a311486 317 if(gps.ns == 'S') {
dyu2021 2:f96f7a311486 318 longitude = gps.longitude*PI/180;
dyu2021 2:f96f7a311486 319 } else {
dyu2021 2:f96f7a311486 320 longitude = -gps.longitude*PI/180;
dyu2021 2:f96f7a311486 321 }
dyu2021 2:f96f7a311486 322 if(gps.ew == 'W') {
dyu2021 2:f96f7a311486 323 latitude = gps.latitude*PI/180;
dyu2021 2:f96f7a311486 324 } else {
dyu2021 2:f96f7a311486 325 latitude = -gps.latitude*PI/180;
dyu2021 2:f96f7a311486 326 }
dyu2021 2:f96f7a311486 327 if(latitude != 0 && longitude != 0 && old_lat != 0 && old_lon != 0) {
dyu2021 4:158ea0c5531c 328 float a = sinf(old_lat)*sinf(latitude)+cosf(old_lat)*cosf(latitude)*cosf(longitude-old_lon);
dyu2021 4:158ea0c5531c 329 if(a > 1) a = 1;
dyu2021 4:158ea0c5531c 330 distance = distance + (.75*acosf(a));
dyu2021 2:f96f7a311486 331 }
dyu2021 2:f96f7a311486 332 old_lat = latitude;
dyu2021 2:f96f7a311486 333 old_lon = longitude;
dyu2021 2:f96f7a311486 334 //pc.printf("%f, %f, %f\r\n", latitude, longitude, distance);
memig3 0:bcfec522ef98 335 }
memig3 0:bcfec522ef98 336 }
dyu2021 4:158ea0c5531c 337 serial_mtx.unlock();
dyu2021 2:f96f7a311486 338 Thread::wait(10000);
memig3 0:bcfec522ef98 339 }
memig3 0:bcfec522ef98 340 }
dyu2021 2:f96f7a311486 341
dyu2021 2:f96f7a311486 342 void saveData() {
dyu2021 2:f96f7a311486 343 // Save the data to the usb flash drive and print to the terminal
dyu2021 2:f96f7a311486 344 FILE *fp = fopen( "/msc/data.txt", "a");
dyu2021 2:f96f7a311486 345 if(fp == NULL) {
dyu2021 2:f96f7a311486 346 error("Could not open file for write\n");
dyu2021 2:f96f7a311486 347 }
dyu2021 2:f96f7a311486 348 time_t seconds = time(NULL);
dyu2021 2:f96f7a311486 349 char date[32];
dyu2021 4:158ea0c5531c 350 strftime(date, 32, "%m/%d/%y", localtime(&seconds));
dyu2021 4:158ea0c5531c 351 fprintf(fp, "%s\t%d\t%d\t%0.2f\t%0.2f\n\r", date, steps, flights, calories, distance);
dyu2021 4:158ea0c5531c 352 pc.printf("%s\t%d\t%d\t%0.2f\t%0.2f\n\r", date, steps, flights, calories, distance);
dyu2021 2:f96f7a311486 353 fclose(fp);
dyu2021 2:f96f7a311486 354 }
dyu2021 3:f3e1ee4aa5ec 355
memig3 0:bcfec522ef98 356
memig3 0:bcfec522ef98 357 int main() {
memig3 0:bcfec522ef98 358 //Set RTC time
memig3 0:bcfec522ef98 359 set_time(1256729737);
memig3 0:bcfec522ef98 360
memig3 0:bcfec522ef98 361 // Next screen button
memig3 0:bcfec522ef98 362 pb.mode(PullUp);
memig3 0:bcfec522ef98 363 pb.attach_deasserted(&next);
memig3 0:bcfec522ef98 364 pb.setSampleFrequency();
memig3 0:bcfec522ef98 365
memig3 0:bcfec522ef98 366 //set up the display
memig3 0:bcfec522ef98 367 uLCD.baudrate(3000000);
memig3 0:bcfec522ef98 368 uLCD.background_color(BLACK);
memig3 0:bcfec522ef98 369 uLCD.cls();
dyu2021 2:f96f7a311486 370 thread1.start(setup_screen);
memig3 0:bcfec522ef98 371
memig3 0:bcfec522ef98 372 while(setup_state) {
dyu2021 2:f96f7a311486 373 pc.printf("%d\r\n", screen);
memig3 0:bcfec522ef98 374 }
dyu2021 2:f96f7a311486 375 thread1.terminate();
memig3 0:bcfec522ef98 376
memig3 0:bcfec522ef98 377 // Off button
memig3 0:bcfec522ef98 378 pb.attach_deasserted(&button);
memig3 0:bcfec522ef98 379
memig3 0:bcfec522ef98 380 // set up the display
memig3 0:bcfec522ef98 381 uLCD.cls();
dyu2021 2:f96f7a311486 382 thread1.start(update_screen);
dyu2021 2:f96f7a311486 383 thread2.start(display_time);
memig3 0:bcfec522ef98 384
memig3 0:bcfec522ef98 385 // LED indicates whether or not data is being collected
memig3 0:bcfec522ef98 386 one = 0;
memig3 0:bcfec522ef98 387 two = 0;
memig3 0:bcfec522ef98 388 three = 0;
memig3 0:bcfec522ef98 389 four = 0;
memig3 0:bcfec522ef98 390 // Start sensors
memig3 0:bcfec522ef98 391 int sample_num = 1;
memig3 0:bcfec522ef98 392 PPG.start();
memig3 0:bcfec522ef98 393 IMU.begin();
memig3 0:bcfec522ef98 394 IMU.calibrate(1);
memig3 0:bcfec522ef98 395 float ax;
memig3 0:bcfec522ef98 396 float ay;
memig3 0:bcfec522ef98 397 float az;
memig3 0:bcfec522ef98 398 float mag = 0;
memig3 0:bcfec522ef98 399 float buffer[2] = {0};
memig3 0:bcfec522ef98 400 float avg_buffer[2] = {0};
memig3 0:bcfec522ef98 401 float avg;
memig3 0:bcfec522ef98 402
memig3 0:bcfec522ef98 403 // Initialize data file on usb flash drive
dyu2021 3:f3e1ee4aa5ec 404 usb_mtx.lock();
dyu2021 4:158ea0c5531c 405 FILE *fp = fopen( "/msc/data.txt", "r+");
memig3 0:bcfec522ef98 406 if(fp == NULL) {
memig3 0:bcfec522ef98 407 error("Could not open file for write\n");
memig3 0:bcfec522ef98 408 }
dyu2021 4:158ea0c5531c 409 //Check to see if file is empty, not working right now
dyu2021 4:158ea0c5531c 410 fseek (fp, 0, SEEK_END);
dyu2021 4:158ea0c5531c 411 int size = ftell(fp);
dyu2021 4:158ea0c5531c 412 if (0 == size) {
dyu2021 4:158ea0c5531c 413 fprintf(fp, "Date\tSteps\tFloors\tCalories\tDistance (ft)\r\n");
dyu2021 4:158ea0c5531c 414 pc.printf("Data.txt rewritten\r\n");
dyu2021 4:158ea0c5531c 415 }
dyu2021 3:f3e1ee4aa5ec 416 fclose(fp);
dyu2021 3:f3e1ee4aa5ec 417 usb_mtx.unlock();
memig3 0:bcfec522ef98 418
dyu2021 2:f96f7a311486 419 thread3.start(readBarometer);
dyu2021 2:f96f7a311486 420 thread4.start(readGPS);
dyu2021 2:f96f7a311486 421 thread5.start(readHR);
dyu2021 4:158ea0c5531c 422
dyu2021 3:f3e1ee4aa5ec 423 usb_timer.start();
memig3 0:bcfec522ef98 424
memig3 0:bcfec522ef98 425 while(run) {
memig3 0:bcfec522ef98 426 // Read Sensors
memig3 0:bcfec522ef98 427 IMU.readAccel();
memig3 0:bcfec522ef98 428 ax = IMU.calcAccel(IMU.ax);
memig3 0:bcfec522ef98 429 ay = IMU.calcAccel(IMU.ay);
memig3 0:bcfec522ef98 430 az = IMU.calcAccel(IMU.az);
memig3 0:bcfec522ef98 431 // Calculate the 3 point moving average of the magnitude of the
memig3 0:bcfec522ef98 432 // acceleration vector
memig3 0:bcfec522ef98 433 mag = sqrt((ax*ax) + (ay*ay) + (az*az));
memig3 0:bcfec522ef98 434 avg = (buffer[0] + buffer[1] + mag) / 3;
memig3 0:bcfec522ef98 435 buffer[0] = buffer[1];
memig3 0:bcfec522ef98 436 buffer[1] = mag;
memig3 0:bcfec522ef98 437 // Count a step if the previous point was a maximum (greater than the
memig3 0:bcfec522ef98 438 // current point and 2 points back) and was greater than the threshold
memig3 0:bcfec522ef98 439 // value of 1.05
memig3 0:bcfec522ef98 440 if(sample_num > 1) {
memig3 0:bcfec522ef98 441 float dif1 = avg_buffer[1] - avg_buffer[0];
memig3 0:bcfec522ef98 442 float dif2 = avg_buffer[1] - avg;
memig3 0:bcfec522ef98 443 float peak_prominence = 0.01;
memig3 0:bcfec522ef98 444 if(dif1 > peak_prominence && dif2 > peak_prominence) {
memig3 0:bcfec522ef98 445 steps++;
memig3 0:bcfec522ef98 446 }
memig3 0:bcfec522ef98 447 }
memig3 0:bcfec522ef98 448 avg_buffer[0] = avg_buffer[1];
memig3 0:bcfec522ef98 449 avg_buffer[1] = avg;
memig3 0:bcfec522ef98 450
memig3 0:bcfec522ef98 451 sample_num++;
memig3 0:bcfec522ef98 452 one = !one;
memig3 0:bcfec522ef98 453 // Sampling rate of ~200 Hz
dyu2021 3:f3e1ee4aa5ec 454 if(usb_timer.read() >= 30) {
dyu2021 4:158ea0c5531c 455 //pc.printf("Starting USB Write\r\n");
dyu2021 3:f3e1ee4aa5ec 456 usb_mtx.lock();
dyu2021 3:f3e1ee4aa5ec 457 saveData();
dyu2021 3:f3e1ee4aa5ec 458 usb_mtx.unlock();
dyu2021 3:f3e1ee4aa5ec 459 usb_timer.stop();
dyu2021 3:f3e1ee4aa5ec 460 usb_timer.reset();
dyu2021 3:f3e1ee4aa5ec 461 usb_timer.start();
dyu2021 3:f3e1ee4aa5ec 462 }
dyu2021 2:f96f7a311486 463 Thread::wait(200);
memig3 0:bcfec522ef98 464 }
memig3 0:bcfec522ef98 465 one = 0;
memig3 0:bcfec522ef98 466 }