Adafruit_Learning_System_Gu.../BLE_Heart_Rate_Trainer/code.py
2022-02-22 13:50:42 -05:00

171 lines
5.1 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 to Seven Segment FeatherWing
Displays percentage of max heart rate on another 7Seg FeatherWing
"""
import time
import board
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
from adafruit_ht16k33.segments import Seg7x4
from digitalio import DigitalInOut, Direction
# Feather on-board status LEDs setup
red_led = DigitalInOut(board.RED_LED)
red_led.direction = Direction.OUTPUT
red_led.value = True
blue_led = DigitalInOut(board.BLUE_LED)
blue_led.direction = Direction.OUTPUT
blue_led.value = False
# target heart rate for interval training
# Change this number depending on your max heart rate, usually figured
# as (220 - your age).
max_rate = 180
# Seven Segment FeatherWing setup
i2c = board.I2C()
display_A = Seg7x4(i2c, address=0x70) # this will be the BPM display
display_A.fill(0) # Clear the display
# Second display has A0 address jumpered
display_B = Seg7x4(i2c, address=0x71) # this will be the % target display
display_B.fill(0) # Clear the display
# display_A "b.P.M."
display_A.set_digit_raw(0, 0b11111100)
display_A.set_digit_raw(1, 0b11110011)
display_A.set_digit_raw(2, 0b00110011)
display_A.set_digit_raw(3, 0b10100111)
# display_B "Prct"
display_B.set_digit_raw(0, 0b01110011)
display_B.set_digit_raw(1, 0b01010000)
display_B.set_digit_raw(2, 0b01011000)
display_B.set_digit_raw(3, 0b01000110)
time.sleep(3)
display_A.fill(0)
for h in range(4):
display_A.set_digit_raw(h, 0b10000000)
# display_B show maximum heart rate value
display_B.fill(0)
display_B.print(max_rate)
time.sleep(2)
# PyLint can't find BLERadio for some reason so special case it here.
ble = adafruit_ble.BLERadio() # pylint: disable=no-member
hr_connection = None
def display_SCAN():
display_A.fill(0)
display_A.set_digit_raw(0, 0b01101101)
display_A.set_digit_raw(1, 0b00111001)
display_A.set_digit_raw(2, 0b01110111)
display_A.set_digit_raw(3, 0b00110111)
def display_bLE():
display_B.fill(0)
display_B.set_digit_raw(0, 0b00000000)
display_B.set_digit_raw(1, 0b01111100)
display_B.set_digit_raw(2, 0b00111000)
display_B.set_digit_raw(3, 0b01111001)
def display_dots(): # "...."
for j in range(4):
display_A.set_digit_raw(j, 0b10000000)
display_B.set_digit_raw(j, 0b10000000)
def display_dashes(): # "----"
for k in range(4):
display_A.set_digit_raw(k, 0b01000000)
display_B.set_digit_raw(k, 0b01000000)
# Start with a fresh connection.
if ble.connected:
display_SCAN()
display_bLE()
time.sleep(1)
for connection in ble.connections:
if HeartRateService in connection:
connection.disconnect()
break
while True:
print("Scanning...")
red_led.value = True
blue_led.value = False
display_SCAN()
display_bLE()
time.sleep(1)
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()
time.sleep(2)
print("Connected")
blue_led.value = True
red_led.value = False
break
# Stop scanning whether or not we are connected.
ble.stop_scan()
print("Stopped scan")
red_led.value = False
blue_led.value = True
time.sleep(0.5)
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)))
display_A.fill(0) # clear the display
display_B.fill(0)
if values.heart_rate is 0:
display_dashes()
else:
display_A.fill(0)
display_B.print(pct_target)
time.sleep(0.1)
display_A.print(bpm)
time.sleep(0.9)
display_A.set_digit_raw(0, 0b00000000)