*A low-cost (₹2,000) alternative to ₹50,000+ hospital-grade ECG monitors
This project implements an end-to-end electrocardiogram (ECG) acquisition, signal-conditioning, and arrhythmia detection pipeline using:
- AD8232 single-lead heart-rate front-end
- ESP32 microcontroller
- MATLAB for offline filter design
- C++ firmware on the ESP32
- Processing IDE for a doctor-friendly real-time waveform display
- Python + wfdb simulation against the MIT-BIH Arrhythmia Database
The system classifies each heartbeat into one of:
NORMAL (60-100 BPM), TACHYCARDIA (>100 BPM), BRADYCARDIA (<60 BPM),
and additionally flags beats with IRREGULAR R-R intervals (>20 % deviation
from the previous beat) - a marker of arrhythmias such as PVCs or atrial
fibrillation.
Cardiovascular disease is the #1 cause of mortality globally. In India, the rural-urban gap in cardiac diagnostics is severe: a 12-lead ECG machine in a tier-3 town costs more than a year of a PHC's equipment budget. This project demonstrates that the DSP core of an ECG monitor - filtering, QRS detection, rhythm classification - fits comfortably on a $5 IoT chip.
The project maps to UN SDG 3 (Health & Well-being), SDG 9 (Industry & Innovation), and SDG 10 (Reduced Inequalities).
+----------+ +--------+ +-------------------+ +-----------------+
| Subject | -> | AD8232 | -> | ESP32 (12-bit ADC | -> | Laptop |
| (LA/RA/ | | front- | | + DSP pipeline) | | (Processing IDE |
| RL leads)| | end | +-------------------+ | waveform plot, |
+----------+ +--------+ | | | | BPM, rhythm |
v v v | classification)|
DC blk Notch FIR +-----------------+
(HP) (50Hz) (40Hz LP) ^
| | UART @ 9600
+--> envelope --> peak detect ---+
|
+--> BPM avg over 500 beats
+--> Tachy / Brady / Irregular
The contaminated input on the left becomes the clean QRS train on the right:
And the magnitude response of the full cascade:
ecg-arrhythmia-detection/
├── matlab/ # MATLAB filter design (the "Recipe")
│ ├── generate_coefficients.m # master script
│ ├── design_bandpass_filter.m # FIR 0.5-40 Hz
│ ├── design_notch_filter.m # IIR notch (50/60 Hz)
│ ├── plot_filter_responses.m # frequency-response figures
│ ├── verify_filters_synthetic.m # sanity check on synthetic ECG
│ └── export_coefficients_to_c.m # write firmware header
│
├── firmware/esp32_ecg/ # ESP32 / Arduino C++ (the "Chef")
│ ├── esp32_ecg.ino # main sketch
│ ├── config.h # pin map + tuning constants
│ └── filter_coefficients.h # auto-generated from MATLAB
│
├── processing/ecg_visualizer/ # Real-time scope on the laptop
│ └── ecg_visualizer.pde
│
├── simulation/ # Python validation pipeline
│ ├── mitbih_loader.py # MIT-BIH database wrapper
│ ├── filters.py # mirrored firmware filters
│ ├── detector.py # peak detect + classify
│ ├── verify_filters.py # magnitude-response checks
│ ├── run_demo.py # end-to-end demo
│ └── requirements.txt
│
├── docs/ # extra documentation
│ ├── hardware_setup.md # wiring & pin assignments
│ ├── dsp_pipeline.md # math behind each stage
│ └── results.md # what we measured
│
└── scripts/ # misc utilities
└── plot_serial_data.py # log + plot Serial output
cd matlab
generate_coefficients % writes ../firmware/esp32_ecg/filter_coefficients.hIf you don't have MATLAB, a pre-generated
filter_coefficients.his already committed - you can skip straight to flashing.
- Install the ESP32 Arduino core in the Arduino IDE (Boards Manager → "esp32" by Espressif).
- Open
firmware/esp32_ecg/esp32_ecg.ino. - Select board: DOIT ESP32 DevKit V1.
- Wire up the AD8232 per
docs/hardware_setup.md. - Hit Upload.
The firmware streams a filtered float per line over Serial at 9600 baud,
plus diagnostic # BEAT BPM=... lines whenever a beat is detected.
# Either use the Arduino Serial Plotter (Tools -> Serial Plotter)
# or run the Processing sketch for a richer display:
processing-java --sketch=processing/ecg_visualizer --runcd simulation
pip install -r requirements.txt
python run_demo.py 100 # normal sinus rhythm
python run_demo.py 208 # PVCs / tachycardia
python run_demo.py 232 --duration 60 # bradycardiaThis downloads the requested record from PhysioNet, runs the exact same filter cascade and detector that lives on the ESP32, and reports beat counts, classification breakdown, and sensitivity vs the gold-standard PhysioNet annotations.
Each sample (~every 1 ms) on the ESP32 goes through:
- ADC read → 12-bit unsigned (0..4095) at GPIO 34.
- DC removal → subtract
ADC_CENTER = 2048(mid-rail). - 1st-order IIR DC-blocker → kills baseline wander (resp., electrode drift) at ~0.5 Hz.
- 2nd-order IIR notch → ~98 dB rejection at 50 Hz mains.
Change
MAINS_FREQ_HZto 60 for the US. - 101-tap FIR bandpass (Hamming window) → smooth roll-off above 40 Hz, linear phase preserved across the diagnostic band.
- Absolute-value moving sum (16-sample window) → envelope.
- Threshold + hysteresis peak detect → R-wave events.
- R-R interval → BPM → classify each beat, push into a 500-sample moving-average ring for a stable display.
See docs/dsp_pipeline.md for the math and
frequency-response plots.
| Metric | Pre-conditioning | Post-conditioning |
|---|---|---|
| SNR | very poor (50 Hz hum + drift dominates) | clean QRS visible |
| Visible QRS complexes | no | yes (P, QRS, T discernible) |
| ADC operating point | ~3800 (saturated, wrong wiring) | ~2048 (mid-rail) |
| Stable BPM readout | no | yes |
| Tachycardia / bradycardia flag | no | yes |
See docs/results.md for full figures.
| Component | Approx. price (INR) |
|---|---|
| ESP32 DOIT DevKit V1 | ₹450 |
| AD8232 ECG Module | ₹350 |
| ECG electrodes (3-pack disposable) | ₹150 |
| Jumper wires, breadboard | ₹100 |
| USB cable | ₹100 |
| Total | ~₹1,150 |
Compared to a clinical 12-lead system at ₹50,000+ this is a ~40x cost reduction. We trade off lead count and FDA-grade isolation, not the DSP fidelity.
- Adaptive thresholding so we never need to hard-code
41.5or620.0. - Pan-Tompkins style derivative + integration for sub-ms QRS timing (we already cite the 1985 paper - this is the natural next step).
- Wi-Fi telemetry to a Blynk / ThingSpeak dashboard.
- Battery-operated PCB so it leaves the breadboard for real field use.
- Pan, J., & Tompkins, W. J. (1985). A Real-Time QRS Detection Algorithm. IEEE Transactions on Biomedical Engineering, 32(3), 230-236.
- Moody, G. B., & Mark, R. G. (2001). The impact of the MIT-BIH Arrhythmia Database. IEEE Eng. in Medicine and Biology Magazine, 20(3), 45-50.
- Espressif Systems. ESP32 Series Datasheet, 2023.
- Analog Devices. AD8232 Single-Lead Heart-Rate Monitor Front End Datasheet.
MIT. Use it, fork it, ship it; just don't sue us if your breadboard catches fire.

