MAX30001G 1.4.2
Arduino library for MAX30001G ECG and BIOZ AFE
Loading...
Searching...
No Matches
Maxim 30001 Arduino Library

This is the MAX30001 library for Arduino. It attempts to be complete and supports impedance spectroscopy.

This library has been validated for ECG, continuous BIOZ, combined ECG+BIOZ, internal calibration paths, and the nonblocking BIOZ scan flow that is driven through setup...(), start(), and repeated update().

Impedance Spectroscopy

This library and example programs enable impedance spectroscopy, reporting impedance magnitude and phase versus modulation frequency.

Internal 1 kOhm resistor scan validation works across the full 128 kHz down to 125 Hz scan range.

External fixture validation was completed over the 1024 to 131072 Hz modulation range.

External scan output uses the cosine fit to estimate complex impedance magnitude and phase.

Uncorrected cosine-fit magnitude is underestimated, so a calibration model was developed. The selected first correction is a simple global magnitude scale with K = 1.25065.

The external BIOZ scan can report a provisional reliability score with each corrected spectrum point:

3 validated region
2 near boundary
1 questionable
0 outside validated region
Corrected magnitude 1024 Hz 2048 Hz 4096 Hz 8192 Hz 18204 Hz 40960 Hz 81920 Hz 131072 Hz
<20 ohm 1 1 1 1 1 1 1 1
20 ohm - 5 kOhm 3 3 3 3 3 3 3 3
5 kOhm - 10 kOhm 3 3 3 3 3 3,2 3,1 3,1
10 kOhm - 33 kOhm 3 3 3 3 1 1 1 1
33 kOhm - 50 kOhm 3 3 3 1 1 1 1 1
50 kOhm - 100 kOhm 2 2 1 1 1 1 1 1
100 kOhm - 150 kOhm 1 0 0 0 0 0 0 0
>150 kOhm 0 0 0 0 0 0 0 0

Phase downgrade rules for marked cells:

  • 3,2: if abs(phase_deg) >= 20, then r = 2; otherwise r = 3.
  • 3,1: if abs(phase_deg) >= 25, then r = 1; otherwise r = 3.

Installation

Install the library in Arduino IDE or clone the GitHub repository into your Arduino libraries folder.

Dependencies

This driver depends on

Documentation

Hardware with MAX30001G

Quick Start

Using Arduino-style setup() / loop() with setup + start/update/stop:

#include <Arduino.h>
#include "max30001g.h"
#include "logger.h"
const uint8_t AFE_CS_PIN = 10; // SPI chip select pin
const int AFE_INT1_PIN = 2; // AFE INTB interrupt
const int AFE_INT2_PIN = -1; // AFE INT2B optional
MAX30001G afe(AFE_CS_PIN, AFE_INT1_PIN, AFE_INT2_PIN);
bool measurementRunning = false; // Global status
void setup() {
// LOG_LEVEL_DEBUG through LOG_LEVEL_NONE
logSetLevel(LOG_LEVEL_DEBUG);
Serial.begin(115200); // Baudrate, up to 921600 for ESP
afe.begin();
// Configure for ECG and BIOZ
afe.setupECGandBIOZ(
1, 2, true, // ECG: speed=256sps, gain=80V/V, 3-lead
0, 1, // BIOZ: speed=~25..32sps, gain=20V/V
1, 0, // BIOZ: DLPF=4Hz, DHPF=bypass
8000, 8000, 0.0, // BIOZ: frequency=8kHz, current[nA], phase[deg]
true, false, false // leadbias=enabled, leadsoffdetect=off, bioz fourleads=false
);
}
void loop() {
// PSEUDO CODE: replace with your own user-action logic.
bool userRequestedStart = /* e.g., UI/event says "start" */ false;
bool userRequestedStop = /* e.g., UI/event says "stop" */ false;
if (userRequestedStart && !measurementRunning) {
afe.start();
measurementRunning = true;
}
if (userRequestedStop && measurementRunning) {
afe.stop();
measurementRunning = false;
}
if (!measurementRunning) {
return;
}
// Service IRQs and drain FIFOs.
if (afe.update()) { // Check for pending interrupts and service them
float value = 0.0f;
// Print all new ECG samples collected during update().
while (ECG_data.available() > 0) {
ECG_data.pop(value);
Serial.print("ECG [mV]: ");
Serial.println(value, 3);
}
// Print all new BIOZ samples collected during update().
while (BIOZ_data.available() > 0) {
BIOZ_data.pop(value);
Serial.print("BIOZ [ohm]: ");
Serial.println(value, 3);
}
// Print all new RTOR samples collected during update().
while (RTOR_data.available() > 0) {
RTOR_data.pop(value);
Serial.print("RR [ms]: ");
Serial.println(value, 1);
if (value > 0.0f) {
Serial.print("HR [bpm]: ");
Serial.println(60000.0f / value, 1);
}
}
}
}
MAX30001G device driver class used by Arduino sketches.
Definition max30001g.h:34
RingBuffer< float, 16 > RTOR_data
Definition max30001g_globals.cpp:15
RingBuffer< float, 128 > BIOZ_data
Definition max30001g_globals.cpp:14
RingBuffer< float, 128 > ECG_data
Definition max30001g_globals.cpp:13

BIOZ spectroscopy uses the same configure/start/update lifecycle, but setupBIOZScan(...) only configures the scan. Call start() once, then keep calling update() until a spectrum becomes available in BIOZ_spectrum.

Main Sketch

The sketch that reflects the latest driver organization most closely is examples/MAX30001G_BLESerial_Display_Sleep/MAX30001G_BLESerial_Display_Sleep.ino.

It is an interactive USB serial and BLE Serial utility for exercising the current driver layers, switching modes, applying settings, running health checks, and validating scan/calibration flows from one sketch. The USB-only variant is examples/MAX30001G/MAX30001G.ino.

When you open the USB serial monitor or connect over BLE Serial and type ?, the sketch prints this help menu:

================================================================================
| MAX30001G ECG and Bio-Impedance Program |
| 2026 Urs Utzinger & GPT |
================================================================================
| GENERAL COMMANDS | DATA COMMANDS |
|----------------------------------------|-------------------------------------|
| ?: help screen | z: toggle data reporting on/off |
| s: show current settings | z[s|b|a]: USB, BLE, both, off |
| a: apply current settings (re-setup) | |
| h: run health check | z[S|B|A]: USB, BLE, both, on |
| i: print device info | c: reset sample counter |
| r: print all registers | f: FIFO reset |
| t: print status registers | |
| p: print config registers | |
| x: reboot | |
================================================================================
| PERSISTENCE | RAM SNAPSHOT |
|----------------------------------------|-------------------------------------|
| Ps: save NVS preferences | (: save volatile register snapshot |
| Pl: load NVS preferences | ): restore volatile register snap |
| Pd: print NVS preferences | |
| Pc: clear NVS preferences | |
|========================================|=====================================|
| OPERATION MODES (auto-stop previous) | START/STOP |
|----------------------------------------|-------------------------------------|
| m1: ECG mode | .: toggle start/stop |
| m2: BIOZ mode | >: start measurement |
| m3: ECG + BIOZ mode | <: stop measurement |
| m4: ECG signal calibration | |
| m5: BIOZ signal calibration | |
| m6: BIOZ internal impedance | |
| m7: BIOZ external impedance | |
| m8: BIOZ impedance spectroscopy | |
|========================================|=====================================|
| ECG SETTINGS | BIOZ SETTINGS |
|----------------------------------------|-------------------------------------|
| Es<n>: speed (0-2) Es1 | Bs<n>: speed (0-1) Bs0 |
| Eg<n>: gain (0-3) Eg2 | Bg<n>: gain (0-3) Bg1 |
| El<n>: dig LPF (0-3,255) El255 | Ba<n>: analog HPF (0-7) Ba1 |
| Eh<n>: dig HPF (0-1,255) Eh255 | Bd<n>: digital LPF(0-3) Bd1 |
| Ee<n>: leads (2 or 3) Ee3 | Bh<n>: digital HPF(0-3) Bh0 |
| Er<n>: R-to-R (0=off,1) Er1 | |
| En<n>: notch (0=off,50,60) En0 | Bf<n>: frequency Hz Bf8000 |
| Eq<n>: notch Q (1-100) Eq20 | Bc<n>: current nA Bc8000 |
| | Bp<n>: phase deg Bp0 |
| | Bl<n>: lead bias (0=off,1) Bl1 |
| | Bo<n>: lead-off (0=off,1) Bo0 |
| | Bw<n>: wires (2 or 4) Bw2 |
|========================================|=====================================|
| BIOZ SCAN SETTINGS | INTERNAL CALIBRATION SETTINGS |
|----------------------------------------|-------------------------------------|
| Sa<n>: averages (1-8) Sa8 | Cr<n>: internal resistor Cr1000 |
| Sf<n>: fast mode (0=off,1) Sf0 | Cm<n>: cal modulation(0-3) Cm0 |
| Sr<n>: full range (0=off,1) Sr0 | Cf<n>: mod frequency(0-4) Cf3 |
| Si<n>: source (0=ext,1=int) Si0 | Ce<n>: ECG sig mode(0/1) Ce1 |
| Sp<n>: phase rng (0=full,1) Sp0 | Cb<n>: BIOZ sig mode(0/1) Cb0 |
| Sh<n>: AHPF mode (0=dyn,1=fix,2=byp) |-------------------------------------|
| Sv<n>: fixed AHPF (0-7) Sv1 | |
| Sx<n>: int AHPF (255,0-7) Sx255 | |
| St<n>: settle (1-64) St24 | Sm<n>: max current nA Sm96000 |
| Sc<n>: cur settle (1-64) Sc24 | So<n>: autorange (0=off,1) So1 |
| | Sy<n>: human-safe (0/1) Sy0 |
|----------------------------------------|-------------------------------------|
| Kp: print scan calibration | Kr: reset scan calibration default |
| Kg<n>: set global K ppm (1250650) | Ke<n>: enable correction (0/1) |
|========================================|=====================================|
| LOG LEVEL | SPECIAL |
|----------------------------------------|-------------------------------------|
| l0: debug (verbose) | w: AFE software reset |
| l1: info (default) | y: AFE synchronize |
| l2: warnings | k: AFE clear latched status flags |
| l3: errors only | |
| l4: critical only | |
| l5: none (silent) | |
================================================================================
Examples:
m1 - Switch to ECG mode
Eg3 - Set ECG gain to 160 V/V (level 3)
Bf40000 - Set BIOZ frequency to 40 kHz
. - Start/stop measurement
z - Toggle continuous data display

Example Sketches

**examples/MAX30001G_BLESerial/MAX30001G_BLESerial_Display_Sleep.ino** and **examples/MAX30001G/MAX30001G.ino**: interactive serial test program covering all options of the software including mode switches, setup helpers, calibration, scan control, and register inspection.

The BLESerial version allows wireless access to the device. You can use BLESerial in SerialUI.

The other maintained example sketches match the current driver structure:

  • examples/ECG/ECG.ino: continuous ECG using setupECG(...), start(), and repeated update()
  • examples/BIOZ/BIOZ.ino: continuous fixed-frequency BIOZ using setupBIOZ(...)
  • examples/ECGandBIOZ/ECGandBIOZ.ino: simultaneous ECG and BIOZ using setupECGandBIOZ(...)
  • examples/BIOZScan/BIOZScan.ino: external nonblocking BIOZ spectroscopy using setupBIOZScan(...)
  • examples/BIOZScan_Internal/BIOZScan_Internal.ino: internal-resistor scan validation using the same scan-owned state machine
  • examples/BIOZScan_Internal_Fast/BIOZScan_Internal_Fast.ino: fast reduced-phase internal-resistor full-spectrum validation
  • examples/Hardware_HealthCheck/Hardware_HealthCheck.ino: startup communication and hardware checks
  • examples/ECG_FIFOInterruptValidation/ECG_FIFOInterruptValidation.ino: ECG FIFO interrupt and ECG_data validation
  • examples/BIOZ_FIFOInterruptValidation/BIOZ_FIFOInterruptValidation.ino: BIOZ FIFO interrupt and BIOZ_data validation
  • examples/ECGandBIOZ_FIFOInterruptValidation/ECGandBIOZ_FIFOInterruptValidation.ino: combined FIFO drain validation
  • examples/BIOZ_Internal_ImpedanceCalibration/BIOZ_Internal_ImpedanceCalibration.ino: internal BIST point measurements outside the scan flow
  • examples/BIOZ_External_ImpedanceCalibration/BIOZ_External_ImpedanceCalibration.ino: external known-load impedance calibration
  • examples/BIOZ_SignalCalibration/BIOZ_SignalCalibration.ino and examples/ECG_SignalCalibration/ECG_SignalCalibration.ino: internal signal-generator calibration paths

Contributing Authors

  • Urs Utzinger, 2025-2026
  • OpenAI Codex, 2025-2026

License

See LICENSE.

Agentic Code Modification

Read Validation.md, Refactor.md, and examples/MAX30001G/MAX30001G.ino first. Then start your agentic programming session.

Block Diagram of MAX30001G

The MAX30001G is a highly integrated analog front end that consists of a differential ECG channel with optional right-leg drive. It employs standard high-pass and low-pass filters, an instrumentation amplifier, and an analog-to-digital converter.

The impedance unit consists of a current driver, analog high-pass filter, and phase-shifted demodulator to measure impedance from 128kHz down to 125Hz modulation frequency at varying phase shifts. Internal-BIST validation shows coherent full-spectrum scans with dynamic AHPF selection. External fixture validation supports a magnitude-corrected cosine-fit scan model for the validated low/moderate impedance region, while high-frequency/high-impedance measurements should be interpreted using the reported reliability score.

Input MUX ECG

Besides ESD protection, the input MUX can detect lead-off and lead-on conditions. In addition, it can switch input electrode polarity and correct common-voltage bias on the subject. Input can be turned off and replaced with an internal signal generator for testing purposes.

Input MUX BIOZ

Similar to the ECG input MUX, the BIOZ input MUX has ESD protection as well as lead-on and lead-off detection. Besides input signal calibration, a programmable resistor can be measured internally as simulated impedance.