While trying to create a circuit that detects whether water is flowing through a pipe by measuring the vibration with a piezoelectric sensor, just to see what happens I taped the sensor around my finger and – to my surprise – got values that were a very noise-free representation of my heart rate!
This is even easier than using LEDs as it only requires a piezoelectric sensor and an Arduino. (and a piece of tape)
The sensor I used is a DFRobot Piezo Disc Vibration Sensor Module.
void setup() { Serial.begin(57600); } void loop() { int avg = 0; for(int i=0;i<64;i++){ avg+=analogRead(A2); } Serial.println(avg/64,DEC); delay(5); }
When defining an arbitrary threshold (e.g. half of the maximum measured value), the rising edge of the signal will pass the threshold once per heartbeat, making measuring it as simple as measuring the time between two successive beats. For less jitter, I chose to calculate the heart rate using the average of the last 16 time differences between the beats.
Here’s a quick and dirty code that calculates the heart rate and outputs the average heart rate over the last 16 beats at every beat:
int threshold = 60; int oldvalue = 0; int newvalue = 0; unsigned long oldmillis = 0; unsigned long newmillis = 0; int cnt = 0; int timings[16]; void setup() { Serial.begin(57600); } void loop() { oldvalue = newvalue; newvalue = 0; for(int i=0; i<64; i++){ // Average over 16 measurements newvalue += analogRead(A2); } newvalue = newvalue/64; // find triggering edge if(oldvalue<threshold && newvalue>=threshold){ oldmillis = newmillis; newmillis = millis(); // fill in the current time difference in ringbuffer timings[cnt%16]= (int)(newmillis-oldmillis); int totalmillis = 0; // calculate average of the last 16 time differences for(int i=0;i<16;i++){ totalmillis += timings[i]; } // calculate heart rate int heartrate = 60000/(totalmillis/16); Serial.println(heartrate,DEC); cnt++; } delay(5); }
If you would like to try this at home, just connect the analog output of the sensor to A2 (or change the code) and connect the 5V and GND lines of the sensor.
Hey man, nice work!
I’m doing an “health wristband” and I need to catch heart beats. Could you test around the wrist and show the results? This method needs to be pressured the sensor on the skin? Or just the touch could work?
Thanks in advance.
This is the best project I’ve found on the subject! Thanks for posting and the program.
You’re super!
Jim
Wau – this is a great idea. If you the first one you should claim a patent. In our institute we have tried to find a simple method to measure the heart frequency but nothing worked very well, e.g. led-based methods are very noisy and need to much energy. Your method worked like a charm (I have just tried it) and needs no energy. The big player in fitness tracking will use it.
Congratulation Felix
Very nice idea, I’m surprised by its simplicity, thank you 🙂 One suggestion though, maybe you better put a protection diode between the analog in and vdd, the piezo can easily generate tens of volts if unadvertently slammed and fry your analog in.
Is it me or does the serial monitor give me lot of gibberish symbols?
Wiring is only one in the A2 and one in the ground, not?
Keep in mind that the serial connection is set to 57600 baud, so you also have to set it to that in the serial monitor!
Hey,
In one statement, patent this.
Since old electronics mags I didn’t see anything as useful.
Nicely done, thanks for sharing.
hello, that means by using this sensor able to detect the heart beat (vibration) on th finger?
Hi!
Can you please tell me why you used 64 in this cycle “for(int i=0; i<64; i++)"?
He did that to get the average of 64 ADC measurements. This adds to resolution and lowers noise. If you modify this so that a complete period of 50Hz hum is covered (maybe using millis() or delay_us()) noise (50Hz become even lower.
Hi,
Can you please explain me more about what is below line 21 till the end?
Thank you in advance!
Hi, can you please eplain how to display the output in java data log?
i can see the output in the serial monitor only !
Thank you
Please send me the circuit off on how to connect the piezoelectric senor to circulate
hey can we use this at the back of our neck or some other places?plz reply
Hey!
Can you tell me the name of this model of piezo vibration sensor?
Nice work though!
Hello,
Could u tell me where to buy this sensor?
Thanks.
change 64 to 16 for good result
Well done,
I was searching for this code all over the internet.
can u explain me how we get a result of heartbeat within 1 minutes? how codes?
what is the circuit of this project? reply me fast
I try to modify your code to transfer heartbeat to my android app but am kind of confuse. Please can anybody help out.
int threshold = 60;
int oldvalue = 0;
int newvalue = 0;
unsigned long oldmillis = 0;
unsigned long newmillis = 0;
int cnt = 0;
int timings[16];
void setup() {
Serial.begin(57600);
}
void loop() {
if(Serial.available()>0){
char re = Serial.read();
switch(re){
case ‘E’:
start();
break;
}
}
}
void start(){
while(1){
oldvalue = newvalue;
newvalue = 0;
for(int i=0; i0){
if (Serial.read()==’Q’) return;
}
}
int floatMap(int newvalue){
oldvalue = newvalue;
newvalue = newvalue/64;
// find triggering edge
if(oldvalue=threshold){
oldmillis = newmillis;
newmillis = millis();
// fill in the current time difference in ringbuffer
timings[cnt%16]= (int)(newmillis-oldmillis);
int totalmillis = 0;
// calculate average of the last 16 time differences
for(int i=0;i<16;i++){
totalmillis += timings[i];
}
// calculate heart rate
int heartrate = 60000/(totalmillis/16);
cnt++;
}
return heartrate;
}
Wow! This is really cool, it really made me want to buy Arduino and try this out. Thanks for sharing the source code!
dude what happens if it is embedded to chest