uECG - a very small wearable ECG

It's cheap, doesn't use a specialized heart rate AFE and can blink LEDs with your pulse :)

Public Chat
Similar projects worth following

While ECG is quite a simple signal, surprisingly few devices provide raw data, and none of them seems to be able to stream raw data on a phone while running.
So we decided to make our own.

uECG can stream data via BLE at 125 Hz or via custom radio protocol to PC at 1 kHz - for this option we developed a USB stick that captures radio signal and translates it into virtual COM port data stream.

Our main goals are low cost, low weight and high signal quality. And it seems we are hitting all of them - system is based on MCP3911 front-end originally developed for energy metering, but it performs nicely for our case too. Also we have buffer precision opamp, NRF52832 as MCU+radio, and some minor stuff.

The system requires relatively low power - without LED indication, device uses less than 10mA even during BLE transmission at 125 Hz (final number isn't clear yet - firmware has many places to optimize power consumption). That allows to use a tiny 120 mAh battery - so weight is also low, about 9 grams.

Signal quality of this setup is quite high - but there will be more on that in logs.


Poincare plot before, during and after running, collected with uECG

Portable Network Graphics (PNG) - 85.45 kB - 04/10/2019 at 18:32



Noise removal algorithm illustration (already works on-board)

Portable Network Graphics (PNG) - 20.73 kB - 04/09/2019 at 21:18



3D model of the PCB

Portable Network Graphics (PNG) - 140.18 kB - 04/06/2019 at 11:39



Schematics in PDF

Adobe Portable Document Format - 86.23 kB - 04/06/2019 at 11:39


KiCad source files

Zip Archive - 56.83 kB - 04/06/2019 at 11:39


  • 1 × nRF52832 (on PCB) popular Bluetooth SoC
  • 1 × MCP3912 (on PCB) a generic AFE
  • 1 × BMI160 (on PCB) IMU
  • 1 × RGB led (on PCB)
  • 1 × micro USB

View all 8 components

  • Of dragons, stress levels and ECGs

    Lucy Sohryu04/15/2019 at 20:04 0 comments

    We're pretty sure nobody tried measuring stress using Skyrim and an ECG device, so we decided to try it ourselves and give uECG another test drive, now with more participants. Unfortunately, since we didn't have any saves with a cave bear or a sabercat (or a spriggan) going off in your face, we had to use a dragon instead. 

    Technically, those were two dragons.

    Fascinating trivia aside, we had a go at the dragon du jour in pairs, one person playing and one person  watching, to see how heart rates and stress levels change depending on how involved you are with the game. The results we've got, after cleaning them up, were wide and varied - about half of the players had elevated stress while fighting dragons, but lower stress while watching; the other half had elevated stress while watching the other fight, but got calmer and focused once it was their turn. For someone, it didn't change much at all! 

    We've got excellent graphs and Poincare plots coming up in the next log, but so far, we've enjoyed this, and are just itching to test ourselves - and our hearts and minds - further, hopefully with something more stressful than a mere dragon. So far, the results were promising.

    Just gonna need more data.

  • Poincare plots are now available! :)

    the_3d604/10/2019 at 18:57 0 comments

    After updating Android app so it stores all consequent beat times, detected on the device, we can build Poincare plots - for two consecutive beats, time of 1st beat is used as X coordinate, time of second beat - as Y coordinate, thus producing one point. A healthy heart has some variations in RR intervals, but they are relatively small, so Poincare plot looks somewhat like ellipse with long axis lying on X=Y line.

    I've tested it before, during, and after running (it was a short ~15 minutes run). This is what I've got:

    It showed a problem that wasn't obvious before: beat detector sometimes skips beats - and thus we see almost perfectly aligned series X=2Y and 2X=Y (and some traces of X=3Y and 3X=Y). In case of real heart problems, there could appear "clouds" in these areas, but they are far from such a perfect straight lines, so this is definitely a problem of detection algorithm. Will work on that!

    Besides this problem, it seems to work really well. Here is a chart of BPM vs time (I've started run after ~50 minutes after I started recording, and during the run, made a pause and then short sprint - all clearly seen on the chart)

  • Uploaded schematics and PCB

    the_3d604/06/2019 at 11:56 0 comments

    Thanks for the followers and likes! :)

    After some more testing of version 2, everything looks good, so we uploaded our schematics and PCB design files (in KiCAD 5). It still is not the final version, but it works as intended and we found no hardware problems (yet) - so if there are some bugs, they are not critical.
    And here is a 3D render of the PCB:

    Firmware is still far from being ready, but we'll share it too when it would work smooth enough.

  • Now we can measure stress!

    the_3d604/04/2019 at 19:18 0 comments

    We added calculation of distribution of differences in consecutive R-R intervals - so now we have a measure of how exactly these intervals change from beat to beat. There are many papers that use percentage of intervals that change by more than 50 millisecond for indicating stress level. But when we got full distribution, it was worth looking at!
    We built a histogram of changes: first bar indicates how many R-R intervals vary by less then 10 millisecond, second bar - from 10 to 20 ms, third bar from 20 to 30 and so on. And I've went through normal, stressed and relaxed states. Here is the result:

    So clearly this histogram is useful for indicating current state - but we need more experiments to determine what exactly it means. For now we just added it in the app interface, in two time scales, and will check how it behaves in different situations. 

    ...also take a look how clear the signal is with the new version, even on the phone with lower data rate and some lost packets! ))

  • Second version is ready!

    the_3d603/28/2019 at 13:51 0 comments

    Just assembled 2nd version!

    It is by all means superior to the first one. Fixed all mistakes and implemented several improvements. Most notable are:

    - signal amplification is now working properly. Useful signal resolution is 12 bits (out of 16 bits ADC - some space reserved to prevent overflows)
     - 50/60 Hz noise filtering now works on-board, so device streams noise-free data on smartphone (since BLE streams is done only at 122 Hz rate, filtering on the phone wouldn't be possible)
     - heartbeat detection algorithm now works at 976 Hz resolution, so precision of R peak timing is much better (~2 milliseconds, but exact value will be clear only after a set of experiments)
     - and a set of small improvements - electrodes connectors are more convenient, LED is placed in a more visible place, charger works both in on and off states, analog supply can be turned off by NRF chip for sleep mode and overall PCB design is more clean, better shielded.

  • Blinking LEDs! What else ECG is good for?

    the_3d603/25/2019 at 12:33 0 comments

    It was quite a surprise that small schematics with LEDs and atmega would attract such a huge noise. Initially there was a simple transistor on the PCB that opens for a short time when each heart beat is detected. But when we attached this contraption, noise became overwhelming.

    To some extent we decreased it using optocoupler on the output instead of transistor. The result is far from perfect - but at least it more or less detects heart beats.

    My hand is really needed there: it blocks significant part of mains noise and thus makes everything much more reliable. But - that video was shot before we developed our new filtering algorithm! Soon we'll see how it works with it and with proper input buffer on the new PCB :)

  • Project timeline

    the_3d603/22/2019 at 15:19 0 comments

    We started this project in November 2018. At some point we just realized that we can make quite good ECG device, so why not? ))
    At the end of December we assembled its first version. We (naturally) made a mistake in the PCB and due to it had to bypass buffer amplifier, directly connecting AFE to skin, which is a really bad option here - AFE has input impedance of only ~30 kOhm, while skin has impedance in 3 MOhm range, so signal is 100x times smaller than it could have been.
    But even in such conditions signal was relatively ok (we had about 6 bit resolution) and allowed us to implement heart beat detector, so we blinked on-board LED and then made it blink a new year lights.

    During Jan-Feb 2019 we slowly improved firmware and app, added on-board calculation of BPM, and some heart rate variability parameters such as SDNN, RMSSD, pNN50.

    Then we made a significant improvement - increased ADC frequency from 122 Hz to 976 Hz (that involved changing readout procedure from poll-based to interrupt-based, and introduction of memory buffers for signal processing, so firmware got quite an update). At this rate, it became possible to take a closer look at 50 Hz noise from mains (in Europe frequency is 50 Hz, while in USA it is 60 Hz). In some conditions this noise becomes even stronger than signal, and often it is of comparable amplitude (it all depends on how close you are to a major power line at the moment).

    Typical signal with noise

    Instead of rather standard approach of filtering out 50 Hz band using FFT, we decided to use a different method: we estimate amplitude/phase of 50 Hz sine wave that best fits the signal during last few seconds, and subtract that wave from current signal. Wave parameters are slowly adjusting as new data become available, but slowly enough to almost ignore R peaks if they happen to have significant 50 Hz component. This way, mains noise is removed almost without affecting useful signal.

    After filtering noise

    This is the current state of the project, we expect to get much better signal once we'll assemble the second PCB version (which should happen really soon).

View all 7 project logs

Enjoy this project?



John Loeffler wrote 06/09/2019 at 14:28 point

I have been looking for those kind of connectors for grounding. Do you have a supplier/Part Number

  Are you sure? yes | no

Kseniia wrote 06/11/2019 at 11:33 point

Oh, these are indeed hard to find, we've been trying to find them under various names until we guessed the correct keyword :) We bought ours on taobao, shipped to us with Meest-China (it's a freight forwarder). Here:

They're called "ECG snap connectors", the Chinese keyword is 心电扣. I believe I also saw them on aliexpress, but it's often faster (not to mention cheaper) to buy them in China directly and forward after that. Also, there is more choice, so for example I could buy our snap connectors from manufacturer directly. To find difficult stuff you can google by various keywords in Google images and then do an image search by uploading most prominent pictures.
Also here's some snap connectors on aliexpress:
(but they cost $24 here, while I bought the same amount for $5.5 on taobao)

  Are you sure? yes | no


[this comment has been deleted]

the_3d6 wrote 04/26/2019 at 19:07 point

Thanks! We are getting it ready for production, hope to start crowdfunding really soon (we almost finished development, now the main goal is to get some visibility so we'll have enough bakers to produce the first batch)

  Are you sure? yes | no

Mark wrote 05/24/2019 at 21:36 point

Interesting.   Where are you crowdfunding and how much are you trying to raise?

  Are you sure? yes | no

Bud Bennett wrote 04/09/2019 at 20:00 point

I really hate it when people comment negatively on my projects, but I really love it that they are interested enough to make a comment. My background includes design of medical equipment in the olden days: 1977-1983. I took a look at your schematic and have a couple of questions, or comments for improvement.

1. It doesn't appear that you need to use a unity gain amplifier (the AC8606) to buffer the ADC. U1B is biased near GND and might have problems tracking signals below GND. U1A doesn't do anything at all, except draw current via the 10Ω load of R3.

2. The MCP3911 has a PGA that should eliminate the need for the AD8606. If you biased the CH0- input a few mV above GNDA and AC-coupled CH0+ it should be all that is needed. Yes, there is some uncertainty as to the input impedance of the MCP3911, but that doesn't worry you with regards to the time constant of C17. which uses that impedance.

3. The need for the onto-isolator U7 escapes me. Please elaborate.

4. The ADC doesn't include a 50-60Hz notch filter. Many other ∑-∆ converters include a 50-60 Hz notch. A notch would make the subsequent signal processing easier.

5. D2 is a mystery to me. Please explain.

Overall I'm impressed with your progress. I like it a lot.

  Are you sure? yes | no

the_3d6 wrote 04/09/2019 at 20:50 point

Hi! No problems with negative comments - but yours aren't negative at all :) Quite the contrary, thanks for taking a deep look at our schematics!

It seems that you've missed that we have not 2 but 3 grounds: GND is digital ground, GNDA is analog ground, and GNDS is a virtual "ground" which is actually at +0.6V and we measure all analog signals around it. Probably our symbols are misleading ))

1. U1A generates virtual ground - divider on its input sets level of about 0.6V and U1A repeats it (via 10R resistor just in case if something goes wrong, no real need in it since amplifier survives short circuit). That level of 0.6V is our zero point around which we work (and normally we stay within a few mV around).

2. MCP3911 has input impedance of about 30k when PGA is set to 32 amplification - and skin has impedance in a few MOhm area (measured that for gel pads and placement we are using) - so without buffering input with AD8606, it works like a voltage divider. Actually in our first iteration we made a mistake and had to omit amplifier completely - and it worked somehow, but signal was much, much worse and very sensitive to contact quality.

3. It is for connecting to external Arduino or other microcontroller: we are detecting heart beats onboard, and send them as short pulses there. Optocoupler makes external connection simple, eliminating possible problems (you can just connect it, and if it doesn't work - connect with opposite polarity). 

4. Yes - but check project logs, I'm really proud of the filter I've made! :) It's better than anything I saw before - including max30003 AFE which is specifically designed for ECG. Our result is seriously better (we work on another project based on max30003 in parallel, so I can compare them in identical conditions). And MCP3911 is the cheapest 16 bit AFE out there! )) (also uploaded illustration of how it works in extreme conditions: )

5. MCP3911 can be damaged if input voltage exceeds +2.0V on any ADC input. Normally we work around 0.6V point, but when the unit is not on the body, input can get anywhere. As soon as it exceeds approximately 1.2V, LED turns on, protecting the input and, at the same time, visually indicating that there is overload! And it actually works, when it's charging via usb, you really can turn it on by touching only one input! ))

  Are you sure? yes | no

Bud Bennett wrote 04/10/2019 at 00:48 point

Fair enough. I grok it now. There is a reason for everything in a schematic, if not entirely obvious. I'm an old school EE, so schematics should have wires connecting components instead of tags. It's easier for those not familiar with the design to understand what's going on. 

Thanks for the answers. Carry on. It obviously works.

  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