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

Files at this revision

API Documentation at this revision

Comitter:
memig3
Date:
Sun Apr 19 14:49:41 2020 +0000
Parent:
25:41ec16a87ebd
Child:
27:9ad8d9c77f62
Commit message:
added a main file that uses tickers and has setup menu

Changed in this revision

maybe_final.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/maybe_final.cpp	Sun Apr 19 14:49:41 2020 +0000
@@ -0,0 +1,394 @@
+#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;
+Ticker HR;
+Ticker setup;
+ 
+int bpm;
+int steps = 0;
+int flights = 0;
+float distance = 0.0;
+float calories = 0;
+
+unsigned long pressure;
+float latitude = 0;
+float longitude = 0;
+float old_lat = 0;
+float old_lon = 0;
+#define PI 3.14159
+unsigned long p_buff[4];
+int count = 0;
+
+int mode = 1;
+int oldMode = 1;
+ 
+bool run = true;
+
+int gender;
+int weight;
+int age;
+int screen = 1;
+int oldScreen = 1;
+bool setup_state = 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;
+}
+
+void next() {
+    oldScreen = screen;
+    screen++;
+    if(screen == 4) {
+        setup_state = 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 setup_screen(void) {
+    if (oldScreen != screen) {
+        uLCD.filled_rectangle(0,0, 128, 128, BLACK);
+        oldScreen++;
+    }
+    switch(screen) {
+        case 1:
+            //Gender
+            uLCD.locate(2, 1);
+            uLCD.text_width(2);
+            uLCD.text_height(2);
+            uLCD.puts("Gender");
+            uLCD.text_width(3);
+            uLCD.text_height(3);
+            uLCD.locate(1, 3);
+            uLCD.putc('M');
+            uLCD.locate(4, 3);
+            uLCD.putc('F');
+            if(pot.read() > 0.5) {
+                gender = 0;
+                uLCD.rectangle(13, 60, 48, 100, BLACK);
+                uLCD.rectangle(75, 60, 110, 100, GREEN);
+            }else {
+                gender = 1;
+                uLCD.rectangle(75, 60, 110, 100, BLACK);
+                uLCD.rectangle(13, 60, 48, 100, GREEN);
+            }
+            break;
+        case 2: 
+            //Weight
+            uLCD.color(WHITE);
+            uLCD.locate(9, 14);
+            uLCD.text_width(1);
+            uLCD.text_height(1);
+            uLCD.puts("lbs");
+            uLCD.locate(2, 1);
+            uLCD.text_width(2);
+            uLCD.text_height(2);
+            uLCD.puts("Weight");
+            weight = 0.45 * (90 + pot.read() * 210);
+            char weight_string[3];
+            if(weight < 100) {
+                sprintf(weight_string, " %d", weight);
+            }else {
+                sprintf(weight_string, "%d", weight);
+            }
+            uLCD.text_width(3);
+            uLCD.text_height(3);
+            uLCD.locate(2, 3);
+            uLCD.color(GREEN);
+            uLCD.puts(weight_string);
+            uLCD.line(35, 100, 110, 100, WHITE);
+            break;
+        case 3:
+            //Age 
+            uLCD.color(WHITE);
+            uLCD.locate(3, 1);
+            uLCD.text_width(2);
+            uLCD.text_height(2);
+            uLCD.puts("Age");
+            age = (int) (10 + pot.read() * 89);
+            char age_string[2];
+            sprintf(age_string, "%d", age);
+            uLCD.text_width(3);
+            uLCD.text_height(3);
+            uLCD.locate(2, 3);
+            uLCD.color(GREEN);
+            uLCD.puts(age_string);
+            uLCD.line(40, 100, 90, 100, WHITE);
+            break;
+    }
+}
+ 
+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", (int)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 readHR(){
+    bpm = PPG.get_BPM();
+    calories = calories + (.0083)*.239*(gender*(-55.0969+.6309*bpm+.1988*weight+.2017*age)+(1-gender)*(-20.4022+.4472*bpm-.1263*weight+.074*age));;
+}
+
+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*PI/180;
+            }else {
+                longitude = -gps.longitude*PI/180;
+            }
+            if(gps.ew == 'W') {
+                latitude = gps.latitude*PI/180;
+            }else {
+                latitude = -gps.latitude*PI/180;
+            }
+            if(latitude != 0 && longitude != 0 && old_lat != 0 && old_lon != 0) {
+                distance = distance + (3963*acosf(sinf(old_lat)*sinf(latitude)+cosf(old_lat)*cosf(latitude)*cosf(longitude-old_lon)));
+            }
+            old_lat = latitude;
+            old_lon = longitude;
+            //pc.printf("%f, %f, %f\r\n", latitude, longitude, distance);
+        }
+    }
+}
+    
+int main() {
+    //Set RTC time
+    set_time(1256729737);
+    
+    // Next screen button
+    pb.mode(PullUp);
+    pb.attach_deasserted(&next);
+    pb.setSampleFrequency();
+    
+    //set up the display
+    uLCD.baudrate(3000000);
+    uLCD.background_color(BLACK);
+    uLCD.cls();
+    setup.attach(&setup_screen, 0.3);
+    
+    while(setup_state) {
+        pc.printf("%d", screen);
+    }
+    
+    // Off button
+    pb.attach_deasserted(&button);
+    
+    // set up the display
+    setup.detach();
+    uLCD.cls();
+    display.attach(&update_screen, 0.5);
+    LCD_clock.attach(&display_time, 0.7);
+    
+    // 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, 10);
+    HR.attach(&readHR, 0.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.01;
+            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