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