Skip to main content

RN2xxx

Latest Version: 1.0.0

This library provides driver code for Microchip’s RN2903 and RN2483 Low-Power Long-Range (LoRa) transceiver modules. These modules provide low-power solution for long range wireless data transmission that complies with the LoRaWAN Class A protocol specifications.

You can view the library’s source code on GitHub. Click here to see information on other versions of this library.

To use this library, add #require "RN2xxx.device.lib.nut:1.0.0" to the top of your device code.

Class Usage

Constructor: RN2xxx(uart, reset[, debug])

The constructor takes two required parameters to instantiate the class: the UART bus that the chip is connected to, and the imp GPIO pin that the module's reset pin is connected to. The reset pin must be active low. The constructor will configure the reset pin. To configure the UART, call the init() method.

The optional debug parameter is a boolean that enables debug logging on incoming and outgoing UART traffic.

#require "RN2xxx.device.lib.nut:1.0.0

local uart = hardware.uart1;
local resetPin = hardware.pinH;

lora <- RN2xxx(uart, resetPin, true);

Class Methods

init(banner[, callback])

The init() method configures the UART and checks for the module’s expected banner. The method takes one required parameter, banner, which should be passed the constant RN2xxx.RN2903_BANNER for the RN2903 module, or RN2xxx.RN2483 for the RN2483 module.

The method can also take an optional parameter, callback, which is a reference to a function that will run when the initialization has completed. The callback takes one parameter, which will be passed an error message if the initialization failed or null if initialization was successful.

lora.init(RN2xxx.RN2903_BANNER function(err) {
    if (err) {
        server.error(err);
    } else {
        lora.send("radio set mod lora");
    }
});

hwReset([callback])

This method toggles the reset pin. It has one, optional parameter, callback, which is a function that will be run when the reset has completed. The callback takes one parameter, which will be passed an error message if the initialization failed or null if initialization was successful.

Note This method blocks for 0.01 seconds.

lora.hwReset(function(err) {
    if (err) server.error(err);
})

send(command)

This method sends a command to the LoRa module. The command is provided in the form of a string. Here are the command references for each module: RN2903 and RN2483. Below are some examples of a few different commands.

// Set the radio mode to lora
lora.send("radio set mod lora");

// Set the radio to continuous receive mode
lora.send("radio rx 0");

// Send "TX OK" message
lora.send("radio tx FF0000005458204F4B00");

setReceiveHandler(receiveCallback)

This method registers a callback function that will be called whenever a response or data is received by the module. The receiveCallback function takes one parameter: the response or data received.

function receive(data) {
    if (data.len() > 10 && data.slice(0,10) == "radio_rx  ") {
        // We have received a packet
        // Add code to handle data here, for now just log the incoming data
        server.log(data);

        // Send ACK
        lora.send("radio tx FF0000005458204F4B00");
    } else if (data == "radio_tx_ok" || data == "radio_err") {
        // Queue next receive
        lora.send("radio rx 0");
    } else if (data != "ok") {
        // Unexpected response
        server.error(data);
    }
}

lora.setReceiveHandler(receive);

Full Example

#require "RN2xxx.device.nut:1.0.0"

// LoRa Settings
const RADIO_MODE = "lora";
const RADIO_FREQ = 915000000;
const RADIO_SPREADING_FACTOR = "sf7"; // 128 chips
const RADIO_BANDWIDTH = 125;
const RADIO_CODING_RATE = "4/5";
const RADIO_CRC = "on"; // CRC header enabled
const RADIO_SYNC_WORD = 12;
const RADIO_WATCHDOG_TIMEOUT = 0;
const RADIO_POWER_OUT = 14;
const RADIO_RX_WINDOW_SIZE = 0; // continuous mode

// LoRa Commands
const MAC_PAUSE = "mac pause";
const RADIO_SET = "radio set";
const RADIO_RX = "radio rx";
const RADIO_TX = "radio tx";

// LoRa Com variables
const TX_HEADER = "FF000000";
const TX_FOOTER = "00";
const ACK_COMMAND = "5458204F4B" // "TX OK"

local initCmdIdx = 0;
initCommands <- [ format("%s mod %s", RADIO_SET, RADIO_MODE),
                  format("%s freq %i", RADIO_SET, RADIO_FREQ),
                  format("%s sf %s", RADIO_SET, RADIO_SPREADING_FACTOR),
                  format("%s bw %i", RADIO_SET, RADIO_BANDWIDTH),
                  format("%s cr %s", RADIO_SET, RADIO_CODING_RATE),
                  format("%s crc %s", RADIO_SET, RADIO_CRC),
                  format("%s sync %i", RADIO_SET, RADIO_SYNC_WORD),
                  format("%s wdt %i", RADIO_SET, RADIO_WATCHDOG_TIMEOUT),
                  format("%s pwr %i", RADIO_SET, RADIO_POWER_OUT),
                  MAC_PAUSE,
                  format("%s %i", RADIO_RX, RADIO_RX_WINDOW_SIZE) ];

local UART = hardware.uart1;
local RESET_PIN = hardware.pinH;
lora <- RN2xxx(UART, RESET_PIN, true);

function receive(data) {
    if (data.len() > 10 && data.slice(0,10) == "radio_rx  ") {
        // We have received a packet
        // Add code to handle data here, for now just log the incoming data
        server.log(data);

        // Send ACK
        lora.send( format("%s %s%s%s", RADIO_TX, TX_HEADER, ACK_COMMAND, TX_FOOTER) );
    } else if (data == "radio_tx_ok" || data == "radio_err") {
        // Queue next receive
        lora.send( format("%s %i", RADIO_RX, RADIO_RX_WINDOW_SIZE) );
    } else if (data != "ok") {
        // Unexpected response
        server.error(data);
    }
}

function sendNextInitCmd(data = null) {
    if (data == "invalid_param") {
        // Set init command failed - log it
        server.error("Radio command failed: " + data);
    } else if (initCmdIdx < initCommands.len()) {
        // Get command at the current index pointer, and increment the index pointer
        local command = initCommands[initCmdIdx++];
        server.log(command);
        // Send command to LoRa
        lora.send(command);
    } else {
        server.log("LoRa radio in receive mode...");
        // Radio ready to receive, set to our receive handler
        lora.setReceiveHandler(receive.bindenv(this));
    }
}

function loraInitHandler(err) {
    if (err) {
        server.error(err);
    } else {
        // Set receive callback to loop through initialization commands
        lora.setReceiveHandler(sendNextInitCmd.bindenv(this));
        // Start sending initialization commands
        sendNextInitCmd();
    }
}

// Initialize LoRa Radio and open a receive handler
lora.init(RN2xxx.RN2903_BANNER loraInitHandler);

Release History

The Electric Imp Dev Center documents the latest version of the library. For past versions, please see the Electric Imp public GitHub repos listed below.

Version Source Code Notes
1.0.0 GitHub Initial release

License

The RN2xxx library is licensed under the MIT License.