Week 12

Goal

For this week, I wanted to develop a communications system for my final project.

Hardware

I decided to use nRF24L01+ radios for their simplicity. First, I perused the datasheet. I wanted to design a chip-down board with an on-board antenna. Anthony ordered chips for me from DigiKey, but I ultimately decided against this because of the following risks:

  • laser-engraving the footprint
  • soldering the chip
  • designing the antenna

(I am now motivated to design a standard set of ISM antenna symbols for the fab library.)

So, I decided to use the ubiquitous nRF24L01+ breakout board. It has 8 pins: 2 for power, 3 for SPI, 2 extra control pins (one is loosely a SPI CS), and an IRQ pin.

My system will use a SAMD21 on one side and a RP2040 on the other. I used the XIAO package for the SAMD21 and the Pico package for the RP2040. For the SAMD21, there is only one option for the SPI. I used D1 and D2 for the other control pins and skipped the IRQ. For the RP2040, there are many options for SPI, but I used the defaults.

Something I discovered quickly was that the radios could not run reliably on high power off of the Pico’s 3v3. The current demand is lower than the current supply according to the datasheets, but the regulator is switching, so perhaps there is interference. I ran both radios off the XIAO’s 3v3, which is a 700mA LDO.

MAC

I want to write my own MAC eventually, but I started with the RF24 MAC which, based on some quick Internet searches, seems to be the de-facto standard for these radios. I downloaded it in the form of an Arduino library, and was able to compile it for both platforms with no problem.

I read through one of the provided examples (GettingStarted.ino). Using that sketch as a guide, I wrote two simple test programs: simple_receiver.ino and simple_transmitter.ino. The pair acts as a Serial pipe.

There are a few caveats. The first is payload size. The largest and default payload size is 32 bytes. The size can be changes dynamically at the transmitter, but the receiver seems to need to know about the size before decoding the preamble. So, I just kept it at 32. For real applications, a struct would be used, and then both sides can be set to the size of the struct.

The other caveat is more of a curiosity than anything else. The example code talks about a 6-byte “address”, but it behaves more like a channel. The transmitter is assigned a 6-byte sequence which is uses to address its packets. Receivers map these addresses to pipes, and receive any packet which matches one of the mapped addresses. The RF24.available() method reports the active pipe via a pointer. This is a great little mechanism that can be really useful for distributed systems.

The MAC also supports ACKs by default, so the transmitter can report whether or not a transmission succeeded. It gets better – the ACK can include a payload! This is great, because the radio has to be set as a receiver or transmitter explicitly, and based on some quick testing, the turnaround time is non-trivial at the MAC level.

Testing

I ran simple_receiver.ino on the Pico and simple_transmitter.ino on the XIAO-SAMD21 (I left the corresponding pin assignments in the source code). I had to set the PA levels to HIGH to get reliable performance, but other than that, the channel worked great. I will note that the receiver can get into a state where it reports receiving null bytes when the transmitter goes offline. I have not been able to reproduce this behavior reliably, though.

Future work

This is a great little radio, and I wish I had more time to play with it. Even within the RF24 MAC, there are a few features I’d like to try. Namely, I’d love to implement a “status” command that utilizes the ACK payloads. I also want to enable use of the IRQ pin (which I did connect in the final board).

More excitingly, I’d love to write my own MAC instead of relying on RF24 – not because I found anything I disliked about RF24, but because it sounds fun. Perhaps I’ll do a TDMA MAC, as I did at Starry. I’m looking forward to an excuse to do so.

Also, a I mentioned, I’d love to design some PCB antennas for our standard FR1 stock.

Sources