SparkFun SAMD21 Pro RF Hookup Guide

Pages
Contributors: Elias The Sparkiest
Favorited Favorite 8

Point to Point Radio Arduino Examples

Note: This example assumes you are using the latest version of the Arduino IDE on your desktop. If this is your first time using Arduino, please review our tutorial on installing the Arduino IDE. If you have not previously installed an Arduino library, please check out our installation guide.

For this example we'll be utilizing the Radio Head Library to utilize the RFM96W Radio Module. You can download the Radio Head library from its' GitHub repo, or click the link below. While you're clicking on buttons, all of the Arduino example code can be downloaded by downloading it from the SAMD21 Pro RF Arduino Examples GitHub repo or clicking the second button below.

One last thing before we go any farther. The SAMD21 is a highly versatile chip and we've taken advantage of that fact by creating two seperate UART lines, one that interfaces with the computer through the micro-B and another one broken out on the RX/TX header on the side of the board. To communicate to the Arduino IDE's serial monitor, we'll be using the statement SerialUSB, rather than the normal Serial that you might be used to. Are they different? Nope! Just different nomenclature for different UART lines.

Point to Point Radio Arduino Examples

Radio Server

Note: For the following two examples to work you'll need one radio module to send your message and another to hear and respond. This example uses two SAMD21 Pro RF's communicating to each other operating in the Americas at 915 MHz. If you are using the SAMD21 Pro RF's in Europe, make sure that you have the antenna length adjusted for 868MHz and set the frequency variable.

Assuming that the Arduino library you downloaded and installed is working correctly, let's move onto our first example. This example and the following example build off of the sample code provided by the RadioHead library but has been tailored for the SAMD21 Pro RF.

language:c
#include <SPI.h>

//Radio Head Library: 
#include <RH_RF95.h>

// We need to provide the RFM95 module's chip select and interrupt pins to the 
// rf95 instance below.On the SparkFun ProRF those pins are 12 and 6 respectively.
RH_RF95 rf95(12, 6);

int LED = 13; //Status LED on pin 13

int packetCounter = 0; //Counts the number of packets sent
long timeSinceLastPacket = 0; //Tracks the time stamp of last packet received
// The broadcast frequency is set to 921.2, but the SADM21 ProRf operates
// anywhere in the range of 902-928MHz in the Americas.
// Europe operates in the frequencies 863-870, center frequency at 
// 868MHz.This works but it is unknown how well the radio configures to this frequency:
//float frequency = 864.1;
float frequency = 921.2;

void setup()
{
  pinMode(LED, OUTPUT);

  SerialUSB.begin(9600);
  // It may be difficult to read serial messages on startup. The following
  // line will wait for serial to be ready before continuing. Comment out if not needed.
  while(!SerialUSB);
  SerialUSB.println("RFM Server!");

  //Initialize the Radio. 
  if (rf95.init() == false){
    SerialUSB.println("Radio Init Failed - Freezing");
    while (1);
  }
  else{
  // An LED indicator to let us know radio initialization has completed.
    SerialUSB.println("Receiver up!");
    digitalWrite(LED, HIGH);
    delay(500);
    digitalWrite(LED, LOW);
    delay(500);
  }

  rf95.setFrequency(frequency); 

 // The default transmitter power is 13dBm, using PA_BOOST.
 // If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then 
 // you can set transmitter powers from 5 to 23 dBm:
 // rf95.setTxPower(14, false);
}

void loop()
{
  if (rf95.available()){
    // Should be a message for us now
    uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
    uint8_t len = sizeof(buf);

    if (rf95.recv(buf, &len)){
      digitalWrite(LED, HIGH); //Turn on status LED
      timeSinceLastPacket = millis(); //Timestamp this packet

      SerialUSB.print("Got message: ");
      SerialUSB.print((char*)buf);
      //SerialUSB.print(" RSSI: ");
      //SerialUSB.print(rf95.lastRssi(), DEC);
      SerialUSB.println();

      // Send a reply
      uint8_t toSend[] = "Hello Back!"; 
      rf95.send(toSend, sizeof(toSend));
      rf95.waitPacketSent();
      SerialUSB.println("Sent a reply");
      digitalWrite(LED, LOW); //Turn off status LED

    }
    else
      SerialUSB.println("Recieve failed");
  }
  //Turn off status LED if we haven't received a packet after 1s
  if(millis() - timeSinceLastPacket > 1000){
    digitalWrite(LED, LOW); //Turn off status LED
    timeSinceLastPacket = millis(); //Don't write LED but every 1s
  }
}

Radio Client

language:c
/*
  Both the TX and RX ProRF boards will need a wire antenna. We recommend a 3" piece of wire.
  This example is a modified version of the example provided by the Radio Head
  Library which can be found here:
  www.github.com/PaulStoffregen/RadioHeadd
*/

#include <SPI.h>

//Radio Head Library:
#include <RH_RF95.h> 

// We need to provide the RFM95 module's chip select and interrupt pins to the
// rf95 instance below.On the SparkFun ProRF those pins are 12 and 6 respectively.
RH_RF95 rf95(12, 6);

int LED = 13; //Status LED is on pin 13

int packetCounter = 0; //Counts the number of packets sent
long timeSinceLastPacket = 0; //Tracks the time stamp of last packet received

// The broadcast frequency is set to 921.2, but the SADM21 ProRf operates
// anywhere in the range of 902-928MHz in the Americas.
// Europe operates in the frequencies 863-870, center frequency at 868MHz.
// This works but it is unknown how well the radio configures to this frequency:
//float frequency = 864.1; 
float frequency = 921.2; //Broadcast frequency

void setup()
{
  pinMode(LED, OUTPUT);

  SerialUSB.begin(9600);
  // It may be difficult to read serial messages on startup. The following line
  // will wait for serial to be ready before continuing. Comment out if not needed.
  while(!SerialUSB); 
  SerialUSB.println("RFM Client!"); 

  //Initialize the Radio.
  if (rf95.init() == false){
    SerialUSB.println("Radio Init Failed - Freezing");
    while (1);
  }
  else{
    //An LED inidicator to let us know radio initialization has completed. 
    SerialUSB.println("Transmitter up!"); 
    digitalWrite(LED, HIGH);
    delay(500);
    digitalWrite(LED, LOW);
    delay(500);
  }

  // Set frequency
  rf95.setFrequency(frequency);

   // The default transmitter power is 13dBm, using PA_BOOST.
   // If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then 
   // you can set transmitter powers from 5 to 23 dBm:
   // Transmitter power can range from 14-20dbm.
   rf95.setTxPower(14, false);
}


void loop()
{
  SerialUSB.println("Sending message");

  //Send a message to the other radio
  uint8_t toSend[] = "Hi there!";
  //sprintf(toSend, "Hi, my counter is: %d", packetCounter++);
  rf95.send(toSend, sizeof(toSend));
  rf95.waitPacketSent();

  // Now wait for a reply
  byte buf[RH_RF95_MAX_MESSAGE_LEN];
  byte len = sizeof(buf);

  if (rf95.waitAvailableTimeout(2000)) {
    // Should be a reply message for us now
    if (rf95.recv(buf, &len)) {
      SerialUSB.print("Got reply: ");
      SerialUSB.println((char*)buf);
      //SerialUSB.print(" RSSI: ");
      //SerialUSB.print(rf95.lastRssi(), DEC);
    }
    else {
      SerialUSB.println("Receive failed");
    }
  }
  else {
    SerialUSB.println("No reply, is the receiver running?");
  }
  delay(500);
}

The "Server" and "Client" nomenclature may be a bit misleading. It might be more accurate to say "call" and "call-back". None the less, there are a few notable changes made from the original examples.

  • Chip Select and Interupt Pins
    • RH_RF95 rf95(12, 6) -- Pin 12 and pin 6 are the assigned pins that run to the RM95 Radio Module's chip select and interrupt pins.
  • SerialUSB or Serial?
    • while(!SerialUSB)-- When the SAMD21 Pro RF starts up, it's not always a smooth transition and messages meant for the serial monitor will get missed. This line will hold your code hostage until you open the serial monitor at which point it will continue on. We have two UART lines for this microcontroller, the one that communicates with the serial monitor is called using the keyword SerialUSB.
  • Frequency Select
    • rf95.setFrequency(frequency) -- The default frequency is kind of random, 921.2 but it falls within the American ISM band: 902-928MHz. If you're in Europe, that band is 863-870MHz. You'll find the variable "frequency" is set a little higher up in the code.

After you upload the code to two SAMD21 Pro RF's, open a serial monitor set at 9600. You should see the following readout in the serial monitors!

This is an image of two serial monitor windows open, reading "Hello" and "Hello Back!".

Click the image for a closer look at the output.