The tempANT+ Project
ANT+ is a wireless protocol used in sports devices. In this project article, Carlo uses this technology, along with Nordic’s nRF52832 MCU, to build a multipurpose sports-wearable device that measures and records body temperature, and pairs with other devices.
Multiprotocol microcontrollers (MCUs) are gaining more and more relevance in the market. The nRF52832 manufactured by Nordic Semiconductor is one of them. In my last article, “Build a Multi-Purpose GPS Tracker” (Circuit Cellar 359, June 2020) [1], I had made use of its younger brother, the nRF51822 using the BLE4.0 protocol. I promised myself that I would explore the multi-protocol functionality and perhaps try using it for commercial product integration.
Here, I describe the results of this new fun experience. A profile development system made available by Dynastream Innovations allowed me to create, in a short time, a small device capable of communicating with navigator sports watches produced by major brands such as Garmin and Suunto. In this way, I tested my circuit on everyday devices, customizing it for my purposes. I used a very popular protocol in the sports devices field called ANT+.
The first prototype was initially born with the idea of developing an ANT+ basic communication infrastructure that allowed pairing with other commercial devices. Then, I added an ambient-temperature-monitoring function. I customized the prototype using a Maxim Integrated chip that features a particularly high accuracy in the body temperature measurement. I thought it might be useful to monitor body temperature in demanding fitness sessions, especially during summer. I wanted to try to make a recording within 24 hours. The pandemic has accustomed us to frequently measure our body temperature. In the end, I made a multipurpose device that can be paired in a few seconds with different types of devices used in the outdoor world. I tested it with the legendary Garmin GPS64t navigator that I often use on my bike rides. It was really satisfying to see the navigator recording a GPS track with integrated temperature values, without having to change anything on the original device.
With all that in mind, I decided to completely share the details of this small project. This includes the firmware based on the ANT+ environment profile, which is useful as a communication infrastructure for various types of environmental probes. The project also involves the creation of a small circuit based on the nRF52832 core to send temperature values detected by a MAX30205 to the paired commercial device. The GPS navigator or the sport watch will process data by viewing the real-time values on the display, or by recording them in a data file.
Some ANT+ devices already on the market are able to perform similar tasks—Garmin’s tempe [2] for example. It is interesting, however, to take part in a development/integration process—a kind of purchased-product personalization. In this way, our curiosity does not end with the mere purchase of a new technological gadget, but rather, it evolves toward the use of an open object shaped for our purposes. It is a way, therefore, to learn how to use the widespread ANT+ protocol and the Dynastream profile environment to make commercial objects more your own.
TO EACH HIS OWN PROFILE!
ANT+ is a managed network that uses “device profiles” to define how to send data over the network in a consistent and efficient way. So, before you start working with ANT+, you will need to understand how the ANT+ profiles work. Each device has a profile, and each profile identifies uniquely a class of devices. The developer company has also designed precise icons that can be used on the packaging of certified devices. Before any project, you must, therefore, choose a profile that suits your case.
— ADVERTISMENT—
—Advertise Here—
So, what is a device profile and how to implement it? Each ANT+ device profile contains the network rules relevant to a specific use case, for example heart rate or temperature monitors. These include settings for the channel parameters, the data transmitted format and other specific parameters that standardize the wireless communication between individual devices. This management of device communications characteristics provides interoperability, so profiles are not isolated!
Any ANT+ device that implements a particular device profile is interoperable with any other ANT+ device implementing the same device profile. This allows an “ecosystem” of interoperable devices to be formed. A temperature ANT+ can be used with any ANT+ watch or navigator that implements the ANT+ Environment Monitor device profile. The Temperature monitor can be interchanged for any other ANT+ environment monitor, from any manufacturer. It is common for display devices to implement several device profiles at once.
For this project, I decided to implement the environment profile, which allows you to measure a variety of environmental parameters. My initial idea was to measure the ambient temperature and send it to a collector device, such as a handheld GPS, for real-time display or recording during tracking. The ANT+ environment sensor may optionally support the ANT File Share Technology (ANT-FS). In this use case, the sensor stores measurement data in a specific formatted file and makes it available upon request. I skipped the development of this optional part, because I use the recording features already present in the target devices, a simpler approach for the first-time user.
IMPLEMENT YOUR PROFILE
Once you have chosen the profile that best suits your goal, you need to implement it. Each profile consists of two fundamental sections:
- Channel and Network configuration parameters
- Data Pages
In the first section, configuration parameters are established by the ANT protocol. You can find all details on the documentation made available on the thisisant.com website at [3]. To get started, take a look at ANT Message Protocol and Usage. Here, I describe only the sensor configuration essentials. It has a Controller role, while the Collector works as a remote. Each sensor must define seven fundamental elements, as shown in Table 1.
The network key is one of the channel configuration parameters that must be set correctly for devices to communicate. To obtain the ANT+ network key for your personal devices, you need to become an ANT+ Adopter and agree to the terms of use. Devices use the network key to identify and access the ANT+ network; the radio module will not hear transmissions occurring on other networks. In my source code (see the Circuit Cellar article code and files download webpage), this field is all zeros, so everyone can use their own key.
Using different networks is a great way to separate devices that aren’t intended to communicate. Developers can define their own way of setting and interpreting the 8-byte ANT payload without getting confused by other devices. If you are only experimenting with ANT+, you can use the public network key too.
For the second section, consider that each ANT+ Message is made up of 8 bytes. The first byte contains a numeric index that refers to the Data Page Number, while the other 7 bytes contain the data transmitted by the sensor. There are four types of Data Page: Main DP, Background DP, Request DP and ANT-FS DP. Details on this part can be found in the ANT + Environment Device Profile documentation at [4]. In Table 2 you can see the structure of Data Page 1. It is the main data page broadcast from tempANT+ to send temperature information.
To simplify the source code, I implemented only the Minimum Data Page Requirements. Therefore, the Data Page 0 and Data Page 1 contain, respectively, the general information and the temperature values, and the 80 and 81 Background Pages contain manufacturer’s identification and product information.
— ADVERTISMENT—
—Advertise Here—
So, only the main data pages 0 and 1 are formally supported. The recommended transmission pattern is alternating main data pages with common data page transmitted every 129 messages. In Figure 1 you can see a typical ANT+ environment sensor broadcast use case. The tempANT+ transmits main data pages with temperature values with rates of 0.5Hz or 4Hz. The display may request every broadcast data page from the sensor. If the requested data page is not supported, the sensor simply does not respond and continues to send data. The collector device handles this “no response” case.
DESIGN AND CONSTRUCTION
The circuit consists of a core module based on Nordic’s nRF52832. I used an inexpensive board made by Holyiot Technology, a partner of Nordic Semiconductor. You can find it on the Internet under the name YJ-16002. It is built around the nRF52832, a multiprotocol system on chip for ULP wireless application. It incorporates an Arm Cortex M4 CPU with floating point unit running at 64MHz, 512KB flash memory, 64KB RAM memory and a powerful radio transceiver on 2.4GHz. It is on-air compatible with nRF51 and nRF24AP series devices from Nordic. The breakout board for temperature measurement can be found by searching the Internet with the keyword “CJMCU-30205.” It is based on the excellent chip MAX30205 produced by Maxim Integrated. The MAX30205 is a human-body-temperature sensor with a high-resolution ADC (16-bit temperature resolution) and a 0.1°C accuracy in the range 37°C to 39°C. Communication is done through an I2C interface, and you can use One-Shot and Shutdown modes to reduce power usage.
The nRF52 series RF transceiver is interoperable with ANT+, BLE 5 (Bluetooth Low Energy) and other 2Mbps 2.4GHz proprietary stacks. As shown in the schematic in Figure 2, the nRF52832 is in the basic configuration with a 32MHz oscillator crystal and a little impedance network adapter for the integrated PCB antenna. I added a high-brightness LED D1, connected to pin P0.17 for circuit status signaling with its limiting resistor R4. Table 3 shows the parts list associated with the schematic.
Pins P0.11 and P0.13 are configured, respectively, as SDA line and SCL line of I2C communication bus between nrf52832 and MAX30205 breakout board. R1 and R2 are the pull-up resistors required for the I2C data bus. The MAX30205 is configured as a continuous measurement sensor, so as soon as it is powered, it begins to evaluate the temperature. The MCU periodically reads the internal 16-bit register (address 0x00), calculates the final value and sends it via ANT+ to the associated device.
An interesting aspect is that the MAX30205 measures the temperature through an Exposure Pad connected to GND. The breakout board has a little hole under the EP, and a thermal interface (I suppose a polymer with high thermal conductivity) to the bottom of the PCB. Therefore, if you do not want to limit yourself to ambient temperature measurement, you can couple a small copper plate to the underlying side that should be put in contact with the body.
The CR2032 battery is sufficient for experimenting, but the MAX30205 can be configured in One-Shot mode. In this way, the chip remains in Shutdown mode most of the time, saving energy. In the same way, the LED emits a flash at each ANT+ packet sent. To save energy, you can turn on the LED only at start-up.
For a simple and very small assembly, I have created an interconnection layer. It is a small card that allows you to simply connect the two cards, adding only one LED, one resistor and a battery holder. As shown in Figure 3, the green small card is in the center. The interconnection board also includes a connection strip for a battery and e JTAG bus (VCC, SWDIO, SWCLK, GND) to update the firmware.
Figure 4 is an illustration of the top and bottom copper layers of the interconnection layer. As you can see, it is a small card with a very simple scheme to connect the two-breakout boards together. Assembly takes place by welding the cards to the interconnecting layer, one above the other, like a sandwich. In Figure 5, you can see the assembled prototype board, viewed from above and below.
THE FIRMWARE
Unlike the project described in my previous article [1], in this project I used the SDK ver.16 for the nRF52 series and the SoftDevice S212, both supplied by Nordic Semiconductor. This SoftDevice contains a highly flexible ANT + stack protocol that supports all features necessary to create a communication network for ANT+-compliant devices. In the firmware source code, there are two interesting sections: the profile structure assigned to the device, and the TWI (Two-Wire Interface) communication driver managing.
To avoid compilation errors, a brief introduction is helpful regarding the Network Key and the integration of SoftDevice S212. After SoftDevice download and before compiling the firmware code, you have to copy the headers to your SDK Install Folder (/components/softdevice/s212/headers) and uncomment the ant_license_key
in the nrf_sdm.h file. When you have obtained your network key or the public one, you have to provide values for the two #defines
in the ant_key_manager_config.h file. These values are fundamental, and will be used during channel and profile initialization.
Unfortunately, the ANT+ Environment profile is not included in the nRF52 SDK. So, we need to start from another profile, for example the similar HRM (Hearth Rate Monitor) profile. Once the structure has been imported, the next step is to add the tempANT+ support for data page requests that could be sent by the GPS handheld, and then decide how to respond to these requests.
In this article, there is not enough space to discuss and analyze all the profile development details. I will describe its logical structure, which is, perhaps, the most difficult part for a beginner. By reading the instructions list in each file, it will be possible to understand all steps in the complete development.
PAGES AND UTILS
The profile static part consists of two directories (sdkInstallDir\components\ant\ant_profiles\ant_envir) named pages and utils. In the pages directory, there are all declarations and functions for the main data pages managing (only page 0 and 1). In the utils directory, instead, there are some support functions, such as the macro to calculate the minutes from the Operating Time, or the definition of the Operating Time Unit to calculate the messages broadcasting frequency. All the definitions of the Background Data page common to multiple profiles are saved in another directory:
sdkInstallDir\components\ant\ant_profiles\ant_common.
In my project, I defined pages 80, 81 and 70. Remove all the unnecessary characteristics of the reference profile, and eventually rename variables to make them easily identifiable in case of future updates. Each page is always implemented in the same way by defining a data structure containing: the page fields, the default values and two functions—one for encoding and one for decoding. Listing 1 gives the main static structure of the Main Data Page. It contains the environmental parameter values we are monitoring.
Listing 1
Main data page 1 structure
typedef struct
{
uint8_t reserved;
uint8_t event_count; /// event count - increments with each measurement
uint8_t _24_hour_low_lsb; /// the lowest temperature recorded over the last 24hours
uint8_t _24_hour_low_msn:4;
uint8_t _24_hour_high_lsn:4; /// the highest temperature recorded over the last 24hours
uint8_t _24_hour_high_msb;
uint8_t current_temp_lsb; /// the current Temperature
uint8_t current_temp_msb;
} ant_env_page1_data_layout_t;
#define DEFAULT_ANT_ENV_PAGE1() (ant_env_page1_data_t)
{
.event_count = 0,
._24_hour_low = 0,
._24_hour_high = 0,
.current_temp = 0
}
void ant_env_page_1_encode(uint8_t * p_page_buffer, ant_env_page1_data_t const * p_page_data);
void ant_env_page_1_decode(uint8_t const * p_page_buffer, ant_env_page1_data_t * p_page_data);
Note that the initial struct
instruction follows the fields sequence indicated in Table 2, whereas in the encode
function, we pass the pointer to the data page and the pointer to the data buffer, to prepare the values for loading the ANT+ message payload transmitted to the collector device. In the decode
function, the reverse operation is performed by extracting the values from the buffer and initializing the data page structure. In this project, the decode function is not necessary, because the tempANT+ tag does not work as a display, but only sends the temperature data.
— ADVERTISMENT—
—Advertise Here—
The profile dynamic part is composed of three main files: ant_envir.c, ant_envir.h and ant_envir_local.h. It is managed by three main functions: the ant_env_sens_init
for initializing the Environment Profile instance; the ant_env_sens_open
for opening the profile instance channel and the ant_env_sens_evt_handler
for handling the sensor ANT events. You can find all these functions in the ant_envir.c file. In this file we define the structure of the ANT+ message, which is simply composed of a 1-byte data page number and a 7-byte payload for sensor specific data. Then, we define the event handler that will actually manage the sending of Data Pages.
TWO-LEVEL HIERARCHY
There is a two-level events hierarchy. The first is general and defines the data direction in transmission or reception. The second is specific and discriminates the type of page to be sent on the identification page number. For tempANT+, only the transmission event is developed. It causes the execution of three functions nested one inside the other: ant_message_send
for setting ANT message payload, sens_message_encode
for setting fields inside the payload, depending on the data page and sd_ant_broadcast_message_tx
an ANT+ stack API for managing the real transmission through the MCU radio module. The event system is synchronized through a timer tick, and for each managed message it is necessary to increment a counter to follow the recommended transmission pattern.
For I2C communication in this firmware, unlike the previous ones, I used the TWI nrfx driver, which has a common use mode for different types of serial devices. The use is more complex than other drivers, but allows you to centralize the peripherals managing. Four main phases are used: enable
driver
and define instance
, callback function
, initialize drive
r and communicate
.
In the first phase, it is necessary to enable the driver in the sdk_config.h file and define an instance. Each instance is associated with a single device, so unlike other types of drivers, here we do not define just a port but an instance for each connected device. In this way, the communication management code is decoupled from the one that processes data of each specific device. The callback
function is used to establish the event management limits. In this project, we precisely define the end of the data reception event from the I2C bus. Each function is linked to a device, so a new function is needed for each device.
Finally, we import the interface initialization functions and the related read and write operations into the main code. In this phase, the physical port specifications are defined: pin assignment, frequency, IRQ priority and so on. In Listing 2 I summarize the different TWI driver use phases, so you can easily re-use them in other serial bus communication projects.
Listing 2
Two-Wire Interface (TWI) nrfx driver sequence
ENABLE DRIVER
sdk_config.h
#ifndef TWI_ENABLED
#define TWI_ENABLED 1
#endif
#ifndef TWI0_ENABLED
#define TWI0_ENABLED 1
#endif
#ifndef TWI0_USE_EASY_DMA
#define TWI0_USE_EASY_DMA 1
#endif
DEFINE INSTANCE
main
static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID);
static volatile bool m_xfer_done = false; /* Indicates if operation on TWI has ended. */
CALLBACK FUNCTION
void twi_handler(nrf_drv_twi_evt_t const *p_event, void *p_context)
{switch (p_event->type)
{case NRF_DRV_TWI_EVT_DONE:
if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_RX){}
m_xfer_done = true;
break;
default:
break;}}
INITIALIZE DRIVER
void twi_init(void)
{ret_code_t err_code;
const nrf_drv_twi_config_t twi_config = {
.scl = TWI_SCL_PIN,
.sda = TWI_SDA_PIN,
.frequency = NRF_DRV_TWI_FREQ_250K,
.interrupt_priority = APP_IRQ_PRIORITY_HIGH,
.clear_bus_init = false};
err_code = nrf_drv_twi_init(&m_twi, &twi_config, twi_handler, NULL);
nrf_drv_twi_enable(&m_twi);
APP_ERROR_CHECK(err_code);}
COMMUNICATE
uint32_t twi_read_TEMP(uint8_t MAXAddr, uint8_t *rxData, uint8_t bytesRx){}
int8_t twi_write(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint16_t length){}
A LIVE EXPERIMENT
I tested the tempANT+ tag with a Garmin 64st GPS navigator. First, power the device and associate it with the navigator that will work both as a display and as a recorder. Connect the battery—the tag immediately begins to detect the temperature, and the white LED flashes regularly. Power the navigator, enter the Setup menu and go to the ANT Sensor item. A list of possible pairing devices will be displayed. Let’s go to Tempe Sensor and enable it. After a few seconds of searching, the status will change from Searching to Connected. During navigation, you can view the temperature value in real time. In Figure 6 I have summarized the pairing sequence through the GPS screens and the final result during navigation.
If we start GPS tracking, the navigator will automatically add an XML label called gpxtpx: atemp to the .gpx file. It contains the detected temperature, for instance <gpxtpx: atemp> 28.7 </ gpxtpx: atemp>. The recording takes place for each GPS point. In this way, it is possible to view the temperatures associated with each geographic position through the Google Maps services or dedicated software such as QGIS.
CONCLUSION AND EXPANSIONS
As I promised in my last article, after describing some developments based on Bluetooth technology, I switched to ANT+—integrating a simple thermometer with a commercial device such as a GPS handheld. This project is a basic application example for ANT+ profile developing. The template can be used for more sophisticated profile development, or to experiment with the ANT+ protocol communications. ANT+ is widely used in sports, so I believe that this experience will be useful in the future to try to interface some new device used during my outdoor training sessions. For now, I hope this circuit can be useful for those who want to experience a device system integration on ANT+.
See you in my next article!
RESOURCES
References:
[1] “Build a Multi-Purpose GPS Tracker” (Circuit Cellar 359, June 2020)
[2] https://www.thisisant.com/directory/tempe-wireless-temperature-sensor
[3] https://www.thisisant.com/developer/ant/ant-basics
[4] https://www.thisisant.com/developer/ant-plus/device-profiles
Dynastream Innovations | www.dynastream.com
Dynastream has moved to:
ANT Wireless | www.thisisant.com
Maxim Integrated | www.maximintegrated.com
Nordic Semiconductor | www.nordicsemi.com
PUBLISHED IN CIRCUIT CELLAR MAGAZINE • DECEMBER 2021 #377 – Get a PDF of the issue
Sponsor this ArticleCarlo Tauraso (carlotauraso@gmail.com) studied computer engineering at the University of Trieste in Italy and wrote his first assembler code for the Sinclair Research ZX Spectrum. He is currently a senior software engineer, who does firmware development on network devices and various types of micro-interfaces for a variety of European companies. Several of Carlo’s articles and programming courses about Microchip Technology PIC MCUs (USB-PIC, CAN bus PIC, SD CARD, C18) have been published in Italy, France and Spain. In his spare time, Carlo enjoys playing with radio scanners and homemade metal detectors.