Skip to content

easyECG and easyEMG profiles, live vitals readouts (3.4.0) - #26

Merged
awhitchurch merged 17 commits into
mainfrom
add-easy-emg-ecg-boards
Nov 6, 2026
Merged

awhitchurch merged 17 commits into
mainfrom
add-easy-emg-ecg-boards

Conversation

@awhitchurch

Copy link
Copy Markdown
Contributor

Everything in 3.4.0, tested through 3.4.0-rc1 to rc5.

New boards

  • easyECG Breakout (57600 baud, 125 Hz): ECG on a paper grid in mV by default (now neutral grey), heart rate and signal status, unfiltered trace as an optional toggle.
  • easyEMG Breakout (115200 baud, 500 Hz): sEMG and RMS envelope in µV on fixed ±2500 µV and 0–700 µV scales, effort (%MVC), and an MVC tile that shows the sketch's MVC step with a Record MVC button. Needs the easyEMG Arduino library 1.1.0 for the MVC tile.

Live view

  • Large vitals readouts beside the chart for boards whose firmware sends them: easyECG, easyEMG, ADS1292R, AFE4490, Sensything OX and HealthyPi 5. Readings clear after 2 s without events.
  • Readouts can warn above a limit and offer a command button.
  • Channels can start on a fixed Y range instead of auto-fit; each strip clips to its own area.
  • A Performance panel (off by default) for diagnosing bursty data on slower machines.

Build

  • macOS 12.0 is now the minimum (was 10.15), from the Flutter 3.47 migration.
  • Hyphenated tags publish as GitHub pre-releases.

Tests: 110 passing.

Both boards stream through a host running the OpenView example from their
Arduino libraries: USB at 57600 baud, packet type 2, 8-byte payload, 125 Hz.
Those sketches impersonate the ADS1292R profile today, and the wire format is
unchanged, so existing firmware works once the new board is selected.

easyECG plots filtered and unfiltered ECG and reports heartRate and
signalStatus. easyEMG plots sEMG and its RMS envelope and reports percentMvc.

Adds ChannelKind.emg so EMG traces get a real color, live and in replay. It
reuses the EEG color rather than adding a theme token.
Flutter 3.47.7 raised the deployment target from 10.15 to 12.0, and pod install
regenerated Podfile.lock. This drops macOS 10.15 and 11 support, which
release.yml still describes as reaching back to Catalina.
Heart rate and other vitals only appeared as raw `key: value` chips in the
header. Boards can now declare readouts in their descriptor, drawn large beside
the chart or above it on narrow windows.

Readouts are declared only where the firmware was confirmed to send the value:
easyECG, easyEMG, ADS1292R, AFE4490, Sensything Ox and HealthyPi 5. MAX30001,
ADS1293 and Pulse Express have decoder fields their sketches leave empty, and
MAX30003 has no sketch to check, so they stay undeclared.

A value of 0 shows as `--` where firmware uses it for "no reading", heart rate
dims while easyECG reports a signal problem, and readings clear after 2 s
without events so a stalled link can't leave an old value looking live.

easyECG's unfiltered trace is now a toggle, off by default. It is still
buffered and recorded.
Auto-fit stretched every window to the strip height, so the trace had no real
proportions and noise could fill the plot. Channels that declare counts per mV
now use a fixed scale with square boxes, one large box being 0.2 s and 0.5 mV.

The baseline is the window's median, so QRS peaks don't move it. Gain changes
the trace but not the grid. Signals beyond the strip get a warning at the edge
they crossed, and Auto remains available from the live controls.

Only easyECG declares a scale. Its 535 counts per mV comes from the schematic's
design gain, so the view is labelled as a nominal scale. Replay stays on
auto-fit because recordings don't store the scale.
Every v* tag was published as a full release, so an -rc tag would become the
latest release and be offered to users by the in-app update check.
Users on older machines report data arriving in bursts with nothing lost, which
doesn't reproduce on an M4. The panel shows frame rate, build and raster time,
how late the UI thread runs, and the gaps between incoming chunks, with a best
guess at the bottleneck and a report to copy.

It is off by default and only measures while open. It sits on the Live screen
because screens aren't kept mounted, so the chart isn't drawing from anywhere
else.
…sy-emg-ecg-boards

# Conflicts:
#	pubspec.yaml
Matches the 06.OpenView sketch on the library's openview-500hz-highpass branch,
which streams faster so more of the sEMG band reaches the chart.
Auto-fit stretched each easyEMG strip to its own min and max, so a
resting trace filled the same height as a contraction and the two
looked alike. A recording of repeated forearm flexes made that plain.

The decoder now scales sEMG and the envelope to µV at the electrodes
(2.418 µV per count: +/-0.256 V over 2048 counts through x51.7, as in
the Arduino library), so live strips and recordings are in µV.

ChannelSpec gains fixedRange: such a channel starts the live view on
its displayMin..displayMax instead of auto. easyEMG uses it with
+/-2500 µV for sEMG and 0-700 µV for the envelope, which hold the
largest contraction in that recording (2.2 mV peak, 620 µV envelope).

Each waveform strip now clips to its own area, so a value past a fixed
range stays inside its strip instead of drawing over the next one.
The maroon (dark) and pink (light) grid read as orange beside the amber
ECG trace and pulled the eye from it. Use a grey one step above the
plain plot grid instead: #4B565C on dark, #D3D8DB on light, so the large
boxes stay easy to measure from while the small boxes stay faint.
A fluorescent-floor run showed effort at 250-360%: the board had taken
its MVC from a barely tensed arm when the port opened, and nothing on
screen said so.

Readouts can now declare warnAbove, which turns the value to the
warning colour with a short hint, and an action, a command shown as a
button in the tile. MetricsLayout sends actions through onCommand; the
Live screen passes ConnectionController.sendCommand.

easyEMG uses both. Effort above 100% reads "Above your MVC: record it
again". A new MVC tile shows the 06.OpenView sketch's step from byte 6
of each packet (Not recorded, Relax, Contract hard now, Too weak,
Recorded), with a Record MVC button that sends 'm' to run the step
again. Byte 6 needs easyEMG library 1.1.0; older sketches send 0, which
reads as Not recorded.
@awhitchurch
awhitchurch merged commit ac59b30 into main Nov 6, 2026
7 checks passed
@awhitchurch
awhitchurch deleted the add-easy-emg-ecg-boards branch November 6, 2026 12:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant