Interfacing an Arduino with a Microchip MRF89XA radio.

Hardware

You'll need two MRF89XAM8A modules and two Arduino boards. The MRF89XAM8A is not 5V compatible, so you'll need a 3V3-Arduino board. Following the instructions on Adafruit shows you how to convert your Arduino Uno to one that has 3V3 IO-voltage. The explanation is for an older version of the Arduino Uno. If you have a Arduino Uno R3, you'll need to order another LDO.

You'll need the following connections between the Arduino Uno and the MRF89XAM8A:

MRF89XA Arduino Uno
1: GND GND
2: RESET do not connect
3: /CSCON IO5
4: IRQ0 IO4
5: SDI ICSP pin 4
6: SCK ICSP pin 3
7:SDO ICSP pin 1
8: /CSDATA IO3
9: IRQ1 IO2
10: VIN 5V (the voltage on this pin should be 3V3 after "3V3"-ing your Arduino Uno)
11: GND GND
12: GND GND

Solder a 100nF capacitor directly on pin 10 and pin 11 of the MRF89XAM8A.

Firmware

This firmware interfaces the MRF89XAM8A, which will communicate at 868MHz. That's in a European ISM-band. If you happen to live in the US, you'd better buy the MRF89XAM9A and program it to work in the 915MHz band.
The MRF89XA chip on this module is a very versatile chip, which makes it also quite complicated to set up correctly. The library only demonstrates a limited part of the functionality (e.g. there's no possibility yet to use different radio channels): FSK-modulation with a datarate of 20kbps.
In order to compile and run the application below, you'll have to download the library.
Make a folder RadioHead in the Arduino library folder and copy all the files from here into that.
The library is based on the RadioHead library, where the MRF89XA driver has been added and changes have been made to accomodate modules with two chip-selects. The RadioHead library is released under GPL V2.

Program one Arduino Uno with #define SERVER_MRF89XA commented out. Program the other Arduino Uno with #define CLIENT_MRF89XA commented out. You'll now have a Client and a Server. Both will communicate to each other in a reliable way (i.e. acknowledgements will be sent to indicate that packets have been received correctly).

/*Demo application of MRF89XA driver
    Copyright (C) 2014  Christoph Tack

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

//#define SERVER_MRF89XA
#define CLIENT_MRF89XA

#include <RH_MRF89XA.h>
#include <RHReliableDatagram.h>

#define CLIENT_ADDRESS 1
#define SERVER_ADDRESS 2

//  IRQ1    = MRF89XAM8A: pin 9 => Arduino Uno pin 2
//  /CSDATA = MRF89XAM8A: pin 8 => Arduino Uno pin 3
//  /CSCON  = MRF89XAM8A: pin 3 => Arduino Uno pin 5
//  IRQ0    = MRF89XAM8A: pin 4 => Arduino Uno pin 4
RH_MRF89XA driver(3, 5, 4, 2);

// Class to manage message delivery and receipt, using the driver declared above
#ifdef CLIENT_MRF89XA
#ifdef SERVER_MRF89XA
#error You have to choose: client OR server, not both
#endif
RHReliableDatagram manager(driver, CLIENT_ADDRESS);
#elif defined(SERVER_MRF89XA)
#ifdef CLIENT_MRF89XA
#error You have to choose: client OR server, not both
#endif
RHReliableDatagram manager(driver, SERVER_ADDRESS);
#endif

uint8_t data[] = "Hello World!";
// Dont put this on the stack:
uint8_t buf[RH_MRF89XA_MAX_MESSAGE_LEN];

void setup()
{
    Serial.begin(9600);
    if (!manager.init()){
        Serial.println("init failed");
        return;
    }
    Serial.println("init ok");
}

void loop()
{
#ifdef CLIENT_MRF89XA
    Serial.println("Sending to mrf89xa_reliable_datagram_server");

    // Send a message to manager_server
    if (manager.sendtoWait(data, sizeof(data), SERVER_ADDRESS))
    {
        // Now wait for a reply from the server
        uint8_t len = sizeof(buf);
        uint8_t from;
        if (manager.recvfromAckTimeout(buf, &len, 2000, &from))
        {
            Serial.print("got reply from : 0x");
            Serial.print(from, HEX);
            Serial.print(": ");
            Serial.println((char*)buf);
        }
        else
        {
            Serial.println("No reply, is mrf89xa_reliable_datagram_server running?");
        }
    }
    delay(500);

#elif defined(SERVER_MRF89XA)
    if (manager.available())
    {
        // Wait for a message addressed to us from the client
        uint8_t len = sizeof(buf);
        uint8_t from;
        if (manager.recvfromAck(buf, &len, &from))
        {
            Serial.print("got request from : 0x");
            Serial.print(from, HEX);
            Serial.print(": ");
            Serial.println((char*)buf);

            // Send a reply back to the originator client
            if (!manager.sendtoWait(data, sizeof(data), from))
                Serial.println("sendtoWait failed");
        }else{
            Serial.println("not valid");
        }
    }
#endif
}


Share