Arduino ECG

Similar projects worth following
Can an Arduino be used as an electrocardiograph?
For a while now, Olimex sells EKG-EMG shield for 20 euros, and electrodes for 10 more.
Is it just a tech toy, or can be useful?
If it can, what's missing?

Building an Arduino ECG is piece of cake:

plug in the shield, plug in electrodes, plug USB cable to PC.

And then what?

Well, then comes the hard part:
1) You get some signals; they are dirty
2) So you need to clean them up
3) Can you read them? Unlikely; so you need some way to send them to your doctor

There's no free software to read, filter and save the data.

That is, there was no free software till we wrote it;)

Ah by the way, we also designed a nice 3d-printed enclosure for it.

All open source:

  • 1 × Arduino Uno ... or compatible. Or pick Yun if you want IoT ECG.
  • 1 × Olimex EKG-EMG shield
  • 1 × Olimex SHIELD-EKG-EMG-PA Electrodes
  • 1 × 3D-printed box ... of custom, open source design, available at gihub.
  • 3 × Screws is it M4 screws or what? Don't know exactly, thwy were just sitting around.

  • And doctor said...

    mikrotron10/05/2016 at 16:42 0 comments

    So we built probably cheapest ECG in the world, and it seems to work.
    But does it really work?
    Well, I wouldn't bet my life on it:)

    So we made a call to association Big heart to small heart, a non-profit, humanitarian organization of doctors, health professionals and parents of children with congenital heart faults and other heart diseases, who happen to know 10000 children who might need such a device.

    They connected us to doctor Hrvoje Kniewald, cardiologist at Department of Pediatric Cardiology in Zagreb, and made appointment.

    To our surprise, we were greeted by six doctors!

    Small room was full of people and we didn't even have opportunity to demontrate the device in action. But we did show them the device, and screenshots.

    The conclusion was, YES, it works!

    And, might be especially useful in one use case: arrhythmia that occurs rarely.

    See, it's easy if you have heart condition and you know you have it. You get to your doc, he scans you and prescribes whatever necessary. But if your heart sometimes, just sometimes behaves, till you get there readings seem fine.

    Doctors have put it very simple for us:
    that's when healthy kid suddenly dies.

    But, personal ECG allows to hook up fast, record the readings, and send the data to doctor by e-mail.

    Err, what file format do you expect?

    Don't bother with that, just send us the data, we'll deal with it.

    Fine, we'll just record to CSV.

    And we do. We also got few technical tips, like how to properly draw ECG, all implemented already.

    Of course, there's some cons.

    First, electrodes are impractical, especially one that needs to be tied to leg. If that takes too long, arrhythmia might pass.
    Well, Olimex already sells different kind of electrodes, like, real ones. We did not purchase these for they are not open source:)

    Second, the device requires PC to work. PC supplies it with electric power, but also with processing power, for it runs the software to display and save the data.
    Well, we already demonstrated one way to build a portable DIY ECG, and this is clearly out of scope for this project.

    Third, it's not very precise device. It does record PQRST - just enough for majority of people with heart conditions. But small beats outside of PQRST cannot be distingushed from noise.
    This might be issue with our filters. So if anyone out there can do better, feel free to do it!

    To conclude this log, I'll just say it's a good feeling knowing you maybe made a life saver.

    You should try it yourself;)

    But make no mistake, this is not a medical device! Certification procedures actually mean something, especially for medical devices: they mean you can bet your life on it.

    Big thanks to Big heart to small heart and their good doctors.

  • A box for cardiotron

    Tomislav Mamić10/05/2016 at 11:40 0 comments

    Having an open PCB around as a medical device is rather impractical. Aside from being easily damaged, these devices are expected to come in contact with people who are not professionals used to dealing with electronic components. Having them placed on conductive surfaces, tossed around from time to time and subjected to all manners of "everyday" abuse is expected.

    To that end, we designed a very simple, but sturdy 3D printed box to protect the electronics. It is based on a popular open SCAD solution by Kelly Egan, modified to fit a slightly different Arduino clone board, the ECG shield and a port for electrodes.

    The board is screwed into the box using 3 screws, and those are the only 3 contact points to the box, other than the cables when plugged in. Lid is snapped on firmly and held by friction. If the box is dropped with enough force (roughly the force of a grown man slamming it into the ground on purpose), the lid may snap off. Using a lever against the four corners of the box will easily snap the lid off step by step.ž

    All in all, it is a simple solution to a simple problem.

  • The PC side of things

    Tomislav Mamić10/04/2016 at 10:13 0 comments

    Fiddling with the ECG signal, I used only two tools - python and matlab. Python does a simple script which draws the signal in real time and measures the RR interval (but does not detect QRS - that's done on the MCU!), as well as saves all the data into a CSV file. A very convenient library I use to draw things on the screen is pygame. It is considerably more powerful than what's realistically needed for this software to work, but drawing things in real time is very easy using its tools.

    I use matlab mostly for trying out filters and signal processing methods to use on the MCU, as well as to display results. It's a convenient tool for testing DSP algorithms. Other than the overlap&average method which is still a bit too hard for ATmega328's memory capacity, nothing really exciting is going on.

    All this code can be found on our github, though most comments are in Croatian... for now!

  • IoT ECG with LCD?

    mikrotron10/03/2016 at 11:14 0 comments

    How about we plug EKG-EMG shield into Arduino Yun, and stack an LCD touch screen on top of it?

    That device could:
    - publish to internet in real-time
    - provide touch-screen user interface
    - display the reading

    I played a bit with it. To make long story short, let me jump to conclusions.

    Good stuff:

    LCD is quite handy, for you need to be still during measurement.
    EKG-EMG shield allows to select input pins, so it's fully stackable, and does not interfere with other shields
    With some power supply, this could really be a DIY IoT ECG, fully portable, able to store data to SD card too.
    Yun also has enough CPU power to filter and display the data, and supports any programming language of choice.

    Bad stuff:

    Touch screen is pretty much useless, for it is too small. Any UI components large enough to press them, don't leave enough space to display actual readings. Furthermore, touch is interrupt, ECG is interrupt, and displaying the data takes time - all that makes development considerably harder. Bottom line - better give up touch screen and use simple buttons.
    Or, here's what I'd ideally put on top:

    Anyway, we'll are going to plug cardiotron to PC, so I don't intend to purse this further.

    Here's some code in case anyone's interested.

    #include <UTFT.h>
    #include <UTouch.h>
    #include <compat/deprecated.h>
    #include <FlexiTimer2.h>
    // EKG STUFF
    // All definitions
    #define NUMCHANNELS 6
    #define HEADERLEN 4
    #define SAMPFREQ 256                      // ADC sampling rate 256
    #define TIMER2VAL (1024/(SAMPFREQ))       // Set 256Hz sampling frequency                    
    #define LED1  13
    #define CAL_SIG 9
    // Global constants and variables
    volatile unsigned char TXBuf[PACKETLEN];  //The transmission packet
    volatile unsigned char TXIndex;           //Next byte to write in the transmission packet.
    volatile unsigned char CurrentCh;         //Current channel being sampled.
    volatile unsigned char counter = 0;	  //Additional divider used to generate CAL_SIG
    volatile unsigned int ADC_Value = 0;	  //ADC current value
    // LCD STUFF
    // Declare which fonts we will be using
    extern uint8_t SmallFont[];
    // Set the pins to the correct ones for your development shield
    UTFT myGLCD(ITDB24E_8,A5,A4,A3,A2);
    UTouch  myTouch( 15,10,14, 9, 8 );
    // JOE's stuff
    int sequence = 0;
    volatile unsigned int values[6];
    int prev1 = 0;
    int prev2 = 0;
    int prev3 = 0;
    unsigned int  touchX, touchY;
    void setup() {
    void setupTouch() {
    void setupEKG() {
      noInterrupts();  // Disable all interrupts before initialization
      // LED1
      pinMode(LED1, OUTPUT);  //Setup LED1 direction
      digitalWrite(LED1,LOW); //Setup LED1 state
      pinMode(CAL_SIG, OUTPUT);
      //Write packet header and footer
      TXBuf[0] = 0xa5;    //Sync 0
      TXBuf[1] = 0x5a;    //Sync 1
      TXBuf[2] = 2;       //Protocol version
      TXBuf[3] = 0;       //Packet counter
      TXBuf[4] = 0x02;    //CH1 High Byte
      TXBuf[5] = 0x00;    //CH1 Low Byte
      TXBuf[6] = 0x02;    //CH2 High Byte
      TXBuf[7] = 0x00;    //CH2 Low Byte
      TXBuf[8] = 0x02;    //CH3 High Byte
      TXBuf[9] = 0x00;    //CH3 Low Byte
      TXBuf[10] = 0x02;   //CH4 High Byte
      TXBuf[11] = 0x00;   //CH4 Low Byte
      TXBuf[12] = 0x02;   //CH5 High Byte
      TXBuf[13] = 0x00;   //CH5 Low Byte
      TXBuf[14] = 0x02;   //CH6 High Byte
      TXBuf[15] = 0x00;   //CH6 Low Byte 
      TXBuf[2 * NUMCHANNELS + HEADERLEN] =  0x01;	// Switches state
      // Timer2
      // Timer2 is used to setup the analag channels sampling frequency and packet update.
      // Whenever interrupt occures, the current read packet is sent to the PC
      // In addition the CAL_SIG is generated as well, so Timer1 is not required in this case!
      FlexiTimer2::set(TIMER2VAL, Timer2_Overflow_ISR);
      // Serial Port
      //Set speed to 57600 bps
      // MCU sleep mode = idle.
      //outb(MCUCR,(inp(MCUCR) | (1<<SE)) & (~(1<<SM0) | ~(1<<SM1) | ~(1<<SM2)));
      interrupts();  // Enable all interrupts after initialization has been completed
    void setupLCD() {
    // Setup the LCD
    Read more »

  • Basic operation and limitations

    Tomislav Mamić10/03/2016 at 10:40 0 comments

    ECG shield

    The first thing to note about this shield is that it provides 1 measurement channel over its differential amplifier. The shield unfortunately contains a bandpass filter with cutoffs at 0.16Hz and 40Hz. It is stackable, but stacked shields seem to require their own electrodes which sounds like it would get very messy very fast.

    Method of measurement

    Image above shows the standard electrode setup. Leads 2 and 3 are inputs to the differential amplifier which then outputs the potential across lead 1.

    A standard heartbeat

    The image above shows a standard heartbeat as recorded on 1 channel ECG. The heartbeat contains 5 notable features marked P, Q, R, S and T. Ideally, we want to reconstruct all 5, but that is not an easy task with the ECG shield we're using. Read on to find out why. Still, even if we don't succeed in getting a clear image of all the features, extracting even just the QRS Complex would make this device a useful tool.

    Modern ECG standard (as seen from this document)

    Regarding the useful information in ECG frequency spectrum, it is ideal to have the lower cutoff as low as 0.05Hz, but this requirement can be relaxed up to 0.67Hz for some applications. It is worth noting that increasing the lower cutoff frequency causes considerable deformation of the ST segment. The deformation we get wouldn't really fit into the "considerable" category, but is is certainly there. When it comes to the upper limit, for adults, 100Hz is recommended while in babies up to 250Hz is required. This is where the Olimex ECG shield falls flat with its lazy 40Hz cutoff. The designers are not entirely to blame, as (really) old hospital ECGs used to run at the same frequency range, but nowadays we would like more measurements per second. One pretty obvious reason to cut off at 40Hz is the 50/60Hz power noise. Creating a multi-stage filter which deals with that separately while still preserving the higher frequencies was probably impractical so they went with the simple band pass.

    What we do with the signal

    Since our signal is already filtered in hardware, there is no need for (or use of) further filtering in the frequency range of the filter itself. When looking at the unfiltered signal, I noticed that, while it probably has some effect on the amplitude of the 50Hz interference, the hardware filter doesn't completely remove it. It does however get rid of anything higher pretty effectively. For this reason I had no qualms applying a low pass 4th order Butterworth filter which cuts off at 45Hz to do away with the power noise once and for all. This also has an added benefit of removing much of the high frequency ADC noise.

    To test the effects of our filter, I pushed an idealized version of PQRST through it as seen in the image below:

    This gives us a good idea of the kinds of deformations we can expect - varying delays among features will distort our idea of the timings - the fastest QRS complex sees the highest delay so it is slightly pushed towards T. Also, since P is slightly faster than T, its delay is higher so the overall duration of the complex is slightly shortened. Looking at amplitudes, there is slight damping, again most prominent at the QRS due to it having the highest amount of high-frequency content. Another thing to notice is slight ringing after the QRS.

    Overall, it seems like a small price to pay for getting rid of most of the high frequency trash introduced by the measurement hardware, especially considering that the useful high frequency content is already destroyed by the shield's hardware filter anyway.

    There is one effect that requires special attention when measuring ECG - the baseline drift. This is an extremely low frequency noise signal which effectively moves your ECG up and down very slowly. A possibly somewhat unusual, but very effective way of dealing with it is running a very slow low-pass filter which effectively calculates the average value of its input, and subtracting its output from the overall signal. Generally,...

    Read more »

  • First measurement

    mikrotron10/01/2016 at 13:02 0 comments

    After assembling the device, I wrote a simple Processing sketch to see what I can get from it. And this is what I got:

    Seems like my heart worked:)
    Mess on the right side is when I started moving my hand to reach the keyboard.
    Well, good so far.

View all 6 project logs

View all instructions

Enjoy this project?



Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates