My Heart Rate on the (Cosm) Cloud!

Recently Seeedstudio (many thanks!) has provided me with a Grove Heart Rate ear-clip sensor:

This cool (and very low price) sensor is attached on your ear and can detect your heart’s pulse through transmitting infrared light and checking the absorption variation caused by the blood flow on your ear lobe. The site of the products provides also the Arduino code for detecting the beats and calculating an average heart rate (in bpm  – beats per minute). The sensor comes with a grove connector, so setting up and running the code took less than 5 mins! (thanks again @seeedstudio for providing me with a complete Grove kit).

After playing with it a while I realized that I could make a cool Cloud-based heart rate tracker by simply using an ADK board and my Android phone. This way I could be completely mobile (given that the 9V battery that powers the ADK board can last!).

I modified the Arduino code to send the heart rate to the Android using the ADB and made also a simple Android app that takes the heart rate and sends it to Cosm  (former Pachube) using the jpachube library.

This is the graph generated from Cosm: (EDIT: Battery has died, will put on again sometime tomorrow ) EDIT (14/05): I’ve put it on again for a few hours!)

EDIT: I will occasionally put on the sensor during the following days.

Despite being very mobile (the cable is long enough to reach my pocket where both boards and mobile phone are) I am sure the graph-feed will stop being live quite soon (will either get bored, battery will die or will take it off to go to sleep…)

The code for the Arduino is the following:


/************************* 2011 Seeedstudio **************************
* File Name : Heart rate sensor.pde
* Author : Seeedteam
* Version : V1.0
* Date : 30/12/2011
* Description : This program can be used to measure heart rate,
the lowest pulse in the program be set to 30.
*************************************************************************/

//Modified by @BuildingIoT
//for communication with Android

#include <SPI.h>
#include <Adb.h>

// Adb connection.
Connection * connection;

// Elapsed time for ADC sampling
long lastTime;

unsigned char pin = 13;
unsigned char counter=0;
unsigned int heart_rate=0;
unsigned long temp[21];
unsigned long sub=0;
volatile unsigned char state = LOW;
bool data_effect=true;
const int max_heartpluse_duty=2000;//you can change it follow your system's request.2000 meams 2 seconds. System return error if the duty overtrip 2 second.

void setup() {
pinMode(pin, OUTPUT);
Serial.begin(9600);
//Serial.println("Please put on the ear clip.");
delay(5000);//
array_init();
//Serial.println("Heart rate test begin.");
attachInterrupt(0, interrupt, RISING);//set interrupt 0,digital port 2

// Initialise the ADB subsystem.
ADB::init();

// Open an ADB stream to the phone's shell. Auto-reconnect
connection = ADB::addConnection("tcp:4567", true, adbEventHandler);
}

void loop() {
digitalWrite(pin, state);

}

void sum()//calculate the heart rate
{
if(data_effect)
{
heart_rate=1200000/(temp[20]-temp[0]);//60*20*1000/20_total_time
//Serial.print("Heart_rate_is:\t");
Serial.println(heart_rate);
connection->write(2, (uint8_t*)&heart_rate);
ADB::poll();
}
data_effect=1;//sign bit
}
void interrupt()
{
temp[counter]=millis();
state = !state;
//Serial.println(counter,DEC);
//Serial.println(temp[counter]);
switch(counter)
{
case(0):
sub=temp[counter]-temp[20];
//Serial.println(sub);
break;
default:
sub=temp[counter]-temp[counter-1];
//Serial.println(sub);
break;
}
if(sub>max_heartpluse_duty)//set 2 seconds as max heart pluse duty
{
data_effect=0;//sign bit
counter=0;
Serial.println("Heart rate measure error,test will restart!" );
array_init();
}
if (counter==20&&data_effect)
{
counter=0;
sum();
}
else if(counter!=20&&data_effect)
counter++;
else
{
counter=0;
data_effect=1;
}
}
void array_init()
{
for(unsigned char i=0;i!=20;++i)
{
temp[i]=0;
}
temp[20]=millis();
}
// Event handler for the shell connection.
void adbEventHandler(Connection * connection, adb_eventType event, uint16_t length, uint8_t * data)
{

}

For the Android app all is needed is an Activity that implements the ADB server and communicates with the Arduino board:


package buildingiot.heartrate;

import java.io.IOException;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

import org.microbridge.server.Server;
import org.microbridge.server.AbstractServerListener;

public class HeartRateOnCloudActivity extends Activity {

// Create TCP server (based on MicroBridge LightWeight Server).
// Note: This Server runs in a separate thread.
Server server = null;

int heartrate = 0;

TextView textView1;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

textView1=(TextView)findViewById(R.id.textView1);

//Create TCP server (based on MicroBridge LightWeight Server)
try {
server = new Server(4568); //Use the same port number used in ADK Main Board firmware
textView1.setText("Starting server..");
server.start();
textView1.setText("server started!");

} catch (IOException e){
Log.e("Seeeduino ADK", "Unable to start TCP server", e);
textView1.setText("server not started!!");

}

server.addListener(new AbstractServerListener() {

@Override
public void onReceive(org.microbridge.server.Client client, byte[] data){
textView1.setText("got arduino data!");
String bpm = new String(data);
textView1.setText(bpm+" bpm");

}
});

}
}

To make it all work you need to have an ADB-enabled Arduino board like this one.

More examples on Android and Arduino communication can be found in my book.

11 Comments

  1. Alex March 20, 2013 6:31 pm Reply

    What arduino board do you use for this project?

    • Charalampos March 22, 2013 10:01 am Reply

      It is this board, any ADK board would do.

      • Alex March 27, 2013 6:55 pm Reply

        Would using an arduni UNO board with an ADK shield work? And if so how much editing of the code would need to be made??

        • Charalampos March 27, 2013 9:39 pm Reply

          Sure, as long as the shield supports ADB (in most cases) there will be no need for code modifications. In any case let me know if you need any help!

          • Alex March 28, 2013 2:07 am

            Thank you, will I be able to use to shields together, I.E. a n ADK shield with a grove shield? or will that cause some issues?

          • Charalampos March 28, 2013 10:28 pm

            Yes, should be ok with digital and analog sensors!

  2. Alex April 10, 2013 9:03 pm Reply

    My parts are now arriving in the post to have a go at this project but I just had a thought wondering if because I’m using a different microcontroller will the pin assignments be different?

  3. Bill July 5, 2013 6:18 pm Reply

    What does the ‘temp [21]’ part in line 25 represent?

    • Charalampos July 7, 2013 9:07 pm Reply

      temp[] stores the time at which a heartbeat (interrupt) has been received. Used to calculate the total time it takes to receive 21 beats in the beginning for calculating the average beat per minute. It’s from Seeedstudio code for the heart rate sensor :-)

Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>