# CircuitPython BLE Heart Rate Zone Trainer Display

## Overview

https://youtu.be/1j6aqB6q6_4

Heart rate zone training can be an excellent way to monitor workout intensity and increase your fitness and endurance. By spending certain periods of workout time at different percentages of your maximum heart rate. For example, warming up at 50-60%, then entering the "fitness zone" of 60-70% for a period, then going into the aerobic zone of 70-80%, finally peaking in the intense anaerobic zone of 80-90%.

Using a Bluetooth LE heart rate monitor armband or chest strap, you can send up-to-the moment heart rate data to a battery-powered Feather nRF5280 Bluefruit equipped with a pair of seven segment LED displays.

Place it on a wall or shelf where you can easily see it while you work out! Or carry it or hook it to your bike. CircuitPython makes it straightforward to connect to your heart rate monitor and stream the heart rate data and zone percentages to the displays.

## Parts & Materials
## Heart Rate Monitor

You'll need a heart rate monitor that supports Bluetooth Low Energy (BLE). I'm using the [Scosche RHYTHM+](https://www.scosche.com/rhythm-plus-heart-rate-monitor-armband) but you should be able to use any monitor that uses the Bluetooth SIG Heart Rate service standard.

These work by flashing green (and sometimes yellow) LEDs against your skin and then measuring the reflected light that returns. The color changes/darkens during the pulse of your heart thanks to all that blood sloshing around!

![circuitpython_rhythm-color-band_config_1000.jpg](https://cdn-learn.adafruit.com/assets/assets/000/087/965/medium640/circuitpython_rhythm-color-band_config_1000.jpg?1580514257)

### Adafruit Feather nRF52840 Express

[Adafruit Feather nRF52840 Express](https://www.adafruit.com/product/4062)
The **Adafruit Feather nRF52840 Express** is the new Feather family member with Bluetooth® Low Energy and _native USB support_ featuring the nRF52840!&nbsp; It's our take on an 'all-in-one' Arduino-compatible + Bluetooth® Low Energy with built-in USB...

In Stock
[Buy Now](https://www.adafruit.com/product/4062)
[Related Guides to the Product](https://learn.adafruit.com/products/4062/guides)
![Angled shot of a Adafruit Feather nRF52840 Express. ](https://cdn-shop.adafruit.com/640x480/4062-02.jpg)

### FeatherWing Tripler Mini Kit - Prototyping Add-on For Feathers

[FeatherWing Tripler Mini Kit - Prototyping Add-on For Feathers](https://www.adafruit.com/product/3417)
This is the **FeatherWing Tripler** - a prototyping add-on and more for all Feather boards. This is similar to our [FeatherWing Proto](https://www.adafruit.com/products/2884) except there are three! The magic of the Tripler comes when you want to connect your Feather to...

In Stock
[Buy Now](https://www.adafruit.com/product/3417)
[Related Guides to the Product](https://learn.adafruit.com/products/3417/guides)
![Triple prototyping feather wing PCB with socket headers installed](https://cdn-shop.adafruit.com/640x480/3417-05.jpg)

### Adafruit 0.56" 4-Digit 7-Segment FeatherWing Display - Red

[Adafruit 0.56" 4-Digit 7-Segment FeatherWing Display - Red](https://www.adafruit.com/product/3108)
One segment? No way dude! 7-Segments for life!

This is the **Red Adafruit 0.56" 4-Digit 7-Segment Display w/ FeatherWing Combo Pack**! We also have these combo packs in [Green](https://www.adafruit.com/products/3107), <a...></a...>

In Stock
[Buy Now](https://www.adafruit.com/product/3108)
[Related Guides to the Product](https://learn.adafruit.com/products/3108/guides)
![Angled shot of a rectangular shaped 7-segment breakout board with an LED matrix soldered on.](https://cdn-shop.adafruit.com/640x480/3108-02.jpg)

### Adafruit 0.56" 4-Digit 7-Segment FeatherWing Display - Blue

[Adafruit 0.56" 4-Digit 7-Segment FeatherWing Display - Blue](https://www.adafruit.com/product/3106)
One segment? No way dude! 7-Segments for life!

This is the **Blue&nbsp;Adafruit 0.56" 4-Digit 7-Segment Display w/ FeatherWing Combo Pack**! We also have these combo packs in [Green](https://www.adafruit.com/products/3107), <a...></a...>

In Stock
[Buy Now](https://www.adafruit.com/product/3106)
[Related Guides to the Product](https://learn.adafruit.com/products/3106/guides)
![Angled shot of a rectangular shaped 7-segment breakout board with an LED matrix soldered on.](https://cdn-shop.adafruit.com/640x480/3106-01.jpg)

### Lithium Ion Polymer Battery - 3.7v 1200mAh

[Lithium Ion Polymer Battery - 3.7v 1200mAh](https://www.adafruit.com/product/258)
Lithium-ion polymer (also known as 'lipo' or 'lipoly') batteries are thin, light, and powerful. The output ranges from 4.2V when completely charged to 3.7V. This battery has a capacity of 1200mAh for a total of about 4.5 Wh. If you need a larger battery, <a...></a...>

In Stock
[Buy Now](https://www.adafruit.com/product/258)
[Related Guides to the Product](https://learn.adafruit.com/products/258/guides)
![Lithium Ion Polymer Battery 3.7v 1200mAh with JST 2-PH connector](https://cdn-shop.adafruit.com/640x480/258-02.jpg)

### Part: USB Cable
quantity: 1
USB A to Micro-B - 3 foot long
[USB Cable](https://www.adafruit.com/product/592)

## Optional

Seven Segment LED displays look pretty good on their own, but they look even better with a colored gel filter in front of them!

I really like the way they look through a small piece of [LEE Filters CL797 Gel Filter Sheet - Deep Purple](http://www.leefilters.com/lighting/colour-details.html#797&filter=cf). I get mine from [Filmtools](https://www.filmtools.com/leegelsheet718.html).

![](https://cdn-learn.adafruit.com/assets/assets/000/087/916/medium800/circuitpython_hrt_build_0585.jpg?1580495202)

## Alt Version

You can build a CLUE variant of this project instead. All you'll need are a CLUE board instead of the Feather and seven segment displays.

### Adafruit CLUE - nRF52840 Express with Bluetooth® LE

[Adafruit CLUE - nRF52840 Express with Bluetooth® LE](https://www.adafruit.com/product/4500)
Do you feel like you just don't have a CLUE? Well, we can help with that - get a CLUE here at Adafruit by picking up this sensor-packed development board. We wanted to build some projects that have a small screen and a lot of sensors. To make it compatible with existing projects, we made...

In Stock
[Buy Now](https://www.adafruit.com/product/4500)
[Related Guides to the Product](https://learn.adafruit.com/products/4500/guides)
![Animated GIF showing CLUE board  displaying data from the many on-board sensors.](https://cdn-shop.adafruit.com/product-videos/640x480/4500-04.jpg)

# CircuitPython BLE Heart Rate Zone Trainer Display

## Understanding BLE 

![](https://cdn-learn.adafruit.com/assets/assets/000/086/706/medium800/leds_512px-BluetoothLogo.svg.png?1578443885)

## BLE Basics

To understand how we communicate between the MagicLight Bulb and the Circuit Playground Bluefruit (CPB), it's first important to get an overview of how Bluetooth Low Energy (BLE) works in general.

The nRF52840 chip on the CPB uses Bluetooth Low Energy, or BLE. BLE is a wireless communication protocol used by many devices, including mobile devices. You can communicate between your CPB and peripherals such as the Magic Light, mobile devices, and even other CPB boards!

There are a few terms and concepts commonly used in BLE with which you may want to familiarize yourself. This will help you understand what your code is doing when you're using CircuitPython and BLE.

Two major concepts to know about are the two modes of BLE devices:

- Broadcasting mode (also called **GAP** for **G** eneric **A** ccess **P** rofile)
- Connected device mode (also called **GATT** for **G** eneric **ATT** ribute Profile).

**GAP** mode deals with broadcasting peripheral advertisements, such as "_I'm a device named LEDBlue-19592CBC_", as well as advertising information necessary to establish a dedicated device connection if desired. The peripheral may also be advertising available services.

**GATT** mode deals with communications and attribute transfer between two devices once they are connected, such as between a heart monitor and a phone, or between your CPB and the Magic Light.

![](https://cdn-learn.adafruit.com/assets/assets/000/086/833/medium800/leds_ble_modes.jpg?1578680670)

## Bluetooth LE Terms

### GAP Mode

#### Device Roles:

- **Peripheral** - The low-power device that broadcasts advertisements. Examples of peripherals include: heart rate monitor, smart watch, fitness tracker, iBeacon, and the Magic Light. The CPB can also work as a peripheral.
- **Central** - The host "computer" that observes advertisements being broadcast by the Peripherals. This is often a mobile device such as a phone, tablet, desktop or laptop, but the CPB can also act as a central (which it will in this project).

#### Terms:

- **Advertising** - Information sent by the peripheral before a dedicated connection has been established. **All** nearby Centrals can observe these advertisements. When a peripheral device advertises, it may be transmitting the name of the device, describing its capabilities, and/or some other piece of data. Central can look for advertising peripherals to connect to, and use that information to determine each peripheral's capabilities (or Services offered, more on that below).

### GATT Mode

#### Device Roles:

- **Server -** In connected mode, a device may take on a new role as a **Server** , providing a Service available to clients. It can now send and receive data packets as requested by the Client device to which it now has a connection.
- **Client -** In connected mode, a device may also take on a new role as **Client** that can send requests to one or more of a Server's available Services to send and receive data packets.

Primary: 

#### Terms:

- **Profile -** A pre-defined collection of **Services** that a BLE device can provide. For example, the Heart Rate Profile, or the Cycling Sensor (bike computer) Profile. These Profiles are defined by the Bluetooth Special Interest Group (SIG). For devices that don't fit into one of the pre-defined Profiles, the manufacturer creates their own Profile. For example, there is not a "Smart Bulb" profile, so the Magic Light manufacturer has created their own unique one.
- **Service** - A function the Server provides. For example, a heart rate monitor armband may have separate Services for **Device Information** , **Battery Service** , and **Heart Rate** itself. Each Service is comprised of collections&nbsp;of information called **Characteristics**. In the case of the Heart Rate Service, the two Characteristics are **Heart Rate Measurement** and **Body Sensor Location.** &nbsp;The peripheral advertises its services.&nbsp;
- **Characteristic -** A Characteristic is a container for the value, or attribute, of a piece of data along with any associated metadata, such as a human-readable name. A characteristic may be readable, writable, or both. For example, the Heart Rate Measurement Characteristic can be served up to the Client device and will report the heart rate measurement as a number, as well as the unit string "bpm" for beats-per-minute. The Magic Light Server has a Characteristic for the RGB value of the bulb which can be written to by the Central to change the color. Characteristics each have a Universal Unique Identifier (UUID) which is a 16-bit or 128-bit ID.
- **Packet** - Data transmitted by a device. BLE devices and host computers transmit and receive data in small bursts called packets.

[This guide](https://learn.adafruit.com/introduction-to-bluetooth-low-energy/introduction) is another good introduction to the concepts of BLE, including GAP, GATT, Profiles, Services, and Characteristics.

# CircuitPython BLE Heart Rate Zone Trainer Display

## Heart Rate Service

The Bluetooth Special Interest Group has a standardized GATT ( **G** eneritt **ATT** ribute Profile) for heart rate monitors called the Heart Rate profile. (You can see a list of all the [GATT services here](https://www.bluetooth.com/specifications/gatt/services/).)

This defines the commands and data that can be exchanged between the heart rate sensor device and the client device such as a phone, tablet, or BLE capable microcontroller (like we'll use in our project).

If you want to see how the Bluetooth SIG defines a GATT, such as the Heart Rate Service, you can look at the official [XML file here](https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Services/org.bluetooth.service.heart_rate.xml).

Even better, run that URL through a code beautifier, such as codebeatify.org for a more human-readable version.

![](https://cdn-learn.adafruit.com/assets/assets/000/087/910/medium800/circuitpython_hrs_xml.png?1580487960)

## Heart Rate Characteristics

The Heart Rate service defines a three characteristics that can be served from the heart rate monitor (HRM) to a connected device.

### Heart Rate Measurement

The most important for most needs is the Heart Rate Measurement Values characteristic which serves up the following information:

- **Heart rate** , in beats per minute (BPM)
- **Contact** -- if the device is in contact with the body or not
- **Energy Expended** , in kilojoules
- **RR Intervals** in 1024ths of seconds -- this is the measurement of intervals between beats

Warning: 

### Body Sensor Location

Heart rate monitors will also include a characteristic for the intended location of the monitor on the body. This is built into the sensor firmware, not something that the device is determining on the fly! Standard values include:

- **Wrist**
- **Chest**
- **Finger**
- **Hand**
- **Ear Lobe**
- **Foot**
- **Other**

### Heart Rate Control Point

If the HRM includes the Energy Expended feature, the heart rate control point characteristic is used to allow the client device to write control points to the HRM.

## nRF Connect View

We can use the nRF Connect app from Nordic on [iOS](https://apps.apple.com/us/app/nrf-connect/id1054362403) and [Android](https://play.google.com/store/apps/details?id=no.nordicsemi.android.mcp&hl=en_US) to connect to a heart rate monitor and look at the service, characteristics, and data.

When we first connect to the device, we can see some data advertised including the device name, available services, connection parameters, manufacturer name, revision number, and more.

![](https://cdn-learn.adafruit.com/assets/assets/000/087/913/medium800/circuitpython_Screenshot_20200131-083207_nRF_Connect.jpg?1580489752)

In this image we can see the HRM device (RHYTHM+) has been connected, and the Heart Rate Measurement characteristic is reporting its data.&nbsp;

![](https://cdn-learn.adafruit.com/assets/assets/000/087/911/medium800/circuitpython_Screenshot_20200131-083028_nRF_Connect.jpg?1580489351)

If we request a read of the Body Sensor Location characteristic, we receive it as shown here:

![](https://cdn-learn.adafruit.com/assets/assets/000/087/912/medium800/circuitpython_Screenshot_20200131-083015_nRF_Connect.jpg?1580489566)

# CircuitPython BLE Heart Rate Zone Trainer Display

## Build the Heart Rate Zone Trainer

![](https://cdn-learn.adafruit.com/assets/assets/000/087/922/medium800/circuitpython_hrt_build_0568_new2k.jpg?1580497280)

To begin, assemble the two seven segment display FeatherWings [as shown here](https://learn.adafruit.com/adafruit-7-segment-led-featherwings/assembly).

Solder male headers to the Feather nRF52840 [as shown here](https://learn.adafruit.com/introducing-the-adafruit-nrf52840-feather/assembly#soldering-in-plain-headers-3-7).

Then, add the plain female headers to the FeatherWing Tripler [as shown here](https://learn.adafruit.com/featherwing-proto-and-doubler/assembly).

## I2C Address Jumper

In order to use two displays on one Feather, we need to give the boards unique I2C addresses.

Leave the red BPM display board at its default state, which will use 0x70 as its address.

For the blue heart rate zone percentage display, we'll solder the jumper pad marked A0, which will give the board the address 0x71.

I did this by soldering a small piece of wire across the two pads as shown here.

![circuitpython_IMG_0590b.jpg](https://cdn-learn.adafruit.com/assets/assets/000/087/926/medium640/circuitpython_IMG_0590b.jpg?1580498498)

![circuitpython_IMG_0591.jpg](https://cdn-learn.adafruit.com/assets/assets/000/087/927/medium640/circuitpython_IMG_0591.jpg?1580498540)

## Assembly

It's best to install the Feather nRF52840 at the top of the trippler so the battery cable doesn't interfere with the displays. (This won't matter if you choose to power over USB instead.)

Then, place the red seven segment display at the middle position.

Place the blue display at the bottom position.

![circuitpython_hrt_build_0571_new2k.jpg](https://cdn-learn.adafruit.com/assets/assets/000/087/925/medium640/circuitpython_hrt_build_0571_new2k.jpg?1580497678)

![circuitpython_hrt_build_0569_new2k.jpg](https://cdn-learn.adafruit.com/assets/assets/000/087/923/medium640/circuitpython_hrt_build_0569_new2k.jpg?1580497501)

![circuitpython_hrt_build_0570_new2k.jpg](https://cdn-learn.adafruit.com/assets/assets/000/087/924/medium640/circuitpython_hrt_build_0570_new2k.jpg?1580497630)

## Battery Power

You can power the Heart Rate Zone Trainer from a LiPoly battery, by plugging it into the Feather's battery plug.

Use a little bit of double stick foam tape to adhere it to the back of the board, and snake the wire under the Feather to keep it out of the way.

To charge the battery, simply plug the Feather into USB power.

![circuitpython_hrt_build_0572_new2k.jpg](https://cdn-learn.adafruit.com/assets/assets/000/087/928/medium640/circuitpython_hrt_build_0572_new2k.jpg?1580498618)

![circuitpython_hrt_build_0573_new2k.jpg](https://cdn-learn.adafruit.com/assets/assets/000/087/929/medium640/circuitpython_hrt_build_0573_new2k.jpg?1580498627)

![circuitpython_hrt_build_0574_new2k.jpg](https://cdn-learn.adafruit.com/assets/assets/000/087/930/medium640/circuitpython_hrt_build_0574_new2k.jpg?1580498635)

## Optional Filter

One nice way to improve the look of your LED displays is with a small piece of [colored gel filter](http://www.leefilters.com/lighting/colour-details.html#797&filter=cf) designed for film and theatrical lighting. It hides the white unlit segments so the lit ones really stand out. In this project I'm using a deep purple gel which gives both the red and blue displays a very nice look. You can experiment with different filters if you use different display colors.

![](https://cdn-learn.adafruit.com/assets/assets/000/087/939/medium800/circuitpython_hrt_build_0585_new2k.jpg?1580499562)

Cut a small section of gel from your sheet to fit the displays.

To adhere them to the displays, I used a couple of thin strips of 3M double stick transparent tape at the top and bottom of the display pair.

You can attach a strip across the top as shown here, and then trim away the excess with a hobby knife.

Repeat this for the bottom display's bottom edge, and then press the gel filter into place.

![circuitpython_hrt_build_0576_new2k.jpg](https://cdn-learn.adafruit.com/assets/assets/000/087/932/medium640/circuitpython_hrt_build_0576_new2k.jpg?1580499349)

![circuitpython_hrt_build_0577_new2k.jpg](https://cdn-learn.adafruit.com/assets/assets/000/087/933/medium640/circuitpython_hrt_build_0577_new2k.jpg?1580499378)

![circuitpython_hrt_build_0578_new2k.jpg](https://cdn-learn.adafruit.com/assets/assets/000/087/934/medium640/circuitpython_hrt_build_0578_new2k.jpg?1580499388)

![circuitpython_hrt_build_0579_new2k.jpg](https://cdn-learn.adafruit.com/assets/assets/000/087/935/medium640/circuitpython_hrt_build_0579_new2k.jpg?1580499444)

![circuitpython_hrt_build_0580_new2k.jpg](https://cdn-learn.adafruit.com/assets/assets/000/087/936/medium640/circuitpython_hrt_build_0580_new2k.jpg?1580499485)

![circuitpython_hrt_build_0583_new2k.jpg](https://cdn-learn.adafruit.com/assets/assets/000/087/937/medium640/circuitpython_hrt_build_0583_new2k.jpg?1580499500)

![circuitpython_hrt_build_0589_new2k.jpg](https://cdn-learn.adafruit.com/assets/assets/000/087/938/medium640/circuitpython_hrt_build_0589_new2k.jpg?1580499528)

Warning: 

Once you code the Feather in CircuitPython on the next page you'll be able to see the beautiful impact of the filter on the displays!

![](https://cdn-learn.adafruit.com/assets/assets/000/087/945/medium800thumb/circuitpython_hrt_build_0584_new2k.jpg?1580500195)

# CircuitPython BLE Heart Rate Zone Trainer Display

## CircuitPython for Feather nRF52840

[CircuitPython](https://github.com/adafruit/circuitpython) is a derivative of [MicroPython](https://micropython.org) designed to simplify experimentation and education on low-cost microcontrollers. It makes it easier than ever to get prototyping by requiring no upfront desktop software downloads. Simply copy and edit files on the **CIRCUITPY** drive to iterate.

The following instructions will show you how to install CircuitPython. If you've already installed CircuitPython but are looking to update it or reinstall it, the same steps work for that as well!

## Set up CircuitPython Quick Start!

Follow this quick step-by-step for super-fast Python power :)

[Download the latest version of CircuitPython for this board via CircuitPython.org](https://circuitpython.org/board/feather_nrf52840_express/)
 **Click the link above to download the latest UF2 file.**

&nbsp;

Download and save it to your desktop (or wherever is handy).

![circuitpython_nRF52840_UF2.png](https://cdn-learn.adafruit.com/assets/assets/000/070/318/medium640/circuitpython_nRF52840_UF2.png?1548963877)

Plug your Feather nRF52840 into your computer using a known-good USB cable.

**A lot of people end up using charge-only USB cables and it is very frustrating! So make sure you have a USB cable you know is good for data sync.**

Double-click the **Reset** button next to the USB connector on your board, and you will see the NeoPixel RGB LED turn green (identified by the arrow in the image). If it turns red, check the USB cable, try another USB port, etc. **Note:** The little red LED next to the USB connector will pulse red. That's ok!

If double-clicking doesn't work the first time, try again. Sometimes it can take a few tries to get the rhythm right!

![circuitpython_FeathernRF52840_Top_Product_Image.jpg](https://cdn-learn.adafruit.com/assets/assets/000/070/319/medium640/circuitpython_FeathernRF52840_Top_Product_Image.jpg?1548963972)

You will see a new disk drive appear called **FTHR840BOOT**.

&nbsp;

&nbsp;

&nbsp;

Drag the **adafruit\_circuitpython\_etc.uf2** file to **FTHR840BOOT****.**

![circuitpython_FTHR840BOOT.png](https://cdn-learn.adafruit.com/assets/assets/000/070/320/medium640/circuitpython_FTHR840BOOT.png?1548964488)

![circuitpython_Drag_nRF52840_UF2.png](https://cdn-learn.adafruit.com/assets/assets/000/070/321/medium640/circuitpython_Drag_nRF52840_UF2.png?1548964497)

The LED will flash. Then, the&nbsp; **FTHR840BOOT** drive will disappear and a new disk drive called **CIRCUITPY** will appear.

&nbsp;

That's it, you're done! :)

![circuitpython_nRF52840_CIRCUITPY.png](https://cdn-learn.adafruit.com/assets/assets/000/070/322/medium640/circuitpython_nRF52840_CIRCUITPY.png?1548964511)

# CircuitPython BLE Heart Rate Zone Trainer Display

## Code the Heart Rate Zone Trainer in CircuitPython

## Libraries

Once your Feather nRF52840 is set up with CircuitPython, you'll also need to add some library files. [Follow this page](https://learn.adafruit.com/welcome-to-circuitpython/circuitpython-libraries) for information on how to download and add libraries to your Feather.

From the library bundle you downloaded in that guide page, transfer the following libraries onto the Feather's **/lib** directory:

- **adafruit\_ble**
- **adafruit\_bus\_device**
- **adafruit\_ht16k33**
- **adafruit\_register**
- **adafruit\_ble\_heart\_rate.mpy**
- **neopixel.mpy**

![circuitpython_hrtzd_libs.png](https://cdn-learn.adafruit.com/assets/assets/000/087/931/medium640/circuitpython_hrtzd_libs.png?1580498913)

## Text Editor

Adafruit recommends using the Mu editor for using your CircuitPython code with the Feather boards. You can get more info in [this guide](https://learn.adafruit.com/welcome-to-circuitpython/installing-mu-editor).

Alternatively, you can use any text editor that saves files.

## Code.py

Copy the code shown below, paste it into Mu. Plug your Feather into your computer via a known good USB cable. In your operating system's file explorer/finder, you should see a new flash drive named **CIRCUITPY**. Save the code from Mu to the Feather's **CIRCUITPY** drive as **code.py**

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/CLUE/CLUE_Heart_Rate_Trainer/code.py

## Code Explainer

The code is doing a few fundamental things.

First, it loads the time and `board` libraries, as well as the necessary libraries to use **BLE** in general, and the **HeartRateService** in specific.

We also load the `HT16K33` library to use the seven segment displays, and the **`digitalio`** library to use the Feather's on-board red and blue indicator LEDs.

```python
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
```

## LED setup

Next, code to prepare the on-board LEDs and turn on the red one, while leaving the blue one turned off, until we start scanning for BLE devices.

```python
# 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
```

## Max Heart Rate Variable

The `max_rate` variable is used to calculate your heart rate training zone percentages. You can change this to suit your maximum heart rate. The simplest way to calculate this is by subtracting your age from 220, but you can get much more specific numbers from a doctor or training specialist.

`max_rate = 180`

## Display Prep

To prep for using the two displays, the `Set7x4` objects on the I2C bus are set using unique addresses. Remember, the second display's A0 pads was jumpered to set the address to 0x71, while leaving the first display at the default address 0x70.

```python
# 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
```

## Seven Segment Display Use

[This guide](https://learn.adafruit.com/adafruit-7-segment-led-featherwings/circuitpython#led-7-segment-display-3-42) includes a great intro to using the matrix displays with CircuitPython.

You can set the display in a few different ways:

- `display_A.print(1234)` will display 1234
- `display_A.set_digit_raw(3, 0b00000001)` will light up the top segment of the fourth digit (far right) only.
- `display[0] = '6'` will display a 6 on the first digit (far left)

During the startup sequence we'll display "b.P.M" on display A (the red one) and "Prct" on the display B (the blue one).

```python
# 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)
```

Here's a good image guide to the raw segment bitmask.

![circuitpython_led_matrices_set_pixel_raw.png](https://cdn-learn.adafruit.com/assets/assets/000/087/950/medium640/circuitpython_led_matrices_set_pixel_raw.png?1580503683)

## Max Heart Rate Display

Next, we'll set display A to "...." and show the max\_rate value for a couple seconds on display B.

```python
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)
```

## BLE Instance

The BLE radio is defined next with `ble = adafruit_ble.BLERadio() `

## Display Functions

We'll keep the code neat by creating some functions that can be used repeatedly to show certain messages on the displays.

```python
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)
```

## Fresh Connection

We scan for a BLE device with the Heart Rate Service being advertised, and set the displays and status LEDs to match.

When we connect, the displays switch to four dots .... and we stop scanning.

```python
# 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)
```

## Device Info

With the heart rate monitor connected, we'll request info that is displayed in the Mu REPL, if your Feather is connected to your computer over USB. This is purely informational for curiosity and debug purposes, and not displayed on the seven segment displays.

```python
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)
```

## Heart Rate and Zone Percent

We've reached the heart of the program! This is the code that loops over and over while the devices are connected.

First, we cast the heart rate service's measurment characteristic attributes that are sent as `values`, and then we cast the heart rate value itself as `bpm`

We'll check at first for non-zero bpm readings, as the heart rate monitor sends a few zeros at first, and we'll ignore them so nobody gets too worried, and just display four dashes.

We'll create a `pct_target` variable that calculates the percentage of the `max_rate` based on current `bpm`.

The displays are cleared and then the percent value is shown on display B and the bpm is shown on display A. This display blinks each time the loop is run, and the whole process repeats every second.

```python
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)
```

On the next page we'll see it in action.

# CircuitPython BLE Heart Rate Zone Trainer Display

## Heart Rate Zone Trainer in Action

![](https://cdn-learn.adafruit.com/assets/assets/000/087/952/medium800/circuitpython_IMG_0617.jpg?1580505696)

You can use the Heart Rate Zone Trainer any time you want to do some exercise, and be aware of your heart rate and the zone percentage you're in. Set it on a surface where you can see it easily, and pay attention to how long you are in different heart rate training zones.

## Setup

Plug in the battery (or a USB power cable).

The display will show the intro text " **b.P.M.**" and " **Prct**" so you know which display is used for what.

Next, your max heart rate is displayed, in this case, **180**.

The device will start scanning for a BLE heart rate monitor, displaying " **SCAN bLE**".

Turn on the heart rate monitor and strap it to your inner arm. At first the displays will show "...." as it connects, and "----" as the first zero bpm values are sent.

&nbsp;

![circuitpython_IMG_0596.jpg](https://cdn-learn.adafruit.com/assets/assets/000/087/953/medium640/circuitpython_IMG_0596.jpg?1580505806)

![circuitpython_IMG_0598.jpg](https://cdn-learn.adafruit.com/assets/assets/000/087/954/medium640/circuitpython_IMG_0598.jpg?1580505876)

![circuitpython_IMG_0599.jpg](https://cdn-learn.adafruit.com/assets/assets/000/087/955/medium640/circuitpython_IMG_0599.jpg?1580505896)

![circuitpython_IMG_0604.jpg](https://cdn-learn.adafruit.com/assets/assets/000/087/957/medium640/circuitpython_IMG_0604.jpg?1580505934)

![circuitpython_IMG_0605.jpg](https://cdn-learn.adafruit.com/assets/assets/000/087/958/medium640/circuitpython_IMG_0605.jpg?1580506060)

![circuitpython_IMG_0608.jpg](https://cdn-learn.adafruit.com/assets/assets/000/087/959/medium640/circuitpython_IMG_0608.jpg?1580506070)

## BPM and Percentage of Max Heart Rate

As the Heart Rate Monitor sends values, the Feather will display the bpm on top and the percentage of max on the bottom.

You can do some jumping jacks or run around a bit to get your heart rate up.

![circuitpython_IMG_0616.jpg](https://cdn-learn.adafruit.com/assets/assets/000/087/960/medium640/circuitpython_IMG_0616.jpg?1580506108)

![circuitpython_IMG_0610.jpg](https://cdn-learn.adafruit.com/assets/assets/000/087/961/medium640/circuitpython_IMG_0610.jpg?1580506157)

Here's an action video -- you'll see the rate going up as I ran for a few minutes.

https://youtu.be/1j6aqB6q6_4

# CircuitPython BLE Heart Rate Zone Trainer Display

## CLUE Heart Rate Trainer

![](https://cdn-learn.adafruit.com/assets/assets/000/088/596/medium800/sensors_clue_hr-19.jpg?1582139019)

Here's a bonus version of the BLE Heart Rate Zone Trainer you can make with the CLUE board alone, no need for external displays!

[Follow these instructions](https://learn.adafruit.com/adafruit-clue/circuitpython) to set up your CLUE with CircuitPython, then [check out this page](https://learn.adafruit.com/adafruit-clue/clue-circuitpython-libraries) for info on adding libraries.

## Libraries

Once your CLUE is set up with CircuitPython and library files in general, we'll add some project specific libraries.

From the library bundle you downloaded in that guide page, transfer any additional libraries shown here onto the CLUE's **/lib** directory on the **CIRCUITPY** drive:

- **adafruit\_apds9960**
- **adafruit\_ble**
- **adafruit\_ble\_heart\_rate.mpy**
- **adafruit\_bmp280.mpy**
- **adafruit\_bus\_device**
- **adafruit\_clue.py**
- **adafruit\_display\_notification**
- **adafruit\_display\_shapes**
- **adafruit\_display\_text**
- **adafruit\_lis3mdl.mpy**
- **adafruit\_lsm6ds.mpy**
- **adafruit\_register**
- **adafruit\_sht31d.mpy**
- **neopixel.mpy**
- **simpleio.mpy**

![sensors_cluehrlib.jpg](https://cdn-learn.adafruit.com/assets/assets/000/088/597/medium640/sensors_cluehrlib.jpg?1582139404)

## Text Editor

Adafruit recommends using the Mu editor for using your CircuitPython code with the Feather boards. You can get more info in [this guide](https://learn.adafruit.com/welcome-to-circuitpython/installing-mu-editor).

Alternatively, you can use any text editor that saves files.

## Code.py

Copy the code shown below, paste it into Mu. Plug your CLUE into your computer via a known good USB cable. In your operating system's file explorer/finder, you should see a new flash drive named **CIRCUITPY**. Save the code from Mu to the CLUE's **CIRCUITPY** drive as **code.py**

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/CLUE/CLUE_Heart_Rate_Trainer/code.py

## Code Explainer

The code is doing a few fundamental things.

First, it loads the `time` and `board` libraries, as well as the necessary libraries to use **BLE** in general, and the `adafruit_ble_heart_rate` library in specific.

We also load the `adafruit_clue` library so we can take advantage of convenient commands that simplify using the CLUE's display.

The `clue_data` variable is created to instantiate the CLUE display object for simple text and titles.

We also set up the `BLERadio` so it can be used to communicate with the sensor.

```python
"""
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
```

## Connection

Next, we scan for a BLE peripheral device advertising that it has the Heart Rate service.

We display the BPM, and "Scanning..." text, specifying their lines and colors on the CLUE TFT display.

When it is found, the CLUE will connect to it and then display the device name and other info. These are regular `print()` statements that show up in the REPL or other serial display, including the CLUE's display.

```python
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)
```

## Measurements

Next we begin displaying the measurements. At first we show dashes while the data streams to the CLUE from the HRM, then switch to real data.

```python
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)
```

## Alarm

We'll do a calculation of the current BPM vs the Max HR and set off an alarm when it goes above 90%.

Well use the buttons and cap touch to adjust max heart rate and alarm on/off.

```python
if pct_target &lt; 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)
```

![](https://cdn-learn.adafruit.com/assets/assets/000/088/598/medium800/sensors_clue_hr-11.jpg?1582140137)

## In Use

You can use the Heart Rate Zone Trainer any time you want to do some exercise, and be aware of your heart rate and the zone percentage you're in. Set it on a surface where you can see it easily, and pay attention to how long you are in different heart rate training zones.

## Setup

Plug in the battery (or a USB power cable).

The display will show that it is scanning for a BLE HRM to connect to.

Turn on the heart rate monitor and strap it to your inner arm.

Next, the CLUE will connect and then show dashed lines for the BPM and Percent of target while the monitor begins streaming the data.

Next, your BPM, Target percentage, and max heart rate are displayed.

![sensors_clue_hr-1.jpg](https://cdn-learn.adafruit.com/assets/assets/000/088/599/medium640/sensors_clue_hr-1.jpg?1582140155)

![sensors_clue_hr-2.jpg](https://cdn-learn.adafruit.com/assets/assets/000/088/600/medium640/sensors_clue_hr-2.jpg?1582140215)

![sensors_clue_hr-3.jpg](https://cdn-learn.adafruit.com/assets/assets/000/088/601/medium640/sensors_clue_hr-3.jpg?1582140257)

![sensors_clue_hr-4.jpg](https://cdn-learn.adafruit.com/assets/assets/000/088/602/medium640/sensors_clue_hr-4.jpg?1582140336)

## Adjustment

Since the CLUE has buttons and cap sense inputs, let's use them!

Press the B button to increase the max HR value one unit at a time.

The A button will decrease it.

To make larger changes, hold the 2 cap sense pad while using the buttons. This will increment the tens place.

![sensors_clue_hr-5.jpg](https://cdn-learn.adafruit.com/assets/assets/000/088/603/medium640/sensors_clue_hr-5.jpg?1582140360)

![sensors_clue_hr-7.jpg](https://cdn-learn.adafruit.com/assets/assets/000/088/604/medium640/sensors_clue_hr-7.jpg?1582140453)

![sensors_clue_hr-12.jpg](https://cdn-learn.adafruit.com/assets/assets/000/088/605/medium640/sensors_clue_hr-12.jpg?1582140465)

![sensors_clue_hr-12.jpg](https://cdn-learn.adafruit.com/assets/assets/000/088/606/medium640/sensors_clue_hr-12.jpg?1582140479)

## Alarm!

If your heart rate goes above 90% of your max HR, the target percentage text will turn red and the alarm buzzer on the CLUE will sound!

Press cap touch 0 to turn off the alarm or touch 1 to turn it back on. Also, take a rest!

![sensors_clue_hr-13.jpg](https://cdn-learn.adafruit.com/assets/assets/000/088/608/medium640/sensors_clue_hr-13.jpg?1582140574)

![sensors_clue_hr-14.jpg](https://cdn-learn.adafruit.com/assets/assets/000/088/609/medium640/sensors_clue_hr-14.jpg?1582140582)

![sensors_clue_hr-15.jpg](https://cdn-learn.adafruit.com/assets/assets/000/088/610/medium640/sensors_clue_hr-15.jpg?1582140589)


## Featured Products

### Adafruit Feather nRF52840 Express

[Adafruit Feather nRF52840 Express](https://www.adafruit.com/product/4062)
The **Adafruit Feather nRF52840 Express** is the new Feather family member with Bluetooth® Low Energy and _native USB support_ featuring the nRF52840!&nbsp; It's our take on an 'all-in-one' Arduino-compatible + Bluetooth® Low Energy with built-in USB...

In Stock
[Buy Now](https://www.adafruit.com/product/4062)
[Related Guides to the Product](https://learn.adafruit.com/products/4062/guides)
### FeatherWing Tripler Mini Kit - Prototyping Add-on For Feathers

[FeatherWing Tripler Mini Kit - Prototyping Add-on For Feathers](https://www.adafruit.com/product/3417)
This is the **FeatherWing Tripler** - a prototyping add-on and more for all Feather boards. This is similar to our [FeatherWing Proto](https://www.adafruit.com/products/2884) except there are three! The magic of the Tripler comes when you want to connect your Feather to...

In Stock
[Buy Now](https://www.adafruit.com/product/3417)
[Related Guides to the Product](https://learn.adafruit.com/products/3417/guides)
### Adafruit 0.56" 4-Digit 7-Segment FeatherWing Display

[Adafruit 0.56" 4-Digit 7-Segment FeatherWing Display](https://www.adafruit.com/product/3140)
One segment? No way dude! 7-Segments for life!

This is the&nbsp; **Adafruit 0.56" 4-Digit 7-Segment Display w/ FeatherWing Combo Pack**! We have these combo packs in [Green](https://www.adafruit.com/products/3107),&nbsp;<a...></a...>

Out of Stock
[Buy Now](https://www.adafruit.com/product/3140)
[Related Guides to the Product](https://learn.adafruit.com/products/3140/guides)
### Adafruit 0.56" 4-Digit 7-Segment FeatherWing Display - Red

[Adafruit 0.56" 4-Digit 7-Segment FeatherWing Display - Red](https://www.adafruit.com/product/3108)
One segment? No way dude! 7-Segments for life!

This is the **Red Adafruit 0.56" 4-Digit 7-Segment Display w/ FeatherWing Combo Pack**! We also have these combo packs in [Green](https://www.adafruit.com/products/3107), <a...></a...>

In Stock
[Buy Now](https://www.adafruit.com/product/3108)
[Related Guides to the Product](https://learn.adafruit.com/products/3108/guides)
### Adafruit 0.56" 4-Digit 7-Segment FeatherWing Display - Blue

[Adafruit 0.56" 4-Digit 7-Segment FeatherWing Display - Blue](https://www.adafruit.com/product/3106)
One segment? No way dude! 7-Segments for life!

This is the **Blue&nbsp;Adafruit 0.56" 4-Digit 7-Segment Display w/ FeatherWing Combo Pack**! We also have these combo packs in [Green](https://www.adafruit.com/products/3107), <a...></a...>

In Stock
[Buy Now](https://www.adafruit.com/product/3106)
[Related Guides to the Product](https://learn.adafruit.com/products/3106/guides)
### Adafruit 4-Digit 7-Segment LED Matrix Display FeatherWing

[Adafruit 4-Digit 7-Segment LED Matrix Display FeatherWing](https://www.adafruit.com/product/3088)
One segment? No way dude! 7-Segments for life!

A Feather board without ambition is a Feather board without FeatherWings!&nbsp;This is the&nbsp; **Adafruit 4-Digit 7-Segment LED Matrix Display FeatherWing**!&nbsp;This 7-segment FeatherWing backpack makes it really easy to add...

In Stock
[Buy Now](https://www.adafruit.com/product/3088)
[Related Guides to the Product](https://learn.adafruit.com/products/3088/guides)
### Red 7-segment clock display - 0.56" digit height

[Red 7-segment clock display - 0.56" digit height](https://www.adafruit.com/product/865)
Design a clock, timer or counter into your next project using our pretty 4-digit seven-segment display. These bright crisp displays are good for adding numeric output. Besides the four 7-segments, there are decimal points on each digit and an extra wire for colon-dots in the center (good for...

In Stock
[Buy Now](https://www.adafruit.com/product/865)
[Related Guides to the Product](https://learn.adafruit.com/products/865/guides)
### Blue 7-segment clock display - 0.56" digit height

[Blue 7-segment clock display - 0.56" digit height](https://www.adafruit.com/product/812)
Design a clock, timer or counter into your next project using our pretty 4-digit seven-segment display. These bright crisp displays are good for adding numeric output. Besides the four 7-segments, there are decimal points on each digit and an extra wire for colon-dots in the center (good for...

In Stock
[Buy Now](https://www.adafruit.com/product/812)
[Related Guides to the Product](https://learn.adafruit.com/products/812/guides)

## Related Guides

- [Introducing the Adafruit nRF52840 Feather](https://learn.adafruit.com/introducing-the-adafruit-nrf52840-feather.md)
- [Introducing Adafruit CLUE](https://learn.adafruit.com/adafruit-clue.md)
- [PyLeap CLUE Custom Conference Badge](https://learn.adafruit.com/pyleap-clue-custom-conference-badge.md)
- [Wearable Continuous Temperature Monitor with Adafruit IO](https://learn.adafruit.com/wearable-temperature-monitor.md)
- [CLUE Custom CircuitPython Badge](https://learn.adafruit.com/clue-custom-circuit-python-badge.md)
- [Which CircuitPython Board is Right for You?](https://learn.adafruit.com/choose-your-circuitpython-board.md)
- [CLUE Sensor Plotter in CircuitPython](https://learn.adafruit.com/clue-sensor-plotter-circuitpython.md)
- [CLUE Rock, Paper, Scissors Game using Bluetooth](https://learn.adafruit.com/rock-paper-scissors-circuitpython.md)
- [Bluetooth Restroom Key Proximity Tracker](https://learn.adafruit.com/bluetooth-restroom-key-proximity-tracker.md)
- [Welcome to CircuitPython!](https://learn.adafruit.com/welcome-to-circuitpython.md)
- [MIDI for Makers](https://learn.adafruit.com/midi-for-makers.md)
- [Deco Two-Key Feather Macro Pad](https://learn.adafruit.com/deco-two-key-keypad-macropad-circuitpython-feather.md)
- [BLE Sniffer with nRF52840](https://learn.adafruit.com/ble-sniffer-with-nrf52840.md)
- [Daily Cheer Automaton](https://learn.adafruit.com/daily-cheer-automaton.md)
- [FeatherWing Proto, Doubler  and Tripler](https://learn.adafruit.com/featherwing-proto-and-doubler.md)
- [7 Segment Display Internet Clock](https://learn.adafruit.com/7-segment-display-internet-clock.md)
- [Adafruit 7-Segment LED FeatherWings](https://learn.adafruit.com/adafruit-7-segment-led-featherwings.md)
