2020-06-22 23:51:06 +02:00
|
|
|
# SPDX-License-Identifier: LGPL-3.0-or-later
|
|
|
|
# Copyright (C) 2020 Daniel Thompson
|
|
|
|
|
2021-01-13 22:51:17 +01:00
|
|
|
"""Heart rate monitor
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
A graphing heart rate monitor using a PPG sensor.
|
|
|
|
|
|
|
|
.. figure:: res/HeartApp.png
|
|
|
|
:width: 179
|
|
|
|
"""
|
|
|
|
|
2020-06-22 23:51:06 +02:00
|
|
|
import wasp
|
|
|
|
import machine
|
2020-06-25 22:59:32 +02:00
|
|
|
import ppg
|
2020-06-24 22:20:18 +02:00
|
|
|
|
2020-06-22 23:51:06 +02:00
|
|
|
class HeartApp():
|
2021-01-13 22:51:17 +01:00
|
|
|
"""Heart rate monitor application."""
|
2020-06-22 23:51:06 +02:00
|
|
|
NAME = 'Heart'
|
|
|
|
|
|
|
|
def foreground(self):
|
|
|
|
"""Activate the application."""
|
|
|
|
wasp.watch.hrs.enable()
|
|
|
|
|
|
|
|
# There is no delay after the enable because the redraw should
|
|
|
|
# take long enough it is not needed
|
|
|
|
draw = wasp.watch.drawable
|
|
|
|
draw.fill()
|
2021-01-03 15:46:47 +01:00
|
|
|
draw.set_color(wasp.system.theme('bright'))
|
2020-06-22 23:51:06 +02:00
|
|
|
draw.string('PPG graph', 0, 6, width=240)
|
|
|
|
|
2020-06-25 22:59:32 +02:00
|
|
|
wasp.system.request_tick(1000 // 8)
|
2020-06-22 23:51:06 +02:00
|
|
|
|
2020-06-25 22:59:32 +02:00
|
|
|
self._hrdata = ppg.PPG(wasp.watch.hrs.read_hrs())
|
2020-06-22 23:51:06 +02:00
|
|
|
self._x = 0
|
|
|
|
|
|
|
|
def background(self):
|
|
|
|
wasp.watch.hrs.disable()
|
2020-06-25 22:59:32 +02:00
|
|
|
del self._hrdata
|
2020-06-22 23:51:06 +02:00
|
|
|
|
2020-06-24 22:20:18 +02:00
|
|
|
def _subtick(self, ticks):
|
2020-06-22 23:51:06 +02:00
|
|
|
"""Notify the application that its periodic tick is due."""
|
2020-06-24 22:20:18 +02:00
|
|
|
draw = wasp.watch.drawable
|
|
|
|
|
2020-06-25 22:59:32 +02:00
|
|
|
spl = self._hrdata.preprocess(wasp.watch.hrs.read_hrs())
|
2020-06-24 22:20:18 +02:00
|
|
|
|
2020-06-25 22:59:32 +02:00
|
|
|
if len(self._hrdata.data) >= 240:
|
2021-01-03 15:46:47 +01:00
|
|
|
draw.set_color(wasp.system.theme('bright'))
|
2020-06-25 22:59:32 +02:00
|
|
|
draw.string('{} bpm'.format(self._hrdata.get_heart_rate()),
|
|
|
|
0, 6, width=240)
|
2020-06-22 23:51:06 +02:00
|
|
|
|
2020-06-25 22:59:32 +02:00
|
|
|
# Graph is orange by default...
|
2020-12-31 20:12:38 +01:00
|
|
|
color = wasp.system.theme('spot1')
|
2020-06-22 23:51:06 +02:00
|
|
|
|
|
|
|
# If the maths goes wrong lets show it in the chart!
|
|
|
|
if spl > 100 or spl < -100:
|
|
|
|
color = 0xffff
|
|
|
|
if spl > 104 or spl < -104:
|
|
|
|
spl = 0
|
2020-06-24 22:20:18 +02:00
|
|
|
spl += 104
|
2020-06-22 23:51:06 +02:00
|
|
|
|
|
|
|
x = self._x
|
|
|
|
draw.fill(0, x, 32, 1, 208-spl)
|
|
|
|
draw.fill(color, x, 239-spl, 1, spl)
|
|
|
|
x += 2
|
|
|
|
if x >= 240:
|
|
|
|
x = 0
|
|
|
|
self._x = x
|
|
|
|
|
|
|
|
def tick(self, ticks):
|
|
|
|
"""This is an outrageous hack but, at present, the RTC can only
|
|
|
|
wake us up every 125ms so we implement sub-ticks using a regular
|
|
|
|
timer to ensure we can read the sensor at 24Hz.
|
|
|
|
"""
|
|
|
|
t = machine.Timer(id=1, period=8000000)
|
|
|
|
t.start()
|
2020-06-24 22:20:18 +02:00
|
|
|
self._subtick(1)
|
2020-06-22 23:51:06 +02:00
|
|
|
wasp.system.keep_awake()
|
|
|
|
|
|
|
|
while t.time() < 41666:
|
|
|
|
pass
|
2020-06-24 22:20:18 +02:00
|
|
|
self._subtick(1)
|
2020-06-22 23:51:06 +02:00
|
|
|
|
|
|
|
while t.time() < 83332:
|
|
|
|
pass
|
2020-06-24 22:20:18 +02:00
|
|
|
self._subtick(1)
|
2020-06-22 23:51:06 +02:00
|
|
|
|
|
|
|
t.stop()
|
|
|
|
del t
|