KY-039 Heartbeat sensor module

From SensorKit X40 Wiki

Revision as of 10:18, 27 February 2017 by Webmaster Wiki (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Picture

none

Technical data / Short description

While sticking a finger between the infrared diode and the photo transistor you can detect the pulse at the signal out.


The explanation of the functionality of an photo transistor is simple: It works like a normal transistor - you will detect a higher electricity if the control voltage is higher. Instead of the control voltage the photo transistor uses the light, is it a strong light you will measure a higher electricity.


none If you connect a transistor with a resistor in a row you can measure nearly 0V at the transistor while the light intensity is high. Is the light intensity low , like the transistor lay in the dark, you can measure a +V voltage.

With this sensor module you can measure a pulse, for that you have to stick a finger between the diode and the transistor. Explanation: If you use a flashlight at your hand you can see that the light shines through. If you hit a blood vessel with that you can see how the blood is pumping through. You can see it because the density of the blood vessel is not the same on every place which means you can see the differences in the light value of the blood flow. You can record this differences with the sensor and calculate the pulse. You can see it at the following oszilloskop-picture.


none


It shows the shifting of voltage at the Y-axis and with that the shift of light at the flowing blood. The peaks above are showing the beating of the heart. If you calculate the beats per recorded time you will get the result of nearly 71 beats/per minute (bpm)


Additional to that you can see that the recorded signal is really small or the transistor has a high sensitivity. To get the best result we recommend to build a circuit like the one in the following picture.


none


Additional to that you should use the little finger for the measurement , plus you should try to not hold the bone between the diode and the transistor.


none



Pinout

none

Code example Arduino

The following code example was written by Dan Truong. He published it under the following [[1]] . It is available under the  [|MIT OpenSource License].

The example below is a german translation, you can get the original via download.

This code shows a so called "Peak-detection". It doesn't record a heartbeat history, instead of that it looks for peaks in the recorded data, which was detected as heartbeat and shown with a LED. You can calculate the pulse with the known delay. If you move the finger to strong, it could take some time till the program reacts to the new situation and gives out the correct data.    


////////////////////////////////////////////////////////////////////////
/// Copyright (c)2015 Dan Truong
/// Permission is granted to use this software under the MIT
/// licence, with my name and copyright kept in source code
/// http://http://opensource.org/licenses/MIT
///
/// KY039 Arduino Heartrate Monitor V1.0 (April 02, 2015)
////////////////////////////////////////////////////////////////////////

// German Comments by Joy-IT


////////////////////////////////////////////////////////////////////////
/// @param[in] IRSensorPin Analog PI which is connected with the sensor
/// @param[in] delay (msec) The delay between the calls of the sample function
//                   You will get the best results if take 5 sample for each heart beat 
///                  Not slower than 150 mSec for 70 BPM pulse 
///                  Better take 60 mSec for a pulse of 200 BPM.
///
/// @Short description
/// This code is a so called Peak-detection.
/// It doesn't record a heart beat history,
/// instead it will search for peaks in the recorded data, 
/// and show them via LED. While knowing the delays you can calculate the pulse.
////////////////////////////////////////////////////////////////////////

int rawValue;


bool
heartbeatDetected(int IRSensorPin, int delay)
{
  static int maxValue = 0;
  static bool isPeak = false;
  
  
  bool result = false;
    
  rawValue = analogRead(IRSensorPin);
  // Measureing of the voltage value at the photo transistor and saving of the result into the rawValue-variable
  rawValue *= (1000/delay);

  // If the difference of the current value and the last value is to high
  // ( maybe because you moved the finger away from the sensor)
  // maxValue will be resetted to get a new basic
  if (<span style="color: #000000;">rawValue * 4L < maxValue</span>) {    maxValue = rawValue * 0.8;  }    // Detect new peak  if (rawValue > maxValue - (1000/delay)) {
    // The peak will be detected here. If the new rawValue is bigger than
	// the last maxValue, it will be detected as a peak.
    if (rawValue > maxValue) {
      maxValue = rawValue;
    }
    // Allocate only one heartbeat to a peak.
    if (isPeak == false) {
      result = true;
    }
    isPeak = true;
  } else if (rawValue < maxValue - (3000/delay)) {
    isPeak = false;
    // Here the maxValue will be decreased at each run
    // because if you don't do that the value would be every time lower or the same.
    // Also if you move the finger a bit the signal would be weaker without that.
    maxValue-=(1000/delay);
 }
  return result;
}


////////////////////////////////////////////////////////////////////////
// Arduino main code
////////////////////////////////////////////////////////////////////////
int ledPin=13;
int analogPin=0;

void setup()
{
  // The included LED of the Arduino (Digital 13), will be used as output here.
  pinMode(ledPin,OUTPUT);
  
  // Serial output initialization
  Serial.begin(9600);
  Serial.println("Heartbeat detection example code");
}

const int delayMsec = 60; // 100msec per sample

// The main program has two tasks: 
// - The LED will light up after detecting a heart beat
// - Calculating of the pulse and outputting of it at the serial out.

void loop()
{
  static int beatMsec = 0;
  int heartRateBPM = 0;
      Serial.println(rawValue);
  if (heartbeatDetected(analogPin, delayMsec)) {
    heartRateBPM = 60000 / beatMsec;
	// LED-output for the heart beat heart beat
    digitalWrite(ledPin,1);

    // Output of the serial data
    Serial.print(rawValue);
    Serial.print(", ");
    Serial.println(heartRateBPM);
    
    beatMsec = 0;
  } else {
    digitalWrite(ledPin,0);
  }
  delay(delayMsec);
  beatMsec += delayMsec;
}

Connections Arduino:

Sensor Signal = [Pin 0]
Sensor +V = [5V]
Sensor - = [Pin GND]

Example program download

KY-039-HeartBeatDetector original by DanTruong


KY-039-HeartBeatDetector german version by Joy-It

Code example Raspberry Pi

!! Attention !! Analog sensor  !! Attention !!

Unlike the Arduino, the Raspberry Pi dont provide an ADC ( analog digital converter ) on its chip. This gives the Raspberry Pi limits if you want to use a non digital sensor [ voltage value exceeded -> digital ON | voltage value deceeded -> digital OFF | example : button pushed [ON] button released [OFF]], but rather its a continous changeable value ( example: potentiometer -> other position = other voltage value).

To evade this, use our Sensorkit X40 with the KY-053 module which provides a 16 Bit ADC, which can be used  with the Raspberry Pi, to upgrade it with 4 additional analog input pins. This will be connected via I2C from the Raspberry Pi, it takes the analog measurment and gives the digital value to the Raspberry Pi.

So we recommend for analog sensors from this set, to interpose the KY-053 module with the ADC. For more information please look at the infosite: KY-053   Analog Digital Converter

!! Attention !! Analog sensor  !! Attention !!

Normally the function to detect a heartbeat should start after the configured delayTime (Standard: 10 ms). If it detects a heartbeat , it will output the pulse. Additional to that you can connect a LED with the LED pin (standard: GPIO24) to visualise the detected heartbeat.

If you move the finger to strong or take it back and put it to the sensor again, the program needs a few seconds (3-5 seconds) till it will give you new correct data.

The program uses the specific ADS1x15 and I2C python-libraries from the company Adafruit to control the ADS1115 ADC. You will find these on the link: [https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code] published under the BSD-License [Link] . You can find the needed libraries in the download package below.


#!/usr/bin/python
# coding=utf-8

#############################################################################################################
### Copyright by Joy-IT
### Published under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
### Commercial use only after permission is requested and granted
###
### Parts of Code based on Dan Truong's KY039 Arduino Heartrate Monitor V1.0
### [https://forum.arduino.cc/index.php?topic=209140.msg2168654] Message #29
#############################################################################################################


# This code is using the ADS1115 and the I2C python libraries for the Raspberry Pi
# It is published by BSD License under the following link
# [https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code]
from Adafruit_ADS1x15 import ADS1x15
from time import sleep

# Additional needed modules will be imported and configured
import time, signal, sys, os
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

# Used variables will be initialized
beatsPerMinute = 0
isPeak = False
result = False
delayTime = 0.01
maxValue = 0
schwelle = 25
beatTime = 0
oldBeatTime = 0

# Address allocation ADS1x15 ADC

ADS1015 = 0x00  # 12-bit ADC
ADS1115 = 0x01	# 16-bit

# Amplification (Gain) will be picked 
gain = 4096  # +/- 4.096V
# gain = 2048  # +/- 2.048V
# gain = 1024  # +/- 1.024V
# gain = 512   # +/- 0.512V
# gain = 256   # +/- 0.256V

# Sample rate of the ADC (SampleRate) will be picked 
sps = 8    # 8 Samples per second
# sps = 16   # 16 Samples per second
# sps = 32   # 32 Samples per second
# sps = 64   # 64 Samples per second
# sps = 128  # 128 Samples per second
# sps = 250  # 250 Samples per second
# sps = 475  # 475 Samples per second
# sps = 860  # 860 Samples per second

# ADC-Channel (1-4) will be picked 
adc_channel = 0    # Channel 0
# adc_channel = 1    # Channel 1
# adc_channel = 2    # Channel 2
# adc_channel = 3    # Channel 3

# Here, the ADC will be initialized - the ADC which is used by the KY-053 is an ADS1115 chipset
adc = ADS1x15(ic=ADS1115)

# LED output pin declaration.
LED_PIN = 24
GPIO.setup(LED_PIN, GPIO.OUT, initial= GPIO.LOW)


#############################################################################################################

# Buzzer output pin declaration.
def heartBeatDetect(schwelle):
        global maxValue
        global isPeak
        global result
        global oldBeatTime

        # Reading of the voltage at the photo transistor
        # saving of the voltage value into the rawValue variable
        # With "adc_channel" the channel which is connected with the ADC will be picked.
        rawValue = adc.readADCSingleEnded(adc_channel, gain, sps)

        # Reset of the result-variable 
        if result == True:
            result = False

        # If the difference between the current value and the last maximum value is to big
        # (maybe bacause you moved the finger to strong for example)
        # Here you see the reset of the maxValue to get a new basic.
        if rawValue * 4 < maxValue:              maxValue = rawValue * 0.8;                # Detecting of the peak. If a new raWValue is higher than the last maxValue,        # it will be detected as a peak from the data.
        if rawValue > (maxValue - schwelle):

              if rawValue > maxValue:
                    maxValue = rawValue
              # One heartbeat will assign to the peak
              if isPeak == False:
                    result = True

              isPeak = True

        else:
            if rawValue < maxValue - schwelle:
              isPeak = False
              # Here the max value will be decreased at each run
              # because if you don't do that the value would be every time lower or the same.
              # Also if you move the finger a bit the signal would be weaker without that.

            maxValue = maxValue - schwelle/2

        # If a heartbeat was detected above, the Output will start.
        if result == True:

            # Calculating of the pulse
            # Here the system time will be recorded for every heartbeat
            # At the next heartbeat, the system time will be compared with the last recorded one
            # The difference between them is the time between the heartbeats
            # with that you can also calculate the pulse
            beatTime = time.time()
            timedifference = beatTime - oldBeatTime
            beatsPerMinute = 60/timedifference
            oldBeatTime = beatTime

            # Additional to the caltulating of the pulse, the heartbeat will light up a LED for a short time
            GPIO.output(LED_PIN, GPIO.HIGH)
            time.sleep(delayTime*10)
            GPIO.output(LED_PIN, GPIO.LOW)

            # Calculated pulse will be given to the function
            return beatsPerMinute

#############################################################################################################

# ########
# Main program loop
# ########
# After the "delayTime" (standard: 10ms) the function to detect a heartbeat will start.
# After detecting a heartbeat, the pulse will be outputted.

try:
        while True:
                time.sleep(delayTime)
                beatsPerMinute = heartBeatDetect(schwelle)
                if result == True:
                    print "---Heartbeat detected !--- Puls:", int(beatsPerMinute),"(bpm)"



except KeyboardInterrupt:
        GPIO.cleanup()

Connection Raspberry Pi:

Sensor KY-039

Signal = Analog 0 [Pin A0 (ADS1115 - KY-053)]
+V = 3,3V [Pin 1]
GND = GND [Pin 6]

ADS1115 - KY-053:

VDD = 3,3V [Pin 01]
GND = GND [Pin 09]
SCL = GPIO03 / SCL [Pin 05]
SDA = GPIO02 / SDA [Pin 03]
A0 = look above [Sensor: Signal]

Example program download

To start with the command:

sudo python KY-0039_HeartBeatDetector.py