Title: Vital Care
By: Md. Kamrul Hussain
Project Category: Design Challenge
Project Name: Design For A Cause 2021
Blog post: 05
Previous Blogs:
Blog No. | Title |
---|---|
01 | Introduction |
02.a | SpO2 basics [PPG] |
02.b | SpO2 [MAX30102] |
03 | Temperature |
In this blog I'll be covering some basics of single LEAD ECG and share my experience of acquiring ECG by constructing a simple Bio potential measurement circuit using Instrumentation amplifier and some basic analog filters. Then I'll show output of AD8232 ECG which is captured and processed using dsPIC33EP512MU810 MCU and a simple but efficient heart rate detection algorithm is implemented. This can be further used for detecting heart rate variability and the data can be sent to NANO 33 IOT through BLE using RN4020 module. I have done most of the experiment few years back taking part in another design challenge of ELEMENT14 community.
Here are the steps -
- design of a simple Bio-Amp with filters for single LEAD ECG
- compare output of AD8232 ECG module
- process the output and apply heart detection algorithm using dsPIC33EP512MU810
**UPDATE: I designed a PCB layout for this purpose previously which contains the AD8232 chip, dsPIC33EP512MU810 MCU and RN4020 BLE module. But this will take time to fabricate and assemble the board. Due to that time constrain I tried to implement it using an Arduino MKR WiFi 1010. I have this board with me and this is similar to the Arduino NANO 33 IOT with the same processor [Arm Cortex-M0 32-bit SAMD21] and WiFi+BLE chip [u-Blox NINA W10]. Therefore, I used it to acquire ECG signal, process it, get the Heart Rate and send it to the cloud.
ECG LEAD arrangement:
Einthoven’s Triangle-
LA = Left arm
RA = Right arm
LL = left leg
LEAD I = LA – RA
LEAD II = LL – RA
LEAD III = LL – LA
Conventional LEAD configuration-
Conventional configuration that is followed in wearable health tech is LEAD I, as it can be implemented in a chest belt. Where the RLD [right leg drive] is introduced as the alternative ground or reference path to cancel out the common noise to improve the SNR [signal to noise ratio] by improving the CMRR [common mode rejection ratio] of the bio amp.
One time / single use ECG electrodes from 'TOP TRACE' were used in experimental purpose. It has Ag-AgCl [silver-silver chloride] electrode with adhesive gel for skin-electrode coupling to provide good contact. Though Ag-AgCl has a little health issue for longer use, but it's only for experiment. I would like to go for carbon electrodes in my final design if it's possible.
Step - 01: design of a simple Bio-Amp with filters for single LEAD ECG
For LEAD I configuration, the conventional LEAD arrangement produces an output of about 0.6 Vp-p. The resultant signal has 50 Hz [in my country] component contributed by the body [common mode signal] and the mains ground of the oscilloscope and hence the computer. In real life the 50 Hz component will be less as because the whole system will be driven by battery power supply and there will be less 50 Hz interference in an open playground. However, a digital filter can be implemented in the software end, but we'll lose information [like P wave will be flattened]. It's not a diagnosis purpose ECG and a very few amount of information can be found by only one LEAD. So, considering that the detailed wave shape is not much important here, we can implement digital filter if it's necessary later on.
Above ECG plot is for LEAD1 captured from ARM using clip electrode. For chest arrangement, the electrodes are placed too closed to RLD or the reference of Einthoven's triangle, which results an ECG output with slightly different shape for T wave and comparatively reduced QRS complex. However, the overall peak to peak voltage is increased from 0.6 Vp-p to about 2 Vp-p for chest arrangement.
the output seems to have high 50 Hz component. If we look into the spectrum view -
Step - 02: compare output of AD8232 ECG module
I have tried to compare the output signal of a single LEAD ECG captured by AD8232, a single chip ECG Bioamp designed by Analog Devices Inc.
Spectrum view shows that 50 Hz noise is added by oscilloscope.
By using an opto-isolator, the 50Hz noise can be eliminated. However, it also inverts the ECG output.
If I compare the output of previous Bio-Amp and AD8232 output -
It shows that the AD8232 is missing detail information in the signal. Like the P-wave is flatten and the whole T-wave is superimposed with the 50Hz noise.
May be that’s because of the filter bandwidth. In my design I had captured in between a range of 0.3Hz to 159Hz where AD8232 limits the low pass far below 50Hz to get rid of common noise. However, this won’t be necessary as it’s not for diagnostic purpose. I just need to get the heart rate with single LEAD ECG, so it’s pretty good enough. Moreover, AD8232 produces a better, sharp QRS complex which will be more helpful.
However, AD8232 responded effectively for removing motion artifacts. For general movement, it maintains the output signal pretty good. But for fast strong movements or contraction of the muscle the signal gets distorted. I have to check it's performance over motion artifacts once again after mounting it on human body.
Step - 03: process the output and apply heart detection algorithm using dsPIC33EP512MU810
For Heart Beat Rate detection from QRS complex of ECG signal, I have used a modified version of the algorithm developed by PAN and TOMPKINS [1985] and further described by HAMILTON and TOMPKINS [1986]. This algorithm has several steps -
- Filtering
- Slope detection
- Moving Window Integral
- Amplitude analysis
- Width analysis
Block Diagram -
I have used AD8232 AFE EVAL and MikroMedia dsPIC33EP from Mikroelektronika in this experiment. Later on the dsPIC33EP256MU810 will be used along with RN4020 BLE module to send the data to Arduino NANO 33 IOT through bluetooth low energy.
Output -
Output of the QRS complex detection at different stage of applying Band Pass Filter, taking Derivative, Squaring function, Moving Window Integral and applying threshold are presented below.
{gallery} QRS complex detection |
---|
Band Pass Filter: 8-20 Hz 32nd order FIR Bertlett with 366Hz sampling at resting condition |
Band Pass Filter: 8-20 Hz 32nd order FIR Bertlett at 366Hz sampling with rapid body movement |
Signal conditioning: After taking Derivative, Squaring function and applying Moving Window Integral at resting condition |
Signal conditioning: After taking Derivative, Squaring function and applying Moving Window Integral with body movement |
Threshold: Applying threshold at half peak point in resting condition |
Threshold: Applying threshold at half peak point in body movement |
BEAT rate [BPM] -
An independent 32.768KHz crystal oscillator is used to clock the timer1 module of dsPIC33EP for RTC. This helps to calculate the beat rate precisely.
The 32.78KHz oscillator is prescaled by 8. So, we have a timer clock of 4096 Hz. Means 4096 clocks in a second.
So, the Beats Per Minute [BPM] will be -
BPM = [4096 / total count by timer1 between two pulses] * 60
Body is in resting condition With body movements
Custom Module :
A custom module is designed with following parameters -
AFE --> AD8232 with 7.2Hz to 25Hz bandwidth.
Gain --> 1100 [inamp = 100, filterout gain = 11]
LEAD configuration --> LEAD 02
Mode --> Three electrode combination [LL - RA with RLD]
RLD --> R7 has been used to limit the loop gain for DC or low frequencies.
Shield --> Electrode cables are shielded with RLD output. Bottom layer of the PCB on the AFE side is copper filled with GND to reduce the noise
MCU --> a dsPIC33EP256 microcontroller is used to process the output signal from the AFE and get the Heart Rate. It also controls the Bluetooth communication.
BLE --> RN4020 from microchip
PCB dimension --> 5.4cm x 3cm double layer
The small form factor will be helpful to mount it on chest comfortably. However, it is not assembled yet.
{gallery} Custom ECG module with BLE |
---|
Circuit Diagram: Analog Front End |
Circuit Diagram: Analog Front End |
PCB: TOP layout |
PCB: Bottom layout |
3D view: TOP |
3D view: Bottom |
Single LEAD ECG with AD8232 using Arduino MKR WiFi1010
Due to the time constrain for finishing this project within the deadline, I tried to implement the ECG acquisition system using an Arduino MKR WiFi 1010. I have this board with me and this is similar to the Arduino NANO 33 IOT with the same processor [Arm Cortex-M0 32-bit SAMD21] and WiFi+BLE chip [u-Blox NINA W10]. Therefore, I used it to acquire ECG signal, process it, get the Heart Rate and send it to the cloud.
Module arrangement:
I have used a ready-made AD8232 module for this purpose. This module was directly hooked up on top of the MKR WiFi 1010 pin headers. I used MCU pins A0 and A1 to provide the 0v and 3.3v respectively to power up the module. The AD8232 chip itself draws only 170uA current and the on board passive circuitry and the beat identification LED draws less than 5mA all together. Therefore, the PIN output of the MCU is strong enough to power up the module. Also, the LEAD OFF detection pins are connected to A4 and A5 as input and the Shutdown pin is connected to A6 as output. The ECG output from the module goes to A3 analog input.
Code snippet for initialization of the AD8232 module driven directly from MCU pins -
#define GND A1 #define POWER A2 #define ECGOUT A3 #define LO_LA A4 #define LO_RA A5 #define SDN A6 //------------------- //------------------------- void setup() { pinMode(GND, OUTPUT); //A1 PROVIDES GROUND [0V] TO AD8232 MODULE pinMode(POWER, OUTPUT); //A2 PROVIDES POWER [3.3V] TO AD8232 MODULE pinMode(LO_LA, INPUT); //A4 TAKES THE LEAD OFF (-) INPUT pinMode(LO_RA, INPUT); //A5 TAKES THE LEAD OFF (+) INPUT pinMode(SDN, OUTPUT); //A6 OUTPUTS THE SHUTDOWN SIGNAL pinMode(LED_BUILTIN, OUTPUT); //D6 - BUILTIN LED INDICATES THE LEAD OFF CONDITION digitalWrite(GND,LOW); //POWER UP THE MODULE [-VE] digitalWrite(POWER,HIGH); //POWER UP THE MODULE [+VE] digitalWrite(SDN,HIGH); //ENABLE THE AD8232 MODULE //----------------------- //---------------------------- }
Signal acquisition and QRS complex detection for heart rate calculation:
ECG single LEAD signal was acquired at PIN A0. It showed comparatively clean signal as I have used a Laptop running on battery to provide isolated supply. It reduced the 50 Hz noise. The AD8232 has excellent CMRR and PSRR which removes other noise regarding muscle contraction, electrode potential etc. However, the line noise can still be noticed and some high frequency components were there. I have to remove it and pre-condition the signal for further QRS complex detection to get the Heart Rate. Steps and filters / processes used are mentioned below -
Steps | Goal | Filter / Process |
---|---|---|
1 | Line noise [notch] and low pass filter | Ewma ADCfilter and KickFiltersRT NOTCH |
2 | Highpass filter to get rid of the DC offset | KickFiltersRT Highpass |
3 | Rectification and amplification | Derivative and Squaring [sq(x)] |
4 | smoothing and integral | Ewma ADCfilter1 [moving average] |
5 | Peak detection | Ewma ADCfilter, V-peak amplitude threshold, millis() for QRS complex beat time threshold |
OUTPUT:
Blue plot gives the RAW ECG from A3 analog input. It has a DC offset of 512 [ADC value - mid point of the supply voltage 3.3v]. AD8232 corrects the baseline wander and shifts it at the mid supply voltage. However, it may contain 50Hz line noise and other high frequency noise due to muscle contraction.
Red plot shows signal after 50Hz notch and low pass filter [STEP 1]. The high frequency small components are removed.
The GREEN plot [STEP 2] is the output of the high pass filter where the DC components are removed.
The Red plot gives the output of taking derivatives and squaring function respectively to identify the peaks of QRS complex [STEP 3]. It takes both the negative and positive change and rectifies it using squaring function [moves to positive side]. Thus the Red plot shows double peaks for both the positive and negative slop of the QRS complex. At the same time the small changes are filtered out and the sharp changes / slopes are amplified more to give clear peaks.
The Green plot represents the smoothing integral of the Red plot using a moving average filter [STEP 4]. The double peaks of the Red plot are integrated and the small changes are reduced more which gives clearance to apply amplitude and time threshold to identify the QRS complex certainly
Basic code snippets looks like this -
while(digitalRead(LO_LA) && digitalRead(LO_RA)){ digitalWrite(LED_BUILTIN, HIGH); LEADstatus = 0; ecgLEAD = LEADstatus; delay(500); //Serial.println("LEADoff"); } digitalWrite(LED_BUILTIN,LOW); LEADstatus = 1; for(uint16_t i = 0; i < samples; i++) { input = analogRead(ECGOUT); float filtered1 = adcFilter1.filter(input); float filtered2 = filtersRT.highpass(filtered1); float derivative = filtered2 - input0; input0 = filtered2; float square = sq(derivative); float beats = adcFilter2.filter(square);
Now, the question is, WHY???
Why so many filters and processing??
Well.... the following plots gives the answer - We need to detect the HEART BEAT even if we move. I'll be using chest belt to place the electrodes. So, my target is even if I jump a little, I should be able to detect the heart beat clearly. If I apply only amplitude threshold at the very beginning of the RAW ECG signal, I won't be able to detect the heart beat clearly when I move. Following plots show that.
This method is less prone to noise and motion artifacts. Peaks can be detected even when large movements modifies the signal a lot. Below, two plots are showing how this method of beat detection is highly effective. The left one resembles strong arm movement and the right one shows a deflected signal due to jumping. In both cases, this algorithm detects the peaks efficiently.
AD8232 can restore the signal almost immediately after strong movements are stopped. It has a very fast recovery from any LEAD off.
Now, the filtered signal is conditioned enough to apply Amplitude and Time threshold. That's STEP 5.
Generally, QRS complex can have 120 - 140 ms time duration.
The peaks have amplitude of 400 - 500. The previous plots during strong body movements showed that the false peaks can be upto 40 - 60. Therefore, I put 50 as the amplitude threshold.
Now still the higher level noise can produce a fake peak detection. To prevent that I am using the time threshold also. When the beats rises above 50 and comes back to 50 the average time duration between these start and end points can be around 70 - 100 ms in my calculation. Therefore, I put a time threshold of 40 ms. So, even if the noise due to strong body movements produces a fake peak, it will not be considered as a QRS complex if the duration is less than 40 ms. I should give a high limit of the time threshold [like 150 ms], but I found that the low limit if good enough.
Heart Rate calculation:
Time difference between two consecutive QRS complex gives the heart beat rate calculated in beats per minute.
Heart rate = 60000 (milliseconds) / QRS peak time difference in milliseconds
Calculated heart beat rates were pretty stable. The green plot represents the heart beat rate. The orange plot actually represents change of peak value due to the respiration.
Code snippets -
if (beats > 50 && QRSstart == 0){ QRSstart = 1; starttime = millis(); beats0 = beats; } if (beats > 50 && QRSstart == 1 && beats > beats0){ beats0 = beats; Rtime = millis(); } if (beats < 50 && QRSstart == 1){ QRSstart = 0; stoptime = millis(); if (stoptime - starttime > 40){ beatrate = 60000 / (Rtime - R0time); R0time = Rtime; }
However, an interesting point is that the QRS complex has a peak value [R peak] which varies with the respiration. When we breath in, the amplitude of the R peak is reduced and when we breath out then the R peak is increased. It can be clearly observed in following plot attached below where the derivatives are taken to emphasis the R peak value variation.. This can be used to get the respiration rate too.
Top Comments