Fitbit code using RTOS
Dependencies: mbed PulseSensor2 SCP1000 mbed-rtos 4DGL-uLCD-SE LSM9DS1_Library_cal PinDetect FatFileSystemCpp GP-20U7
main.cpp@4:158ea0c5531c, 2020-04-22 (annotated)
- 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?
User | Revision | Line number | New 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 | } |