Jaime Andres Rincon Arango
Published © MIT

BIO-Smart Wear

My application is based on the use of this kind of devices to connect our body to the cloud.

AdvancedFull instructions provided5 hours12,704
BIO-Smart Wear

Things used in this project

Hardware components

Arduino 101
Arduino 101
×1
SparkFun Single Lead Heart Rate Monitor - AD8232
SparkFun Single Lead Heart Rate Monitor - AD8232
×1
Texas Instruments Lm35
×1
pulse sensor
×1

Software apps and online services

Arduino IDE
Arduino IDE
node-js
JASON
JaCalIVE

Hand tools and fabrication machines

Sport T shirt
Soldering iron (generic)
Soldering iron (generic)
ECG Electrode

Story

Read more

Schematics

Circuit

Code

Arduino 101 Read signals

Arduino
#include <CurieBLE.h>
#include <CurieIMU.h>



// Create my own UUIDs; used https://www.uuidgenerator.net/
#define SMARTWEAR_SERVICE_UUID "2947ac9e-fc38-11e5-86aa-5e5517507c66"
#define AX_CHAR_UUID "2947af14-fc38-11e5-86aa-5e5517507c66"
#define AY_CHAR_UUID "2947b090-fc38-11e5-86aa-5e5517507c66"
#define AZ_CHAR_UUID "2947b180-fc38-11e5-86aa-5e5517507c66"
#define GX_CHAR_UUID "2947b252-fc38-11e5-86aa-5e5517507c66"
#define GY_CHAR_UUID "2947b5ae-fc38-11e5-86aa-5e5517507c66"
#define GZ_CHAR_UUID "2947b694-fc38-11e5-86aa-5e5517507c66"
#define ECG_CHAR_UUID "0c3f3508-089a-11e7-93ae-92361f002671"
#define PPG_CHAR_UUID "0c3f38fa-089a-11e7-93ae-92361f002671"
#define TEMP_CHAR_UUID "0c3f38fB-089a-11e7-93ae-92361f002671"

#define TIMER2VAL (1024/(SAMPFREQ))
#define SAMPFREQ 256

// Arduino 101 acts as a BLE peripheral
BLEPeripheral blePeripheral;

// IMU data is registered as a BLE service
BLEService imuService(SMARTWEAR_SERVICE_UUID);

// Each IMU data point is its own characteristic
BLEIntCharacteristic axChar(AX_CHAR_UUID, BLERead | BLENotify);
BLEIntCharacteristic ayChar(AY_CHAR_UUID, BLERead | BLENotify);
BLEIntCharacteristic azChar(AZ_CHAR_UUID, BLERead | BLENotify);
BLEIntCharacteristic gxChar(GX_CHAR_UUID, BLERead | BLENotify);
BLEIntCharacteristic gyChar(GY_CHAR_UUID, BLERead | BLENotify);
BLEIntCharacteristic gzChar(GZ_CHAR_UUID, BLERead | BLENotify);
BLEIntCharacteristic ecgChar(ECG_CHAR_UUID, BLERead | BLENotify);
BLEIntCharacteristic ppgChar(PPG_CHAR_UUID, BLERead | BLENotify);
BLEIntCharacteristic tempChar(TEMP_CHAR_UUID, BLERead | BLENotify);


// Assign pin to indicate BLE connection
const int INDICATOR_PIN = 13;

int ax = 0;
int ay = 0;
int az = 0;
int gx = 0;
int gy = 0;
int gz = 0;
int ecg = 0;
int ppg = 0;
int counter = 0;
float celsius = 0.0;
long previousMillis = 0;

void setup() {

  // Initialize IMU
  Serial.println("Initializing IMU...");
  CurieIMU.begin();
  CurieIMU.autoCalibrateGyroOffset();
  CurieIMU.autoCalibrateAccelerometerOffset(X_AXIS, 0);
  CurieIMU.autoCalibrateAccelerometerOffset(Y_AXIS, 0);
  CurieIMU.autoCalibrateAccelerometerOffset(Z_AXIS, 1);

  // Initialize BLE peripheral
  blePeripheral.setLocalName("SmartWear");
  blePeripheral.setAdvertisedServiceUuid(imuService.uuid());
  blePeripheral.addAttribute(imuService);
  blePeripheral.addAttribute(axChar);
  blePeripheral.addAttribute(ayChar);
  blePeripheral.addAttribute(azChar);
  blePeripheral.addAttribute(gxChar);
  blePeripheral.addAttribute(gyChar);
  blePeripheral.addAttribute(gzChar);
  blePeripheral.addAttribute(ecgChar);
  blePeripheral.addAttribute(ppgChar);
  blePeripheral.addAttribute(tempChar);

  // Set initial values
  axChar.setValue(ax);
  ayChar.setValue(ay);
  azChar.setValue(az);
  gxChar.setValue(gx);
  gyChar.setValue(gy);
  gzChar.setValue(gz);

  ecgChar.setValue(ecg);
  ppgChar.setValue(ppg);

  tempChar.setValue(celsius);


  // Now, activate the BLE peripheral
  blePeripheral.begin();
  Serial.println("Bluetooth device active, waiting for connections...");
}

void loop() {
  // Check if the connection to the central is active or not
  BLECentral central = blePeripheral.central();

  if (central) {
    Serial.print("Connected to central: ");
    Serial.println(central.address());
    digitalWrite(INDICATOR_PIN, HIGH);

    while (central.connected()) {
      updateImuData();
      updatePPG();
      updateECG();
      updateTemperature();
    }

    Serial.print("Disconnected from central: ");
    Serial.println(central.address());
    digitalWrite(INDICATOR_PIN, LOW);
  }
}


void updateECG() {
  int valueECG = analogRead(1);
  ecgChar.setValue(valueECG);
}

void updatePPG() {
  int valuePPG = analogRead(0);
  ppgChar.setValue(valuePPG);
}

void updateTemperature() {
  int value = analogRead(2);
  float millivolts = (value / 1023.0) * 5000;
  celsius = millivolts / 10;
  tempChar.setValue(celsius);
}

void updateImuData() {
  CurieIMU.readMotionSensor(ax, ay, az, gx, gy, gz);

  axChar.setValue(ax);
  ayChar.setValue(ay);
  azChar.setValue(az);
  gxChar.setValue(gx);
  gyChar.setValue(gy);
  gzChar.setValue(gz);
  //gzChar.setValue('\n');

}

Intel Edison Bluetooth Server

JavaScript
var noble = require('noble');

// These should correspond to the peripheral's service
var IMU_SERVICE_UUID = '2947ac9efc3811e586aa5e5517507c66';

var ECG_CHAR_UUID = "2947af14-fc38-11e5-86aa-5e5517507c66"
var PPG_CHAR_UUID = "2947b090-fc38-11e5-86aa-5e5517507c66"
var AX_CHAR_UUID = "0c3f3508-089a-11e7-93ae-92361f002671"
var AY_CHAR_UUID = "0c3f38fa-089a-11e7-93ae-92361f002671"
var AZ_CHAR_UUID = "2947b180-fc38-11e5-86aa-5e5517507c66"
var GX_CHAR_UUID = "2947b252-fc38-11e5-86aa-5e5517507c66"
var GY_CHAR_UUID = "2947b5ae-fc38-11e5-86aa-5e5517507c66"
var GZ_CHAR_UUID = "2947b694-fc38-11e5-86aa-5e5517507c66"


var net = require('net');
var client = net.connect(4445, function() { //'connect' listener
  console.log('client connected');
  var Data =  "SDA_0X02:ECG,PPG,accx,accy,accz,Gyro,gyrox,gyroy,gyroz";
  client.write(Data);
  client.write('\r\n')
  
});

noble.on('stateChange', function(state) {
  if(state === 'poweredOn') {
    console.log('Start BLE scan...')
    noble.startScanning([IMU_SERVICE_UUID], false);
  }
  else {
    console.log('Cannot scan... state is not poweredOn')
    noble.stopScanning();
  }
});

// Discover the peripheral's IMU service and corresponding characteristics
// Then, emit each data point on the socket stream
noble.on('discover', function(peripheral) {
  peripheral.connect(function(error) {
    console.log('Connected to peripheral: ' + peripheral.uuid);
    peripheral.discoverServices([IMU_SERVICE_UUID], function(error, services) {
      var imuService = services[0];
      console.log('Discovered IMU service');

      imuService.discoverCharacteristics([], function(error, characteristics) {
		  characteristics.forEach(function(characteristic) {
			console.log('discovered characteristics');
			// Assign Characteristics
			var characteristic_ECG = characteristics[0];
			var characteristic_PPG = characteristics[1];
			var characteristic_accX = characteristics[2];
			var characteristic_accY = characteristics[3];
			var characteristic_accZ = characteristics[4];
			var characteristic_gX = characteristics[5];
			var characteristic_gY = characteristics[6];
			var characteristic_gz = characteristics[7];
			
			
			// Subscribe to each characteristic
			characteristic_ECG.subscribe(function(error) {
			  if(error) console.log(error);
			});

			characteristic_PPG.subscribe(function(error) {
			  if(error) console.log(error);
			});

			characteristic_accX.subscribe(function(error) {
			  if(error) console.log(error);
			});

			characteristic_accY.subscribe(function(error) {
			  if(error) console.log(error);
			});		
			
			characteristic_accZ.subscribe(function(error) {
			  if(error) console.log(error);
			});
			
			characteristic_gX.subscribe(function(error) {
			  if(error) console.log(error);
			});

			characteristic_gY.subscribe(function(error) {
			  if(error) console.log(error);
			});		
			
			characteristic_gZ.subscribe(function(error) {
			  if(error) console.log(error);
			});
			
			writeSensorData(characteristic) ;
		
		
        });
      });
    });
  });
});

function getSocketLabel(uuid) {
  var label = null;

  if(uuid == AX_CHAR_UUID) {
    label = 'ax:edison';
  }
  else if(uuid == AY_CHAR_UUID) {
    label = 'ay:edison';
  }
  else if(uuid == AZ_CHAR_UUID) {
    label = 'az:edison';
  }
  else if(uuid == GX_CHAR_UUID) {
    label = 'gx:edison';
  }
  else if(uuid == GY_CHAR_UUID) {
    label = 'gy:edison';
  }
  else if(uuid == GZ_CHAR_UUID) {
    label = 'ecg:edison';
  }
  else if(uuid == ECG_CHAR_UUID) {
    label = 'gz:edison';
  }
  else if(uuid == PPG_CHAR_UUID) {
    label = 'ppg:edison';
  }

  return label;
}


function writeSensorData(characteristic) {
  var socketLabel = getSocketLabel(characteristic.uuid);
  console.log(socketLabel);

  characteristic.on('read', function(data) {
	client.write(socketLabel + " " + data.readUInt8(0));
	client.write('\r\n')
  
    //socket.emit(socketLabel, data.readUInt8(0));
  });

  characteristic.notify('true', function(error) { if (error) throw error; });
}

SCARLET Agent

Credits

Jaime Andres Rincon Arango

Jaime Andres Rincon Arango

23 projects • 97 followers
Phd in informatics and research in multi-agent system, IoT, IoMT and artificial intelligence.
Thanks to Solanye Guerra.

Comments