← Engineering projects

Founder’s featured project / educational prototype

Portable
Biosignal Monitor.

ECG, EMG and optical sensing, integrated into one RP2040 system with a shared display and custom enclosure.

Enclosure design · supplied CAD study

Supplied Fusion 360 study of the biosignal monitor enclosure with openings for the display and sensor
Open original image ↗
Enclosure design study · CAD, not a photograph of the finished device

Read the story: starting problem → process & contribution → results → reflection. The technical guide and files follow.

Three experiments.
One physical system.

The problem

Separate sensors, separate setups.

Exploring ECG, muscle activity and optical sensing usually means managing different signal paths, interfaces and power requirements. This project brings those experiments into one portable prototype.

What it does

A shared interface for three modes.

The application displays an ECG waveform and pulse estimate, an adjustable EMG threshold, and MAX30102 red / infrared readings with a prototype oxygen-saturation estimate.

Eason’s role

Integration, software and enclosure.

The project combines existing sensor modules and software references with application adaptation, physical integration and a Fusion 360 enclosure design.

Current result

A working educational prototype.

The builder reports that the display, controls and all three modes operated successfully. Original code, two STL meshes and the build documentation are available. Accuracy against a medical reference instrument has not been established.

The work behind the device.

Eason Yang’s project work spans integration, application adaptation, enclosure design and debugging. The project uses commercially available modules and existing software references.

01 / System integration

Bring the modules together.

I integrated the STEPico controller, ECG, EMG and optical modules, display and controls into a single prototype. The wiring record follows the application’s GPIO assignments and my recorded supply connections.

02 / Application

Make three modes share one interface.

I adapted the MicroPython application around a shared TFT display, mode button, optical reset and adjustable EMG threshold. The application and dependency files are available for inspection.

03 / Mechanical design

Design around the electronics.

I developed the Fusion 360 enclosure layout around the boards, display, openings and mounting space. Three CAD studies and two original enclosure meshes document this work.

04 / Debugging

Work through the prototype.

I tested the display, controls and three modes. The development record also describes replacing a STEPico after an operating and heating problem.

Built on existing work

STEPico, AD8232, MAX30102, the EMG amplifier, MEGO Dual and ST7789 are existing hardware modules. The application draws on EIM’s biomedical reference code and supplied libraries, fonts and the st7789 display driver. Original file attributions are retained. The contribution is the prototype’s integration and development; reference modules and library code are credited separately.

From breadboard to printed base.

Build photographs document the breadboard wiring, live display and physical enclosure assembly. Eason confirmed that the controls and all three modes operated.

Open the offline photo record →

CheckMethod / evidenceResult and limit
Display, controls & three modesPrior use of the physical prototype, confirmed by the builder on 21 Oct 2026.Eason’s operation check

The test date, detailed procedure and measurement log are not recorded.

Runtime & display driverRecorded Pico Shell output: sys.implementation and import st7789.Recorded output

MicroPython 1.20.0 on RP2040; display import succeeds. The original UF2 image is unavailable.

Optical calculator behaviourHost checks for reset, flat input and complete synthetic waves; separate zero-baseline stress input.Passes with a known edge case

Reset and normal synthetic checks pass; the zero-baseline case raises ZeroDivisionError. This does not measure SpO₂ accuracy.

One documented iteration / August 2025

Replacing a controller restored operation.

  1. Problem

    The build record describes an operating fault and observed heating.

  2. Change

    The STEPico controller was replaced.

  3. Observed result

    The record reports restored operation and no further observed heating. It does not establish the fault’s cause.

This is an educational prototype. EMG conditioning, negative rail voltage and body-connected isolation remain unverified in this record. Read the power and assembly notes →

Reflection & next steps

What the build shows.
What comes next.

The build demonstrates an integrated prototype: three sensing modes sharing a controller, display and enclosure. The controller replacement records a useful debugging result, while leaving the original fault’s cause unresolved.

The next step is a dated demonstration of the controls and screen responses, followed by separately documented checks of measurement accuracy. A future code revision can address the optical calculator’s zero-baseline error.

Recording the original firmware image, enclosure print settings and fastening details would make the build easier for another student to reproduce. The supplied code and design files remain available below.

Continue to the technical record ↓

Build guide / technical documentation

Inspect it.
Reproduce the build.

Start with the module references, then follow the wiring, controller setup and source notes. The complete ZIP includes an offline entry page.

Download complete project ↓v1.2 · 22 Oct 2026 · 6.09 MB

One system, several working parts.

Uploaded CAD module layout — reference assembly, not a photograph of the finished device

Uploaded CAD layout showing STEPico, a display, sensor modules, controls, and the U-shaped power module
Open original image ↗
Uploaded CAD module layout · original image

The modules at a glance.

Product reference photos and details from the supplied screenshots. Each card includes source credit and the original build photograph.

Body1 → MEGO Dual component reference.

The supplied Fusion archive is named “mego dual” and complements the earlier visual match. The connection record routes MEGO +VCC to EMG +VS, and -VEE to -VS. The positive output is reported as +5 V; the negative voltage setting remains unverified.

Part / moduleQty.Role and evidence
STEPico / RP20401CAD label + program

Main controller; ADC, SPI display, software I2C, buttons, and indicator.

ST7789 1.54-inch, 240 × 240 TFT1CAD label + program

Shared display for the three operating modes.

AD8232 ECG breakout1Photograph + CAD label

The photograph identifies the 3.3V, GND and OUTPUT terminals. The program assigns ECG sampling to GP28.

MAX30102 breakout1CAD label + driver import

Red and infrared optical samples over software I2C.

EMG amplifier module1Supplied photograph; chip identity unconfirmed

The board has +VS / GND / -VS power terminals and SIG / GND output terminals. A specific amplifier chip cannot be identified from the photograph.

MEGO Dual power module — Body1 reference1CAD archive supplied; wiring reported by builder

The supplied Fusion archive is named mego dual. The connection record routes +VCC and -VEE to EMG +VS and -VS. The positive output is reported as +5 V; the negative voltage setting is not verified.

Potentiometer1CAD label + program

Adjusts the EMG threshold through GP26. Resistance value is unconfirmed.

Pushbuttons2CAD labels + program

Mode selection and oximeter sampling reset.

Printed enclosure parts2Uploaded STL files

Two original meshes. Print settings, fasteners, and final fit still need a documented build record.

Trace a wire. Find its pin.

Five breadboard-style sheets pair coloured jumper paths with GPIO labels and physical header-pin numbers. Each sheet shows one part of the same system. Module artwork and placement are illustrative; source assignments, builder-reported supplies and proposed additions are labelled separately.

01 / MAX30102 optical sensor

01 / MAX30102 optical sensor

01 / MAX30102 optical sensor. SoftI2C uses GP6 / physical pin 9 for SDA and GP9 / physical pin 12 for SCL. VIN uses 3V3.
Open original image ↗
SoftI2C uses GP6 / physical pin 9 for SDA and GP9 / physical pin 12 for SCL. VIN uses 3V3.
02 / ST7789 SPI display

02 / ST7789 SPI display

02 / ST7789 SPI display. Five display signals follow the application. The dashed GP20 backlight path is proposed and needs software configuration; check the display's printed terminal order.
Open original image ↗
Five display signals follow the application. The dashed GP20 backlight path is proposed and needs software configuration; check the display's printed terminal order.
03 / AD8232 ECG module

03 / AD8232 ECG module

03 / AD8232 ECG module. OUTPUT goes to GP28 / physical pin 34. The 3.3V and GND connections follow the builder's confirmation.
Open original image ↗
OUTPUT goes to GP28 / physical pin 34. The 3.3V and GND connections follow the builder's confirmation.
04 / Potentiometer and buttons

04 / Potentiometer and buttons

04 / Potentiometer and buttons. The wiper uses GP26. GP2 and GP3 each close to GND through a normally-open switch; the source enables internal pull-ups.
Open original image ↗
The wiper uses GP26. GP2 and GP3 each close to GND through a normally-open switch; the source enables internal pull-ups.
05 / EMG and MEGO supply

05 / EMG and MEGO supply

05 / EMG and MEGO supply. MEGO feeds the EMG power terminals. The dashed SIG path marks the pending conditioning and ADC-range check; the negative voltage setting remains unverified.
Open original image ↗
MEGO feeds the EMG power terminals. The dashed SIG path marks the pending conditioning and ADC-range check; the negative voltage setting remains unverified.

Use a shared distribution point for 3V3 and GND when combining the sheets. Match module terminal names to the board’s printed labels. The display sheet arranges its terminal strip for readability; its physical header order still needs confirmation.

Download all five wiring sheets ↓

The GPIO map in the code.

The original overview and source evidence are retained below. GP labels are GPIO numbers. The power diagram records supply connections; the proposed GP20 backlight path is absent from the uploaded program.

Signal assignments reconstructed from the uploaded application

Code-derived signal map for STEPico, ECG, EMG, the potentiometer, optical module, display, buttons and indicator
Open original image ↗
FunctionSignal / GPIOSource and interpretation
ECG analog inputAD8232 OUTPUT (module attribution from CAD)GP28 / ADC2pulse = ADC(28)Source line 38

The ADC assignment is explicit; the physical wire has not been inspected.

EMG analog inputEMG module SIGGP27 / ADC1muscle = ADC(27)Source line 53

The supplied photograph establishes the module's +VS, GND, -VS and SIG labels. Its chip marking is not legible; check output conditioning and range before an ADC connection.

Threshold controlPotentiometer wiperGP26 / ADC0pot = ADC(26)Source line 54

The potentiometer adjusts the software threshold. The builder reports 3V3 and GND supply connections for the modules other than EMG.

Display clockST7789 SCL / SCKGP10SPI(1, ... sck=Pin(10))Source line 31

SPI clock. The display's SCL label is not an I2C connection in this program.

Display dataST7789 SDA / MOSIGP11SPI(1, ... mosi=Pin(11))Source line 31

SPI data into the display; no display MISO is specified.

Display chip selectST7789 CSGP13cs=Pin(13, Pin.OUT)Source line 32

SPI1 is requested at 40 MHz with polarity=1 and phase=1.

Display data / commandST7789 DCGP14dc=Pin(14, Pin.OUT)Source line 32

Control signal.

Display resetST7789 RES / RSTGP15reset=Pin(15, Pin.OUT)Source line 32

The program does not assign a backlight pin.

Oximeter dataMAX30102 SDAGP6SoftI2C(sda=Pin(6), ...)Source line 72

Software I2C, requested at 400 kHz. Keep this assignment when using this source.

Oximeter clockMAX30102 SCLGP9SoftI2C(... scl=Pin(9), ...)Source line 72

This is the uploaded SoftI2C configuration, rather than a generic hardware-I2C pin pair.

Mode buttonNormally-open pushbuttonGP2Pin(2, Pin.IN, Pin.PULL_UP)Source line 17

The code expects a high-to-low transition. Closing the switch to GND is the intended active-low arrangement.

Oximeter reset buttonNormally-open pushbuttonGP3Pin(3, Pin.IN, Pin.PULL_UP)Source line 70

A low input resets the red/IR calculation buffers; this does not establish medical calibration.

RGB indicatorSTEPico on-board LED chainGP23rgb_pin = Pin(23)Source line 63–64

The source addresses one NeoPixel. No external LED connection is inferred.

Supply and analog verification

Standard RP2040 ADC inputs use a 0–3.3 V range. Check the EMG output range and conditioning before connecting it to GP27. Amplifier supply voltage does not establish a compatible ADC signal range. The builder’s power connections are recorded below; the analog conditioning and isolation arrangement still need a bench check.

This is a bench-level educational reference. Body-connected use requires a separately checked, isolated measurement setup and qualified supervision.

Follow the reported connections.

The builder confirms STEPico 3V3 and GND for the modules other than EMG. The EMG supply path follows the connection record. GP20 is an optional backlight assignment selected for this guide; it is not configured in the uploaded application.

Power reference — builder-reported connections, with unverified settings labelled

Reported power connections from STEPico 3V3 and GND to the ECG module, optical breakout, display and potentiometer, with a separate MEGO supply for EMG
Open original image ↗
ModuleSupply connectionGround and evidence
AD82323.3V → STEPico 3V3GND → STEPico GND

Builder confirmation + photographed pin labels

MAX30102 breakoutVIN → STEPico 3V3GND → STEPico GND

Builder confirmation + photographed pin labels

ST7789 displayVCC → STEPico 3V3GND → STEPico GND

Builder confirmation

PotentiometerOuter terminals → STEPico 3V3 and GND; wiper → GP26Common STEPico GND

Builder supply confirmation; GP26 from source

EMG module+VS → MEGO +VCC; -VS → MEGO -VEEPower GND → MEGO GND; signal GND → STEPico GND

Builder connection record; positive output reported +5 V, negative voltage unverified

Display backlight — proposedBL → GP20; requires matching software configurationCommon STEPico GND

Optional assignment selected for this guide; not present in the uploaded program

Build a record as you assemble.

  1. Check the mechanical references

    Open both enclosure meshes and compare the board positions with the CAD layout. Use the MEGO archive as a component reference. Verify STL scale in the slicer.

  2. Prepare the enclosure

    Record the material, print orientation, settings, fasteners and clearances used for the actual build. These details are not established by the supplied meshes.

  3. Place the modules

    Use the photographs to identify connectors and pin labels. Plan access to USB-C, the display, controls and sensor connectors before securing the boards.

  4. Trace the power paths

    Follow the reported 3V3 and common GND connections. Keep the separate EMG supply path clearly labelled and check analog output conditioning and range.

  5. Connect the signal pins

    Follow the source GPIO table. MAX30102 uses SoftI2C on GP6 / GP9. GP2 selects the mode; GP3 resets the optical calculation buffers.

  6. Keep the operating record

    The builder reports prior successful tests of the display, controls and all three operating modes. The current record includes MicroPython 1.20.0 and a successful st7789 import.

A documented debugging observation

The supplied August 2025 build log reports that replacing the STEPico restored operation and stopped the observed heating. The cause of the earlier fault was not established.

Set up the controller.

Follow these six steps for a new board. A board already running compatible MicroPython with st7789 can continue at step 5. The workflow adapts the manufacturer’s STEPico guide to this project’s display driver and Python files.

Recorded working environment

The builder’s Shell reports MicroPython 1.20.0 on RP2040 and successfully imports st7789. The builder confirms earlier hardware tests passed. The original firmware image is unavailable; the supplied files listed below do not identify that image.

  1. 1. Prepare Thonny and USB

    Install Thonny from thonny.org. Connect STEPico with a USB-C data cable.

  2. 2. Choose the firmware

    Use an RP2040 / Raspberry Pi Pico build that provides the st7789 display driver. The builder’s working board reports MicroPython 1.20.0; the exact original firmware image is unavailable. The driver project provides precompiled RP2 firmware as an upstream reference.

  3. 3. Enter BOOT mode

    Hold BOOT, press and release RUN, then release BOOT. Alternatively, hold BOOT while plugging in USB. A drive named RPI-RP2 should appear.

  4. 4. Transfer the UF2 image

    Drag the compatible .uf2 file onto RPI-RP2. STEPico restarts and the drive disappears. This installs the runtime; Python files are transferred through Thonny afterwards.

  5. 5. Connect the interpreter

    In Thonny, select the MicroPython Raspberry Pi Pico / RP2040 interpreter and the board’s serial port. Open the Shell. For a new installation, import st7789 to confirm that the display driver is available.

  6. 6. Copy and start the project

    Extract application-source.zip. In Thonny’s Files view, copy the four root Python files and the max30102 folder to the device root, preserving both files inside that folder. Open main.py and choose Run current script (F5).

Firmware installs the board’s runtime. main.py and its libraries are copied into that runtime’s filesystem. On a fresh board, the upstream st7789 project’s precompiled RP2 build is a driver-inclusive reference; it has not been confirmed as the builder’s original image.

Keep these paths intact.

Path on PicoPurpose
main.pyProject application
SpO2Calculators.pySupplied calculator with reset()
vga1_16x16.py16 × 16 display font
vga1_8x8.pyFont imported at startup
max30102/__init__.pyOptical sensor driver
max30102/circular_buffer.pyDriver buffer dependency
Supplied firmware references

Internal version strings and UF2 block structure were inspected. These files are not the current board’s reported 1.20.0 image, and their display-driver compatibility has not been established. They are recorded as references and are not bundled as project firmware.

Supplied filenameInternal version
RPI_PICO-20250415-v1.25.0.uf21.25.0
RPI_PICO-20250809-v1.26.0.uf21.26.0
RPI_PICO-20260824-v1.29.0.uf21.29.0

Understand the three modes.

MODE 0 / ECG

Waveform & pulse estimate

Reads GP28, draws a trace, and estimates BPM from threshold crossings in a ten-second window.

MODE 1 / EMG

A threshold you can adjust

Reads GP27 and compares it with the potentiometer on GP26. The source’s displayed voltage scale needs review.

MODE 2 / OPTICAL

Red and infrared samples

Reads MAX30102 over software I2C. GP3 resets the calculation buffers; GP23 drives the on-board indicator.

Six files, ready to inspect.

The source ZIP now contains main.py, the latest supplied SpO2Calculators.py, the MAX30102 package and both fonts. File contents are unchanged; names and directories match the program’s imports. The Pico reports MicroPython 1.20.0 on RP2040. The supplied Shell output confirms that st7789 imports successfully, and the builder reports prior hardware tests passed.

  • st7789The Pico reports MicroPython 1.20.0 on RP2040, and the supplied Shell output confirms import st7789 succeeds. The original firmware image was not supplied; no firmware is bundled.
  • max30102Both __init__.py and circular_buffer.py are included unchanged in the max30102 directory. The newly supplied buffer matches the earlier copy.
  • SpO2Calculators.pyThe latest device copy includes reset() and a guard for incomplete cycles. Constructor, reset and synthetic-wave checks pass on the host; zero-denominator handling still needs work.
  • vga1_16x16.pyIncluded unchanged. The 16 × 16 font imported as myfont.
  • vga1_8x8.pyIncluded unchanged. Imported at startup even though font8 is not used later in this source.

The latest calculator includes reset() and an incomplete-cycle guard. Host checks pass for reset, flat input and complete synthetic waves. A zero-baseline stress check still raises ZeroDivisionError. The buffer’s pop_head() issue lies outside this application’s current pop-from-storage read path. The builder reports successful prior operation of the display, controls and all three modes. The host stress finding is retained as an edge case for a future code revision.

Copy the files to the Pico

Extract the ZIP and preserve its directory structure. The five root entries are main.py, SpO2Calculators.py, vga1_16x16.py, vga1_8x8.py and the max30102 folder, which contains __init__.py and circular_buffer.py. Use Thonny’s Files view to copy them to the device root after preserving the existing device files.

The builder’s Pico returns <module 'st7789'> when importing the display driver. For a fresh Pico, the Python source ZIP requires a compatible runtime with this driver available. A .uf2 file is a board firmware image, installed separately from the Python application; the builder’s original image has not been supplied.

Notes from the uploaded source

  • The EMG calculation divides read_u16() by 30000. The standard full-scale mapping uses 65535, so its displayed “voltage” should be treated as a prototype scale until checked.
  • The optical estimate has not been validated against a reference instrument in this release. The reset button restarts the calculations.
  • No servo or PWM output is implemented in the uploaded program.
  • The application reports a missing optical sensor at startup; complete recovery behaviour is not established.

The supplied source is preserved unchanged. Hardware test status is recorded from the builder’s confirmation.

Take the files with you.

Source release · 22 Oct 2026 · original application, supplied fonts and meshes, MEGO reference CAD, and documented signal and power connections.

Everything in one ZIP

Download the complete project.

Code, supplied libraries, both STL meshes, MEGO reference CAD, five wiring sheets, module and build photographs, and offline tutorials in one ZIP. Extract it and open START_HERE.html.

Version 1.2Updated 6.09 MB
Code

Application & supplied libraries

Six unchanged Python files: main.py, the latest supplied calculator, the MAX30102 package and both fonts, arranged for copying to the Pico. The display driver imports successfully; the builder reports prior hardware tests passed.

ZIP · 6 Python files · 12.9 KBDownload ↓
CAD & design

Enclosure print files

Both original meshes: ECG_Part_1.stl and ECG_Part_2.stl. Check model scale, orientation, clearances, and slicer settings before printing.

ZIP · 2 STL meshes · 109.1 KBDownload ↓
Build notes

Pictorial wiring guide

Five breadboard-style sheets with coloured jumper paths, GPIO and physical pin numbers, and labelled module terminals. Includes SVG and PNG versions with an offline index.

ZIP · 5 wiring sheets · 583.0 KBDownload ↓
Build notes

Code-derived signal map

A labelled SVG showing the program's GPIO assignments. Supply paths are documented in the separate power map; EMG output conditioning still needs verification.

SVG · scalable diagram · 7.5 KBDownload ↓
Build notes

Reported power connections

STEPico 3V3 and common GND connections, plus the separate MEGO-to-EMG supply path. Reported wiring is distinguished from the optional backlight assignment.

SVG · scalable diagram · 6.6 KBDownload ↓
CAD & design

MEGO Dual reference CAD

The supplied Fusion archive for the power module, preserved unchanged. This is a component reference, not the complete enclosure assembly.

F3Z · Fusion archive · 443.8 KBDownload ↓
Build notes

STEPico setup guide

Six manufacturer-based steps for a new board: Thonny, driver-compatible firmware, BOOT / RUN, UF2 transfer, interpreter selection and the six project files. Includes the recorded working environment and supplied firmware references.

HTML · printable setup steps · 6.8 KBDownload ↓
Build notes

Build and dependency notes

A printable guide to the module photographs, pictorial wiring sheets, source assignments, dependencies, and remaining checks.

HTML · printable guide · 35.6 KBDownload ↓