Cardiogram - a Portable ECG Device for Daily Use on the Go

by xJaagrav in Circuits > Wearables

72 Views, 2 Favorites, 0 Comments

Cardiogram - a Portable ECG Device for Daily Use on the Go

2BBA9824-E9FD-4885-AD01-226E8DD6D9CD_1_201_a 1.jpg
mockup.png

Nearly 50 million people in India suffer from heart diseases, and therefore in this day and age, it becomes essential that we monitor the ECG of such patients on a regular basis. Measuring ECGs should be as easy, quick and affordable as measuring Steps, or Blood pressure, or body temperature.

Our goal with Cardiogram was to build something super portable, mobile, and user friendly device that is comfortable to wear, and the user can wear it once and forget about it, while it continues to record the ECGs at given intervals of time. This alongside a companion app would not only add to the smooth user experience that we want to offer, but also make it easy for us to further process and analyze the data, to figure out the Cardiac health degradation and other historical data that gets recorded over time.

Supplies

cg-2.png

For building the Cardiogram device, you'd need the following stuff:

  1. ESP32C3 / ESP32S3 / nRF52840
  2. Preferably get the nRF52840 as it's a MCU that is specifically designed to develop wearables, and has very low power consumption as compared to Espressif's MCUs for BLE.
  3. If you're in India, you can find one here:
  4. ESP32C3 (Used in this project)
  5. ESP32S3
  6. Arduino Nano BLE Sense
  7. nRF52840 (Best choice)
  8. I was stuck with ESP32C3 as unfortunately it was the only thing available at the time I was building this project, which was for a hackathon. So choose the right MCU, that your budget and requirements support the best. We wanted to get nRF52840 but it got sold out right when we were ready to order it.
  9. UpsideDown Labs Heart Bioamp Candy
  10. Make sure to reach out to UpsideDown Labs and request them for a custom sensor as the original Heart Bioamp Candy sensor does not support the above mentioned MCUs right out of the box. I did so as well. So make sure you order directly from their official website. https://store.upsidedownlabs.tech/product/heart-bioamp-candy/
  11. When you get this sensor, you'll also get a kit free with it that comes with chest straps and sticky gel electrodes which were also used in this project, as shown in the cover image.
  12. 500 mAH 3.7V Li-Po Battery
  13. Choose a battery based on your need and as you see fit for the product you're building. Make sure to take in account the power consumption of whatever MCU you choose to use for best performance.
  14. Self locking switch
  15. Needed to turn the device on/off
  16. Arduino IDE
  17. Autodesk Fusion - In case you want to modify the CADs. I used the non commercial free version for designing the main product

Before We Begin

IMG_2451.jpeg
IMG_2484.jpeg
IMG_2298.jpeg
IMG_2288.jpeg
IMG_2291.jpeg

We made this project for the Techsprint hackathon that happened at Graphic Era University at Dehradun. Our schedule was incredibly tight so we ended up working on both the app and device during our train journey to Dehradun. So this article is less of a step by step guide for building this device and more about the experience we had building this fun little project.

Apart from participating in this hackathon, we found out that the founder of Sunfox, a company that appeared on Sharktank for their portable ECG device, was an alum of Graphic Era University itself, so we wasted no time and shared our project with him. Thanks to that, we had the opportunity to not only visit and get a tour of Sunfox's offices in Dehradun but also got a chance to meet with the founder Rajat Jain, and had an amazing discussion on what it takes to be an entrepreneur like him. He is one of the most amazing people I've ever met in my life so far, and the fact that he spent over a couple hours discussing his entire journey with us that also on a Sunday, really tells how great of a person and mentor he is. I deeply admire his resilience and passion for developing the array of products and building a company like Sunfox. It truly shifted our perspective and helped us understand the level of effort required to turn this prototype into a real product, as this prototype is nearly how Sunfox also started close to a decade ago.

Designing the Device

IMG_2372.jpeg
cg-1.png
Screenshot 2025-05-02 at 10.37.35 AM.png
cg-2.png

For the outer body of the design, I had to step into the shoes of a 3D/Industrial designer. I had a vision, but I had no skill. Luckily I knew some concepts in 3D designing as I had used blender before when I wanted to be a game developer, so after launching Autodesk Fusion for the first time, it didn't take me long before I figured out all the features I needed to design my shell. After spending a couple of hours I finally had the first STL, ready to be 3D printed. Luckily enough, my friend Sarbik Betal helped me with printing my designs using his Bambu Lab A1 3D printer, right before the day we boarded our train to Dehradun. We now had the opportunity to present our creation as a fully developed product prototype—something we initially believed would not only add significant value but also give us an edge over other projects, as our goal was to build a complete, market-ready product. With the help of this 3D model, we had a product to support our vision for this project.

Now I know this is just a shell, and perhaps a very simple design, but it is my first time using Fusion and designing a 3D print, but I am quite happy with it as it fits every component we used perfectly, even after I designed it on the basis of rough measurements that I took for it's internals. I expected there to be more iterations, but the first design was just perfect enough to fit everything inside perfectly.

Building the Circuit

circuit_image.png
IMG_2376.jpeg
IMG_2363.jpeg
IMG_2361.jpeg

Probably the most easiest part of the project, just soldering a bunch of wires to connect all our components together. Here's the circuit diagram, that you can follow to connect all your components along with the pin connection table.

Yeah I know in the circuit diagram I have used an ESP32S3, but that was the only Seeed studio MCU available on Cirkit that had the battery terminals, but anyway, even on an ESP32C3, the wiring would be exactly same. Here's the table.

Component Pin Connected To Wire Color
ESP32-C3 3V3 VCC (Heart BioAmp Candy) Red
ESP32-C3 GND GND (Heart BioAmp Candy) Black
ESP32-C3 GPIO (e.g., D0) OUT (Heart BioAmp Candy) Yellow
Battery + (Positive) 3V3 via power switch Red
Battery − (Ground) GND line Black
Power Switch Inline between Battery + and ESP32 3V3 Controls power to circuit Green (Switch wire)


Also make sure to use the antenna provided with the ESP32C3 as it is essential for having good connectivity, cause we faced some issues that we were too dumb to predict, where we noticed a lag in the realtime data on the app side, which improved significantly after connecting the antenna, not only was there little to no lag anymore but also the occasional disconnection of the device due to poor network was also resolved.

Writing the Firmware

Screenshot 2025-05-09 at 10.48.11 AM.png

Now this was by far the hardest step in this project. It was not integrating BLE to connect with our own mobile app, it wasn't with getting the sensor to work, it was with dealing with the unexpected noise that we kept encountering every now and then. During our conversation with Rajat Jain, the founder of Sunfox, he mentioned that in his 10 years long experience building Spandan, handling noise continues to be one of the major challenges that they still struggle with to this day, despite of achieving 99% medically accurate ECG results.

So what is this noise exactly? Here are all the instances when I noticed this noise that makes it difficult to analyse and process ECG data.

  1. See when I first bought the Heart Bioamp Candy sensor by Upside Down Labs, I used an Arduino Uno to test if the sensor was functioning as expected. Indeed it was working really well, however when I used the ESP32C3, I noticed this unexpected amount of noise that just didn't make sense to me. As it turns out, the 3.3V regulator on a XIAO ESP32C3 produces more noise than Arduino Uno's Linear 5V regulator. Plus even the WiFi/BLE components could emit high frequency noise during transmission. So in every step while building this project, I kept regretting using ESP32C3, I mean there are ways by which you can electrically reduce the noise using capacitors, but of course, I wasn't carrying any caps as I didn't expect this noise, which I found out about during my train journey.
  2. Another instance where I noticed noise was when I was putting stress on my chest muscles. Of course muscle signals are also electrical signals, so I wrote it off as muscle noise. This is actually termed as Muscle Artifacts, a term we learnt yet again from Rajat Jain. Therefore even Sunfox suggests their users to lie down during the ECG data recording.
  3. And finally we also noticed noise when we were just present in certain environments or touching random objects, like the static charge coming from rubber seats or electricity flowing in our laptop's charging cables.

Now how the hell did we handle this noise? See I tried my best, going through various noise reduction algorithms and methods that were already out on the internet, and yet after putting nearly a day into just researching for a solution, I reached out to Deepak Khatri, the founder of Upside Down Labs, who suggested to use the ECG filter that was present in Upside Down Labs' GitHub repos for Heart Bioamp firmware. While the filtering helped by removing low and high frequency noise—resulting in cleaner ECG graphs—it didn’t actually address the aforementioned noise issues we encountered. The ECG data itself remained noisy; the filter just made that noise appear more polished.

In the end, I decided to go with the noisy signal data, as this was just a hackathon/educational project and we could never achieve medical grade accuracy with the components we used. Therefore I moved on with implementing the rest of the features we wanted to have. So this device would have 2 modes, as I imagined

  1. Standby: This is the period when the MCU is not streaming the ECG data via BLE, however is awaiting or has successfully connected to a phone.
  2. Streaming: This is when the MCU will start streaming the ECG data via BLE to the phone.

This required a lot of tweaking however I was able to wrap up on the code needed for this within a couple of hours, and next it was again my responsibility to connect and integrate and make the whole system work together, where the smartphone would send a signal to the device to start streaming the ECG data, the stream would continue for 30 seconds, during which time it would update the graph and metrics shown on the app in realtime, and then end with a session report that would include the average BPM and some other metrics calculated onboard on the ESP32C3.

Downloads

Developing the App

Screenshot 2025-05-09 at 2.14.01 PM.png
Cardiogram final
Cardiogram initial
IMG_2374.jpeg

This was supposed to be the integration hell for us, as this is where the device and the smartphone app would need to talk to each other and function as a single unit. I had very less experience in BLE products, I'd only worked with one BLE based project before, which was a BLE based smart light for a company named Poplight. Now Poplight's app was written in Flutter, so we had both an android and an iOS app. For this project I initially chose React Native as well, of course I wanted to have both an android and an iOS app, and building all of that with Expo would just make things much easier for us cause we needed an app QUICK. However our team had me and Arpan Das, 2 SwiftUI iOS developers, who would any day prefer Swift and SwiftUI over any languages and frameworks to build apps. I mean we could've probably developed with Expo, but Expo has its own serious disadvantages, so we ended up following our heart 😬, and developed the app using SwiftUI.

Arpan was the UX engineer behind the beautiful UI and app for Cardiogram, which he both designed and developed within a few days, during our train journey.

Here I was only responsible for connecting the device with the smartphone, and then get the streamed data from the device which could then be rendered out as a graph. Initially things were very laggy, the data being streamed was way too quick for SwiftCharts to handle. SwiftCharts on the other hand not being optimized for quick handling of data made it worse, though the fix for this was simple, on the receiving end we intentionally slowed things down a bit so that SwiftCharts would have that extra processing time to render new data and also play a linear animation. Check the attached 2 videos in order to see the difference between, what we initially had and what we ended up with. We implemented multiple ways to make the rendering of graph seem smoother, in fact use some completely different framework for charts, however SwiftUI being fairly new, we didn't find a lot of frameworks for our specific use-case, and in fact, it made more sense that streaming data every 8-10ms might just be too fast anyway. However we could not slow down the data from device's end as it could lead to data loss, and I mean I know there are other ways to slow down data and still not have data loss, but we were too tired to try other approaches and ended up manually slowing down the data on the BLEManager that received the data from the device while streaming. This seemed to work without any data loss, so we ended up keeping it. Luckily the simplest solution turned out to be the best one.


Stay tuned, will update this article once we make the SwiftUI app GitHub repo public.

The Website and the Backend

Screenshot 2025-05-02 at 9.57.57 AM 1.png
IMG_2288.jpeg
WhatsApp Image 2025-05-09 at 00.59.30.jpeg

Now for the website and the backend, we had Tanish Sen and Protyasish Majumder working together, so the idea was after every recording session, we would store all of that analytical data to our database. We used Supabase for the database, they ended up using the Supabase JS SDK directly in the frontend so that we didn't have to spend extra time building and hosting another API. Thanks to this, we were able to accumulate the ECG data of the user so now we could say we have the historical ECG data recorded based on which we could analyze and maybe also detect degradations in the cardiac condition of the user. This data could also be beneficial for us to build ML models to further detect certain heart conditions and events for the user and notify them accordingly.

However our main intention behind storing this data in a database was to enable patients to share their ECG reports that we generated with their doctors. That feature automatically added a massive value for the patients, thanks to Tanish's and Protyasish's expertise in web, they were able to quickly design and develop this together during the 48 hour hackathon, and display the data sent from the Cardiogram device on a web interface that could be useful to a doctor.

Conclusion

Cardiogram
IMG_2423.jpeg
WhatsApp Image 2025-05-09 at 00.59.25.jpeg
IMG_2370.jpeg
IMG_2354.jpeg

It was honestly an AMAZING experience. I mean we travelled to Dehradun for participating in this hackathon but SO much more happened. Arpan and I won 2 presentation awards. We didn't win the main TechSprint hackathon, probably because we didn't make a Gen AI project according to the theme, though we were told we got very close to winning this hackathon, and were praised a lot by the other professors, students and external judges who saw our project. We made loads of amazing connections, met the freaking founder of Sunfox, shared our idea with a few others as well during our train journey, who were curious to see 4 kids with laptops building something through the night. And of course we also had the opportunity to visit some beautiful places near Dehradun. Plus I've never seen more beautiful people ever in my life as I did at Graphic Era, they were kind, helpful, and took care of us as much as possible. It's seriously an amazing campus that they've got, and now I can only wish I made a better choice choosing my university 3 years ago. It's a beautiful city with beautiful people, and my friends and I made memories that will stay with us for the rest of our lives. Tanish and Protyasish in fact missed their flight on our way back, while I was in the toilet taking a dump as the final call got announced at 2 in the morning, Arpan and I somehow managed to get on the flight, so definitely an experience to never forget.


Credits:

Protyasish Majumder: https://www.linkedin.com/in/protyasish/

Arpan Das: https://github.com/arpanverse

Tanish Sen: https://www.linkedin.com/in/tanishsen/

Jaagrav Seal: https://www.linkedin.com/in/jaagrav/


Special thanks to,

Rajat Jain: https://www.linkedin.com/in/jairajat

Deepak Khatri: https://www.linkedin.com/in/lorforlinux

Dr Hriday Gupta: https://www.linkedin.com/in/hridaykumargupta