Wireless Communication via the mRF24J40MA

Tracking what's going on inside your robot is difficult at the best of times. Perhaps you have an LCD display, or a serial connection to your development machine. At some point, however, you'll have to unleash your creation and let it roam free.

I decided to add a wireless transceiver module to Fitzy and Carraldo so I could track what the sensors were reporting and more importantly what the robots were 'thinking' and what they had deduced about their environment. An email I received from a fellow builder in Australia suggested the 2.4GHz NRF24L01+ which can be had on Ebay for ridiculously low prices.

nRF24L01+ modules available on eBay

These looked pretty appealing but in the end I opted not to use them. The range seems pretty variable. Some people report getting 50-100ft (line of sight) whereas others get as little as a few feet. For a future project I think I'll give these guys a go simply because they're almost free.

In the end the transceiver card I choose was the mRF24J40MA from Microchip. It is also a 2.4GHz device and supports ZigBee (although I don't use it) and also several Microchip protocols called MiWi. The MiWi protocol is simpler than ZigBee but has a much lighter footprint. The card, as you can see, is minute. It communicates via SPI, and can be had via DigiKey for about $12. There are also some longer range versions that are supposed to be good for up to a kilometer or two (line of sight).

nRF24J40MA 2.4GHz Transceiver module
2.4GHz mRF24J40MA Transceiver module.

What sold me was the ZENA packet sniffer that Microchip sells. I bought one from DigiKey for about $50. In retrospect it was $50 wasted, but more on that later.

Zena Packet Sniffer

The Good, the Bad and the Ugly

Microchip provides a MIWI library that can run on PIC18, PIC24, PIC32 and PIC33 (the family that I'm using) chips. That said, getting it to compile, let alone run, proved not to be trivial for me. I did succeed in the end but by that time I'd moved to a simpler library. Mind you, some of my wounds were self-inflicted but when I think of a library I think of something a bit more self-contained and easier to integrate into your own project..

In the end, Google led me to a site belonging to NerdFever. In pursuit of model rocketry he had taken the Microchip code, pared it down, and packaged it for the dsPIC32 chips. My code for the dsPIC33 is based on his. Thanks Dave. I'll be releasing that code in the next installment where I'm building a base station to allow my PC to receive and send MiWi packets.

SPI Interface

The microcontroller communicates with the mRF24J40MA via SPI. This was my first introduction to this protocol. The microcontroller acts as the master and the attached device is the slave. To communicate, the master sets the outgoing bit onto SDO and toggles the SCK (clock) line high then low (there are variations where levels are reversed). Interestingly, the slave sends data back to the master at the same time by setting its SDO line. Typically SPI will send (and receive) 8 or 16 bits of data with each write. As I read the datasheet the mRF24J40MA should support a 10MHz SCK signal. The SPI interface is very amenable to bit-banging since the clock can be completely asynchronous. You just bang out the bits as you're able. The dsPIC has built in hardware that I used which speeds transmission up a bit.

SPI connection from PIC to mRF24J40MA board

In addition to the SPI lines (SCK, SDO and SDI) there are several other control lines needed by the mRF24J40MA card.

CS is an active low chip select line. SPI only tolerates one device on the bus at a time. To get around this, many SPI devices will have a chip select line. When enabled, that device will connect to the SPI bus. When disabled, the device will tri-state its lines, electrically disconnecting itself.

The RESET is an active low line as well. When lowered, the mRF24J40MA will do a cold reset. Apparently you can initiate a reset via SPI as well.

WAKE can be used to wake the device from sleep modes. This pin is disabled by default. It's function can be enabled by SPI. The WAKE command can also be initiated via SPI. I do not use this function.

The INT line will signal the microcontroller about events that have occurred within the mRF24J40 chip. This is tied to INT0 on my dsPIC33.

Fitzy on the bench having his wireless card debugged
Fitzy on the bench having his SPI - wireless communication debugged.

Shortcuts Better Not Taken

Here's where I made a foolish mistake. Because I am missing lines on my connector to toggle CS and RESET, I thought I might be able to get away without them. I thought I would permanently enable the chip (presto, no need for CS) and use software resets (and no need for RESET). This was a serious mistake.

SPI has no defined start or stop condition. So, there's no way for the devices to tell what's going on other than watching the SCK clock. The problem is that during startup conditions are undefined and strange things can appear on data lines. The mRF24J40MA was sensing some extraneous pulses on the SCK line and thought it was partway through a command when the dsPIC33 started sending. This lead to the odd situation where the oscilloscope shows communication going on but the MRF24J40MA responds with complete garbage.

Rigol LA watching SPI signals
SPI shows data being sent via SDO (D2) when I'm not reading!

This being my first time to use SPI, it took me a while to recognize this. I'd wondered why the mRF24J40MA would sometimes send data even when it was being written to. Now I realize that it was just a synchronization problem. The mRF24J40MA and the dsPIC33 where just out of step. Performing a RESET would have solved the whole problem but I'd not implemented that line.

The Solution

The connector on Fitzy's main board that goes to the wireless card also has lines for I2C on it. Out of laziness I hadn't used these and lost a few weeks to frustration. Now, I am attaching these lines to a PCA9536DP which is an I2C controlled 4 bit I/O port chip. Using this chip I've implemented a proper CS and RESET line, plus an LED so I can signal what the wireless card is doing.

I2C I/O expander used to add cs and reset lines
I2C I/O port used to add /CS and /RESET lines. All lines come from Fitzy's main board

MicroChip ZENA MIWI Packet Sniffer - Bad Doggy!

There was one other item that tripped me up. I'd originally chosen the mRF24J40 because of the ZENA packet sniffer. I though for sure that this would make life a lot easier during development.

Well, I was wrong.

The ZENA is a small USB dongle. It comes with an ~5' extension cable. I dutifully plugged the ZENA into the cable, and the cable into the PC. For three weeks I struggled with nary a packet to be seen.

Eventually I got Fitzy and Carraldo communicating with each other but still no packets on the ZENA. !!!!!! Eventually, remembering some uncooperative devices I'd met in the past, I removed the cable and plugged the ZENA directly into the PC. Presto. It worked and started displaying the packets that Fitzy and Carraldo were sending.

So, while the sniffer now works, it was of ZERO help while troubleshooting my software. Sigh.

Anyway, in the next section I'll be building a USB connected Base Station so that my PC can receive and send MiWi packets. I'm using an FT232RL chip that implements a virtual COM port on the PC, so programming should be a snap. See you.

Next Section: Wireless Base Station Alpha