Heart Rate Display

by jgschmidt in Circuits > Arduino

3794 Views, 51 Favorites, 0 Comments

Heart Rate Display

hb-1.jpg

There are lots of heartbeat monitors - FitBit is a popular one. The heart rate (HR) can display on your wrist and your phone. However, arm- or wrist-band HR monitors are not very accurate, nor responsive. For accuracy and responsiveness, I have not found anything that is equal to, or better than, the Polar chest strap devices. These also come with wrist and smart phone displays. The problem with these displays is that they are awkward to use while you are exercising. It's hard to concentrate on a wrist display in the middle of running, for example. Smart phone displays time out, or show too much other information, making it hard to focus on just the HR number. These systems are good for recording and later review, but I wanted something that would display my heart rate in real time, and just my heart rate, on a large display.

In spite of working professionally with embedded systems for over 3 decades, I only recently started working with the Arduino collection of devices. A single, simple development environment allows you to work with a wide range of devices, from simple 8-bit controllers to 32-bit devices that support WiFi, Bluetooth, LORA and AI applications.

Here is where I found Bluetooth-capable boards that can communicate to the Polar Bluetooth-enabled chest straps. Connect one of these to a large (relatively speaking) OLED display, and I could probably get what I want.

Supplies

hb-2.jpg
hb-3.jpg

The initial developmental and testing was done using the Arduino UNO R4 WiFi, which is based on the ESP32 processor that includes WiFi and Bluetooth support. The Arduino Integrated Development Environment (IDE) includes all the libraries to support this processor. Once I had the project working, I moved it to a smaller and cheaper board so I could package my new HR monitor in a case with battery. Parts I used include:

  1. Polar H7 heart monitor with Bluetooth - there are newer models, but you can still find the older H7 model on Amazon and eBay
  2. Arduino UNO R4 Wifi (for development and testing) - Amazon
  3. 2.4 inch OLED display - Amazon
  4. Adafruit ESP32 Feather V2 (for the final design) - Adafruit
  5. Rechargeable lithium battery - Adafruit
  6. On/Off switch - parts on hand
  7. 3D-printed case - STL files are on GitHub along with the code

Other resources include:

Technical details about the Arduino IDE and working with the ESP32 processor

Adafruit has extensive tutorials and libraries which I relied on to complete this project.

About Polar Heart Rate Monitors

I don't know when I first started using Polar heart rate monitors - I'm pretty sure it was long before smart phones and Bluetooth were part of our daily vocabulary. The original chest straps, like the T31, didn't have replaceable batteries and sent out a unique, non-standard radio signal that could be received by nearby compatible receivers, usually in the form of a wrist watch. My gym-grade treadmill that I've had a long time, has a Polar receiver built into it, with a nice, large display.

With the arrival of Bluetooth Low Energy (BLE) protocols around 2009, heart rate monitors included this so they could connect to smart phones. Fortunately, Polar still includes the original radio signal in their sensors for backward compatibility. Both the H7 and H10 sensors still talk to my pre-BLE watch bands and my treadmill.

My T31 and T34 chest straps expired a while back and I've been using the H7 sensor and transmitter, which I used for this project. The H7 came with a watch I rarely used - I usually relied on the treadmill display, and the Polar app on my phone. Some testing revealed that I can see the heart rate on both the watch and the treadmill, along with one BLE display, but I can not see it on two BLE displays at the same time, or a BLE display and the Polar app on my phone at the same time.

As I was looking in my exercise junk collection I also found a Polar H10 sensor. Testing it, I found that it works with this project just like the H7 does. You just need to enter the correct device name and serial number into the program.

Bottom line on connectivity is: only 1 BLE connection at a time, and any number of legacy radio connections.

Getting Organized

This is my first real Arduino project, however, due to my past work with embedded systems, I am familiar with the landscape and just need do some studying to adapt to the local "dialects". All Arduino hardware and software is in the public domain and the circuit designs and software are on GitHub, along with extensive documentation. It is scattered in various organizational and personal repositories and can be a challenge to track down. If you get lost looking for something, go to a vendor website. They will host their own documentation, or point to a GitHub repository. You can also get to sources from the Arduino IDE library manager. Each library has a "More info" link that points to the corresponding Github repository.

In order to get this project going, I needed a working Polar chest strap. I started out with my H7. Since I had not used it in a while, I replaced the battery and verified it worked by connecting it via Bluetooth to the Polar app on my phone.

Second, I needed a development workbench. I got an official Arduino board that supports Bluetooth, the UNO R4 WiFi. I downloaded the latest IDE, along with the necessary hardware and software libraries. The details for this are available on the Arduino website. There are lots of cheap clone Arduino ESP32 boards available, but according to some forum comments they frequently have "gotchas" such as different pinouts, missing bootloaders, or needing extra libraries. I was not looking for any additional challenges just yet, and would stick with the official hardware for now.

Third, I selected a display. To connect a display to a processor you generally need a hardware driver and a graphics library that's compatible with your processor. The Arduino environment excels at making everything plug-and-play. Actually, it's the vendors who develop hardware and supporting software who do this work so that everything integrates. Adafruit is one of these vendors. They have some displays, along with detailed instructions for using the drivers and graphics libraries they've developed. I found a nice 2.4 inch OLED display on Amazon that is compatible with the Adafruit libraries.

The Software

hb-4.jpg

The Display

After connecting the board to my computer and loading the blink program (the embedded world's equivalent of "Hello world.") I worked on getting the display to show some text. Small text would display informational messages, and a very large font would display the heart rate. I found a display similar to mine at Adafruit and followed the tutorials linked to it. The software stack for the display requires the following:


#include <SPI.h>
#include <Wire.h>

#include <Adafruit_SH110X.h> // Hardware driver
#include <Adafruit_GFX.h>            // Adafruit graphics library
#include <U8g2_for_Adafruit_GFX.h>   // use U8g2 font library


Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

U8G2_FOR_ADAFRUIT_GFX u8g2_for_adafruit_gfx;         // all text output goes through this


SPI and Wire libraries support the I2C hardware interface to the display.

Adafruit_SH110X talks to the display controller chip.

The next two lines bring in graphics and text libraries. These are independent of the display controller and will work with all sorts of displays of various sizes.

The next line instantiates a display object which supports a variety of graphics primitives.

Additional libraries are needed for drawing text. There are some options here and I selected the U8G2 library, which includes a large collection of fonts of different sizes, all in one library. Documentation for it can be found here.

There are some conditional compile sections related to the two displays and drivers I tried out.

Bluetooth

There are two flavors of Bluetooth (BT). Regular BT supports streaming audio to wireless speakers, headsets and earbuds. Another version, BLE, which stands for Bluetooth Low Energy, is designed for sending small amounts of data at low data rates. This is used for things like heart monitors, environmental sensors, and the like. The Polar heart monitor uses BLE. Different versions of the ESP32 processor support different wireless protocols. Some will support only one or two of WiFi, BT, and/or BLE. If you are using a different board for this project, be sure it supports BLE.

When the libraries for BLE are installed, several example programs are installed as well. This is a good way to test your hardware and software setup. In the IDE select

File->Examples->ArduinoBLE->Central->Scan

This will scan for any BLE devices that are available to offer up some data. You may be surprised by how many devices are out there, clamoring to be heard.

In addition to verifying that your workbench is working, you need to use the scanner to find the device name for the heart monitor you want to connect to. Put on your heart monitor and run the scanner. You should find an entry that looks like this:

Discovered a peripheral

-----------------------

Address: 00:22:d0:8c:50:50

Local Name: Polar H7 8C505015

Service UUIDs: 180d

RSSI: -55

The Local Name entry will be coded into the program to identify the device you want to connect with. See line 94 in the program.

For the Arduino hardware to communicate with the Polar heart sensor, you need to add another library to the project:

#include <ArduinoBLE.h>

I did not do a deep dive into the BLE protocol. Instead, I relied on some code I found here that does what I need it to. The last code block in the post is the one that works.

See my code file for additional details.

I'm sure all sorts of improvements could be made to the code. For example:

  1. Currently if you lose the connection by going out of range or blocking the signal, you have to cycle power to reconnect.
  2. The specific Polar sensor is hard-coded in the software. Ideally, it would connect automatically to the one with the strongest signal, if more than one is detected. (When BT scans for devices, it also returns an RSSI value, which is an indicator of signal strength.) I ended up building two of these, one for my wife, who is the original requester, and one for me. They can only talk to their matching chest straps.
  3. I have not tested with other Polar sensor models. As far as I know it only works with the H7 model.

Once I understand the Arduino IDE, and the BLE protocols a bit more I'll work on those. For now, I'm happy with what I have.

Creating a Product

PolarDisplay_bb.png
hb-6.jpg
hb-5.jpg
hb-7.jpg

The project goal has been met! I have a large display showing my heart rate from my Polar chest strap. Now it needs a package to make it user friendly. I settled on a cube-like appearance with the display filling one face, an on/off switch and a charging/programming port.

The original Arduino UNO R4 WiFi board I used for development is large, expensive, and over-kill for this project. I want to save it for developing other projects.

Adafruit has a large selection of Arduino boards that are designed to be incorporated into end-products. I selected the ESP32 Feather V2 board with these key features:

  1. It's small.
  2. It has a lithium battery connection with builtin charger.
  3. The ENable pin on the board can be used as a power on/off control.
  4. There is a STEMMA QT connector for connecting the OLED display.
  5. The only solder connections would be for the two wires connecting EN and ground pins to a switch.

The connection diagram is shown above. The only soldering I had to do was some jumpers on the OLED display to support I2C, adding a QWIIC cable to the display, and connecting two wires to the on/off switch.

Since I'm running this from a battery, having a fuel gauge is useful. Most Arduino boards come with Analog to Digital Converters (ADC) and they can be used to measure a voltage. The code for that looks like this:

#ifdef ARDUINO_ADAFRUIT_FEATHER_ESP32_V2               // this board has builtin has voltage detector
 #define VBATPIN A13
 float measuredvbat = analogReadMilliVolts(VBATPIN);
 measuredvbat *= 2;   // we divided by 2, so multiply back
 measuredvbat /= 1000; // convert to volts!
 Serial.print("VBat: " ); Serial.println(measuredvbat);
 u8g2_for_adafruit_gfx.setCursor(0,62);    
 u8g2_for_adafruit_gfx.print("Battery (V):"); 
 u8g2_for_adafruit_gfx.setCursor(90,62);    
 u8g2_for_adafruit_gfx.print(measuredvbat);           // display LiPo battery voltage
#endif

The Feather board includes a voltage divider connected to the battery connection and ground. The divided voltage goes to an ADC pin, which is read by a builtin library function. When I built the second version I used the Adafruit ItsyBitsy ESP32 which did not have the voltage divider built in. I connected two 1% 100K resisters between the GND and BAT connections, and connected the middle to the A2 pin.

Why a voltage divider? (If you know the answer, skip to the next paragraph.) The processor runs at 3.3 volts and the ADC can only report voltages between 0 and 3.3. The battery voltage can be as high as 4.2 volts when fully charged. Normally the ADC wouldn't be able to report this accurately, in fact, the ADC pin might not tolerate this and break the processor. Connecting two equal resistors (in this case) across the voltage divides it in half, resulting in a range that is measurable. The calculations in the code produce a useful display of the battery voltage. Similar strategies can be used to measure other even higher voltages by adjusting the ratios in the voltage divider.

The picture above shows all the parts nestled inside the 3D-printed enclosure. Not clearly visible is the small piece of clear plastic 3D printer filament which acts as a light pipe to channel the light from the charging LED on the board to a spot next to the power plug. This turns off when the battery is fully charged. The board's USB connection is accessible through the side of the case for charging and/or reprogramming.

Two dimensions of the case design are dictated by the size of the display. The third dimension is driven by the battery. I wanted to lay it flat on the floor of the case for stability, and to avoid blocking the antenna that's on the circuit board.

Ta Da...

hb-8.jpg
hb-1.jpg

All done. When the monitor turns on it shows which Polar sensor it's looking for and shows the current battery voltage. When the sensor is worn, the heart rate is displayed and can be seen easily across the room. I've tested the distance to 45 feet, which is larger than my exercise space.

I've tested this with several ESP32 boards - check the code listing for details. That I can easily move this project among different boards is a testament to the flexibility and robustness of the Arduino hardware and software environment. I did notice something interesting... The time to compile and load the project onto a different board can vary, a lot. The more complex the processor, the more translations and libraries need to be brought in.

Thank you to devlove1 for posting their code. And many thanks to all the people at Adafruit for making some fine, and fun, products, and providing excellent documentation. I couldn't have done this without you.

Happy building!