Skip to content

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ECGFilter

PlatformIO Registry Framework License: MIT

A high-performance, real-time digital signal processing library implementing a 4th-order Infinite Impulse Response (IIR) Butterworth Bandpass Filter. Designed specifically for embedded microcontrollers like the Arduino Uno R4 WiFi (ARM Cortex-M4) to clean up ECG/biopotential waveforms from analog frontends like the AD8232.

This filter completely attenuates low-frequency baseline wander (< 0.5 Hz) caused by respiration and electrode movement, as well as high-frequency muscle artifacts / powerline harmonics (> 40 Hz), yielding a crisp, diagnostic-grade trace ready for QRS feature extraction and BPM calculation.


🚀 Key Features

  • 4th-Order Precision: Aggressive roll-off slope to separate true cardiac vectors from physiological noise.
  • Cascaded Biquad Structure: Implemented using Direct Form I Cascaded Second-Order Sections (Biquads) to prevent numerical rounding errors and maintain absolute floating-point stability.
  • Hardware Accelerated Ready: Perfectly optimized for the Renesas RA4M1 48MHz FPU on the Arduino Uno R4.
  • Deterministic Execution: Ultra-lightweight per-step time complexity (O(1)) makes it highly safe for hardware interrupts and strict real-time loops.

📐 Filter Specification

Parameter Value Description
Sampling Frequency (Fs) 125 Hz Fixed temporal step (8000 μs interval)
Low Cutoff (Fc1) 0.5 Hz Eliminates deep breathing & baseline sway
High Cutoff (Fc2) 40.0 Hz Crushes high-frequency electromyogram (EMG) noise
Passband Ripple 0 dB Flat passband response (Butterworth characteristic)

🛠 Directory Layout

The repository matches the standard PlatformIO Library Manager specification:

ECGFilter/
├── docs/                   # Extended design documentation & transfer functions
├── examples/               # Out-of-the-box working application examples
│   └── basic_filtering/
│       └── basic_filtering.ino
├── src/                    # Embedded source code
│   ├── ECGFilter.cpp
│   └── ECGFilter.h
├── library.json            # PlatformIO metadata configurations
└── README.md               # Library documentation
---

## 📦 Installation

### PlatformIO (Recommended)
Add the library dependency directly to your `platformio.ini` environment configuration:

```ini
lib_deps =
    anuragpanda/ECGFilter @ ^1.0.1

Arduino IDE

  1. Download the latest source package release as a .zip.
  2. Navigate to SketchInclude LibraryAdd .ZIP Library... inside the IDE.

💻 Quick Start & Integration

To achieve accurate digital filtering, the analog frontend must be read at a highly consistent, uniform sampling rate. The example below configures a hardware independent micros-based loop to run precisely at 125 Hz (8000 μs interval).

#include <Arduino.h>
#include <EEGFilter.h>

// Hardware Pin Configuration
const int PIN_EEG_OUT = A0;   // Analog input reading the raw conditioned EEG waveform

// Instantiate the EEGFilter core engine instance
EEGFilter filter;

// Fixed temporal constraint configuration:
// 1,000,000 microseconds / 256 Hz sampling rate = 3,906.25 microseconds per sample step
// We use 3906 microseconds to maintain alignment close to the target interval
const unsigned long TIMESTEP_US = 3906; 
unsigned long scheduledTime = 0;

void setup() {
    // Open high-speed serial pipeline for stable telemetry visualization
    Serial.begin(115200);
    while (!Serial) {
        ; // Pause execution until hardware serial stream synchronizes
    }
    
    // Initialize filter internal delay registers and state structures
    filter.begin();
    
    // Seed initial clock tracking variable
    scheduledTime = micros();
}

void loop() {
    // Strict, jitter-free real-time execution checker via rollover-safe subtraction
    if (micros() - scheduledTime >= TIMESTEP_US) {
        // Increment next step checkpoint execution marker dynamically
        scheduledTime += TIMESTEP_US;

        // Sample the raw instantaneous ADC voltage channel
        int rawADC = analogRead(PIN_EEG_OUT);
        
        // Execute the 4th-order biquad DSP progression step (0.5 Hz - 29.5 Hz)
        float cleanEEG = filter.step(static_cast<float>(rawADC));
        
        // Output space-delimited trace logs directly optimized for Telemetry/Serial Plotters
        Serial.print(rawADC);
        Serial.print(" ");
        Serial.println(cleanEEG);
    }
}

📈 Signal Performance Evaluation

When plotting the raw stream against the filtered stream in your IDE's telemetry view:

  1. Raw Trace ($A_0$ input): Susceptible to sudden diagonal shifting or shifting vertically across the grid window as the patient takes deep breaths.
  2. Filtered Trace (filter.step() output): Stays strictly anchored to a steady horizontal line. The P-waves, QRS complexes, and T-waves emerge perfectly sharpened, with zero phase-shift jitter or noise ripples.

📄 License & Attribution

This project is licensed under the terms of the MIT License. Check out library.json for full distribution details. Developed for reliable biopotential signal conditioning on modern embedded architectures.

About

A high-performance, real-time digital signal processing library

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages