141 lines
4.7 KiB
Python
141 lines
4.7 KiB
Python
# SPDX-FileCopyrightText: 2020 John Park for Adafruit Industries
|
|
#
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
"""
|
|
Heart Rate Trainer
|
|
Read heart rate data from a heart rate peripheral using the standard BLE
|
|
Heart Rate service.
|
|
Displays BPM value and percentage of max heart rate on CLUE
|
|
"""
|
|
|
|
import time
|
|
from adafruit_clue import clue
|
|
import adafruit_ble
|
|
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
|
|
from adafruit_ble.services.standard.device_info import DeviceInfoService
|
|
from adafruit_ble_heart_rate import HeartRateService
|
|
|
|
clue_data = clue.simple_text_display(title="Heart Rate", title_color = clue.PINK,
|
|
title_scale=1, text_scale=3)
|
|
|
|
alarm_enable = True
|
|
|
|
# target heart rate for interval training
|
|
# Change this number depending on your max heart rate, usually figured
|
|
# as (220 - your age).
|
|
max_rate = 180
|
|
|
|
# PyLint can't find BLERadio for some reason so special case it here.
|
|
ble = adafruit_ble.BLERadio() # pylint: disable=no-member
|
|
|
|
hr_connection = None
|
|
|
|
# Start with a fresh connection.
|
|
if ble.connected:
|
|
print("SCAN")
|
|
print("BLE")
|
|
time.sleep(1)
|
|
|
|
for connection in ble.connections:
|
|
if HeartRateService in connection:
|
|
connection.disconnect()
|
|
break
|
|
|
|
while True:
|
|
print("Scanning...")
|
|
print("SCAN")
|
|
print("BLE")
|
|
time.sleep(1)
|
|
clue_data[0].text = "BPM: ---"
|
|
clue_data[0].color = ((30, 0, 0))
|
|
clue_data[1].text = "Scanning..."
|
|
clue_data[3].text = ""
|
|
clue_data[1].color = ((130, 130, 0))
|
|
clue_data.show()
|
|
|
|
for adv in ble.start_scan(ProvideServicesAdvertisement, timeout=5):
|
|
if HeartRateService in adv.services:
|
|
print("found a HeartRateService advertisement")
|
|
hr_connection = ble.connect(adv)
|
|
#display_dots()
|
|
print("....")
|
|
time.sleep(2)
|
|
print("Connected")
|
|
break
|
|
|
|
# Stop scanning whether or not we are connected.
|
|
ble.stop_scan()
|
|
print("Stopped scan")
|
|
time.sleep(0.1)
|
|
|
|
if hr_connection and hr_connection.connected:
|
|
print("Fetch connection")
|
|
if DeviceInfoService in hr_connection:
|
|
dis = hr_connection[DeviceInfoService]
|
|
try:
|
|
manufacturer = dis.manufacturer
|
|
except AttributeError:
|
|
manufacturer = "(Manufacturer Not specified)"
|
|
try:
|
|
model_number = dis.model_number
|
|
except AttributeError:
|
|
model_number = "(Model number not specified)"
|
|
print("Device:", manufacturer, model_number)
|
|
else:
|
|
print("No device information")
|
|
hr_service = hr_connection[HeartRateService]
|
|
print("Location:", hr_service.location)
|
|
|
|
while hr_connection.connected:
|
|
values = hr_service.measurement_values
|
|
#print(values) # returns the full heart_rate data set
|
|
if values:
|
|
bpm = (values.heart_rate)
|
|
if bpm is not 0:
|
|
pct_target = (round(100*(bpm/max_rate)))
|
|
if values.heart_rate is 0:
|
|
print("----")
|
|
clue_data[0].text = "BPM: ---"
|
|
clue_data[0].color = ((80, 0, 0))
|
|
clue_data[1].text = "Target: --"
|
|
clue_data[1].color = ((0, 0, 80))
|
|
else:
|
|
clue_data[0].text = "BPM: {0:d}".format(bpm)
|
|
clue_data[0].color = clue.RED
|
|
|
|
clue_data[1].text = "Target: {0:d}%".format(pct_target)
|
|
if pct_target < 90:
|
|
alarm = False
|
|
clue_data[1].color = clue.CYAN
|
|
else:
|
|
alarm = True
|
|
clue_data[1].color = clue.RED
|
|
|
|
clue_data[3].text = "Max HR: : {0:d}".format(max_rate)
|
|
clue_data[3].color = clue.BLUE
|
|
clue_data.show()
|
|
|
|
if alarm and alarm_enable:
|
|
clue.start_tone(2000)
|
|
else:
|
|
clue.stop_tone()
|
|
|
|
# Inputs
|
|
if clue.button_a:
|
|
if clue.touch_2: # hold cap touch 2 for bigger change rate
|
|
max_rate = max_rate -10
|
|
else:
|
|
max_rate = max_rate - 1
|
|
if clue.button_b:
|
|
if clue.touch_2:
|
|
max_rate = max_rate + 10
|
|
else:
|
|
max_rate = max_rate + 1
|
|
|
|
if clue.touch_0:
|
|
alarm_enable = False
|
|
if clue.touch_1:
|
|
alarm_enable = True
|
|
|
|
time.sleep(0.2)
|