Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed PulseSensor2 SCP1000 mbed-rtos 4DGL-uLCD-SE LSM9DS1_Library_cal PinDetect FatFileSystemCpp GP-20U7
Diff: main.cpp
- Revision:
- 31:3363c6923beb
- Parent:
- 25:41ec16a87ebd
- Child:
- 32:cdbd7de8ae10
--- a/main.cpp Wed Apr 22 14:52:37 2020 +0000
+++ b/main.cpp Wed Apr 22 20:00:57 2020 +0000
@@ -2,10 +2,11 @@
#include "rtos.h"
#include "LSM9DS1.h"
#include "SCP1000.h"
-#include "MSCFileSystem.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);
@@ -18,39 +19,64 @@
DigitalOut four = LED4;
AnalogIn pot(p20);
PinDetect pb(p21);
-
+GPS gps(p13, p14);
+
#define FSNAME "msc"
-MSCFileSystem msc(FSNAME);
+MSCFileSystem msc(FSNAME);
-volatile int bpm;
-volatile int steps = 0;
-volatile int flights = 0;
-volatile float distance = 0.0;
-volatile int calories = 0;
-volatile unsigned long pressure;
+int bpm;
+int steps = 0;
+int flights = 0;
+float distance = 0.0;
+float calories = 0;
+int oldSteps = 0;
+const int stepGoal = 100;
+float stride_length = 0.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;
-volatile int mode = 1;
-volatile int oldMode = 1;
-
+bool run = true;
+
+int gender;
+int weight;
+int age;
+int screen = 1;
+int oldScreen = 1;
+bool setup_state = true;
+
+Timer usb_timer;
+
Thread thread1;
Thread thread2;
Thread thread3;
Thread thread4;
Thread thread5;
-
-bool run = true;
-Mutex mtx;
+Mutex serial_mtx;
+Mutex usb_mtx;
// 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;
- thread1.terminate();
- thread2.terminate();
- thread3.terminate();
- thread4.terminate();
- thread5.terminate();
+}
+
+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
@@ -60,36 +86,28 @@
float m1;
float m2;
float m3;
- while(1) {
- 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
- if (oldMode != mode) {
- mtx.lock();
- uLCD.filled_rectangle(0,0, 128, 128, BLACK);
- mtx.unlock();
- }
- Thread::wait(200);
+ 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() {
while(1) {
- mtx.lock();
+ serial_mtx.lock();
uLCD.locate(1, 1);
uLCD.color(WHITE);
uLCD.text_width(2);
@@ -98,44 +116,116 @@
char timeBuffer[32];
strftime(timeBuffer, 32, "%I:%M %p\r\n", localtime(&seconds));
uLCD.printf("%s", timeBuffer);
- mtx.unlock();
- Thread::wait(500);
+ serial_mtx.unlock();
+ Thread::wait(700);
+ }
+}
+
+void setup_screen(void) {
+ while(1) {
+ serial_mtx.lock();
+ 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;
+ }
+ serial_mtx.unlock();
+ Thread::wait(100);
}
}
-/*
-//Make sure program still alive
-void blink_led() {
+void update_screen(void) {
while(1) {
- led2 = !led2;
- Thread::wait(1000);
- }
-}
-*/
-
-void update_screen(void) {
- while(1) {
- mtx.lock();
+ read_pot();
+ serial_mtx.lock();
+ 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.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);
+ uLCD.filled_rectangle(10, 110, 10 + int(steps * (110/stepGoal)), 115, WHITE);
break;
case 2:
// Heart rate
- uLCD.media_init();
- uLCD.set_sector_address(0x0000, 0x000A);
- uLCD.display_image(50, 45);
+ //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);
@@ -144,31 +234,31 @@
break;
case 3:
//Distance
- uLCD.media_init();
- uLCD.set_sector_address(0x0000, 0x000F);
- uLCD.display_image(50, 45);
+ //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);
+ uLCD.printf("%4.2f ft", distance);
break;
case 4:
//Calories
- uLCD.media_init();
- uLCD.set_sector_address(0x0000, 0x0000);
- uLCD.display_image(50, 45);
+ //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);
+ 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.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);
@@ -176,52 +266,127 @@
uLCD.printf("%2d floors", flights);
break;
}
- mtx.unlock();
+ serial_mtx.unlock();
Thread::wait(100);
}
}
-
-//Read heart rate sensor, only want to read it if in heart rate mode
-void read_heartRate() {
- while(mode == 2 && run) {
+
+void readHR(){
+ while(1) {
bpm = PPG.get_BPM();
- Thread::wait(400);
+ //calories = calories + (.0083)*.239*(gender*(-55.0969+.6309*bpm+.1988*weight+.2017*age)+(1-gender)*(-20.4022+.4472*bpm-.1263*weight+.074*age));
+ calories = calories + (.0083)*0.239*(gender*(-55.0969+.6309*bpm+.1988*0.453592*weight
+ +.2017*age)+(1-gender)*(-20.4022+.4472*bpm-.1263*0.453592*weight+.074*age));
+ //converted weight from lbs to kilograms
+
+ //Alternate way to calculate distance (likely more accurate)
+ //distance = distance + (steps - oldSteps)* stride_length;
+ //oldSteps = steps;
+ Thread::wait(500);
}
}
-
-//Read barometer and count floors
-void read_barometer() {
- unsigned long pressure_buff[10] = {0};
- while(run) {
+
+void readBarometer()
+{
+ while(1) {
pressure = scp1000.readPressure();
- //Floor counting algo here
- /*if(pressure != 0 && pressure_buff[0] != 0 && pressure - pressure_buff[0] > 100) {
- flights++;
+ if(count >= 0) count--;
+ unsigned long dif;
+ if(pressure < p_buff[0]) {
+ dif = p_buff[0] - pressure;
+ } else {
+ dif = 0;
}
- for(int i = 0; i < (sizeof pressure_buff) - 1; i++) {
- pressure_buff[i] = pressure_buff[i + 1];
+ if(pressure != 0 && p_buff[0] != 0 && dif > 40 && dif < 60 && count < 0) {
+ flights++;
+ count = 2;
}
- pressure_buff[9] = pressure;*/
- Thread::wait(200);
+ p_buff[0] = p_buff[1];
+ p_buff[1] = p_buff[2];
+ p_buff[2] = p_buff[3];
+ p_buff[3] = pressure;
+ Thread::wait(2000);
}
}
+void readGPS(){
+ while(1) {
+ serial_mtx.lock();
+ 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) {
+ float a = sinf(old_lat)*sinf(latitude)+cosf(old_lat)*cosf(latitude)*cosf(longitude-old_lon);
+ if(a > 1) a = 1;
+ distance = distance + (.75*acosf(a));
+ }
+ old_lat = latitude;
+ old_lon = longitude;
+ //pc.printf("%f, %f, %f\r\n", latitude, longitude, distance);
+ }
+ }
+ serial_mtx.unlock();
+ Thread::wait(10000);
+ }
+}
+
+void saveData() {
+ // Save the data to the usb flash drive and print to the terminal
+ FILE *fp = fopen( "/msc/data.txt", "a");
+ if(fp == NULL) {
+ error("Could not open file for write\n");
+ }
+ time_t seconds = time(NULL);
+ char date[32];
+ strftime(date, 32, "%m/%d/%y", localtime(&seconds));
+ fprintf(fp, "%s\t%d\t%d\t%0.2f\t%0.2f\n\r", date, steps, flights, calories, distance);
+ pc.printf("%s\t%d\t%d\t%0.2f\t%0.2f\n\r", date, steps, flights, calories, distance);
+ fclose(fp);
+}
+
+
int main() {
- // Off button
+ //Set RTC time
+ set_time(1256729737);
+
+ // Next screen button
pb.mode(PullUp);
- pb.attach_deasserted(&button);
+ pb.attach_deasserted(&next);
pb.setSampleFrequency();
- // set up the display
+ //set up the display
uLCD.baudrate(3000000);
uLCD.background_color(BLACK);
uLCD.cls();
+ thread1.start(setup_screen);
- //Set RTC time
- set_time(1256729737);
+ while(setup_state) {
+ pc.printf("%d\r\n", screen);
+ }
+ thread1.terminate();
+
+ // Off button
+ pb.attach_deasserted(&button);
+
+ // set up the display
+ uLCD.cls();
+ thread1.start(update_screen);
+ thread2.start(display_time);
// 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();
@@ -236,23 +401,29 @@
float avg;
// Initialize data file on usb flash drive
- FILE *fp = fopen( "/msc/data.txt", "w");
+ usb_mtx.lock();
+ FILE *fp = fopen( "/msc/data.txt", "r+");
if(fp == NULL) {
error("Could not open file for write\n");
}
- fprintf(fp, "Sample Number, Pressure (Pa), Acceleration Magnitude (Gs), Heart Rate (bpm)\n");
+ //Check to see if file is empty, not working right now
+ fseek (fp, 0, SEEK_END);
+ int size = ftell(fp);
+ if (0 == size) {
+ fprintf(fp, "Date\tSteps\tFloors\tCalories\tDistance (ft)\r\n");
+ pc.printf("Data.txt rewritten\r\n");
+ }
+ fclose(fp);
+ usb_mtx.unlock();
- //Start threads
- thread1.start(update_screen);
- thread2.start(display_time);
- thread3.start(read_pot);
- thread4.start(read_heartRate);
- thread5.start(read_barometer);
-
+ thread3.start(readBarometer);
+ thread4.start(readGPS);
+ thread5.start(readHR);
+
+ usb_timer.start();
+
while(run) {
// Read Sensors
- //bpm = PPG.get_BPM();
- //pressure = scp1000.readPressure();
IMU.readAccel();
ax = IMU.calcAccel(IMU.ax);
ay = IMU.calcAccel(IMU.ay);
@@ -269,7 +440,7 @@
if(sample_num > 1) {
float dif1 = avg_buffer[1] - avg_buffer[0];
float dif2 = avg_buffer[1] - avg;
- float peak_prominence = 0.03;
+ float peak_prominence = 0.01;
if(dif1 > peak_prominence && dif2 > peak_prominence) {
steps++;
}
@@ -277,14 +448,19 @@
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\r\n", sample_num, pressure, avg, bpm);
- pc.printf("%d, %lu, %f, %d\r\n", sample_num, pressure, avg, bpm);
sample_num++;
one = !one;
// Sampling rate of ~200 Hz
- Thread::wait(50);
+ if(usb_timer.read() >= 30) {
+ //pc.printf("Starting USB Write\r\n");
+ usb_mtx.lock();
+ saveData();
+ usb_mtx.unlock();
+ usb_timer.stop();
+ usb_timer.reset();
+ usb_timer.start();
+ }
+ Thread::wait(200);
}
- fclose(fp);
one = 0;
}
\ No newline at end of file

