Bluetooth low-energy temperature beacon using the nRF24L01: cheap and compatible with existing smartphone apps!

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!

wpid-wp-1444076649110.jpeg  wpid-wp-1444076692964.jpeg
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).

wpid-wp-1444076633700.jpegIt’s more about how you wire them up, I guess.


  1.  GND -> GND on the Arduino
  2. VCC -> 3.3v on the Arduino
  3. CE -> PIN 9 (see below)
  4. CSN -> PIN 10 (see below)
  5. SCK -> PIN 13 on the Arduino Uno
  6. MOSI -> PIN 11 on the Arduino Uno
  7. MISO -> PIN 12 on the Arduino Uno
  8. 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!

  • Mike

    Note that Eddystone-URL packet sizes can be smaller, because of the variable-length URL component. Have you tried broadcasting a short URL? See for details.

    • simonebaracchi

      As I got it, each Eddystone packet, including Eddystone-URL, must have a fixed 11 bytes prefix. That leaves you about 5 bytes of custom data… not quite enough for a URL. See here:

    • Mike

      I see. I wasn’t sure which bytes were included in the count. Also, I don’t know what the value 21 means here: Note that URLs in Eddystone-URL are encoded, so it’s possible to make them shorter: It still might not be enough to put in a meaningful URL.

    • simonebaracchi

      That’s the maximum raw packet size (but not including some other mandatory fields added later in the code, such as checksums). Each packet must contain device flags (specifying what your device can or can’t do, 3 bytes) and its name (which apparently can be empty, but takes up two bytes anyway… in this library at least) which together account for the 5 bytes of difference from the 16 bytes limit

  • FesterBesterTester

    I don’t understand the 16 byte payload limit. Both the nRF24L01 and the nRF24L01+ have a max payload length of 32 bytes. See section 7.3 of the datasheet. What am I missing?

    • admin

      32 byte is referred to the nRF24 protocol, this code forces the nRF24L01 to mimic BLE, so a certain amount of bytes is dedicated to mandatory BLE fields, CRCs, etc.

    • Jens Jensen

      It is explained in detail in Dmitry Grinberg’s article which is linked to in the second paragraph of this article.

  • Serg

    Nice job!
    And what’s the power consumption on both beacon and phone side? Wouldn’t it drain the power of my smartphone while it’s sitting on the broadcast channel?