Skip to content

Latest commit

 

History

6 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ECG Prototype MVP V1

Research-only ECG capture prototype for an Arduino Uno R4 WiFi and AD8232 single-lead ECG front end.

The goal is to produce ECG files that look like the HL7 v3 AnnotatedECG XMLs used by real ECG systems, while keeping the hardware simple enough for an MVP bench prototype.

This repository contains:

  • Arduino firmware that streams compact ECG samples over USB serial.
  • A desktop capture tool that records HL7 AnnotatedECG-style XML, exports key events to CSV, and can generate a 500 Hz model-compatible XML file from 1000 Hz captures.
  • Basic tests that validate XML output, event detection, and downsampling logic without hardware.

What The Capture Script Does

tools/capture_ecg.py is the main desktop script. It:

  1. Sends RATE and START commands to the Arduino over USB serial.
  2. Reads streamed rows in this format:
seq,t_us,raw_adc,lead_off
  1. Converts raw ADC values into baseline-centered microvolt-like ECG digits using the configured AD8232 gain.
  2. Writes a full ECG XML file using an HL7 v3 AnnotatedECG-style structure.
  3. Writes a companion CSV containing key events and quality markers.
  4. Optionally downsamples 1000 Hz captures into a derived 500 Hz XML file for model compatibility.
  5. Can run in --simulate mode without hardware for testing the software pipeline.

The generated XML is intentionally deidentified by default. The example metadata file uses redacted placeholders, and real names, dates of birth, IDs, or clinical diagnoses should not be committed to Git.

How It Works

The Arduino handles only timing and raw sampling:

AD8232 OUTPUT -> Arduino A0 -> USB serial rows

The Python script handles file generation and analysis:

USB serial rows -> samples -> HL7-style XML + events CSV + optional 500 Hz XML

The default XML contains:

  • root element: AnnotatedECG in the HL7 v3 namespace
  • time sequence: TIME_ABSOLUTE
  • Lead I signal sequence: MDC_ECG_LEAD_I
  • waveform values: integer uV digits in SLIST_PQ
  • optional deidentified caseinformation metadata from JSON

The Uno R4 + AD8232 MVP records Lead I only. The sample real ECG files you shared include 12 leads, but this prototype only has one analog ECG channel.

Safety Notice

This MVP is an educational/research prototype only. It is not a medical device and must not be used for diagnosis, monitoring, treatment decisions, or emergency assessment.

When testing on a person, prefer running the laptop on battery power and avoid attaching body-connected circuits to unsafe mains-powered instruments.

Hardware Wiring

AD8232 pin Arduino Uno R4 WiFi pin
3.3V 3.3V
GND GND
OUTPUT A0
LO+ D2
LO- D3

Start with the AD8232 electrode cable or a simple thumb-pad fixture for Lead I. USB serial is the only v0 data link.

Firmware

Open and upload:

firmware/ecg_prototype_uno_r4_ad8232/ecg_prototype_uno_r4_ad8232.ino

Default behavior:

  • Sample rate: 500 Hz
  • ADC resolution: 12 bit
  • Serial baud: 230400
  • Stream format:
seq,t_us,raw_adc,lead_off

Commands can be sent over Serial Monitor or the capture tool:

  • RATE 500
  • RATE 1000
  • START
  • STOP
  • STATUS

Desktop Capture

Install Python dependencies:

py -m pip install -r requirements.txt

Capture 10 seconds at 500 Hz:

py tools/capture_ecg.py --port COM5 --rate 500 --duration 10 --out recordings

Capture 10 seconds at 1000 Hz and also generate a 500 Hz XML file:

py tools/capture_ecg.py --port COM5 --rate 1000 --duration 10 --out recordings --downsample-500

Run without hardware using synthetic ECG-like data:

py tools/capture_ecg.py --simulate --rate 1000 --duration 10 --out recordings --downsample-500

The Uno R4 + AD8232 MVP only records Lead I. The uV values are baseline-centered and divided by an estimated AD8232 front-end gain. The default gain is 1000, which is useful for MVP captures but should be calibrated before clinical or dataset use:

py tools/capture_ecg.py --port COM5 --rate 1000 --duration 10 --front-end-gain 1000 --out recordings

See docs/ad8232_calibration.md for the calibration workflow.

Optional metadata can be added with a JSON file:

py tools/capture_ecg.py --port COM5 --rate 1000 --duration 10 --metadata-json metadata/example_metadata.json --out recordings

Keep patient-identifying values out of Git. The example metadata file uses redacted placeholders.

If you need the original debug XML instead:

py tools/capture_ecg.py --port COM5 --rate 500 --duration 10 --xml-format custom --out recordings

Optional live plot requires matplotlib:

py -m pip install matplotlib
py tools/capture_ecg.py --port COM5 --rate 500 --duration 10 --plot

Outputs

Each capture creates:

  • <recording_id>.xml: full recording as HL7 AnnotatedECG-style XML by default.
  • <recording_id>_events.csv: lead-off, saturation, flatline, noisy segment, R-peak, RR interval, and heart-rate summary events.
  • <recording_id>_500hz.xml: optional model-compatible 500 Hz XML generated from a higher-rate recording.

Example output folder:

recordings/
  ks-20260525T070954Z-5a6c40d4.xml
  ks-20260525T070954Z-5a6c40d4_events.csv
  ks-20260525T070954Z-5a6c40d4-500hz.xml

The event CSV columns are:

recording_id,event_type,t_start_ms,t_end_ms,value,confidence,notes

The most useful early event types are:

  • lead_off
  • saturation
  • flatline
  • noisy_segment
  • r_peak
  • rr_interval
  • heart_rate

Validation

Run tests:

py -m unittest discover tests

If py is unavailable, use the full Python executable path installed on your machine.

The tests use simulated samples, parse the generated XML, validate event CSV rows, and check 1000 Hz to 500 Hz downsampling.

About

Source code for capturing ECG signals using an Arduino UNI R4 and AD8232 ECG sensors.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages