1
0
Fork 0

apps: heart: Implement a debug mode to copy out raw data

Signed-off-by: Daniel Thompson <daniel@redfelineninja.org.uk>
This commit is contained in:
Daniel Thompson 2021-05-05 21:06:39 +01:00
parent 3bbd808115
commit 92812e5ad2
2 changed files with 57 additions and 1 deletions

View file

@ -8,6 +8,28 @@ A graphing heart rate monitor using a PPG sensor.
.. figure:: res/HeartApp.png .. figure:: res/HeartApp.png
:width: 179 :width: 179
This program also implements some (entirely optional) debug features to
store the raw heart data to the filesystem so that the samples can be used
to further refine the heart rate detection algorithm.
To enable the logging feature select the heart rate application using the
watch UI and then run the following command via wasptool:
.. code-block:: sh
./tools/wasptool --eval 'wasp.system.app.debug = True'
Once debug has been enabled then the watch will automatically log heart
rate data whenever the heart rate application is running (and only
when it is running). Setting the debug flag to False will disable the
logging when the heart rate monitor next exits.
Finally to download the logs for analysis try:
.. code-block:: sh
./tools/wasptool --pull hrs.data
""" """
import wasp import wasp
@ -18,6 +40,10 @@ class HeartApp():
"""Heart rate monitor application.""" """Heart rate monitor application."""
NAME = 'Heart' NAME = 'Heart'
def __init__(self):
self._debug = False
self._hrdata = None
def foreground(self): def foreground(self):
"""Activate the application.""" """Activate the application."""
wasp.watch.hrs.enable() wasp.watch.hrs.enable()
@ -32,11 +58,13 @@ class HeartApp():
wasp.system.request_tick(1000 // 8) wasp.system.request_tick(1000 // 8)
self._hrdata = ppg.PPG(wasp.watch.hrs.read_hrs()) self._hrdata = ppg.PPG(wasp.watch.hrs.read_hrs())
if self._debug:
self._hrdata.enable_debug()
self._x = 0 self._x = 0
def background(self): def background(self):
wasp.watch.hrs.disable() wasp.watch.hrs.disable()
del self._hrdata self._hrdata = None
def _subtick(self, ticks): def _subtick(self, ticks):
"""Notify the application that its periodic tick is due.""" """Notify the application that its periodic tick is due."""
@ -87,3 +115,13 @@ class HeartApp():
t.stop() t.stop()
del t del t
@property
def debug(self):
return self._debug
@debug.setter
def debug(self, value):
self._debug = value
if value and self._hrdata:
self._hrdata.enable_debug()

View file

@ -10,6 +10,7 @@ raw PPG signals into something useful.
import array import array
import micropython import micropython
import watch
@micropython.viper @micropython.viper
def _compare(d1, d2, count: int, shift: int) -> int: def _compare(d1, d2, count: int, shift: int) -> int:
@ -94,6 +95,7 @@ class PPG():
def __init__(self, spl): def __init__(self, spl):
self._offset = spl self._offset = spl
self.data = array.array('b') self.data = array.array('b')
self.debug = None
self._hpf = Biquad(0.87033078, -1.74066156, 0.87033078, self._hpf = Biquad(0.87033078, -1.74066156, 0.87033078,
-1.72377617, 0.75754694) -1.72377617, 0.75754694)
@ -106,6 +108,8 @@ class PPG():
Must be called at 24Hz for accurate heart rate calculations. Must be called at 24Hz for accurate heart rate calculations.
""" """
if self.debug != None:
self.debug.append(spl)
spl -= self._offset spl -= self._offset
spl = self._hpf.step(spl) spl = self._hpf.step(spl)
spl = self._agc.step(spl) spl = self._agc.step(spl)
@ -167,4 +171,18 @@ class PPG():
# Clear out the accumulated data # Clear out the accumulated data
self.data = array.array('b') self.data = array.array('b')
# Dump the debug data
if self.debug:
with open('hrs.data', 'ab') as f:
# Re-sync marker
f.write(b'\xff\xff')
now = watch.rtc.get_localtime()
f.write(array.array('H', now[:6]))
f.write(self.debug)
self.debug = array.array('H')
return hr return hr
def enable_debug(self):
if self.debug == None:
self.debug = array.array('H')