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: 4DGL-uLCD-SE LSM9DS1_Library-KVS MBed_Adafruit-GPS-Library PinDetect X_NUCLEO_53L0A1 mbed-rtos mbed
main.cpp
- Committer:
- ksastry3
- Date:
- 2017-12-06
- Revision:
- 0:8a797b9e2fe4
- Child:
- 1:abc522e41d63
File content as of revision 0:8a797b9e2fe4:
/* Code for ECE 4180-A Final Design Project */
/* Kartik Sastry, Robert Walsh, Krishna Peri */
/* mbed Based Fitness Wearable Prototype */
/******************************************************************************/
/* Devices Used and Pin Assignments */
/******************************************************************************/
/*
- mbed LPC1768 Microcontroller
- Adafruit VL53L0X Time of Flight Distance Sensor (LIDAR)
I2C p9, p10
DigitalOut p26
- Heart Rate Sensor / Pulse Oximeter - Maxim MAXREFDES117#
I2C p9, p10
- LSM9DS1 9 degrees-of-freedom Inertial Measurement Unit (IMU)
I2C p9, p10
- Adafruit Ultimate GPS Breakout V3 (GPS)
Serial 14, 15
- 4D Systems 4DGL-uLCD LCD Display (LCD)
Serial p27, p28, p30
- Pushbutton (Wire one switch pole to p7, the other directly to ground. No need for external pullup resistor.)
PinDetect p7
*/
/******************************************************************************/
/* Libraries and Include Files */
/******************************************************************************/
#include "mbed.h"
#include "rtos.h"
//#include "SDFileSystem.h"
#include "uLCD_4DGL.h"
#include "LSM9DS1.h"
#include "MBed_Adafruit_GPS.h"
#include "XNucleo53L0A1.h"
#include "math.h"
#include <stdio.h>
#include "PinDetect.h"
/******************************************************************************/
/* I/O Object Declarations */
/******************************************************************************/
Serial pc(USBTX, USBRX); // Interface to PC over virtual COM
uLCD_4DGL uLCD(p28, p27, p30); // LCD
LSM9DS1 imu(p9, p10, 0xD6, 0x3C); // IMU
//Serial * gps_Serial; // GPS
#define VL53L0_I2C_SDA p9 // LIDAR
#define VL53L0_I2C_SCL p10 // I2C sensor pins for LIDAR
DigitalOut shdn(p26); // This VL53L0X board test application performs a range measurement in polling mode
// Use 3.3(Vout) for Vin, p9 for SDA, p10 for SCL, P26 for shdn on mbed LPC1768
PinDetect myPushbutton(p7); // For Mode Selection Feature
/******************************************************************************/
/* Global Variables (Carefully Managed) */
/******************************************************************************/
// Globals for IMU
float new_x = 0, new_y = 0, new_z = 0;
bool start = 0;
int count = 0;
// Globals For GPS
// Declare
Serial gps_Serial(p13,p14); // Serial object for use w/ GPS
Adafruit_GPS myGPS(&gps_Serial); // Object of Adafruit's GPS class
Timer refresh_Timer; // Sets up a timer for use in loop; how often do we print GPS info?
const int refresh_Time = 2000; // refresh time in ms
char c; // when read via Adafruit_GPS::read(), the class returns single character stored here
// Globals For LIDAR
static XNucleo53L0A1 *board=NULL;
int status;
uint32_t distance;
/******************************************************************************/
/* Necessary Mutex Locks */
/******************************************************************************/
Mutex mySerialMutex; // On PC com port
Mutex myLCDMutex; // On uLCD
/******************************************************************************/
/* Device Selection / Thread Control */
/******************************************************************************/
enum DATA_ACQ_MODE {MODE_IMU_SELECT, MODE_GPS_SELECT, MODE_LIDAR_SELECT}; // by default mapped to {0, 1, 2}
volatile int myMode = MODE_IMU_SELECT; // To be changed by pushbutton presses
// Short ISR - serviced when interrupt given by myPushbutton hit
void changeMode_ISR(void) {
myMode = (myMode + 1) % 3; // mod 3 makes it periodic (0,1,2,0,1,2)
}
/******************************************************************************/
/* Function Prototypes of Threads */
/******************************************************************************/
void IMU_THREAD();
void GPS_THREAD();
void LIDAR_THREAD();
void LCD_THREAD();
/******************************************************************************/
/* Main Thread: Initialization and Heart Rate */
/******************************************************************************/
int main() {
// Set up IMU
uLCD.baudrate(300000);
imu.begin();
if (!imu.begin()) {
pc.printf("(IMU) Failed to communicate with LSM9DS1.\n");
}
imu.calibrate();
imu.readAccel();
// Set up GPS
myGPS.begin(9600); // sets baud rate for GPS communication; note this may be changed via Adafruit_GPS::sendCommand(char *)
// a list of GPS commands is available at http://www.adafruit.com/datasheets/PMTK_A08.pdf
myGPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); // these commands are defined in MBed_Adafruit_GPS.h; a link is provided there for command creation
myGPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);
myGPS.sendCommand(PGCMD_ANTENNA);
pc.printf("(GPS) Connection established at 9600 baud...\n");
Thread::wait(1*1000);
refresh_Timer.start(); // starts the clock on the timer
// Set up LIDAR
DevI2C *device_i2c = new DevI2C(VL53L0_I2C_SDA, VL53L0_I2C_SCL); // LIDAR Objects:
board = XNucleo53L0A1::instance(device_i2c, A2, D8, D2); // creates the 53L0A1 expansion board singleton obj
shdn = 0; // must reset sensor for an mbed reset to work
Thread::wait(0.1*1000);
shdn = 1;
Thread::wait(0.1*1000);
status = board->init_board(); // init the 53L0A1 board with default values
while (status) {
pc.printf("(LIDAR) Failed to init board! \r\n");
status = board->init_board();
}
// Set up Mode Selecting Pushbutton (Debounced, Interrupt Based)
myPushbutton.mode(PullUp); // Use internal pullups for pushbutton
Thread::wait(.01*1000); // Delay for initial pullup to take effect
myPushbutton.attach_deasserted(&changeMode_ISR); // Setup Interrupt Service Routines. PullUp implies 1->0 change means hit
myPushbutton.setSampleFrequency(); // Start sampling pushbutton inputs using interruptsUsing default 50 Hz (20 ms period)
// Launch Threads
Thread IMU_THREAD(IMU_THREAD);
Thread GPS_THREAD(GPS_THREAD);
Thread LIDAR_THREAD(LIDAR_THREAD);
Thread LCD_THREAD(LCD_THREAD);
// Main Thread
while(true) {
// <DO THINGS!>
Thread::wait(5000);
}
}
/******************************************************************************/
/* Thread 2: IMU Measurement */
/******************************************************************************/
void IMU_THREAD() {
// Change Axis..............................................................................................................
while (myMode == MODE_IMU_SELECT) {
imu.readAccel();
new_x = imu.calcAccel(imu.ax);
new_y = imu.calcAccel(imu.ay);
new_z = imu.calcAccel(imu.az);
mySerialMutex.lock();
pc.printf("z: %f\r\n", new_z);
mySerialMutex.unlock();
if (new_z > 1.25){
start = 1;
}
if (start == 1 & new_z < .90){
count += 1;
start = 0;
}
mySerialMutex.lock();
pc.printf("count: %d\r\n", count);
mySerialMutex.unlock();
Thread::wait(.1*1000);
}
}
/******************************************************************************/
/* Thread 3: GPS Measurement */
/******************************************************************************/
void GPS_THREAD() {
// pc.baud(9600); // sets virtual COM serial communication to high rate; this is to allow more time to be spent on GPS retrieval
while (myMode == MODE_GPS_SELECT) {
c = myGPS.read(); // queries the GPS
// if (c) { pc.printf("%c", c); } // this line will echo the GPS data if not paused
// check if we recieved a new message from GPS, if so, attempt to parse it,
if ( myGPS.newNMEAreceived() ) {
if ( !myGPS.parse(myGPS.lastNMEA()) ) {
continue;
}
}
// check if enough time has passed to warrant printing GPS info to screen
// note if refresh_Time is too low or pc.baud is too low, GPS data may be lost during printing
if (refresh_Timer.read_ms() >= refresh_Time) {
refresh_Timer.reset();
mySerialMutex.lock();
pc.printf("Time: %d:%d:%d.%u\n\r", myGPS.hour, myGPS.minute, myGPS.seconds, myGPS.milliseconds);
pc.printf("Date: %d/%d/20%d\n\r", myGPS.day, myGPS.month, myGPS.year);
pc.printf("Fix: %d\n\r", (int) myGPS.fix);
pc.printf("Quality: %d\n\r", (int) myGPS.fixquality);
if (myGPS.fix) {
pc.printf("Location: %5.2f%c, %5.2f%c\n\r", myGPS.latitude, myGPS.lat, myGPS.longitude, myGPS.lon);
pc.printf("Speed: %5.2f knots\n\r", myGPS.speed);
// pc.printf("Angle: %5.2f\n", myGPS.angle);
// pc.printf("Altitude: %5.2f\n", myGPS.altitude);
pc.printf("Satellites: %d\n\r", myGPS.satellites);
}
mySerialMutex.unlock();
}
}
}
/******************************************************************************/
/* Thread 4: LIDAR Measurements */
/******************************************************************************/
void LIDAR_THREAD() {
// loop taking and printing distance
while (myMode == MODE_LIDAR_SELECT) {
status = board->sensor_centre->get_distance(&distance);
if (status == VL53L0X_ERROR_NONE) {
mySerialMutex.lock();
pc.printf("D=%ld mm\r\n", distance);
mySerialMutex.unlock();
}
}
}
/******************************************************************************/
/* Thread 5: LCD Display */
/******************************************************************************/
void LCD_THREAD() {
}