Go Down

Topic: KY039 Arduino Heart rate code (Read 86768 times) previous topic - next topic

skylion

Guys...need help...i was not using ky039 module....i only use red led,ir transmitter and receiver...and i have connect to op amp to make it smooth...but when i was run i get the result is 700++...but i find the person who are done this project and used the same component but get different result...i wonder how can i get the same result as that person..


int ledPin = 13;
int sensorPin = 0;
double alpha = 0.75; //using 75% of the average of the previous values and 25% of the current value
int period = 10; // This is how long the code delays in milliseconds between readings (10 mSec)
double change = 0.0; //to be used to detect the peaks

void setup()
{
pinMode(ledPin, OUTPUT);
Serial.begin(115200);
}
void loop()
{
static double oldValue = 0; // used for averaging.
static double oldChange = 0;
int rawValue = analogRead(sensorPin); // This reads in the value from the analog pin
double value = alpha * oldValue + (1 - alpha) * rawValue; // Calculate an average using 75% of the previous value and 25% of the new
change = value - oldValue;
digitalWrite(ledPin, (change < 0.00 && oldChange > 0.00));

delay(1000);
Serial.println("Red IR");
Serial.print(rawValue);
Serial.print(" ");
Serial.print(value);
Serial.println(" ");
oldValue = value;
oldChange = change;
}
 

jurs

wonder how can i get the same result as that person..
Why do you ask?

Because you don't understand anything about the code you posted?

Perhaps preplace:
Code: [Select]
delay(1000);
Serial.println("Red IR");

with
Code: [Select]
delay(period);

and watch if something different happens.

I don't know whether it may work, but to me it sounds much more reasonable to measure the input each 10 milliseconds instead of once per second only.

sonyhome

skylion, try my code, and also look at the desvription on how the led is oriented through the finger. you seem to be getting data pulses. btw, 1000 is 1 sample per second, and you want like minimum 5 samples per pulse.

skylion

Thx sonyhome for your help..i think i already get the result for the oxygen saturation..now i want to ask about measure heartbeat and oxygen saturation in one program..i have 2 sepatare coding

This is for measuring heartbeat:

// Pins
const int ledPin = 13;
const int sensePin = 0;

// LED blink variables
int ledState = LOW;
long ledOnMillis = 0;
long ledOnInterval = 50;

// Hearbeat detect variables
int newHeartReading = 0;
int lastHeartReading = 0;
int Delta = 0;
int recentReadings[8] = {0,0,0,0,0,0,0,0};
int historySize = 8;
int recentTotal = 0;
int readingsIndex = 0;
boolean highChange = false;
int totalThreshold = 2;

// Heartbeat Timing
long lastHeartbeatTime = 0;
long debounceDelay = 150;
int currentHeartrate = 0;

void setup() {
// initialize the serial communication:
Serial.begin(115200);
// initialize the digital pin as an output:
pinMode(ledPin, OUTPUT);
}

void loop() {
// Turn off LED
digitalWrite(ledPin, LOW);

// Read analogue pin.
newHeartReading = analogRead(sensePin);
//Serial.println(newHeartReading);
//Calculate Delta
Delta = newHeartReading - lastHeartReading;
lastHeartReading = newHeartReading;

// Find new recent total
recentTotal = recentTotal - recentReadings[readingsIndex] + Delta;
// replace indexed recent value
recentReadings[readingsIndex] = Delta;
// increment index
readingsIndex = (readingsIndex + 1) % historySize;

//Debug
//Serial.println(recentTotal);

// Decide whether to start an LED Blink.
if (recentTotal >= totalThreshold) {
// Possible heartbeart, check time
if (millis() - lastHeartbeatTime >= debounceDelay) {
// Heartbeat
digitalWrite(ledPin, HIGH);
currentHeartrate = 60000 / (millis() - lastHeartbeatTime);
lastHeartbeatTime = millis();
// Print Results
//Serial.println("Beat");
if (currentHeartrate <= 200)
{ Serial.println(currentHeartrate); } } } delay(10); }


This one for measure oxygen level;

int ledPin = 13;
int sensorPin = 0;
double alpha = 0.75; //using 75% of the average of the previous values and 25% of the current value
int period = 5; // This is how long the code delays in milliseconds between readings (10 mSec)
double change = 0.0; //to be used to detect the peaks
int z;

void setup()
{
pinMode(ledPin, OUTPUT);
Serial.begin(115200);
}
void loop()
{
static double oldValue = 0; // used for averaging.
static double oldChange = 0;
int rawValue = analogRead(sensorPin)-700; // This reads in the value from the analog pin
double value = alpha * oldValue + (1 - alpha) * (rawValue);// Calculate an average using 75% of the previous value and 25% of the new
change = value - oldValue;
z = log(1/value)/(log(1/rawValue));
digitalWrite(ledPin, (change < 0.00 && oldChange > 0.00));


delay(2000);
Serial.println("IR Intensity led intensity");
Serial.print(rawValue);
Serial.print("            ");
Serial.print(value);
Serial.println("            ");
oldValue = value;
oldChange = change;
}
 
 and also the formula is unread..when i click the serial monitor the value z was 0..

anyone can help?

sonyhome

z = log(1/value)/(log(1/rawValue));

replace with:

z = log(1.0/value)/(log(1.0/rawValue));

You may want to say what is your native language, maybe I or someone else speaks it.

mlinaje

I have tried hard to work with this module both, powering from arduino and externally powering it. In both cases I do not get values that make sense for bpm (i.e., let's say 60-200bpm).
IR LED is working, since I am able to see it in the dark with a camera.

When using external power, intensity is higher (arduino pins are around 40mA aprox.) and the IR LED is brighter.

Any new idea not detailed in this forum?

jurs

Any new idea not detailed in this forum?
Check the alignment of LED beam and sensor direction like shown in reply #27.

Then the analogRead values should be "in the middle" of the measuring range (i.e. 300...800) and not at the threshold of sensitivity.

AlexMolnar

HELLO. This is my first post so sorry if I say something stupid.

I used the schematic and the code from this page : https://tkkrlab.nl/wiki/Arduino_KY-039_Detect_the_heartbeat_module

Can anyone tell me how to interpret the numbers so that I can get the heart beat/pulse?

I posted the numbers I measured in attachment.

Thank you.

jurs

Can anyone tell me how to interpret the numbers so that I can get the heart beat/pulse?

I posted the numbers I measured in attachment.
For correct sensor adjustment see my reply #27 and the picture I posted.

Your data with many, many 0 measurements show that the LED in your hardware is not correctly adjusted to send its beam to the IR sensor.

As far as the code is concerned, you are doing measurement of the raw sensor data in a given moment:
Code: [Select]
   int rawValue = analogRead (sensorPin);

And then you are doing a low-pass filtering ("smooting", "averaging") of the values:
Code: [Select]
   double value = alpha * oldValue + (1 - alpha) * rawValue;

So "rawValue" is a momentary value measured at a single moment.
This number can change very quickly from one measure to the next.

And "value" is an filtered average value, created from several measured values.
This number can change slowly from one measure to the next, as it is an average created from several measurements.

So when printing both you will see this in your data:
- sometimes "rawValue" is higher than "value"
- sometime "rawValue" is lower than "value"

If you'd do that correctly (LED adjustment, low-pass filter value), you could see that the speed of this change will be in the rhythm of the heartbeat.

sonyhome

I'd say try the piece of code I submitted instead of that calculated value that does not work too good.

philpugh

I built one of these pulse rate sensors for a company whilst at university back in 1971.  Using similar components that were then available - but the solution didn't include any processors!!

Key things to think about.  The level of the signal you are interested in is 'swamped' by the level of "DC" voltage seen by the sensor.  This "DC" offset voltage will vary enormously between people and also for the same person in different conditions (e.g. hot or cold, well or ill).

You should shield the sensor from external light - especially mains driven - which adds a further signal conditioning problem - that's why the ones used in (eg) hospitals clip over the finger.  With care you should be able to get some readings but I suspect that the variations in output levels will make it difficult to detect accurately.

icksjot

On my KY-039 the little yellow men put a red LED in wrong direction >:(
Any questions?

harshdshah32

HI all. I used the same code and get the output between 4080-4094. What should be the output of this sensor ?
Is there any equation so I can convert this output numbers in regular pulse number , eg. Like 60-100.

this is my code.
int ledPin = 13;
int sensorPin = A0;
int alpha = 0.75;   //try with double
int period = 1000;
//double change = 0.0;

//double minval = 0.0;
void setup ()
{
  pinMode(ledPin,OUTPUT);
  Serial.begin(9600);
}
void loop ()
{
    static int oldValue = 0;
 //   static double oldChange = 0;
 
    int rawValue = analogRead(A0);
    Serial.println(rawValue);
    digitalWrite(ledPin,HIGH);
    int value = alpha * oldValue + (1 - alpha) * rawValue;

    // Serial.println(rawValue);
    Serial.println("   and,  ");
    Serial.println (value);
   
    digitalWrite(ledPin, LOW);
    oldValue = value;
 
    delay (period);
}

KamalLagh

For correct sensor adjustment see my reply #27 and the picture I posted.

Your data with many, many 0 measurements show that the LED in your hardware is not correctly adjusted to send its beam to the IR sensor.

As far as the code is concerned, you are doing measurement of the raw sensor data in a given moment:
Code: [Select]
   int rawValue = analogRead (sensorPin);

And then you are doing a low-pass filtering ("smooting", "averaging") of the values:
Code: [Select]
   double value = alpha * oldValue + (1 - alpha) * rawValue;

So "rawValue" is a momentary value measured at a single moment.
This number can change very quickly from one measure to the next.

And "value" is an filtered average value, created from several measured values.
This number can change slowly from one measure to the next, as it is an average created from several measurements.

So when printing both you will see this in your data:
- sometimes "rawValue" is higher than "value"
- sometime "rawValue" is lower than "value"

If you'd do that correctly (LED adjustment, low-pass filter value), you could see that the speed of this change will be in the rhythm of the heartbeat.

Hi,
But why the speed of this change will be in the rhythm of the heartbeat?

Go Up