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 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