Heartbeat Logger

A portable device that logs a snippet of your heart at the push of a button.

Similar projects worth following
Something odd about your fleshy engine? Your heart tumbling like a pair of sneakers in a washing machine?

I thought so myself back in 2014, while still being a student, and decided to make it an exercise in embedded hardware and software design. Since these odd sensations came without warning once a week or so, I needed a device that could measure the electro cardiogram and store it on a memory card to show a doctor later.

I succeeded in building something that fulfilled the criteria and it's been dead for some years now. However, I feel there is room for quite some improvement, so as of 2019 I'm doing a brush up on the concept:

- No bluetooth
- Smaller, leaner
- Only logs short sequences upon button push
- Connects as USB mass storage device, no micro SD
- The discrete analog front end is replaced with a dedicated ECG chip

What makes you tick?

Within each individual muscle cell in our heart there is a difference of charge between the inside and the membrane. Ions start gushing out from the control node in the heart and into the resting cell, making this difference of charge decrease until the cell contracts. A moment later the ions flow back and the cell returns to it's resting state. This will spread like a wave through your heart, and is called a heartbeat!

While this wave of contracting cells is spreading throughout your heart, we can measure the difference of charge between the resting cells and the contracted cells as an electric potential, or voltage if you will. Amplifying this tiny signal and plotting this voltage on paper as it happens is basically the ECG -- the Electrocardiogram.

KiCAD design files for version 4.00.

Zip Archive - 2.12 MB - 06/29/2019 at 16:24



Matlab function to read and plot the logged binary file.

m - 2.83 kB - 02/01/2016 at 15:15



A sample file from the first logger prototype. Noise free, no time stamps.

octet-stream - 12.00 kB - 02/01/2016 at 15:15


Source code for the prototype with Xmega A3BU micro controller.

application/zip - 259.46 kB - 12/23/2015 at 22:43


  • Consumin'

    Ole Andreas Utstumo10/25/2019 at 13:47 0 comments

    Did a crude test on current consumption during runtime. During runtime, the MAX ECG circuit is the only thing running constantly, waking the MCU up from Stop mode every 32 samples so it can receive these via SPI and store them in the RAM buffer.

    180 ish uA on average. On a 240 mAh coin cell battery that should provide well over a week of runtime. All components are selected to operate below the "knee" of the battery discharge profile.

  • Loggin'

    Ole Andreas Utstumo09/07/2019 at 20:14 0 comments

    Fatfs is working with the new flash chip, the USB MSC services are running, the ECG front end is now also running smoothly via SPI and we're logging data to files.

    Binary data straight from the front end obviously won't look good in a text editor...

    And if you're working with STM32 and haven't tried out SEGGER's excellent software packages, I strongly urge you to. They provide by far the most handy tools I've used yet for embedded debugging. The real time variable graphing tool is damn cool:

  • Blinkin'.

    Ole Andreas Utstumo09/01/2019 at 17:51 0 comments

    All good so far.

  • Mounted.

    Ole Andreas Utstumo09/01/2019 at 17:48 0 comments

    Three cards were mounted a while back. Hand mounting SMD components on a PCB backside is as usual a pain in the arse... I will hopefully never fall for that one again.

  • Design files uploaded

    Ole Andreas Utstumo06/29/2019 at 17:35 2 comments

    ... And can now be found on the main project page. I hope I didn't leave anything important out of the project folder :-)

  • Finishing up design & ordering

    Ole Andreas Utstumo06/29/2019 at 15:24 2 comments

    I think I'm done routing for now. It all fits nicely in a small package.
    The components will close the airwires when mounted
    I'll also upload the files and gerbers after I've done some tidying up.

  • Divided by rings

    Ole Andreas Utstumo06/28/2019 at 21:48 0 comments

    Isolating and looking at my power planes in KiCAD, they seem a bit more divided than I wished they were..

    The clearance in the design rules is set to 0.2 mm, and the copper fill strangely gives way to via annular rings in other layers... Looking at the 3D Viewer it's more obvious what's going on:

    The via pad stack has annular rings in layers where they are unused -- and the copper fill respects the clearance just as being told. Poking around on the internet revealed that other people had the same issue, however, only workarounds seem to be available at the moment... I'm not gonna dig too deep into KiCAD, so I will let this one rest for now.

  • Recommendations are just that pt. 2

    Ole Andreas Utstumo06/20/2019 at 11:11 0 comments

    As Jan pointed out in the previous log, the solder on the battery contact pad will oxidize. If the resistance in the contact builds up too much, we can solve it by placing some metal more resistant to corrosion and oxidation, like gold on the pad.

    A quick search reveals that there are SMD components which can help us out.

    I'll implement Jan's idea of having a triangle of contact points.

    Initially I'll just use the pads with solder, and have these as a backup :-)

  • Recommendations are just that.

    Ole Andreas Utstumo06/16/2019 at 21:12 2 comments

    Okay, my initial plan was using a four layer PCB with power planes as the inner layers, and signals traversing the outermost layers, to make for painless routing. That is until I checked the price of a prototype series with blind and buried vias at PCBWay.
    Obviously there are a bit more steps to the production of buried via PCBs than your regular 1.6 mm double sided green wafers of crispbread, and for a hobby project it's way more than what I want to commit. So I'll still run with a four layer PCB to keep my power planes intact, and let the signal vias run through the entire PCB. Then we're at 70 USD for 10 30x30 mm boards.

    So here comes the next problem: The CR2032 holder I picked requires a damn large pad on the bottom side for contact with the negative side of the battery.
    Which makes through vias problematic in 50% of the boards area when placed on the back side. I can pull GND down to the battery terminal, but anything else will short to the battery..
    I quite like the simplicity of these kinds of holders, though...
    Battery holder courtesy of Marijo Blazević (
    Maybe there is a trick we can pull? The datasheet for the battery holder recommends a footprint, but there's no one saying we can do our own interpretation. As long as we make robust mechanical and electrical contact we should be good. So
    Instead of resting the entire negative face of the battery on a gold treated copper pad we can make two "rails" that are almost right underneath the springs on top push the battery down. The pads will be surrounded by solder stop which might have more height than the pad:
    That would be bad news for our electrical contact, so we could try to gain control over this uncertain situation by adding solder paste to the pad.

    That should do the trick, and now we have freed the necessary space to route the rest!

    As some one pointed out in the comments below, solder will oxidize. Hopefully it will be a minor problem...
    To be continued...

  • Recovering

    Ole Andreas Utstumo06/01/2019 at 16:40 0 comments

    Among the things that could have caused the mass storage device to crash is timing issues. As the datasheet suggests, a minimum deselect time between each word in the write cycle must be T_BP = 10 µs.

    The HAL framework has no delay function for microseconds, so unless you want to implement this yourself, you could employ a dirty trick like this:

            for(uint16_t k=1; k < 55; k++){

    A "nop" is an instruction that does nothing, but occupies a certain number of clock cycles and therefore a tiny amount of time. However, if you start changing the core frequency of the MCU, then interesting things happen, which it truly did in my case. Resetting the clocks to default, checking the write operation in the scope and adjusting k in the delay cycle above we're back on track. However, increasing the clock of the SPI has marginal impact:

    Those blue streaks are two bytes written to the flash plus a control byte. The parts where nothing is happening is sadly overhead in the HAL libraries and can be overcome by writing your own SPI functions, or minimized by increasing the clock of the core. For my use it's good enough.

View all 52 project logs

Enjoy this project?



helge wrote 05/23/2016 at 21:08 point

It's so encouraging and satisfying to witness you seeing this project through. Thanks man.

  Are you sure? yes | no

Ole Andreas Utstumo wrote 05/24/2016 at 07:11 point

Thanks for your feedback, helge, that means a lot! I'll update with a video of the logger as soon as I get more electrode pads in the mail.

  Are you sure? yes | no

Jan--Henrik wrote 01/03/2016 at 19:54 point

Hi, if you're planning to also do some ECG recordings after wilson, you can also monitor the patients respiration by measuring the resistance between the electrodes.

It will increase as the patient will breath in.

  Are you sure? yes | no

Ole Andreas Utstumo wrote 01/03/2016 at 20:14 point

Thanks for the tip, Jan Henrik, I'll look into it, though I'm generally cautious of driving any current into the body for measurement as long as I'm not 110% sure of what I'm doing ;)

  Are you sure? yes | no

Jan--Henrik wrote 01/03/2016 at 21:02 point

Dont worry, you dont need to drive current into the body, you can measure the resistance in other ways :)

  Are you sure? yes | no

Ole Andreas Utstumo wrote 01/05/2016 at 17:18 point

You could apply a voltage, but I'd be even more careful with that. Otherwise I can't think of any other way... You wanna share your secret? :)

I did google this a bit and found an app note from Texas Instruments detailing this kind of measurement: Seems like the prevalent way is by injecting a high frequency current below 100µA into the chest and then measure the impedance.  

Another way of measuring respiration derives the respiration from the ECG readings themselves, and is shared here: This method doesn't require any additional hardware :)

  Are you sure? yes | no

dim liakos wrote 11/30/2015 at 22:06 point

Hi Ole Andreas,

Good Job!

I'm working on a similar project to receive an ecg with xmega a3bu  xplained board.

Will you post the c code? need to see the adc reading for ecg and bat status


  Are you sure? yes | no

Ole Andreas Utstumo wrote 11/30/2015 at 23:23 point

Thanks, dim!

I'm afraid that code is stored somewhere on my old laptop back home. I won't be able to post it untill the 23th of December.

The software employed DMA (Direct Memory Access) to read the ADC values and store them in RAM. I had some trouble with it, but this blog post sorted it all out:

For reading the ADC in an ordinary manner I would suggest creating an example project based on your Xplained board in Atmel Studio and build upon that. There are examples of reading the ADC and of sending the values over CDC to your computer.

Good luck, and check back in Christmas!

  Are you sure? yes | no

Peter Wasilewski wrote 09/14/2015 at 19:45 point

I have a question about the PCB. How did You manage to do so well-looking vias ? Are they a special kind of rivets ? 

Have You tried the lichtenberg's alloy ? It covers the board with a beautiful silver coating, very easy to solder at any time. I think it would preserve the copper  from oxidation.

  Are you sure? yes | no

Ole Andreas Utstumo wrote 09/14/2015 at 23:08 point

Well, thank you! It's just copper rivets carefully inserted with what I suspect is an ordinary riveting tool :) 

Oxidation is starting to become very visible by now, but the prototype already
contains several hardware bugs that should be corrected, so this thing
doesn't need to last long. I'll consider fixing them and order up some
crisp PCBs on the internet with solder mask and all. Making PCBs by etching copper boards, drilling and riveting is great for understanding the raw simplicity of electronics, it is however a lot of work... Thanks for the tip, though!

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

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