ECG Display With Arduino

54,925

575

169

Introduction: ECG Display With Arduino

This ECG (Electrocardiogram) unit has an integrated display. The display can show individual heart beats in a large format, the train of heart beats in a small format and a Poincaré plot.

It is battery powered and can be worn round your neck on a lanyard.

It is built from an AD8232 module (£7 with leads), an Arduino Nano (£3) and a 2.8" TFT display (£6) plus a few resistors, a pushbutton and so on - the sort of things you already have. For power, you can use 4 AA cells or a single Lithium cell.

You might be interested in your heart during the Covid-19 pandemic. Covid-19 can sometimes give rise to cardiac complications including arrhythmia, ischaemia, infarction, tachycardia and conduction problems. But by the time that happens, you're probably lying in an intensive care ward.

Step 1: Safety and Medical Disclaimer

Here's some legal blurb and a discussion of electrical safety. The most important point is do not operate the circuit when it's plugged into a PC which is plugged into the mains. Oh yes - and don't blame me if you kill yourself.

I am not a medical professional. This Instructable was created for information purposes only. It does not describe a medical device. The information given here is not intended to be a substitute for professional medical advice. If you think you have a medical condition you should contact a qualified health professional. If you think you have a medical emergency you should contact your local emergency services. The device described here is not a substitute for professional medical diagnosis, ECG interpretation or treatment. You are encouraged to confirm any information in this Instructable.

As I have no control over how you build the electronics described here, I cannot guarantee its safety as a medical device. I think it is perfectly safe for me to use but you should make up your own mind. It's running off 4 AA cells or a single Lithium cell for goodness sake - how dangerous can it be?

If you have been fitted with an internal defibrillator or pacemaker, do not attach electrodes to your body and mess about with circuits.

Professional medical electronics should conform to IEC 60601. I have designed medical electronics in the past but it was a few years ago. I seem to have lost my copy of IEC60601 which is annoying as you have to pay for it. Would this device get IEC 60601 approval? How safe is it?

IEC 60601 is a huge document. The most interesting questions to an electronics designer are:

  • how much current can I pass through the patient?
  • what electrical isolation is required?
  • what happens if a "component" fails?
  • how much electromagnetic interference can I produce?
  • what about a defibrillator?

How much current can I pass through the patient? In "Normal Working" operation the current limit is 100uA a.c. and 10uA d.c. and in single fault condition it is 500uA a.c. and 50uA d.c. This circuit would be classed as an "Applied Part".

I don't know what circuit the manufacturer of the AD8232 module has used. When I examine the one I have, it appears to be one of the circuits in the "Application Circuits" section of the AD8232 datasheet.

The input impedance of the chip pins is 10Gohm so the "Normal Working" operation the current is under 1nA.

The electrodes are connected to the chip through 180k resistors. The chip operates at 3.3V so if the chip goes wrong, the maximum current is 3.3/180k = 18uA.

So the chip and its circuit is safe so long as it's battery operated.

What electrical isolation is required? An "Applied Part" has to be double isolated at 4000VAC. Your desktop PC is not electrically isolated to that degree therefore you should never operate the circuit when it's plugged into a PC which is plugged into the mains. A standard PC power supply almost certainly does not comply with the electrical IEC 60601-1 requirements from several standpoints, e.g. leakage current, dielectric strength.

Can you operate it when it's plugged into a PC which is running on batteries? It wouldn't be allowed for a medical device but for a domestic device it probably would be allowed. (Domestic regulations are less stringent.)

Did I operate it when plugged into a PC which was plugged into the mains? I'm not saying. I've been using desktop PCs for decades and have never got a shock off one. I'm just telling you that you shouldn't do it.

Would the circuit's isolation conform to IEC 60601? If it were battery operated then that's one layer of isolation. Where's the second layer? I guess maybe you'd need two insulated boxes one inside another. IEC 60601 sometimes seems a little silly.

The circuit should have no exposed conductive surfaces that are connected to the electronics. You have to worry about electrostatic discharge: what it the patient rubs a balloon on their hair then touches the box?

The patient shouldn't be able to touch the electronics or the battery or whatever. Yes, I know you've never got a shock off a 6V battery - I'm just telling you the regulations.

Electrical isolation also depends on the creepage distances on the PCB and air clearances. The AD8232 module uses 0603 resistors on its input. An 0603 doesn't have sufficient creepage.

Is the electrode connector suitable? No way. It's a 3.5mm stereo jack plug. You could tape the electrodes to your chest then poke the jack plug into a mains outlet. I don't know why you'd want to but you could - right?

What happens if a "component" fails? IEC 60601 says that the device must remain safe under a 'single fault condition'. A medical device must operate safely not only in normal conditions, but also in abnormal and single fault conditions. The standard does not require that the medical device remains safe with two or more independent faults. A "fault" is typically a component failure.

What counts as a "component"? I have no idea. You could go through each of the electronic components and say "what happens if this goes short-circuit?" and "what happens if this goes open-circuit?". Is the PCB a "component"? How can it fail? Can it suddenly re-arrange itself and connect battery to two electrodes? I can't find a definition of a "component" or "fault".

If it's battery operated and a "component" is an electronic component like a resistor or an IC then the circuit is safe.

How much electromagnetic interference can I produce?EMC is a big problem when designing medical equipment. Hospitals are full of electronic stuff that people's lives depend on so the EMC requirements for medical equipment are a lot tougher than for domestic electronics.

I have no idea how much EMC the board produces. The biggest culprit is probably the Arduino. I've never had an Arduino interfere with a TV or cellphone but I suppose it might.

In theory, you should put the circuit in a Faraday cage and worry about what wires go in and out. In practice, I don't suppose you've ever thought about EMC when you build an Arduino circuit, have you?

What about a defibrillator? So you've built your medical electronics and done the safety analysis and then IEC 60601 has one more surprise for you. Your circuit has to survive a defibrillator.

What is the standard for a defibrillator? I couldn't find one. Each manufacturer decides for themselves and the physician can decide what to apply. Shall we guess a capacitor charged to 300V containing 300 joules? That's connected to your chest somewhere near the ECG electrodes. I suspect that will fry the circuit. IEC 60601 says that the device must remain safe - it doesn't say that it has to continue to work.

A proper medical ECG can survive a defibrillator and go on working. Normally, you would have some protection diodes on the connections to the electrodes. The AD8232 module doesn't have them.

The bottom line is: you could make this circuit into a medical device that would conform to IEC 60601 but it would be a lot of work and testing and certification would be a huge expense. This is just a circuit you're building for fun.

See here and here for discussions of the dangers of a small battery. I have measured the resistance between the electrodes as 150k so, in the worst case, a 6V battery gives a 40uA current - well below the milliamps needed for a battery to be dangerous.

Step 2: AD8232 Module

The AD8232 chip contains a high quality, low noise instrumentation amplifier and signal conditioning to remove noise. It is intended primarily for recording ECG and takes a lot of the hard work out of designing a system.

Buy a module like the one in the photo. Search eBay for "AD8232 module" or "ecg module". For convenience, get one with leads and electrode pads.

Connect it to an Arduino Nano (or Uno or Mini with a 16MHz 328P) as shown above. I used a solderless breadboard.

The AD8232 includes "leads off detection". If either lead is disconnected, the LO+ or LO- pins of the module go high. For initial testing, I connected the LO+ and LO- pins to two LEDs though 1k resistors to ground. The LEDs light when a lead is disconnected. For the final circuit, remove the LEDs and connect LO+ and LO- to the Arduino. Don't leave the LEDs connected - the AD8232 pins won't go high enough for the Arduino inputs to register HIGH.

Download the ArdECG0.ino sketch and upload it to the Nano. Connect the Nano to a PC running on batteries. In the Arduino IDE, select the Tools|SerialPlotter menu command. Set the baud to 57600.

With the module I bought, the electrode leads are coloured:

  • LA Left Arm: Green
  • RA Right Arm: Red
  • RL Right Leg: Yellow

Yours may be coloured differently. Which lead is which? try touching the leads together:

  • Non touching: both LEDs lit
  • LA touching RA: both LEDs lit
  • LA touching RL: LO+ LED is off
  • RA touching RL: RO- LED is off

My module came with only 3 sticky electrodes. They'll get used up quickly so I decided to make my own. I happened to have some of the popper connectors left over from another project. I used tinplate for the electrodes themselves. Copper coins work as well but tarnish more quickly and stain your skin. As electrode jelly, I mixed thick shampoo and salt. I stuck them onto my chest with masking tape - it would last a few hours.

Attach the electrodes as shown in the picture above.

  • LA to the left side of your chest below the clavicle (collar bone)
  • RA to the right side of your chest below the clavicle
  • RL somewhere low down away from the heart

The RL electrode is called "Right Leg" but it doesn't actually need to be on your leg. It's a reference electrodethat reduces common-mode interference. Anywhere well below and away from your heart is fine. The lower-left of the abdomen is good. Try to avoid muscles - their movement and electrical activity could interfere with the signal.

Google for "ecg 3 lead electrode placement" for other diagrams.

Step 3: Fake Pulse

The ArdECG0.ino sketch can produce a fake "pulse". It's not a very realistic fake but it produces pulses of about the right size at about the right frequency. It's convenient to use it when debugging your unit.

The 100k resistors persuade the AD8232 that there are electrode attached. There are some pads on the AD8232 module PCB labelled RA, LA, RL. I just poked some wires into them.

Step 4: The Heart

Doctors think of the heart as a complex organ but to an electronics designer, it is simply a generator of electrical potentials - several tens of millivolts.

The sinoatrial node (SA node) acts as an oscillator generating a pulse every second or so. Electronically, it's a relaxation oscillator (or Van der Pol oscillator).

The pulse travels slowly to the muscles of the atria and to the atrioventricular node (AV node). The muscles of the atria contract and then relax. As they contract, they pump blood into the ventricles. As they relax, the atria take in blood through the veins from the body or the lungs.

The AV node delays the pulse (by 120-200mS) then sends it to the muscles of the ventricles. Electronically, it too is a relaxation oscillator but its period is much longer than the SA oscillator. It is "prematurely" triggered by the SA oscillator so they become entrained. If the SA oscillator fails, the AV oscillator can oscillate on its own as a backup system.

The muscles of the ventricles contract and then relax. As they contract, they pump blood to the body or the lungs.

The whole process takes around 500mS.

It takes more power to pump blood round the body so the biggest signal we see is from the muscles of the left ventricle.

Sodium, potassium and calcium ions are pumped across the membranes of the cells of the heart muscles. When a heart muscle is relaxed, the difference in ion concentrations causes a 90mV potential difference across the cell membrane. Inside the cell is more negative.

When an action potential occurs a muscle contraction is triggered, Sodium channels open, Na+ ions rush into the cell by diffusion and the voltage goes to zero. That's called "depolarisation". After a 100mS delay, potassium channels open, K+ ions rush out of the cell and re-establish the 90mV resting potential. That's called "repolarisation". Ion pumps then restore the ion concentrations. (Calcium ions are also involved but I'm ignoring them.)

When an action potential occurs in a cell, the cell next to it is triggered. So the action potential spreads through the muscle and also via the Purkinje fibers. It's a slow process; no fast nerve conduction involved.

  • Muscle cell conduction is 0.3–0.4 m/s.
  • Purkinje fiber conduction is 2–3 m/s.
  • Normal neuron conduction is 70-120 m/s.

Purkinje fibers can oscillate by themselves at 20-40 bpm and so act as a backup system if the SA and AV oscillators fail.

An ECG records the action potentials of the different muscles. The action potentials of the muscles are transmitted through the chest wall and skin by simple electrical conduction. So the conduction is fast. By the time it reaches the skin the signal is around 1mV.

Because different action potentials occur in different regions of the heart, by repositioning the ECG electrodes you can record activities in different muscles. With the electrodes at the left and right under the clavicles, you'll get the classical PQRST shape you see in a textbook (called "Lead I"). If you position the electrodes elsewhere you can pick-up other details of heart activity; different positions for pairs of electrodes are called "axes".

It's confusing, when doctors talk about "leads" and "axes". When they say "lead", they don't mean a lead - i.e. an electrode. Remember, what an ECG displays is the difference between two electrodes - it's a differential amplifier. The LL or RL electrode acts as a ground to help with common-mode rejection. A "12 Lead" ECG has 6 electrodes called V1 to V6 which are in a line in front of and to the bottom-left of the heart. Then there are RA and LA near your armpits. There may be two reference electrodes: LL and RL; the extra one doesn't seem to do much so there's usually just one. Pairs of electrodes are also called "leads" - LA-RA is called "Lead I", LL-RA is called "Lead II" and LL-LA is called "Lead III". It's a mess.

The correct placement is:

  • V1 is placed on the 4th intercostal space on the Right side of the sternum
  • V2 is placed on the 4th intercostal space on the Left side of the sternum
  • V4 is placed in the 5th intercostal space in a perpendicular line from the left nipple
  • V3 is placed between V2 and V4
  • V6 is in the 4th intercostal space in the left mid-axillary line (from the armpit to the hip)
  • V5 is placed between V4 and V6

(Right and Left are patient Right and Left. On most males, the 4th intercostal space is between the nipples and is the indentation or soft area between the ribs.)

The maths is:

  • Lead I: LA - RA
  • Lead II: LL - RA
  • Lead III: LL - LA
  • Lead aVR: RA - average of (LA,LL)
  • Lead aVL: RL - average of (RA,LL)
  • Lead aVF: LL - average of (RA,RL)
  • Lead V1: V1 - average of (RA,RL,LL)
  • Lead V2: V2 - average of (RA,RL,LL)
  • Lead V3: V3 - average of (RA,RL,LL)
  • Lead V4: V4 - average of (RA,RL,LL)
  • Lead V5: V5 - average of (RA,RL,LL)
  • Lead V6: V6 - average of (RA,RL,LL)

The different "leads" are like looking towards the centre of the heart from different directions in 3D (see diagram above). The directions are called "axes". To add more confusion the heart also has an "axis" - the electrical activity is symmetrical about that axis. If part of the heart goes wrong, the heart's axis might have "deviation". If "leads" I, II and III look roughly the same, that's normal; if they're different, that's "deviation".

Broadly, what can go wrong with the whole system is that the nodes (oscillators) or the different muscles stop functioning properly. For instance, parts of the muscles might be starved of oxygen and they don't produce an action potential. Or the SA node might run at the wrong rate or the SA and AV nodes might become disconnected and the oscillators run at different rates.

Step 5: Adding a Display

The display is a 2.8" colour TFT LCD screen with a ILI9341 controller, 320x240 pixels. I chose a 320x240 SPI display because can be updated reasonably quickly and uses few Arduino pins.

Search eBay for "320 240 TFT SPI" and you'll find a variety of displays. Get one that looks the same as the photo. A display without a touch screen is cheaper.

I don't use the touch screen function in this project. I want to run the unit on 4 AA cells or a Li-ion cell. As the AA cells discharge their voltage falls. I've found that the Arduino, display and AD8232 work fine with a supply voltage as low as 3V but the touch-screen stops below 4.5V.

The LCD has the following pins:

  • VCC 5V
  • GND ground
  • CS LCD chip select
  • RESET reset
  • DC data/command
  • MOSI SPI bus MOSI of Arduino
  • SCK SPI bus SCLK
  • LED back light
  • MISO SPI data out of LCD (ignored)
  • T_CLK SPI bus SCLK (ignored)
  • T_CS touch chip select (ignored)
  • T_DIN MOSI of Arduino (ignored)
  • T_DO SPI data out of touch (ignored)
  • T_IRQ touch interrupt request (ignored)

The display I bought has a built-in 3V3 regulator. If you look on the back of the PCB, you'll see it connected to the VCC pin. It's a 662K chip. So the module can be powered by 5V and you can connect it directly to your 5V Arduino pin. The LED power pin can also be connected directly to the 5V pin.

(Check that your display has a 3V3 regulator. If it doesn't and it requires 3.3V power then it takes around 50mA which is just at the limit of what the Arduino Nano's 3.3V regulator can provide. So it may be a mistake to power the display from the Nano's 3.3V pin. You'll should supply your own regulator.)

The logic pins of the display require 3.3V signals. You can't connect them directly to the 5V I/O pins of the Arduino. I've used resistors to drop the voltage.

Adafruit very kindly publish an ILI9341 library and several other libraries are available in Github and elsewhere. I tried a few and didn't like any of them. Some simply didn't work and all were huge. You write an Arduino sketch that draws a line and some text and you find your memory if 75% full. So I wrote my own drivers.

Wire up the display as shown and download the ArdECG1.ino sketch.

I've decided I don't like the way the Arduino IDE uses "libraries". It makes version control difficult. So I now keep the code needed to compile a sketch together. Put all these files in the same folder:

  • ArdECG1.ino
  • SimpleILI9341.h
  • SimpleILI9341.cpp

SimpleILI9341 has a standard set of drawing commands very similar to all such libraries.

Some of the "fast" libraries you can download use special timing loops and are upset when other, maybe slower, devices are used on the same bus. SimpleILI9341 is written in C rather than assembler so isn't quite as fast as it could be but is much more portable and it shares the SPI bus politely with other devices. A Windows program can be downloaded which allows you to make your own fonts and icons.

You can download the ILI9341 data sheet from the web. You send it a command by

set DC low     
set CS low      
send a command byte      
set CS high

and send it data by

set DC high     
set CS low     
send zero or more data bytes     
set CS high

You can see how I do it in the tft_write functions. The data bytes might be a whole row of pixels or a setting for a control register.

The ILI9341Begin() function in the library shows you the initialisation command set I've chosen. You might want to change the commands if you choose a different ILI9341 display (e.g. with more pixels) or want a different orientation. I hope my code is easy for you to see how to change if you need to.

In the circuit diagram are components in a box labelled "Fake Pulse". Do not include them in your final build. They are useful during development and debugging. In the ArdECG1.ino sketch there is a #define to enable/disable fake pulse generation. It's somewhere near the top:

#define bHasFakeECG

Comment out the line to remove the fake pulse.

Step 6: Display Modes

I've used a pushbutton to cycle round the different views of the ECG:

  • Large display
  • Small display
  • Poincaré display

The large display allows you to examine one or two heart beats in detail.

The small display allows you to examine a couple of dozen heart beats to see the regularity of the rhythm.

The Poincaré display shows a history of the rhythm.

The following Steps briefly describe what you might look for in each display. Don't take my word for it. There are lots of pages on the web for teaching student doctors and nurses how to interpret ECGs. They're worth reading.

Step 7: Large Display

The large display mode allows you to examine one or two heart beats in detail. It shows a red background grid to make it look more like a ECG standard chart.

An ECG chart has large and small red squares printed on. The standard scale is

  • the x-axis is time with one large square being 200mS
  • the y-axis is voltage with one large square being 0.5mV.

Of course, the doctor could have fiddled with the knobs of the ECG machine and changed the gain or the chart speed but pictures in textbooks will show the standard scale.

The display shows the beats per minute in the top left corner. The sketch attempts to recognise "beats" but will be confused by noise or poor electrode connections.

The sketch tries to keep a peak in the left third of the screen so it isn't jumping around too much and is easier to study. It can only do so it the heart beat is regular but a healthy heart doesn't beat regularly so that feature doesn't work too well.

You should be able to see the classic ECG trace you get in a textbook.

The first bump is P wave. That's the atrial depolarisation - the muscles of the atria starting to contract. There's a pause - the "PR segment" - while blood flows into the ventricles.

The big spike is the QRS complex. That's the ventricular depolarisation - the muscles of the ventricles starting to contract. There's another pause while blood flows out of the ventricles.

The next bump is the T wave. That's ventricular repolarisation as the muscles of the ventricles relax. There's another pause and it all happens again.

There ought to be a bump for atrial repolarisation but it's hidden under the QRS complex. There can be a U depolarisation wave but it's often too small to be seen.

It takes years to train a cardiologist but you should be able to see broadly what's going on. Here, here and here are some web pages. Or search for "ECG interpretation".

The P wave can tell you about what's going on in the atria. For instance the shape of the P wave can tell you whether the left and right atria are acting together. If the P waves and the QRS waves are not synchronised then the two oscillators have become disconnected.

The QRS and ST segments show what's going on in the ventricles. An elevated ST segment can indicate a myocardial infarction ("heart attack"). A depressed ST segment can indicate a myocardial ischaemia ("angina"). Both are due to parts of the ventricle muscles not functioning properly. Ischaemia is when a region of the muscles is struggling due to lack of oxygen; infarction is when a region is in really in a bad way and has given up. But don't panic if you seem to have an elevated ST - it can also be due to the electrodes not being positioned properly.

Step 8: Small Display

The small display mode allows you to see the overall heart rate and look for irregularities. A "normal" heart rate depends on age

  • 3-5 years: 80-120 bpm
  • 6-10 years: 70-110 bpm
  • 11-14 years: 60-105 bpm
  • 15+ years: 60-100 bpm

The average woman's heart rate is 4bpm higher than a man's. Both male and female average heart rate drops by 4bpm as you get old.

"Bradycardia" is a heart rate below the normal range: less than 60bpm in adults. "Tachycardia" is a heart rate above the normal range: more than 100bpm in adults.

Clearly, the heart rate averaged over the last minute will depend on how hard you are exercising or how excited you are. The time between heart beats (the R-R interval) can also vary from beat to beat. One beat might be, for instance, 10% shorter than the next. That variability from beat to beat is called HRV (heart rate variability).

Higher HRV is considered to be a "good thing". Supposedly, the more variable the heart beat is, the better the heart is able to respond to different requirements. HRV decreases as heart rate increases (as you'll see in the next display). HRV also decreases with age, with infarction, with diabetes and all sorts of other conditions

"Ectopic" beats are an interval that is too short or too long. A major cause is something wrong with the conduction system. Premature atrial, junctional and ventricular contractions can occur. I cannot find a definition of when a short or long interval is classed as ectopic rather than due to normal HRV but automatic systems often decide that any interval more that 20%-30% different from the preceding one are "ectopic". Ectopic beats sometimes have a different shape from normal ones.

Ectopic beats could be indications of something wrong. They could be due to damage from a heart attack, cardiomyopathy, valve malfunction, etc. Or they could be harmless perhaps caused by alcohol, caffeine, prescription drugs, stress, etc.

Step 9: Poincaré Display

The Poincaré display mode plots the length of one interval (from R to R) on the x-axis against the length of the next interval on the y-axis.

500 points are stored in a circular buffer. When the buffer is full, old points are overdrawn in black.

The axes are labelled in BPM.

Some researchers think that HRV, ectopic beats and other irregularities in heart rate are best detected by a Poincaré display. Although ECG Poincaré plots been around since 1990, they are not "mainstream" and many workers prefer a simple chart.

If you google for "ecg poincare" you will find a lot of research papers.

Here is a good discussion of what can be seen in a Poincaré plot.

A normal Poincaré plot shows a diagonal band of points tapering to the bottom left. This demonstrates that . HRV decreases as heart rate increases. An overall fatter band indicates greater HRV.

Tachycardia shows as a small group of dots near the lower left. Bradycardia shows as a scattered group towards the top right. Arrhythmia shows up as groups of dots away from the main diagonal. Fibrillation shows as a large cloud at the bottom left. A column of dots at the top left may be premature ventricular contractions. Pauses in beats show as clouds in the top-middle and right middle.

Step 10: Filtering

I found that the circuit had little noise so long as it was running on its own battery and the electrodes were making good contact. But there is some noise and I thought I'd try removing it with a digital filter.

You can read about digital filtering on an Arduino in my Speech Recognition project. I won't repeat it all here. As the sample rate is very low - every 5mS - the Arduino has plenty of time to do the maths.

There is a good discussion of digital filtering here and an online calculator for the coefficients here. The calculator gives the coefficients as real numbers; multiply them by 65536 before plugging them into my code.

Of course, you don't want the filter to mess up the shape of the "signal" - just to remove the "noise". It's important to look at the display with and without filtering and convince yourself you like the results. In particular, the Q and S parts of the wave have frequency components close to the "noise" frequencies you are trying to remove. You don't want the filter to alter them.

I tried a low-pass filter (40Hz Q=1) and it made some difference. The noise gets worse if you hold your hand near a mains device like a desk lamp. So I tried a 50Hz notch filter (Q=1 OR Q=2) - that removed a lot of noise. I liked the result and stuck with that. It seems that most of the noise is mains hum.

(In your country, mains hum might be at 60Hz. I've included a 60Hz notch filter as well.)

I have a philosophical distrust of filters. I think words like "signal" and "noise" can be a delusion. The "truth" is what you get from the ADC. Anything you do to the data after that is just you making the data prettier so it pleases you more.

I also wondered if a high-pass filter could remove the big fluctuations due to muscle movement. I added a high-pass filter with a cut-off frequency of 2Hz (Q=1). It may have fixed the big fluctuations but it also really messed up the P and T waves. I took it out.

You'll see calls to the different filter functions in the main loop() function. Comment them out (or in) as you see fit.

Step 11: Building It

I put the voltage convertor resistors on a piece of stripboard and soldered it to the pins of the display. The AD8232 module is stuck onto the back of the display with sticky pads and a 2.5mm spacer. The Nano is suspended in between the two boards by soldered wire links. The whole assembly is quite compact and solid.

I thought about 3D printing a case but went for old-school methods. I glued 0.7mm polystyrene sheet together to make a box. The strap is old elastic that had lost its elasticity.

Shielding makes some difference to the noise level so I lined the back of the box with kitchen foil. A "brush" made from stripped cable connects it to ground

Step 12: Power Supply

Now it needs a battery. The total current consumption is around 127mA and I'd like it to run for 8 hours so that's 1000mAh.

Surprisingly, the Arduino, the AD8232 module and the display all run fine with 3.7V on the "5V" pin. By the time it gets down to 3V, the display if getting dim but everything still works.

My first thought was to run it 4 AA cells. An AA cell has a capacity of over 1000mAh. The initial voltage of 4 typical AA cells is more than 6V but it drops to 4.8V as it discharges. The Arduino cannot withstand 6V on its "5V" pin so we must connect the 4 AA battery pack to the Arduino's Vin pin. The Arduino has a regulator with a dropout of around 0.7V so the voltage of the Arduino's "5V" pin will be above 4V for most of the battery life.

AA cells are a good choice. They have the advantage that "recharging" takes a minute. The only problem is their huge size. A nice slim unit would have a big fat battery pack on the back.

When a local electronics shop closed I bought a big bag of Li-ion battery packs at a good price. It included several NP-BG1 packs (for Sony Cyber-shot). An NP-BG1 contains a 1000mAh Li-ion cell (capacity depends on manufacturer).

What if we connect a 3.7V Li-ion cell to the "5V" pin of the Arduino? It all works fine. That simplifies the power supply. So I added a Li-ion cell and a 3.4mm barrel jack to charge it.

(The NP-BG1 contains a thermistor to check for overheating so a 3-pin connector would have been better. But the thermistor is the wrong value for the charger I'm using and I did without.)

The On/Off switch connects the cell to either the Arduino or the charger so it's impossible to charge the unit when it's in use.

Step 13: Future

How can this project be expanded?

It would be nice to save a whole day's worth of data. With a sample period of 5mS, that's 17Mbytes of data. At first sight, an SD card would be ideal but the write time of an SD card is very variable. Sometimes it takes a couple of mS but sometimes it erases a large number of blocks of flash memory and takes couple of hundred mS. An SD card can cope with the average data rate so I'd probably have a second Arduino that buffered the data stream from the ECG Arduino and wrote it occasionally in large blocks - I wouldn't trust multi-tasking on a single Arduino but it might work. Serial EEPROMS are available that can write fast enough but only hold a few Mbits. A large flash memory chip may be the way to go - you may be able to erase it all (a slow operation) at the start of the day then write individual bytes in a few mS. But an SD card has the advantage that you can take it out and plug it into a PC.

There are a ridiculous number of ECG file formats. The HL7 aECG standard might be the one to go for.

If you stored a whole day's data then the Poincaré plot becomes really useful. Click on a point and that beat is displayed so you can quickly find weird beats.

Pulse arrival time (PAT) or pulse transit time (PTT) is the time interval between a R wave in the ECG and the measurement of the pulse on (e.g.) your finger with a pulseoximeter. Pulseoximeters are very easy to build. It seems that pulse arrival time is related to blood pressure. It needs calibrating for each individual but then it's a simple non-invasive way of measuring blood pressure over a whole day. It can also be used to estimate arterial stiffness. There is a linear relationship between pulse transit velocity and systolic blood pressure.

Can the ECG act as an electro-oculograph? I taped the ECG electrodes just to the outside of my left and right eye sockets. It worked. I could easily measure a 0.7mV "square wave" as I moved my eyes to the left or right. The problem is that the ECG module I'm using has built-in filters. The high-pass filter removes signals below about 5Hz so it a slow square wave looks like this.

Maybe using the AD8232 chip without the rest of the module would mean a different filter could be used but the AD8232 has lots of other built-in signal processing. I think it would be worth trying if you're interested in electrooculography.

Taping the electrodes above and below the eye didn't work at all well. I could hardly see an effect. But a blink was easily visible.

I also tried to get electromyograms using the ECG machine. It didn't work. I think myograms should be regarded as fast AC signals. Electromyogram circuits generally include a rectifier and smoother so the overall AC "energy" of the signal is measured. The filtering in the AD8232 module removes all those high frequencies and myograms don't show up at all.

8 People Made This Project!

Recommendations

  • Tinkercad to Fusion 360 Challenge

    Tinkercad to Fusion 360 Challenge
  • Science Fair Challenge

    Science Fair Challenge
  • Chocolate Challenge

    Chocolate Challenge

169 Comments

0
KostasGk
KostasGk

6 weeks ago

Hello forum-members,

first of all thank you very much Peter Balch for posting your project online. It is very helpful! I have another issue and maybe you, with your experience, or some members can help me on solving this. Did anyone try to perform an ECG-measurement by using only the RA and LA(without RL)? I purchased the ECG module from SparkFun with the AD8232 chip and in its datasheet there is mentioned that this IC can perform a two electrode ECG measurement(read caption "Right Leg Drive Amplifier", "AC Leads Off Detection", "Heart Rate Measurement Next to the Heart"). If anybode tried this, can he/she give me instructions on how to activate this method?

Best regards

Kosta

0
Peter Balch
Peter Balch

Reply 5 weeks ago

The easiest answer is "try it and see". You're unlikely do to any harm to the circuit.

(I say "unlikely" as I suppose you might have built up a static charge by walking on a nylon carpet. The Sparkfun board and the chip don't seem to have much static protection.)

The datasheet says "In two-electrode configurations, RLD can be used to bias the inputs through 10MΩ resistors as described in the Leads Off Detection section. If left unused, it is recommended to configure A2 as a follower by connecting RLDFB directly to RLD." Unfortunately, you can't do that because the RLDFB pin of the chip isn't exposed on the PCB.

The leads off detection works by sensing when either amplifier input voltage is within 0.5 V from the positive rail (3.3V). The Sparkfun board has 10M resistors to the positive rail. To stop leads off being reported you could add 10M resistors to ground at the RA and LA pins.

I think that if you are just using 2 leads, you should leave RL disconnected. You'll probably get more noise that way.

What RL does is to keep the user's body at a potential about half way between the gnd and 3.3V - e.g. at 1.6V. If RA and/or LA drift to gnd or 3.3V then the amplifier won't be able to see their signal. To keep RA and LA somewhere in between gnd and 3.3V, I'd suggest adding the 10M resistors I mentioned.

If that fails, you could try connecting
RA to gnd with a 1M resistor
RA to 3.3V with a 1M resistor
LA to gnd with a 1M resistor
LA to 3.3V with a 1M resistor

Let us know how you get on.

Peter

0
Pulse_MP
Pulse_MP

Question 2 months ago

Hey there!
I tried making this circuit and got everything together, put it on a breadboard, turned the thing on and.....nothing. The screen shows a flatline at the very bottom of the display, and the BPM counter doesn't appear at all. I've checked my connections, and everything seems to be in order. The leads are also making good contact, funnily enough the display shows the "disconnected lead" messages, and cycling through the different graphs works fine as well.
I should mention that (since the nano hasn't arrived yet) i adapted the device to run on an arduino uno, though i made sure to use the correct pins, since the uno has all of the pins needed for this project (at least to the pin-out diagrams i found). I didn't change the code in any way whatsoever.

Any advice on how i could fix this?
Many thanks!

0
Peter Balch
Peter Balch

Answer 2 months ago

> the display shows the "disconnected lead" messages

Therefore either the leads are disconnected from the AD8232 module or the AD8232 module is disconnected from the Arduino.

Did you build the circuit in Step 2? In other words, did you try it with LEDs?

Try touching the leads together:

Non touching: both LEDs lit
LA touching RA: both LEDs lit
LA touching RL: LO+ LED is off
RA touching RL: RO- LED is off

That will tell you if the AD8232 module is working correctly.

As I say: For the final circuit, remove the LEDs and connect LO+ and LO- to the Arduino. Don't leave the LEDs connected - the AD8232 pins won't go high enough for the Arduino inputs to register HIGH.

> The screen shows a flatline at the very bottom of the display

Thefore the ADC input to the Arduino is seeing zero volts.

Once again, did you build the circuit in Step 2? In the Arduino IDE, select the Tools|SerialPlotter menu command. You should see a signal.

That tells you that your module and Arduino are working.


Can you check the voltage with a meter of oscilloscope? I thnk it's meant to be at an average of 1.5V - I can't remember but it will be something like that. Measure the voltage at both the module and at the Arduino. Try measuring it with the wire that connects them disconnected.

At the start of ArdECG0.ino file, it says

const int ECG_IN = A0;

At the start of ArdECG1.ino file, it says

const int ECG_IN = A2;

Naturally, the pin number of the circuit you've built should match the pin defined in the INO file you're using.

Peter

0
Pulse_MP
Pulse_MP

Reply 2 months ago

Good evening!
Thank you for your help so far. The lead-messages were only present when i disconnected them from my body, but otherwise they are working fine. Maybe i should have said that more clearly before.
Anyhow, i did in fact not try the step n° 2, since i figured it would work fine just like that. But i will try it tomorrow, maybe that fixes it, or at least helps me/ us figure out the issue.
However i am still confused as to why the BPM aren't showing up on the screen. Does that box only appear when the arduino receives a signal or should it be there all the time?
One more question: what kind of signal am i looking for in the plotter? I rarely work with it, so i'm not sure what to expect.
I can and will however measure the voltage tomorrow, but just to be clear, where exactly should i measure the voltage, and what should it read? (sometimes i'm just a little dense, so just asking to make sure)

Again, thank you for the quick response and advice. Looking forward to completing this project!

0
Peter Balch
Peter Balch

Reply 2 months ago

> i am still confused as to why the BPM aren't showing up on the screen. Does that box only appear when the arduino receives a signal

Yes.

> One more question: what kind of signal am i looking for in the plotter? I rarely work with it, so i'm not sure what to expect.

You should see the typical ECG signal.

> where exactly should i measure the voltage,

On the output of the AD8232 module and also on the A2 input to the Arduino.

> and what should it read?

I don't remember. Probably between 1V and 2V

0
Pulse_MP
Pulse_MP

Reply 2 months ago

Ok, i did some testing. Here's what i found:
1. The leads work fine. The LED test worked perfectly
2. The voltages i measured were at about 2V, no problems there
3. The plotter shows a flatline at about 1V. This doesn't change even if i unplug all the leads.

I also made sure to check the wires and other connections just in case, but all works fine. Any ideas?

Edit: I forgot to mention something that might be important. When i restart the arduino or cut and then re-apply power to the system, there is a spike going to the top of the screen on the far left side of the display. It only happens once per boot-up, until the power is disconnected again. Maybe this helps

0
Peter Balch
Peter Balch

Reply 2 months ago

> The plotter shows a flatline at about 1V.

What do you mean "about 1V"? How do you know it's 1V?

Here's a tutorial on the Serial Plotter tool.

https://docs.arduino.cc/software/ide-v2/tutorials/ide-v2-serial-plotter

Everything you've said makes it seem like you've not connected the output from the AD8232 module to the correct analog input of the Arduino. What pin are you using?

Disconnect the AD8232 module from the analog input then try altering the input voltage - connect it to 0V or 5V or a 1.5V battery.

0
Pulse_MP
Pulse_MP

Reply 2 months ago

I know (or at least deduced) the voltage is 1V (1.023 to be exact), because on the plotter there is a straight line, that stays constantly between the values 900 and 1200 on the y-axis. Whilst i was testing, i also decided to check the serial monitor, from which i got a list that showed me (what i believe to be) the actual value the pin was reading. Each line had the time, an arrow, and the number 1023 behind it, i assumed that was the input voltage. The following is a sample from what it reads:

19:28:18.985 -> 1023
19:28:18.985 -> 1023
19:28:19.031 -> 1023
19:28:19.031 -> 1023

...and so on. There is one oddity at the very beginning of the list, which looks like this:

[...]
19:28:18.985 -> 1023
19:28:18.985 -> testADC
19:28:18.985 -> 0 0 1024
19:28:18.985 -> 1023
19:28:19.031 -> 1023
19:28:19.031 -> 1023



I connected the output of the AD8232 to A2 on the arduino, i checked the code to be sure, cause in the copy i have the code says this regarding pin A2:
// pins
const int ECG_IN = A2;

Applying a different voltage to the pin changes nothing, the plotter still shows the same line, neither does connecting it to ground.
I am probably as confused as you. I hope i'm not bothering you too much, and appreciate the help! Also thanks for the plotting-tutorial, will be trying that soon =)
Hopefully we can solve this mystery.

0
Pulse_MP
Pulse_MP

Reply 2 months ago

I did the ADC tests (did i not?). Connecting it to different input-voltages changed nothing.
However, in the meantime i have read up on the ADC, to make sure i know what you are talking about. The interesting part is, that the nano might have different ADC-capabilities than the uno, so the problem might be with the processing. A quote from the website:

"The Zero, Due, MKR family and Nano 33 (BLE and IoT) boards have 12-bit ADC capabilities that can be accessed by changing the resolution to 12. This will return values from analogRead() between 0 and 4095.
The Portenta H7 has a 16 bit ADC, which will allow values between 0 and 65535."

(Source: https://www.arduino.cc/reference/en/language/functions/zero-due-mkr-family/analogreadresolution/)

I am not that familiar with the different boards, so i might just be mistaking things. I will probably just wait for the nano to arrive, and go from there. Perhaps it is just some funky stuff with the board.

Have a nice day/night!

0
Peter Balch
Peter Balch

Reply 2 months ago

As I said before: "Everything you've said makes it seem like you've not connected the output from the AD8232 module to the correct analog input of the Arduino. What pin are you using?"

Which software are you using? Step 2 or Step 5? In Step 2, you'll see that the output from the AD8232 module is connected to A0. In Step 5, you'll see that the output from the AD8232 module is connected to A2.

If the Aduino doesn't respond to changes to the ADC input then the Arduino is broken. But I doubt that is the case.

Did you try going through any of the online Aduino ADC tutorials? They will test the ADC.

The Nano and the Uno use the same IC so their ADCs are identical.

0
Pulse_MP
Pulse_MP

Reply 2 months ago

I am currently using the code from Step 5. However i always check the code and instructions to make sure the pins are connected correctly, and only use the code from step 2 as long as needed and switch back to step 5 when i'm done.

I also did the tutorial, and the ADC works fine. Additionally, i tested the circuits combined, i. e. i connected the potentiometer to A2 as shown in the tutorial, instead of the AD8232s output. However, this didn't change anything.

Everything else appears to be working without any issues.

Are there any "stupid" reasons why the circuit could be having problems? Things that you assumed i did when building the project? As i said before, i can be really dense sometimes, so maybe the problem is me being stupid, and not the circuit. I checked it so many times now, but it never hurts to make sure, now does it?
Again, thanks for the help!

0
Peter Balch
Peter Balch

Reply 2 months ago

You say "the ADC works fine". Which pin? As I said before, the pin number of the circuit you've built should match the pin defined in the INO file you're using. At the start of ArdECG0.ino file, it says ECG_IN=A0 and in ArdECG1.ino it says ECG_IN=A2.

Which tutorial? I suggested two

https://www.arduino.cc/en/Tutorial/BuiltInExamples...
https://www.arduino.cc/reference/en/language/funct...

Did the ADC work when using an external ADC reference voltage? If you look at the circuit diagrams you'll see that Vref - the ADC reference voltage - is connected to 3.3V.

Using a meter, what voltage do you measure on Vref?

0
Pulse_MP
Pulse_MP

Reply 2 months ago

I am using pin A2 right now. As i said, i check the code to be sure, especially whenever i change the code for testing.

I did the first tutorial, since the second one (at least to me) is simply a definition, there is no practical examples to test. The first tutorial worked perfectly.

The meter reads 2,5 V on the pin i selected.

I say this so vaguely, because i think i found (at least) one issue: the pin i used for vref is named "IOref". I only noticed this now, so that might have been the issue. However, the arduino uno has no pin that is called "vref", only the already mentioned pin "IOref" and a pin called "aref".

Could this be the problem and if so, what should i do?

0
Peter Balch
Peter Balch

Reply 2 months ago

I asked: "Using a meter, what voltage do you measure on Vref?"

To which you replied "The meter reads 2,5 V on the pin i selected".

Which pin? VRef ??

> I did the first tutorial, since the second one (at least to me) is simply a definition,

Yes, it explains how VRef works - if you're using an external reference voltage for the ADC, you must connect that external reference voltage to something.

I've never used an Uno so I don't know how the pins are arranged or named. I don't know what IOREF is.

Here's a instructable that might be helpful.

https://www.instructables.com/The-Arduino-AREF-Pin...

> Could this be the problem

If VRef is at 0V then you'll get weird readings from the ADC.

0
Pulse_MP
Pulse_MP

Reply 2 months ago

>Which pin? VRef ??
I measured it on IOref, since i hadn't noticed the issue just then. There is no pin named "Vref", only "IOref" and "Aref".
2.5V is the voltage of IOref, Aref measures 40.0mV on the meter, in case that is of interest.

From looking at the tutorial about the "Aref" it seems like it does the same thing as the Vref, doesn't it? I will do some testing with this, maybe i can find a solution for the UNO board.
However, i will probably just wait for the nano to arrive, just in case it has to do with the board. I will get back to you once i tested it, and i hope it will be working then.
Have a nice day!

0
Gilles BILLARD
Gilles BILLARD

1 year ago

Hi,
I've copied the 3 files in a new folder on my desktop; Openned ArdECG1 in Arduino 1.8.13 IDE; Ran compil and got many errors like these ones:
****************************************************************************
C:\Users\billa\Desktop\ArdECG1\ArdECG1.ino: In function 'void DrawGridPoincare()':
ArdECG1:160:40: error: invalid conversion from 'const byte* {aka const unsigned char*}' to 'word {aka unsigned int}' [-fpermissive]
DrawInt(f[i], MediumFont, TFT_WHITE);
^
In file included from C:\Users\billa\Desktop\ArdECG1\ArdECG1.ino:8:0:
sketch\SimpleILI9341.h:54:6: note: initializing argument 2 of 'void DrawInt(int, word, uint16_t)'
void DrawInt(int i, word Font, uint16_t color);
^~~~~~~
ArdECG1:162:40: error: invalid conversion from 'const byte* {aka const unsigned char*}' to 'word {aka unsigned int}' [-fpermissive]
DrawInt(f[i], MediumFont, TFT_WHITE);
^
In file included from C:\Users\billa\Desktop\ArdECG1\ArdECG1.ino:8:0:
sketch\SimpleILI9341.h:54:6: note: initializing argument 2 of 'void DrawInt(int, word, uint16_t)'
void DrawInt(int i, word Font, uint16_t color);
.......................................
************************************************************************
PS: I use MiniCore boards library (compil OKay with AVR boards libray)
One idea ?

0
Peter Balch
Peter Balch

Reply 1 year ago

Are these errors all to do with using fonts?

The error "invalid conversion from 'const byte*' to 'word' in 'DrawInt(f[i], MediumFont, TFT_WHITE);'" might be to do with the 'MediumFont' parameter.

I've implemented Fonts in a weird way that could be unique to Arduinos.

So as to save RAM space, constant arrays (such as fonts) can be held in ROM. They are declared as e.g.

const byte MediumFont[] PROGMEM = {
15, // ymax
4, // descender
...

note the PROGMEM construct. You can google for how PROGMEM is implemented and what it means.

You have to use special code "pgm_read_byte_near" to access data stored in a PROGMEM array. For instance...

void DrawInt(int i, word Font, uint16_t color)
calls

void DrawChar(uint8_t c, word Font, uint16_t color)
which uses the construction (e.g.)

b = pgm_read_byte_near(Font);
Could it be that the MiniCore boards library has some other way of storing constant arrays in ROM?

Peter

0
Gilles BILLARD
Gilles BILLARD

Reply 1 year ago

I was on the way but did not went up to the ROM and PROGMEM ;
The fact is, depending on how one burn the minicore bootloader, EEPROM can be retained or not; Is the problem located in that option ?
Anyway, I re-burned the pro-mini I used with the standard Bootloader to make your prgm running... and it is running properly.
I did not succeed in viewing my ECG, probably because I use a 128 x 128 display ST7735 based on; but I will go on tomorrow with the fake pulse for testing and will keep you advised..(the 3 grids are OKay, the L-OFF and R off are mirrored if electrodes are disconnected, hart beat led blinking and no trace...may be this is due to ST7735 in my LCD instead of a ILI9341)