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 25:41ec16a87ebd, committed 2020-04-19
- Comitter:
- memig3
- Date:
- Sun Apr 19 01:22:01 2020 +0000
- Parent:
- 24:841ceaf2cf69
- Child:
- 26:b906c42c0b9c
- Commit message:
- added main_ticker.cpp which is a main function that records GPS latitude and longitude and has step and floor counting implemented. It uses tickers instead of rtos because of issues with too many serial devices when adding GPS
Changed in this revision
main.cpp | Show annotated file Show diff for this revision Revisions of this file |
main_ticker.cpp | Show annotated file Show diff for this revision Revisions of this file |
--- a/main.cpp Sat Apr 18 17:54:15 2020 +0000 +++ b/main.cpp Sun Apr 19 01:22:01 2020 +0000 @@ -6,7 +6,6 @@ #include "PulseSensor.h" #include "PinDetect.h" #include "uLCD_4DGL.h" -#include "LL.h" SCP1000 scp1000(p5,p6,p7,p8); LSM9DS1 IMU(p9, p10, 0xD6, 0x3C);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main_ticker.cpp Sun Apr 19 01:22:01 2020 +0000 @@ -0,0 +1,277 @@ +#include "mbed.h" +#include "LSM9DS1.h" +#include "SCP1000.h" +#include "PulseSensor.h" +#include "PinDetect.h" +#include "uLCD_4DGL.h" +#include "GPS.h" +#include "MSCFileSystem.h" + +SCP1000 scp1000(p5,p6,p7,p8); +LSM9DS1 IMU(p9, p10, 0xD6, 0x3C); +PulseSensor PPG(p17); +uLCD_4DGL uLCD(p28,p27,p29); +Serial pc(USBTX, USBRX); +DigitalOut one = LED1; +DigitalOut two = LED2; +DigitalOut three = LED3; +DigitalOut four = LED4; +AnalogIn pot(p20); +PinDetect pb(p21); +GPS gps(p13, p14); + +#define FSNAME "msc" +MSCFileSystem msc(FSNAME); + +Ticker display; +Ticker LCD_clock; +Ticker Barometer; +Ticker GPS; + +int bpm; +int steps = 0; +int flights = 0; +float distance = 0.0; +int calories = 0; + +unsigned long pressure; +float latitude = 0; +float longitude = 0; +unsigned long p_buff[4]; +int count = 0; + +int mode = 1; +int oldMode = 1; + +bool run = true; + +// when the pushbotton is pressed the run flag is set to false and the main +// function while loop exits so that the data file can be closed +// so press the button when you're ready to be done collecting data +void button (void) { + run = 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 +void read_pot() { + float m1; + float m2; + float m3; + oldMode = mode; + m1 = pot.read(); + m2 = pot.read(); + m3 = pot.read(); + if(m1 < 0.2 && m2 < 0.2 && m3 < 0.2) { + mode = 1; + } else if(m1 >= 0.2 && m1 < 0.4 && m2 >= 0.2 && m2 < 0.4 && m3 >= 0.2 && m3 < 0.4) { + mode = 2; + } else if(m1 >= 0.4 && m1 < 0.6 && m2 >= 0.4 && m2 < 0.6 && m3 >= 0.4 && m3 < 0.6) { + mode = 3; + } else if(m1 >= 0.6 && m1 < 0.8 && m2 >= 0.6 && m2 < 0.8 && m3 >= 0.6 && m3 < 0.8) { + mode = 4; + } 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 +void display_time() { + uLCD.locate(1, 1); + uLCD.color(WHITE); + uLCD.text_width(2); + uLCD.text_height(3); + time_t seconds = time(NULL); + char timeBuffer[32]; + strftime(timeBuffer, 32, "%I:%M %p\r\n", localtime(&seconds)); + uLCD.printf("%s", timeBuffer); +} + +void update_screen(void) { + read_pot(); + if (oldMode != mode) { + uLCD.filled_rectangle(0,0, 128, 128, BLACK); + } + // print the information to the LCD display + switch(mode) { + case 1: + //Step count + uLCD.media_init(); + uLCD.set_sector_address(0x0000, 0x0005); + uLCD.display_image(50, 45); + uLCD.filled_rectangle(10, 110, 118, 115, BLACK); + uLCD.locate(3, 11); + uLCD.text_height(1); + uLCD.text_width(1); + uLCD.color(WHITE); + uLCD.printf("%4d steps",steps); + //uLCD.filled_rectangle(10, 110, 118, 115, WHITE); + break; + case 2: + // Heart rate + uLCD.media_init(); + uLCD.set_sector_address(0x0000, 0x000A); + uLCD.display_image(50, 45); + uLCD.locate(5, 11); + uLCD.text_height(1); + uLCD.text_width(1); + uLCD.color(WHITE); + uLCD.printf("%3d BPM", bpm); + break; + case 3: + //Distance + uLCD.media_init(); + uLCD.set_sector_address(0x0000, 0x000F); + uLCD.display_image(50, 45); + uLCD.locate(6, 11); + uLCD.text_height(1); + uLCD.text_width(1); + uLCD.color(WHITE); + uLCD.printf("%4.2f MI", distance); + break; + case 4: + //Calories + uLCD.media_init(); + uLCD.set_sector_address(0x0000, 0x0000); + uLCD.display_image(50, 45); + uLCD.locate(4, 11); + uLCD.text_height(1); + uLCD.text_width(1); + uLCD.color(WHITE); + uLCD.printf("%4d cal", calories); + break; + case 5: + //Floors + uLCD.media_init(); + uLCD.set_sector_address(0x0000, 0x0014); + uLCD.display_image(50, 45); + uLCD.locate(4, 11); + uLCD.text_height(1); + uLCD.text_width(1); + uLCD.color(WHITE); + uLCD.printf("%2d floors", flights); + break; + } +} + +void readBarometer(){ + pressure = scp1000.readPressure(); + if(count >= 0) count--; + unsigned long dif; + if(pressure < p_buff[0]) { + dif = p_buff[0] - pressure; + }else { + dif = 0; + } + if(pressure != 0 && p_buff[0] != 0 && dif > 40 && dif < 60 && count < 0) { + flights++; + count = 2; + } + p_buff[0] = p_buff[1]; + p_buff[1] = p_buff[2]; + p_buff[2] = p_buff[3]; + p_buff[3] = pressure; +} + +void readGPS(){ + if(gps.connected()) { + if(gps.sample()) { + if(gps.ns == 'S') { + longitude = gps.longitude; + }else { + longitude = -gps.longitude; + } + if(gps.ew == 'W') { + latitude = gps.latitude; + }else { + latitude = -gps.latitude; + } + } + } +} + +int main() { + // Off button + pb.mode(PullUp); + pb.attach_deasserted(&button); + pb.setSampleFrequency(); + + // set up the display + uLCD.baudrate(3000000); + uLCD.background_color(BLACK); + uLCD.cls(); + display.attach(&update_screen, 0.5); + LCD_clock.attach(&display_time, 0.7); + + //Set RTC time + set_time(1256729737); + + // LED indicates whether or not data is being collected + one = 0; + two = 0; + three = 0; + four = 0; + // Start sensors + int sample_num = 1; + PPG.start(); + IMU.begin(); + IMU.calibrate(1); + float ax; + float ay; + float az; + float mag = 0; + float buffer[2] = {0}; + float avg_buffer[2] = {0}; + float avg; + + // Initialize data file on usb flash drive + FILE *fp = fopen( "/msc/data.txt", "w"); + if(fp == NULL) { + error("Could not open file for write\n"); + } + fprintf(fp, "Sample Number, Pressure (Pa), Acceleration Magnitude (Gs), Heart Rate (bpm), Latitude (degrees), Longitude (degrees)\n"); + + Barometer.attach(&readBarometer, 2); + GPS.attach(&readGPS, 5); + + while(run) { + // Read Sensors + + bpm = PPG.get_BPM(); + IMU.readAccel(); + ax = IMU.calcAccel(IMU.ax); + ay = IMU.calcAccel(IMU.ay); + az = IMU.calcAccel(IMU.az); + // Calculate the 3 point moving average of the magnitude of the + // acceleration vector + mag = sqrt((ax*ax) + (ay*ay) + (az*az)); + 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 + if(sample_num > 1) { + float dif1 = avg_buffer[1] - avg_buffer[0]; + float dif2 = avg_buffer[1] - avg; + float peak_prominence = 0.03; + if(dif1 > peak_prominence && dif2 > peak_prominence) { + steps++; + } + } + avg_buffer[0] = avg_buffer[1]; + avg_buffer[1] = avg; + + // Save the data to the usb flash drive and print to the terminal + //fprintf(fp, "%d, %lu, %f, %d, %f, %f\r\n", sample_num, pressure, avg, bpm, latitude, longitude); + //pc.printf("%d, %lu, %f, %d, %f, %f\r\n", sample_num, pressure, avg, bpm, latitude, longitude); + sample_num++; + one = !one; + // Sampling rate of ~200 Hz + wait(0.2); + } + fclose(fp); + one = 0; +} \ No newline at end of file