This project is a blood pressure analysis system produced for a Digital Signal Processing course, using the LilyGO T-Display-S3 ESP32 board. It actuates a small air pump and air valve solenoid via MOSFET drivers and microcontroller control. The system features a real-time graph of pressure values displayed on the onboard TFT, as well as compile-time options to include serial debugging and a special "hi-speed" mode which disables the TFT update while logging.
Note: This is an academic project and is not intended to replace real medical equipment. This is not a professionally developed or built device and should not be used to make any assessment of health or otherwise be used to diagnose medical conditions.
- Pressure Monitoring: Reads pressure values from a Sparkfun Qwiic Micropressure module using I²C protocol.
- Pressure Control: Uses a solenoid valve to open and close valves and pressurizes an arm cuff to 200 mmHg.
- Real-Time Graphing: Displays pressure readings over time on the TFT display.
- Status Indicators: Shows current solenoid status (ON/OFF) and pressure value, as well as timestamp and loop duration (sample time).
- Self Calibrating: A robust calibration algorithm adjusts to atmospheric pressure, and can be recalibrated any time.
Blood pressure is an important biometric widely used in the healthcare and medical device industry. Systolic pressure is a measure of the force of blood flow as it is pumped out of the heart. Diastolic pressure is a measure of the blood pressure in between heartbeats, while the heart is filling with blood. Measurement of these values is typically measured by ear using a sphygmomanometer. The typical procedure is to pressurize the subject's arm cuff to a high pressure, typically 180-200 mmHg for the average adult, and then to slowly release pressure until the pulse is detectable (systolic), noting this value, and then continuing to release pressure until the pulse is no longer detectable (diastolic). Many devices exist which automatically perform this procedure, some of which measure these values during the pressurization stage. This procedure is an ideal project to develop for applications in digital signal processing.
- Microcontroller:
- Pressure Sensor:
- DC Air Pump:
- Any 4.5V 1-3 LPM DC air pump (e.g., Adafruit Air Pump And Vacuum Dc Motor - 4.5 V And 2.5 Lpm - Zr370-02pm).
- Air Solenoid Valve:
- Any 3-6V solenoid valve (e.g., DFRobot DFR0866).
- Power Supply:
- 5V USB power supply for the LilyGO board.
- Other Components:
- Level shifter or MOSFET (e.g., IRLB3813, IRLZ44N) for solenoid control.
- A blood-pressure cuff and related fittings, as necessary (this will depend primarily on selected components).
Component | LilyGO Pin | Notes |
---|---|---|
Pressure Sensor Signal (I²C) | GPIO44 (SCL) | Connect sensor SCL to SCL pin. |
Pressure Sensor Signal (I²C) | GPIO43 (SDA) | Connect sensor SDA to SDA pin. |
Solenoid Control | GPIO21 | Use a MOSFET to drive the solenoid. |
Pump Control | GPIO16 | Use a MOSFET to drive the pump. |
- Install PlatformIO in your shell of choice, or use the VS Code extension.
git clone https://github.com/Jbsco/esp-bp
cd esp-bp
- In
src/main.cpp
edit compile-time defines to use different pins or select option debug or hi-speed modes:
// Enable/disable serial debug output
#define SERIAL_DEBUG_OUTPUT 1
#define HI_SPEED_DEBUG 1
#define PIN_BAT_VOLT 4
// Solenoid & pump pins
// To gates of IRLB3813PbF FETs or similar
#define SOLENOID_PIN 21 // GPIO pin to control pressure solenoid
#define DRIVER_PIN 16 // GPIO pin to control pump driver
Connect the board and run the following in PlatformIO:
pio run --target upload
Monitor directly in the terminal with:
pio run --target monitor
- Connect all hardware as per the wiring table.
- Power on the system.
- Monitor the real-time graph and solenoid status on the TFT display.
- Use the serial monitor (baud: 115200) for debugging.
- Use the MATLAB script to perform analysis directly.
- Adjust debug modes as needed and re-flash.
- Calibrate the pressure sensor with the programmed procedure.
- Simply press button 2. The system will release pressure and wait for the difference between consectutive measurements to be less than 0.01 mmHg 50 times. After this, 100 measurements are averaged. All pressure readings will have this value subtracted, and readings will be relative to atmospheric pressure.
PXL_20250408_1844513842.mp4
MATLAB:
The included MATLAB script can begin pressurization as well as process data over serial. This is most effective when using the hi-speed debug mode, as sample rates nearly double when skipping TFT updates. The loop time is around 6ms in this mode, so sampling is fast and data is improved. The script plots the pressure run, performs an FFT, applies a band-pass filter and adds another plot/FFT, then applies a narrower band-pass and ands a final plot/FFT. The Q-factor of the second FFT is also determined and used as a factor to relax thresholding, which is used to determine systolic and diastolic pressure output to the console. In the majority of cases, the subject's pulse is clearly visible after filtering, and the output values are close to results from a reference device. Future improvements will include improvement to the dynamic thresholding pipeline to improve accuracy of systolic and diastolic pressure output.
Some Linux installations of MATLAB may encounter a lock file error for ttyACM0. A shell script is provided to temporarily resolve this issue by creating the required file with permissions to allow MATLAB to proceed. It runs the following commands:
sudo touch /run/lock/LCK..ttyACM0
sudo chgrp $USER /run/lock/LCK..ttyACM0
sudo chown $USER /run/lock/LCK..ttyACM0
The script uses ttyACM0 as the default argument, but can take other ports as the argument instead.
The system was compared with a typical battery-operated system to check accuracy. It should be noted that automated devices may not be accurate themselves. Generally, the performance is expected to be similar, within 10mmHg or so.
Run 1:
Output:
Diastolic: 79.084
Systolic: 138.463
Run 2:
Output:
Diastolic: 82.020
Systolic: 133.168
Run 3:
Output:
Diastolic: 82.768
Systolic: 120.599
The system design and measurement method was sufficient to make accurate recordings of blood pressure to record systolic and diastolic values. Filtering of the recorded signal was very effective at isolating heart rate. Processing this data could be refined further. Detrend strategies were tested alongside FFT and filtering, but thresholding proved to be a more immediately accessible method to determine systolic and diastolic values. Not all values were observed to be in agreement with the reference device. Run #3 systolic pressure was the furthest from what was observed on the reference device, but generally most values were within single-digit ranges. Further testing on subjects with a wider range of resting heart rate is needed before further adjustment to the calculation and processing, as resting heart is known to vary between subjects and over the course of a day. This repository will continue to be maintained as a resource for other engineering students working with embedded systems or in biomedical fields.
- Test additional subjects with a wider range of resting blood pressure, and refine calculation and processing algorithm.
- Extend to any other possible control outputs.
- Translate MATLAB analysis to Python.
- Implement processing pipeline onboard ESP32.
- https://github.com/sparkfun/SparkFun_MicroPressure_Arduino_Library
- https://www.sparkfun.com/sparkfun-qwiic-micropressure-sensor.html
- https://registry.platformio.org/libraries/sparkfun/SparkFun%20MicroPressure%20Library
- Dr. Talles Santos, Univeristy of Colorado Boulder
- Confluence Hall Labs - Colorado Mesa University