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
main.cpp
- Committer:
- dyu2021
- Date:
- 2020-04-17
- Revision:
- 23:1971e5cb6e3f
- Parent:
- 22:9442c37f793f
- Child:
- 24:841ceaf2cf69
File content as of revision 23:1971e5cb6e3f:
#include "mbed.h"
#include "rtos.h"
#include "LSM9DS1.h"
#include "SCP1000.h"
#include "MSCFileSystem.h"
#include "PulseSensor.h"
#include "PinDetect.h"
#include "uLCD_4DGL.h"
SCP1000 scp1000(p5,p6,p7,p8);
LSM9DS1 IMU(p9, p10, 0xD6, 0x3C);
PulseSensor PPG(p20);
uLCD_4DGL uLCD(p28,p27,p21);
Serial pc(USBTX, USBRX);
DigitalOut myled = LED1;
DigitalOut led2(LED2);
AnalogIn pot(p19);
PinDetect pb(p29);
#define FSNAME "msc"
MSCFileSystem msc(FSNAME);
volatile int bpm;
volatile int steps = 0;
volatile int flights = 0;
volatile float distance = 0.0;
volatile int calories = 0;
//char stat_string[3];
volatile int mode = 1;
volatile int oldMode = 1;
Mutex mtx;
Thread thread1;
Thread thread2;
Thread thread3;
Thread thread4;
Thread thread5;
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;
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);
}
}
//Display the time on the top
void display_time() {
while(1) {
mtx.lock();
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);
mtx.unlock();
Thread::wait(500);
}
}
void update_screen(void) {
while(1) {
mtx.lock();
// print the information to the LCD display
switch(mode) {
case 1:
//Step count
/*
uLCD.media_init();
uLCD.set_sector_address(0x0000, 0x0000);
uLCD.display_image(0,0);
*/
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.locate(5, 11);
uLCD.text_height(1);
uLCD.text_width(1);
uLCD.color(WHITE);
uLCD.printf("%3d BPM", bpm);
break;
case 3:
//Distance
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.locate(4, 11);
uLCD.text_height(1);
uLCD.text_width(1);
uLCD.color(WHITE);
uLCD.printf("%4d cal", calories);
break;
case 5:
//Floors
uLCD.locate(4, 11);
uLCD.text_height(1);
uLCD.text_width(1);
uLCD.color(WHITE);
uLCD.printf("%2d floors", flights);
break;
}
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) {
bpm = PPG.get_BPM();
Thread::wait(400);
}
}
//Read barometer and count floors
void read_barometer() {
unsigned long pressure;
while(run) {
pressure = scp1000.readPressure();
//Floor counting algo here
Thread::wait(200);
}
}
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();
//Set RTC time
set_time(1256729737);
// LED indicates whether or not data is being collected
myled = 0;
// Start sensors
int sample_num = 0;
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), ax (Gs), ay (Gs), az (Gs), lowpassed magnitude (Gs), heart rate (bpm)\n");
//Start threads
thread1.start(update_screen);
thread2.start(display_time);
thread3.start(read_pot);
thread4.start(read_heartRate);
thread5.start(read_barometer);
while(run) {
// Read Sensors
//bpm = PPG.get_BPM();
//pressure = scp1000.readPressure();
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) {
if((avg_buffer[1] > avg_buffer[0]) && (avg < avg_buffer[1]) && (avg_buffer[1] > 1.05)) {
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, %f, %f, %f, %d\r\n", sample_num, pressure, ax, ay, az, avg, bpm);
pc.printf("%d, %lu, %f, %f, %f, %f, %d\r\n", sample_num, pressure, ax, ay, az, avg, bpm);
sample_num++;
myled = 1;
// Sampling rate of ~200 Hz
Thread::wait(50);
}
fclose(fp);
myled = 0;
}

