Sunday, July 27, 2014

nRF24L01+ sniffer - part 2


The requirement to use cheap commodity hardware resulted in the use of a standard Arduino Uno R3 and a single nRF24L01+ module. Some male-female Dupont cables connect the radio to the Arduino. Other Arduino's based on AtMega328 should also work, as long as they have a serial interface to the PC and 3.3V power supply for the radio (the nRF24 I/O pins are 5V tolerant).
Be careful as multiple variants exist of the nRF24L01+ modules, and they don't all use the same layout for the pin header!

Connect the two as follows:
nRF24L01+ module pinout

FunctionArduino Uno pinnRF24L01+

Some applications don't connect the IRQ line, but the sniffer requires it to quickly respond to received packets.
This is what my sniffer looks like:

nRF24 sniffer hardware: Arduino Uno, prototype shield, some Dupont cables and nRF24L01+ module
I didn't have any male-female Dupont cables at hand, so I put a prototype shield inbetween to turn the female headers into male.


The required software is split in the following parts:
  • Sketch running on the Arduino: configures the nRF24 radio and reads any messages received using SPI. It determines the actual payload size for each message and adds a microsecond-resolution timestamp. The messages are buffered in the Atmega328 and sent to the host over a serial connection. It keeps track of the number of lost messages, when the buffer is full.
  • Console application 'Nrf24Sniff.exe' (currently only Windows) which sends configuration data to the Arduino sketch and reads captured packets from the sketch, using a serial connection. The packets received are forwarded in libpcap-format to a named pipe. Wireshark will be instructed to capture from this named pipe (too bad it cannot capture directly from a serial connection).
  • Wireshark to visualize the captured packets, filter them and gather statistics.
  • Wireshark will be extended with one or more plugins (called dissectors, currently only precompiled for Windows) which recognize the nRF24 packet format and take it apart. Protocols which use the nRF24 as transport layer (e.g. MySensors) require a separate dissector.


As you can see in the description above, the console application and Wireshark dissectors are currently only available for Windows (anyone who volunteers to port them to Linux and/or Mac, please do so and let me know).
In the description below I assume you've already downloaded and installed:
  • Wireshark - I used 1.10.8, either 32- or 64-bits
  • Arduino IDE - I used 1.5.6-r2, but I guess any 1.5.x version will do
First download and extract the software I developed as a single zip-file from my GitHub repository.

Arduino sniffer sketch
Either move the contents from the 'Arduino' directory to your Arduino users' directory (c:\users\<yourname>\Documents\Arduino) or copy it elsewhere and instruct the Arduino IDE to use that directory by pointing Preferences -> Sketchbook location to it and restart. I'm a bit reluctant when it comes to copying libraries to your regular users' Arduino directory as it might conflict with any libraries already present. Beware that I changed some small thinks in the RF24 library that's included.
Start the Arduino IDE, load the NRF24_sniff sketch, connect the hardware setup as described above, select the correct board & comport and download the compiled sketch.

The Windows console application which transfers captured data from a serial interface to a named pipe can be found in the 'SerialToPipe/bin/Win32' directory. Just copy this executable somewhere convenient.

Wireshark dissector(s)
Choose the directory matching your 32- or 64-bits install from 'Wireshark/bin/Win32' or 'Wireshark/bin/Win64' and copy the nrf24.dll to the Wireshark plugins directory, e.g. 'c:\Program Files\Wireshark\plugins\1.10.8\'.
Those using the MySensors library can also copy either mysensors1.dll (version 1.3 of the library) or mysensors2.dll (version 1.4beta), depending on the library version you're working with. Better not copy both of them as these are heuristic dissectors which have problems detecting the protocol version reliably.


Connect the hardware running the sniffer sketch to your PC (either using an RS232 connection or a serial-to-USB bridge as present on the Arduino Uno). Note the comport assigned by Windows (the same port as in the Arduino IDE). Assure the Arduino IDE's Serial Monitor is not running as it will block access to the serial port.

Nrf24sniff.exe can be started from a cmd-window. It supports a number of commandline parameters which control its behaviour (display them using 'Nrf24Sniff.exe -h'):

For example, when monitoring MySensors 1.4beta traffic (at non-default 1Mb/s), using the Arduino Uno sniffer connected to com17, I run the tool as follows:

Nrf24Sniff.exe -P17 -c76 -r0 -l5 -p4 -a0xA8A8E1FC00 -C2

The address length is set to 5 bytes (-l5), of which 4 bytes are used as base address (-p4) (Please refer to part 1 of this series for a description of addressing schemes). Passing only the comport would have been sufficient in this case, as the rest of the parameters are all set to defaults.

Now run it:

Keep it running and open another console window to start Wireshark:

This instructs Wireshark to start capturing from interface (-i) \\.\pipe\wireshark (that's the named pipe Nrf24Sniff.exe will be writing to) and to start capturing immediately (-k). More commandline options for Wireshark can be found here.

After Wireshark starts capturing, the Nrf24Sniff console window will display a 'Wait for sniffer to restart' message for a few seconds (at most):

If it hangs here, restart the sniffer hardware manually by pressing the reset button on the Arduino (I'm working on that...).

As Wireshark has no clue how to interpret the data coming through our named pipe, we have to tell it which dissector to use.
Switch over to Wireshark and select Edit -> Preferences.
In the preferences window, open the protocols tree, scroll down and select DLT_USER.
Press the edit button for the 'Encapsulations table' and press New. Enter the data as in the screenshot below:

Press OK, OK, OK. Any packets on air that match the radio configuration should now be captured in Wireshark!

The Nrf24Sniff console shows a count of packets captured and lost:

What's next

The next and last part of this series will dive into the possibilities of Wireshark and the dissectors I've implemented for nRF24 packets and the MySensors protocol.

Aug 3 - statically linked Nrf24sniff.exe, so dependency on msvcr110.dll no longer exists. Should also work on WinXP now.


  1. When i upload the sniffer.ino , i get the error: circularbuffer.h is missed??
    i use arduino 1.5.8

  2. You need first to Import the libraries CircularBuffer and RF24

  3. I use wireshark 1.12.1 and receive and error
    "The procedure entry point tvb_length cold not be located in the dynamic library......"
    Some one cold help me?

  4. Hey Ariel,

    I developed using Wireshark 1.10.8. Probably the API has slightly changed since then.
    Please try with Wireshark 1.10.x.

  5. Is it possible to use this with an Arduino Mega 2560 or an Arduino Pro?

    1. In principle it should work (maybe you have to change some pin assignments). I didn't test it, though.

  6. Hi.. I experimented a bit with your code and found some things I'd like to mention for others:

    The code seems to be only able to capture Enhanced Shock Burst messages. I've also experienced problems whithout enabling the dynamic payload length bit on the TX device. The mentioned limitation in part 3 (node addresses can only be 1 byte long), isn't present in the nrf24 dissector... It's only in the mysensors dissector.

    Anyways... Good work... I'll try to port the PC stuff to linux... If I succeed I'll contact you on github.

    1. Hey Didi!

      Thanks for the remarks! You're right about the node address: it used to be present, but I added a piece of configuration data (after writing this article) which is exchanged between the sniffer and the nrf24 dissector. I forgot to remove the limitation from this article ;-)
      It would be very nice if we could have a shared codebase for both Windows & Linux. Keep me informed!



    2. Sure.. I'm trying to change as little as possible... I will definitely not touch the Arduino Code for example, because I've got no clue of that and it seems to be a solid working piece of code which doesn't really come with any limitations... (Am I right assuming that it would even be possible to capture normal messages (Non Enhanced Shockburst) with just a new nrf24 dissector?)

      There are major differences in serial connection handling on windows and linux though...

      Greetings, Didi

    3. Edit:
      Have you ever tried to receive Enhanced ShockBurst message with NoAck Bit set? I'm not sure wheter I've made a mistake in my TX code or not... I'll try to debug that anyways sooner or later, but it would be awesome if you could save me some time with that information. :)

      Greetings, Didi

  7. Hi,

    I ported the Serial2Pipe Tool to linux and filed a pull request on Github.

    I was also able to answer my questions above on my own:
    The Arduino code is also assuming Enhanced Shockburst messages with a dynamic payload.
    The error seems to be in my TX code. So this project just works like expected.

    Greetings, Didi.

  8. This comment has been removed by the author.

  9. Hello. I copied files to "d:\Program Files\Wireshark\plugins\2.0.2\nrf24.dll"
    But I received an error. Please, see the picture

    1. Use Wireshark 1.10.8, as I did. Wireshark tends to change their plugin interface regularly and this is what you've probably ran into.
      You can get it here:

      Good luck!

    2. This comment has been removed by the author.

    3. Thank You very much for reply. It worked. I receive no errors, but I can't catch any packets.
      I connected GateWay and a node with humidity sensor. Domotics is receiving data but I can't see it in the Wireshark. Can You, please, help me?
      I'm using Mysensors 1.5

      Connect Wireshark to \\.\pipe\wireshark to continue...
      Wait for sniffer to restart Ok

      Channel: 76
      Datarate: 1Mb/s
      Address: 0xa8a8e1fc**
      Max payload: 32
      CRC length: 2
      Captured 0 packets, Lost 0 packets

    4. Here is data from serial (I stopped Wireshark for this and commented binary_output )

      -- RF24 Sniff --
      4e 4c00050400fce1a8a80000000220 Channel: 76
      Datarate: 1Mb/s
      Address: 0xA8A8E1FC**
      Max payload: 32
      CRC length: 2

      STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
      RX_ADDR_P0-1 = 0xa8a8e1fc 0xc2c2c2c2

      //Some other data


      And this is all.
      What am I doing wrong?

    5. This comment has been removed by the author.

    6. I changed to -r2 and it works :)

    7. Yup, -r2 sets datarate to 250KBit/s, which is default for MySensors.
      Great to hear you finally gor it working!
      To anybody else not capturing any packets: check-double-check the wireless parameters! Wrong configuration will cause you to capture nothing.

  10. I set up everything as per your instructions, but Wireshark doesn't sniff any traffic. No errors, just captured 0 packets, lost 0 packets. When I unplug nRF24L01+ from Arduino during the sniffing process it shows me "illegal serial packet size 9". Any ideas what I could possibly do wrong? I checked and doublechecked all the instructions everything 100 times. Thanks in advance.

    1. I`m getting the same problem.
      any ideas how to solve this?

  11. This comment has been removed by the author.

  12. Hi. Is it possible to record data by Raspberry Pi and then analyse on the PC? I need to log data from the chineese power meter "mhf120200P" that uses nrf24 to transmit data. But I do not know the detailes of the signal (channel, etc..)

  13. I get the following error message after starting the sniffer:

    "M:\Arduino\Projecten\NRF24_Sniffer-master\SerialToPipe\bin\Win32>nrf24sniff.exe -P9 -r2 -c76 -l5 -p4 -C2-a0xA8A8E1FC00

    Connect Wireshark to \\.\pipe\wireshark to continue...
    Wait for sniffer to restart -
    ALERT: Failed waiting for sniffer to restart"

    The Sniffer exits as soon as I start Wireshark....any suggestion?

    1. Problem solved!! Forgot to uncomment #define BINARY_OUTPUT