/ BLE_Heart_Rate_Trainer / code.py
code.py
1 # SPDX-FileCopyrightText: 2020 John Park for Adafruit Industries 2 # 3 # SPDX-License-Identifier: MIT 4 5 """ 6 Heart Rate Trainer 7 Read heart rate data from a heart rate peripheral using the standard BLE 8 Heart Rate service. 9 Displays BPM value to Seven Segment FeatherWing 10 Displays percentage of max heart rate on another 7Seg FeatherWing 11 """ 12 13 import time 14 import board 15 16 import adafruit_ble 17 from adafruit_ble.advertising.standard import ProvideServicesAdvertisement 18 from adafruit_ble.services.standard.device_info import DeviceInfoService 19 from adafruit_ble_heart_rate import HeartRateService 20 21 from adafruit_ht16k33.segments import Seg7x4 22 23 from digitalio import DigitalInOut, Direction 24 25 # Feather on-board status LEDs setup 26 red_led = DigitalInOut(board.RED_LED) 27 red_led.direction = Direction.OUTPUT 28 red_led.value = True 29 30 blue_led = DigitalInOut(board.BLUE_LED) 31 blue_led.direction = Direction.OUTPUT 32 blue_led.value = False 33 34 # target heart rate for interval training 35 # Change this number depending on your max heart rate, usually figured 36 # as (220 - your age). 37 max_rate = 180 38 39 # Seven Segment FeatherWing setup 40 i2c = board.I2C() 41 display_A = Seg7x4(i2c, address=0x70) # this will be the BPM display 42 display_A.fill(0) # Clear the display 43 # Second display has A0 address jumpered 44 display_B = Seg7x4(i2c, address=0x71) # this will be the % target display 45 display_B.fill(0) # Clear the display 46 47 # display_A "b.P.M." 48 display_A.set_digit_raw(0, 0b11111100) 49 display_A.set_digit_raw(1, 0b11110011) 50 display_A.set_digit_raw(2, 0b00110011) 51 display_A.set_digit_raw(3, 0b10100111) 52 # display_B "Prct" 53 display_B.set_digit_raw(0, 0b01110011) 54 display_B.set_digit_raw(1, 0b01010000) 55 display_B.set_digit_raw(2, 0b01011000) 56 display_B.set_digit_raw(3, 0b01000110) 57 time.sleep(3) 58 59 display_A.fill(0) 60 for h in range(4): 61 display_A.set_digit_raw(h, 0b10000000) 62 # display_B show maximum heart rate value 63 display_B.fill(0) 64 display_B.print(max_rate) 65 time.sleep(2) 66 67 # PyLint can't find BLERadio for some reason so special case it here. 68 ble = adafruit_ble.BLERadio() # pylint: disable=no-member 69 70 hr_connection = None 71 72 def display_SCAN(): 73 display_A.fill(0) 74 display_A.set_digit_raw(0, 0b01101101) 75 display_A.set_digit_raw(1, 0b00111001) 76 display_A.set_digit_raw(2, 0b01110111) 77 display_A.set_digit_raw(3, 0b00110111) 78 79 80 def display_bLE(): 81 display_B.fill(0) 82 display_B.set_digit_raw(0, 0b00000000) 83 display_B.set_digit_raw(1, 0b01111100) 84 display_B.set_digit_raw(2, 0b00111000) 85 display_B.set_digit_raw(3, 0b01111001) 86 87 def display_dots(): # "...." 88 for j in range(4): 89 display_A.set_digit_raw(j, 0b10000000) 90 display_B.set_digit_raw(j, 0b10000000) 91 92 def display_dashes(): # "----" 93 for k in range(4): 94 display_A.set_digit_raw(k, 0b01000000) 95 display_B.set_digit_raw(k, 0b01000000) 96 97 # Start with a fresh connection. 98 if ble.connected: 99 display_SCAN() 100 display_bLE() 101 time.sleep(1) 102 103 for connection in ble.connections: 104 if HeartRateService in connection: 105 connection.disconnect() 106 break 107 108 while True: 109 print("Scanning...") 110 red_led.value = True 111 blue_led.value = False 112 display_SCAN() 113 display_bLE() 114 time.sleep(1) 115 116 117 for adv in ble.start_scan(ProvideServicesAdvertisement, timeout=5): 118 if HeartRateService in adv.services: 119 print("found a HeartRateService advertisement") 120 hr_connection = ble.connect(adv) 121 display_dots() 122 time.sleep(2) 123 print("Connected") 124 blue_led.value = True 125 red_led.value = False 126 break 127 128 # Stop scanning whether or not we are connected. 129 ble.stop_scan() 130 print("Stopped scan") 131 red_led.value = False 132 blue_led.value = True 133 time.sleep(0.5) 134 135 if hr_connection and hr_connection.connected: 136 print("Fetch connection") 137 if DeviceInfoService in hr_connection: 138 dis = hr_connection[DeviceInfoService] 139 try: 140 manufacturer = dis.manufacturer 141 except AttributeError: 142 manufacturer = "(Manufacturer Not specified)" 143 try: 144 model_number = dis.model_number 145 except AttributeError: 146 model_number = "(Model number not specified)" 147 print("Device:", manufacturer, model_number) 148 else: 149 print("No device information") 150 hr_service = hr_connection[HeartRateService] 151 print("Location:", hr_service.location) 152 153 while hr_connection.connected: 154 values = hr_service.measurement_values 155 print(values) # returns the full heart_rate data set 156 if values: 157 bpm = (values.heart_rate) 158 if bpm is not 0: 159 pct_target = (round(100*(bpm/max_rate))) 160 display_A.fill(0) # clear the display 161 display_B.fill(0) 162 if values.heart_rate is 0: 163 display_dashes() 164 else: 165 display_A.fill(0) 166 display_B.print(pct_target) 167 time.sleep(0.1) 168 display_A.print(bpm) 169 170 time.sleep(0.9) 171 display_A.set_digit_raw(0, 0b00000000)