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.
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | /************************* 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | 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.