The reason I did this project is because I have a slight overheating issue in a server room; I was wondering if there would be some way to check another room’s temperature from my desk. That’s how I came up with a “wireless thermometer” that can send readings to my Android phone, and my colleagues can use it too!
You might have heard about the nRF24L01: it is a cheap (0.80€) radio frequency module that, back in 2013, Dmitry Grinberg was able to use to “fake” a BTLE beacon. Real Bluetooth 4.0 modules are, nowadays, about 5€ each.
I wondered if I could use it to make a BTLE compatible temperature beacon. Turns out there are 3 major BTLE beacon protocols: iBeacon (by Apple), Eddystone (by Google), and AltBeacon (by Radius Networks). And well, none of them can be emulated with the nRF24L01, since it is only able to send a 16-byte payload (among other limitations), and all three of those protocols require bigger PDUs.
BUT!!! Although I didn’t find a name for it, Nordic Semiconductors Bluetooth ICs (namely the nRF8001 and nRF51822) have their own protocol they use to send telemetry data (which means: temperature, battery level and device ID); turns out this protocol is simple enough to be emulated by the nRF24L01 as well, although with some limitations. They also are so nice to distribute a suite of Android and iOS apps to work with them; the most relevant apps are nRF Master Control Panel (useful for debugging BTLE devices) and nRF Temp 2.0 (a temperature logger; I think it was meant to track device overheating, but hey). You can also download the source code from the app page!
However, the temperature in my room is quite boring, as shown from those screenshots of Nordic Semiconductors apps. (nRF Master Control Panel on the left, nRF Temp 2.0 on the right).
The temperature beacon hardware is very simple. Just wire up your microcontroller to a nRF24L01 and a temperature sensor of your choice (I used a DHT11 I had lying around).
It’s more about how you wire them up, I guess.
- GND -> GND on the Arduino
- VCC -> 3.3v on the Arduino
- CE -> PIN 9 (see below)
- CSN -> PIN 10 (see below)
- SCK -> PIN 13 on the Arduino Uno
- MOSI -> PIN 11 on the Arduino Uno
- MISO -> PIN 12 on the Arduino Uno
- IRQ -> not used
Be especially careful about the power pin: altough the nRF24L01 can work with your 5v Arduino, you must power it at 3.3v!
While SCK/MOSI/MISO are pretty much wired to 13-11-12 pins in order to use SPI, CE and CSN can be moved to a pin of your choice.
About the DHT11, just wire its output pin to A0, and the other two to ground/+5v.
On the software side, I did a couple modifications on floe’s BTLE library to allow mimicking of the nRF8001 and nRF51822; you can find the BTLE library here. With this library, you can now create your temperature beacon. (Notice I used pins 9 and 10 as CE and CSN, as mentioned previously).
Did you know? Most Arduinos have an onboard temperature sensor! The reasoning behind this probably is that a device malfunction would overheat it. Unfortunately this can’t be easily used as an ambient temperature sensor, because the chip temperature is widely influenced by its heat dissipation. That’s why I used a DHT11. (You can read more about this on Arduino Playground here).
Among other limitations, this setup is not able to use more than 3 of the 40 BT 4.0 channels, and broadcast a name longer than 8 characters (remember that 16 byte limit?). I’m pretty sure it could be used to broadcast the battery level as well.
Sadly, it does not seem somebody has thought of writing a standard protocol for broadcasting some other non-temperature parameter (atmosphere pressure, light, noise level, etc). To a certain extent, nRF Master Control Panel can be used to receive arbitrary data from the Arduino (as float or as integer value), but it’s not suitable for logging and combined with the 16 byte limit it’s quite limited (BT also has a 2 bytes overhead for every field you want to send, hence: 8 bytes device name + 4 bytes temperature + 2*2 bytes of overhead = 16 bytes). If I’m wrong, let me know!
I hope you enjoyed this article!