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: BLE_API mbed nRF51822 X_NUCLEO_IDB0XA1
Fork of Biometricos_0 by
main.cpp
- Committer:
- Jacacent
- Date:
- 2018-04-10
- Revision:
- 1:49659ca954b3
- Parent:
- 0:fb0d095dc5dd
File content as of revision 1:49659ca954b3:
#include "mbed.h"
#include "biometricos.h"
#include "Hotboards_rtcc.h"
#include "MMA8451Q.h"
#include "MAX30100_PulseOximeter.h"
#include "ble/BLE.h"
#include "ble/services/UARTService.h"
#define NEED_CONSOLE_OUTPUT 1
#define MMA8451_I2C_ADDRESS (0x1d<<1)
#define REPORTING_PERIOD_MS 1000
#if NEED_CONSOLE_OUTPUT
Serial pc(LED_RED,LED_ORANGE);
#define DEBUG(...) { pc.printf(__VA_ARGS__); }
#else
#define DEBUG(...)
#endif
/* general ------------------------------------------------------------------ */
I2C i2c(I2C_SDA, I2C_SCL);
Ticker counter_tick;
bool timestmap = 0;
float tick_time;
uint8_t data[13];
uint32_t general_counter;
void increment_counter() {
general_counter++;
}
uint16_t get_cicles(float seconds) {
return seconds * (1/tick_time);
}
void general_init() {
tick_time = 0.01;
i2c.frequency(100000);
counter_tick.attach(&increment_counter, tick_time);
}
/* -------------------------------------------------------------------------- */
/* led_red ------------------------------------------------------------------ */
/*DigitalOut led_red(LED_RED);
Ticker led_red_ticker;
void periodicCallback(void) {
led_red = !led_red;
}
void led_red_init() {
led_red_ticker.attach(periodicCallback, 3);
}*/
/* -------------------------------------------------------------------------- */
/* real time clock ---------------------------------------------------------- */
Hotboards_rtcc rtcc(i2c);
void rtcc_init(){
if(rtcc.begin()) {
DEBUG("rtcc initialized!\r\n");
timestmap = 1;
} else {
DEBUG("rtcc not initialized!\r\n");
timestmap = 0;
}
}
bool rtcc_now(DateTime &t) {
if(rtcc.getStatus()) {
if(!rtcc.now(t)) {
DEBUG("Error rtcc.now(t)\r\n");
return 0;
}
} else {
DEBUG("Error rtcc.getStatus()\r\n");
return 0;
}
return true;
}
uint8_t rtcc_verify(const uint8_t *d) {
DateTime t;
if(rtcc_now(t)) {
DEBUG("Time- %d:%d:%d Date- %d/ %d/ %d\r\n",t.hour(),t.minute(),t.second(),t.day(),t.month()+1,t.year());
if((d[2] == t.minute()) && (d[3] == t.hour()) && (d[4] == t.day()) && (d[5] == t.month()) && (d[6] == (t.year() - 2000))) {
DEBUG("MCP79410 good\r\n");
return 1;
} else {
rtcc.setVBAT(1);
if(rtcc.adjust(DateTime(d[6] + 2000, d[5], d[4], d[3], d[2], d[1]))) {
DEBUG("MCP79410 adjusted\r\n");
return 2;
} else {
DEBUG("MCP79410 not adjusted\r\n");
return 0;
}
}
} else {
DEBUG("Error rtcc_now in rtcc_verify\r\n");
return 0;
}
}
/* -------------------------------------------------------------------------- */
/* bluetooth ---------------------------------------------------------------- */
uint8_t device_name[] = "HNCR-06";
BLEDevice ble;
UARTService *uartServicePtr;
void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) {
DEBUG("ble disconnected!\r\n");
DEBUG("ble restarting the advertising process\r\n");
ble.startAdvertising();
}
void connectionCallback(const Gap::ConnectionCallbackParams_t *params) {
DEBUG("ble connected!\r\n");
}
void onDataWritten(const GattWriteCallbackParams *params) {
if ((uartServicePtr != NULL) && (params->handle == uartServicePtr->getTXCharacteristicHandle())) {
DEBUG("received %u bytes\r\n", params->len);
uint8_t data_send[2];
uint8_t bytes_send;
switch (params->data[0]) {
case 0x00:
data_send[0] = 0x00;
data_send[1] = rtcc_verify(params->data);
bytes_send = 2;
break;
}
ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), data_send, bytes_send);
}
}
void ble_init() {
DEBUG("ble initialized!\r\n");
ble.init();
ble.onConnection(connectionCallback);
ble.onDisconnection(disconnectionCallback);
ble.onDataWritten(onDataWritten);
ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,
(const uint8_t *)device_name, sizeof(device_name) - 1);
ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
(const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed));
ble.setAdvertisingInterval(1000);
ble.startAdvertising();
}
void send_ble(uint8_t *data, uint8_t size) {
if (uartServicePtr != NULL && ble.getGapState().connected) {
ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), data, size);
} else {
// DEBUG("Error send_ble\r\n");
}
}
void send_behavior(uint8_t i) {
uint8_t bytes_send;
if(!timestmap) {
data[1] = 0x00;
bytes_send = i;
} else {
DateTime t;
if(rtcc_now(t)) {
data[1] = 0x01;
data[i] = t.second();
data[i+1] = t.minute();
data[i+2] = t.hour();
data[i+3] = t.day();
data[i+4] = t.month();
data[i+5] = (t.year() - 2000);
bytes_send = i+6;
} else {
DEBUG("Error rtcc_now in lm35_sens\r\n");
bytes_send = 0;
}
}
if(bytes_send)
send_ble(data, bytes_send);
}
/* -------------------------------------------------------------------------- */
/* button ------------------------------------------------------------------- */
DigitalIn button(USER_BUTTON, PullUp);
bool button_state, button_last_state;
uint16_t button_debounce_delay;
uint32_t button_last_debounce_time;
void button_init() {
button_debounce_delay = get_cicles(0.5);
button_last_state = 0;
}
void button_sens() {
int reading = button;
if(reading != button_last_state) {
button_last_debounce_time = general_counter;
}
if(general_counter >= (button_last_debounce_time + button_debounce_delay)) {
if(reading != button_state) {
button_state = reading;
if(button_state) {
DEBUG("button_state == 1\r\n");
} else {
DEBUG("button_state == 0\r\n");
}
data[0] = 0x02;
data[2] = button_state;
send_behavior(3);
}
}
button_last_state = reading;
}
/* -------------------------------------------------------------------------- */
/* lm35 temperature sensor -------------------------------------------------- */
AnalogIn lm35(TEMP);
bool lm35_state;
float lm35_temperature_celsius, factor_temperature;
uint8_t lm35_num_samples;
uint16_t lm35_polling_time_main, lm35_min, lm35_max;
uint16_t lm35_samples_counter, lm35_polling_time_samples, lm35_samples[5];
uint32_t lm35_last_counter_value, lm35_last_samples_counter_value;
uint16_t lm35_get_adc_value(float degrees_celsius) {
return degrees_celsius / factor_temperature;
}
void lm35_init() {
lm35_last_counter_value = 0;
lm35_samples_counter = 0;
lm35_last_samples_counter_value = 0;
lm35_num_samples = 5;
lm35_polling_time_samples = get_cicles(0.5);
lm35_polling_time_main = get_cicles(3);
factor_temperature = 0.3200391; // ((3.274 * 100) / 1023)
lm35_min = lm35_get_adc_value(20);//62.4923
lm35_max = lm35_get_adc_value(50);//156.2309
uint16_t val = lm35.read_u16();
if(val >= lm35_min && val <= lm35_max) {
DEBUG("lm35 initialized!\r\n");
lm35_state = 1;
} else {
DEBUG("lm35 not initialized!\r\n");
lm35_state = 0;
}
}
void lm35_sens() {
if(lm35_state)
if(general_counter >= (lm35_last_counter_value + lm35_polling_time_main))
if(general_counter >= (lm35_last_samples_counter_value + lm35_polling_time_samples)) {
uint16_t val = lm35.read_u16();
if(val >= lm35_min && val <= lm35_max) {
uint16_t temperature_sample = val;
data[0] = 0x01;
data[2] = temperature_sample & 0xff;
data[3] = temperature_sample >> 8;
send_behavior(4);
lm35_last_counter_value = general_counter;
}
lm35_last_samples_counter_value = general_counter;
}
}
/* -------------------------------------------------------------------------- */
/* termistor breathing sensor ---------------------------------------------- */
AnalogIn breath(BREATHING);
bool init_exhalation, breathing_status;
uint8_t val, min_val_allowed, max_val_allowed;
uint8_t base, base_umbral, umbral, dif, max_val_readed;
uint16_t breathing_pollingTime;
uint32_t breathing_last_counter_value;
uint16_t breath_get_temp() {
return breath.read_u16() - 768;
}
void breathing_init() {
init_exhalation = 0;
max_val_readed = 0;
breathing_status = 0;
breathing_last_counter_value = 0;
min_val_allowed = 80;
max_val_allowed = 150;
base_umbral = 4;
dif = 2;
breathing_pollingTime = get_cicles(5);
base = breath_get_temp();
if(base > min_val_allowed && base < max_val_allowed) {
DEBUG("breathing initialized!\r\n");
umbral = base - base_umbral;
breathing_status = 1;
} else {
DEBUG("breathing not initialized!\r\n");
breathing_status = 0;
}
}
void breath_sens() {
if(breathing_status) {
val = breath_get_temp();
//DEBUG("%d\r\n", val);
if(val > min_val_allowed && val < max_val_allowed) {
if(val > max_val_readed)
max_val_readed = val;
if((general_counter >= (breathing_last_counter_value + breathing_pollingTime))) {
base = max_val_readed;
umbral = base - base_umbral;
max_val_readed = 0;
//DEBUG("Updated %d %d %d\r\n",val, base ,umbral);
breathing_last_counter_value = general_counter;
}
if(val < umbral && !init_exhalation) {
init_exhalation = true;
//DEBUG("init_exhalation\r\n");
}
//DEBUG("%d %d\r\n",val, umbral);
if(val > (umbral + dif) && init_exhalation) {
DEBUG("Inhalation\r\n");
data[0] = 0x05;
data[2] = 0x01;
send_behavior(3);
init_exhalation = false;
}
}
}
}
/* -------------------------------------------------------------------------- */
/* max30100 herat rate and oximetry sensor ---------------------------------- */
MAX30100 max30100(i2c);
PulseOximeter pox(max30100);
bool max30100_status;
float max_heart_rate, min_heart_rate;
uint8_t min_sp02, max_sp02;
uint8_t samples_max30100, heart_rate_min_dif, sp02_min_dif, counter_max30100;
float samples_heart_rate[5];
uint8_t samples_sp02[5];
Timer t;
void pox_init() {
max30100_status = 0;
samples_max30100 = 5;
heart_rate_min_dif = 6;
sp02_min_dif = 2;
counter_max30100 = 0;
if(pox.begin()) {
DEBUG("max30100 initialized!\r\n");
max30100_status = 1;
t.start();
} else {
DEBUG("max30100 not initialized!\r\n");
max30100_status = 0;
}
}
void pox_sens() {
if(max30100_status) {
// Make sure to call update as fast as possible
if(!pox.update()) {
DEBUG("Error: if(!pox.update())\r\n");
pox_init();
}
// Asynchronously dump heart rate and oxidation levels to the serial
// For both, a value of 0 means "invalid"
if (t.read_ms() > REPORTING_PERIOD_MS) {
float new_heart_rate = pox.getHeartRate();
uint8_t new_sp02 = pox.getSpO2();
if(new_heart_rate != 0 && new_sp02 != 0) {
DEBUG("Heart rate: %f bmp\r\n", new_heart_rate);
DEBUG("SpO2: %d%\r\n\n", new_sp02);
uint32_t int_heart_rate;
memcpy(&int_heart_rate,&new_heart_rate,4);
data[0] = 0x03;
data[2] = new_sp02;
data[3] = (int_heart_rate & 0xFF);
data[4] = ((int_heart_rate >> 8) & 0xFF);
data[5] = ((int_heart_rate >> 16) & 0xFF);
data[6] = ((int_heart_rate >> 24) & 0xFF);
send_behavior(7);
//DEBUG("No finger\r\n");
}
t.reset();
}
}
}
/* -------------------------------------------------------------------------- */
/* mma8451q accelerometer --------------------------------------------------- */
MMA8451Q mma(i2c, MMA8451_I2C_ADDRESS);
bool mma_status, mma_new_value = false;
float mma_y;
uint8_t sample_counter = 0;
uint8_t num_samples = 3;
uint8_t mma_samples[3];
void mma_init() {
if(mma.begin()) {
mma_status = 1;
DEBUG("MMA8451 initialized\r\n");
} else {
mma_status = 0;
DEBUG("MMA8451 not initialized\r\n");
}
}
bool mma_get_acc_y(float &y) {
if(mma.getAccY(y))
y = abs(y);
else
return 0;
return 1;
}
void mma_sens() {
if(mma_status)
if(mma.getStatus()) {
float y;
if(mma_get_acc_y(y)) {
if(y > 1.2) {
mma_new_value = true;
if(mma_y < y)
mma_y = y;
} else if(mma_new_value) {
mma_samples[sample_counter++] = mma_y;
if(sample_counter == num_samples) {
for (uint8_t i = 0; i < num_samples; i++) {
if(mma_y < mma_samples[i])
mma_y = mma_samples[i];
}
uint8_t val = (mma_y - 1) * 255;
DEBUG("%d\r\n", val);
sample_counter = 0;
data[0] = 0x04;
data[2] = val;
send_behavior(3);
}
mma_new_value = false;
mma_y = 0;
}
} else{
DEBUG("MMA8451 Error getAccAxis()\r\n");
mma.setStatus(false);
}
} else
mma_init();
}
/* -------------------------------------------------------------------------- */
/* ecg ---------------------------------------------------------------------- */
AnalogIn ecg(ECG_OUT);
DigitalIn ecg_lo_p(ECG_LO_PLUS);
DigitalIn ecg_lo_m(ECG_LO_MIN);
bool ecg_status;
uint8_t ecg_samples[20], ecg_samples_counter;
uint16_t ecg_polling_time_main;
uint32_t ecg_last_counter_value;
void ecg_init() {
ecg_samples_counter = 1;
ecg_last_counter_value = 0;
ecg_polling_time_main = get_cicles(0.02);
ecg_samples[0] = 0x06;
if(!ecg_lo_p && !ecg_lo_m){
ecg_status = 1;
DEBUG("ecg initialized\r\n");
} else {
ecg_status = 0;
DEBUG("ecg not initialized\r\n");
}
}
uint8_t get_ecg_value() {
uint16_t val = ecg.read_u16();
if(val > 232 && val < 743) {
return (val - 232)/2;
} else {
return 0;
}
}
void ecg_sens() {
if(ecg_status)
if(general_counter >= (ecg_last_counter_value + ecg_polling_time_main)) {
if(!ecg_lo_p && !ecg_lo_m){
uint8_t val = get_ecg_value();
ecg_samples[ecg_samples_counter++] = val;
if(ecg_samples_counter == 20) {
send_ble(ecg_samples, 20);
ecg_samples_counter = 1;
}
ecg_last_counter_value = general_counter;
}
}
}
/* -------------------------------------------------------------------------- */
int main(void)
{
pc.printf("\r\nMensaje de prueba DEBUG");
DEBUG("\r\nInitialising program\r\n");
ble_init();
UARTService uartService(ble);
uartServicePtr = &uartService;
// rtcc_init();
general_init();
//led_red_init();
button_init();
lm35_init();
mma_init();
breathing_init();
pox_init();
ecg_init();
while (true) {
button_sens();
lm35_sens();
mma_sens();
breath_sens();
pox_sens();
ecg_sens();
ble.waitForEvent();
}
}