first commit BLE heart rate trainer code
This commit is contained in:
parent
51519c007d
commit
1b2fe4efcb
1 changed files with 167 additions and 0 deletions
167
BLE_Heart_Rate_Trainer/ble_heart_rate_trainer.py
Normal file
167
BLE_Heart_Rate_Trainer/ble_heart_rate_trainer.py
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
"""
|
||||
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.brightness = 15
|
||||
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.brightness = 15
|
||||
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 "...."
|
||||
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)
|
||||
|
||||
# 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)
|
||||
# "...."
|
||||
for j in range(4):
|
||||
display_A.set_digit_raw(j, 0b10000000)
|
||||
display_B.set_digit_raw(j, 0b10000000)
|
||||
|
||||
#display_B.fill(0)
|
||||
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:
|
||||
for k in range(4):
|
||||
display_A.set_digit_raw(k, 0b01000000)
|
||||
display_B.set_digit_raw(k, 0b01000000)
|
||||
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)
|
||||
Loading…
Reference in a new issue