Thursday 29 January 2015

Arduino MRF24J40 Wireless Shield

We will equip Arduino with wireless connectivity basing on MRF24J4 module by Microchip. As a sample application, we will remotely control a relay, operated by a floating input, and we will virtualize the Arduino USB serial port.
The MRF24J40MA radio module is manufactured by Microchip, that also provides useful and complete software libraries (identified as MiApp) for module management (creation of a complex wireless network, network identification, device addressing, sending and receiving data, etc. …). Clearly, Microchip provides those libraries free of charge only if they are compiled with MPLAB (Microchip C compiler and development environment) and executed in a Microchip CPU (PIC microcontrollers).
On other hands, Microchip provides the data-sheet of all its devices (MRF24J40MA included) and the complete knowledge base for their management. So, nothing prevents you from deeply study the data-sheet and, starting from zero, write down your own libraries for the CPU and development environment you want to use.
From these considerations, we decided to start the project that we are presenting on these pages whose ultimate goal is to use the wireless module MRF24J40MA with an Arduino hardware platform. The additional shield we developed, to have the radio module and all its components working properly, has also an output relay and an opto-coupled input. The rationale behind this choice is to equip the shield not only with the radio part but also with at least a pair of input / output so that it could be more than enough for simple applications.
Regarding our newly developed software libraries for Arduino, those cannot fully cover all of the features offered by the Microchip proprietary libraries (that allow you to create different types of networks, broadcast communications, etc ….). The operations already available are enough for the basic management of a WiFi network: module initialization, setting of network PAN ID, set the node network address, transmit and receive data. Because of these differences between Arduino and Microchip libraries, some features have been simplified. In particular, we have removed the distinction between Coordinator and End Device node but hierarchically all nodes have the same level and offer the same functionality. Maybe you lose some application optimization but surely, you have huge advantages (which, in our opinion, largely cover the disadvantages) from the point of view of simplicity and ease of use.

WiFi Hardware Chip 
MRF24J40 is a RF transceiver, compatible with 2.4GHz IEEE 802.15.4 standard.
For our applications, we will use the full version of the module (MRF24J40MA) that besides the transceiver integrates also a tuned antenna, quartz and other external components required for WiFi communication. It has a mechanical strip shape, 2,54mm step and has already passed all wireless required certifications.
To interface with an external MCU it has an SPI port, interrupt, wake and reset pins; there are also pins for power feed.
The access to the various radio functions is through the read / write of a long series of internal chip registers (for details, please consult the full product description). Our libraries shall manage these registers, hiding at Arduino application level the implementation details but offering the general function calls for configuration and communication.

Arduino MRF24J40 Library

The MRF24J40 libraries for Arduino offer some basic functions of wireless network configuration and communication. They have not all the features of Microchip MiApp but there are all the necessary functions to set up a WiFi network, to address nodes and to allow direct data exchange between them.
The library provides an object called Mrf24j for the complete WiFi stack management. The object constructor gets as input the number of Arduino pin to be used for reset, chip select and radio module interrupt (the SPI port is the default, ie pins 11, 12 and 13 for the Arduino Uno).
There is a reset function that, through the reset pin as defined above, resets the chip (best practice is to reset hardware every time the software starts) and a Init (to be called after the reset) that initializes the SPI port and the registers of the radio module.
To work properly and to exchange messages, every node needs to specify which WiFi network (PAN ID, clearly the same for all) they belong and which is its unique network address. To set the PAN ID we have to use two functions (void set_pan (word PANID) and word get_pan (void)) that respectively write and read the PAN ID chosen.

Instead to configure nodes addresses, we will use void address16_write (word address16) and word address16_read (void) (since the variable is a 16-bit word, we cannot have more than 256 nodes in the network).
Other config functions that may be useful are:

void set_channel (byte channel) that allows you to specify what radio channel to be used;
void set_promiscuous (boolean enabled) that allows you to configure whether to use normal or promiscuous rx (i.e. if you want to receive any packets from the channel);
void rx_enable(void) and void rx_disable (void) that respectively enable or disable the receiving section;
void set_palna (boolean enabled) that allows you to enable the external controller PA / LNA;
void set_bufferPHY (boolean bp), which allows to enable the receival of both user data and physical communication payload.
Let us check how the communication works and the functions involved. The first thing to say is that the whole mechanism is implemented in a special way using Arduino CPU interrupt. This implementation is perhaps a bit more difficult than usual but allows you to manage everything more efficiently involving the Arduino CPU only when necessary.
The radio chip has a pin that sends an interrupt to the CPU to indicate that it has data ready; The Arduino software must be written to handle the interrupt indicating what to do in these cases. As we shall see later by analyzing the source code, we use the Arduino attachInterrupt to indicate which function must be executed when a “change interrupt” occurs from the MRF radio interrupt pin.
The software library contains the function void interrupt_handler(void) called directly by the specified interrupt handler. The handler reads all the data from the radio module and makes it “available” again to receive further information.
Other things to define are the two functions that respectively receive and transmit data. Once you have defined these functions, the MRF24J40 library offers the methods void check_flags (void (* rx_handler) (void), void (* tx_handler) (void)) that must be called cyclically (typically in the method loop ()) to manage properly the defined handlers, avoiding overlapping between Rx and Tx.

Finally, the real functions for transmitting and receiving are respectively void send16 (word dest16, char * data) that needs parameters like network address of the destination node and the pointer to the data buffer to be transmitted and rx_info_t * get_rxinfo (void), which returns a pointer to a structure type rx_info_t specially defined to encapsulate all the information received.

Electrical Wiring



The hardware is based mainly on the WiFi module MRF24J40MA (chip U1). The radio chip needs to be managed by a main CPU through the SPI port, to receive commands and send responses. The SPI port is located on pins 5, 6, 7 and must be connected to Arduino SPI pins (SCK, MISO and MOSI).
The radio module requires a power supply of 3.3V, while the Arduino digital port works at +5V, so you cannot make a direct connection but you must match the right voltage levels. Our choice fell on an integrated circuit designed for this purpose, the chip 74HC4050D (U2 chip in the diagram). Since all the connections between Arduino and MRF24J40MA need different voltages, we will convert all of them through the 74HC4050D.
In addition to the SPI port, the radio chip also provides the Wake, Interrupt, Reset and Chip Select pins. The Wake pin is directly connected to the positive voltage level because we choose to keep always the radio on.
The Interrupt pin is connected to Arduino D2 digital port; this is because Arduino can control the pin D2 via an interrupt and, as we can see by analyzing the sketch source code, this mechanism allows a more efficient resources management.
The other two pins (Reset and Chip Select) can be operated from any other Arduino digital port; to leave a certain amount of freedom of choice (in order to be ready for further development or additional shields), we have prepared two solder bridges to each pin; by soldering one of them, you can make your own choice.
Finishing the radio module analysis, we note the 100nF capacitor C3 connected to the WiFi chip power pin (as required by the data-sheet) and the presence of a LED (green LED in the diagram) connected to the Chip Select pin of MRF24J40MA itself (in order to get the visual indication of the presence of the communication).
With regard to the communication part of the electric scheme, the analysis is done; however, we choose not to implement a simple transmission shield but equip it with at least a minimum set of input and output. In particular, we have provided a photo-coupled input (based on the photo-coupler 4N25) and an output relay (RL1 relay driven by BJT T1 stage). Also for these I / O, we decided to leave freedom of choice about which Arduino port to be used (always using the technique of the two solder bridges).
Testing
To test this sample application you need to have at least two systems MRF24J40 + Arduino Shield.
To program Arduino we use the same procedure through IDE; but first you need to modify the source code to fit the hardware pin-out chosen and change the network addresses of the two nodes. In particular, replace the variables pinResetMRF, pinCSMRF, pinShieldRele and pinShieldInput; thisNodeAddress and destNodeAddress to define source / destination nodes.
At this point you are ready to turn the system on and play with it. Try to change the status of an opto-coupler and verify that the relay of the other shots. Finally, connect with different USB cables a PC to one card; open on the PC a serial terminal (HyperTerminal or similar,”connected” to a different virtual COM port), select the configuration 9600, 8, N, 1 and no flow control and check that when “writing” the data in a window (remember that if you do not have local echo enabled you do not see what you type), these are transmitted and received on the serial port by all cards.

2 comments:

  1. can you quote making one of these?

    ReplyDelete
  2. Do you sell this setup? Source the PCA? 240-558-2014 x223

    ReplyDelete