Using the Adafruit Feather for Fun and Training

“Make us a transmitter for training.”

This has been one of the single most requested items since I’ve been in business. Unfortunately, there has been no easy answers. I’ve tried a number of different approaches but nothing seemed robust enough or cost effective enough for the average tech to produce. There are many RF chips and modules to choose from, but unless you want to take the time to hand solder surface mount components, you’re better off just taping down the button of a key fob.

Prototype Transmitters
Prototype Transmitters

Fortunately, Adafruit has saved the day with their line of Radiofruits. At my 9 to 5 job I came across the Adafruit Feather 32u4 RFM96 LoRa radio. The specs on this thing are intense. With a mere 7 inch piece of 22 AWG wire soldered to the antenna ports, two units were able to achieve a successful transmission and reception from 1 mile away. What’s even better is that because this transmitter is tied to a microcontroller, that transmission can set off all manner of activities.

Adafruit Feather 32u4 LoRa 433MHz
Adafruit Feather 32u4 LoRa 433MHz

Not as Advertised

At first glance this glorious little, long range transmitter looks like a one trick pony, but it hides a few surprises. The big eye brow raising moment was when I started playing around with the frequency agility of this device. It’s advertised as operating at 433 MHz, but in the example code given by Adafruit, you must specify the frequency. So after moving up and down the spectrum, it was discovered that the frequency actually ranges from 363 MHz to 569 MHz. Another transmitter Adafruit sells has similar characteristics around 915 MHz.

Legal Note

Transmit responsibly. Using this transmitter could get you in some hot water if you are transmitting too powerfully in the wrong frequency range. Be careful and don’t break the law. That is all.

The Build

Start by buying the transmitter. Follow the link here: https://www.adafruit.com/product/3079

Go here to figure out your antenna options: https://learn.adafruit.com/adafruit-feather-32u4-radio-with-lora-radio-module/antenna-options

You will be programming the transmitter with the Arduino IDE software. Follow this tutorial for the correct setup: https://learn.adafruit.com/adafruit-feather-32u4-radio-with-lora-radio-module/setup

Next you’ll need to setup the Arduino IDE and your operating system to accept the Adafruit Feather. Follow the tutorial here: https://learn.adafruit.com/adafruit-feather-32u4-radio-with-lora-radio-module/using-with-arduino-ide

Plug in transmitter. Go to the Tools menu and make sure you have the correct Board and Port selected. The board will be the Adafruit Feather 32u4 and the port will be the port with the same name displayed next to it:

Copy and paste the code below into the Arduino IDE.

#include <SPI.h>
#include <RH_RF95.h>

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//WHAT DO YOU WANT THIS TO DO?
// 1 - Transmit a single, set frequency
// 2 - Burst; specify frequency, length of burst, and how often to activate
// 3 - Spread spectrum; specify start and stop freq and hop interval
// 4 - Spread Spectrum Burst - This option allows you to turn your spread spectrum signal
//                            off and on like a burst transmitter.
// 5 - Spread Spectrum, Frequency Hoping, Burst - Allows the user to do everything entailed in
//                                           option 4, but the signal will randomly jump
//                                           between two specified frequencies.

//Choose the number of the option you want.
int WhatToDo = 5;

//FOR OPTION 1 - Single Set Frequency
//Center frequency must be in MHz with a frequency between 363MHz AND 569MHz
float centerFrequency = 433.0;

//FOR OPTION 2 - Burst
//The burst center frequency must be in MHz with a frequency between 363MHz AND 569MHz
float burstCenterFrequency = 433.0;
//How long should the transmission occur? Time is in milliseconds: Ex: 5000 = 5 seconds
int burstLength = 500; 
//How often should this burst occur? Time is in milliseconds
int burstInterval = 2000;

//FOR OPTION 3 - Spread Spectrum
//The start frequency for the spread in MHz between 363MHz AND 569MHz
float startFrequency = 435.0;
//The stop frequency for the spread in MHz between 363MHz AND 569MHz
float stopFrequency = 437.0;
//How often should the signal jump to another frequency? Time in milliseconds
int hopInterval = 0;

//FOR OPTION 4 - Spread Spectrum Burst
//Make sure all of the OPTION 3 variables are assigned and the burstLength and
//burstInterval variables from OPTION 2.

//FOR OPTION 5 - Spread Spectrum, Frequency Hoping, Burst (AKA the kitchen sink)
//Fill out hopInterval in OPTION 3. Fill out burstLength and burstInterval variables in
//OPTION 2. Also, fill out the variables below.

//How wide should the spread spectrum signal be? Bandwidth is in MHz.
float signalBandwidth = 2;

//As the spread spectrum signal jumps around, what is the upper most frequency it should
//bound itself by. The limit is 569MHz. The number must be in MHz.
float upperLimit = 440.0;

//Define the lower limit as well
float lowerLimit = 420.0;

//SIGNAL AMPLITUDE
//Specify an amplitude level between 5(weakest) and 23(strongest). This transmitter
//is a beast. Even 5 will blow you away.
int amplitude = 5;
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

//Defines pins needed for RF Tx & Rx to function
#define RFM95_CS 8
#define RFM95_RST 4
#define RFM95_INT 7 

//Test Data to be sent. This data can be many characters but it can affect
//transmission time.
uint8_t data[] = "0";

//Helps with timing delays without using Delay function
unsigned long startTime = 0;

//Helps with the selection of frequencies in OPTION 5
float randomFreq;

// Single instance of the radio driver
RH_RF95 rf95(RFM95_CS, RFM95_INT);

void setup() 
{
  pinMode(RFM95_RST, OUTPUT);
  digitalWrite(RFM95_RST, HIGH);

  // manual reset
  digitalWrite(RFM95_RST, LOW);
  delay(10);
  digitalWrite(RFM95_RST, HIGH);
  delay(10);

  while (!rf95.init()) 
  {
    while (1);
  }

  // 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(amplitude, false);
}

void loop()
{
  //The following if statements control what action the transmitter takes. The action
  //depends upon what the user has placed in the WhatToDo variable.
  
  //Option 1
  if (WhatToDo == 1)
  {
    //Sets the frequency to centerFrequency
    rf95.setFrequency(centerFrequency);
    
    //Sends the dadta
    rf95.send(data, sizeof(data));
    
    //Waits for data to be sent
    rf95.waitPacketSent();
  }
  
  //Option 2
  else if(WhatToDo == 2)
  {
    //Delays for the amount of time in burstInterval
    delay(burstInterval);
    rf95.setFrequency(burstCenterFrequency);
    
    //Stores how long the feather has been On. Number is in milliseconds.
    startTime = millis();
    
    //Continues to transmit for the length of time specified by burstLength
    while (millis()<=startTime+burstLength)
    {
      rf95.send(data, sizeof(data));
      rf95.waitPacketSent();
    }
  }
  
  //Option 3
  else if(WhatToDo == 3)
  {
    //Set the frequnecy to a random frequency between startFrequnecy and stopFrequency.
    //The math allows the random transmission to occur in tenth of a MHz increments.
    rf95.setFrequency((random(startFrequency*10,stopFrequency*10))/10.0);
    
    //Delay the transmission for time specified in hopInterval
    delay(hopInterval);
    rf95.send(data, sizeof(data));
    rf95.waitPacketSent();
  }
  
  //Options 4
  else if(WhatToDo == 4)
  {
    //Delay transmitting for the time specified in burstInterval
    delay (burstInterval);
    startTime = millis();

    //Transmit for the amount of time specified in burstLength
    while(millis()<=startTime+burstLength)
    {
      //During the transmission time specified in burstLength, wait the amount of time
      //specified in hopInterval when switching frequencies.
      delay(hopInterval);
      
      //As in option 3, causes the spectrum spread to be random.
      rf95.setFrequency((random(startFrequency*10,stopFrequency*10))/10.0);
      
      rf95.send(data, sizeof(data));
      rf95.waitPacketSent();
    }
  }

  //Options 5
  else if(WhatToDo == 5)
  {
    //Delay transmitting for the time specified in burstInterval
    delay (burstInterval);
    startTime = millis();

    //Calcutes a random frequency between the lower and upper limits specified
    randomFreq=(random(lowerLimit*10,upperLimit*10))/10.0;
    
    //Transmit for the amount of time specified in burstLength
    while(millis()<=startTime+burstLength)
    {
      //During the transmission time specified in burstLength, wait the amount of time
      //specified in hopInterval when switching frequencies.
      delay(hopInterval);

      //Sets the frequency using the bandwidth specified and the frequency limits
      rf95.setFrequency((random((randomFreq-(signalBandwidth/2))*10,(randomFreq+(signalBandwidth/2))*10))/10.0);
      
      rf95.send(data, sizeof(data));
      rf95.waitPacketSent();
    }
  }
}

Code Explanation

Incidentally, the code can all be found on my github page if you wish to contribute.

Once you’ve copied all the code into the Arduino interface, you’ll need to edit it to suit your needs. You’ll notice that there is a section of the code that is bounded by lots of ++++++++++ signs. This block is dedicated to setting the options for the transmitter. Every time you see // at the beginning of a line, that represents an explanatory comment about the code that follows. You, as the user, should read each comment and enter the value you desire after the = sign for each line.

For instance, the first option that needs to be assigned is called WhatToDo. You are given 4 options:

  1. Transmit a single, set Frequency
  2. Burst
  3. Spread Spectrum
  4. Spread Spectrum Burst
  5. Spread Spectrum, Frequency Hoping, Burst **UPDATE 7/11/2018**

Choose 1, 2, 3, 4, or 5 and place it on the right side of the = sign for WhatToDo. Continue to fill out information until you reach the the + sign boundary in the code. You’ll notice that most lines end in a semi-colon. That semi-colon is needed for those lines, so don’t get rid of it.

You’ll notice that there are some time related variables. You can set these variables to be a random value. One way of doing this is with the random() command. For example, let’s say you want the hopInterval variables to randomly hop the spread spectrum pulse from 100ms to 900ms. Instead of placing a number for that variable you would say:

hopInterval = random(100,900);

Now the hop will occur at an unexpected interval bounded by times you specified.

If you feel like making new transmission schemes, I’ve commented the rest of the code well enough so that you can pick out what’s going on. Let me know if you make something great, and I’ll add it to the main code with your permission.

Once the code is all filled out to your specifications, click the Verify button (the check mark). Once the code has compiled, click the Upload button (the arrow button). The firmware will be pushed to the Feather and your selected behavior will commence.

Power

Understandably you’re not going to want to leave the transmitter attached to a laptop. Once the firmware has been uploaded and you’re pleased with the transmission, disconnect the Feather and give it its own power source. I ordered the optional Lithium Ion battery here: https://www.adafruit.com/product/258

Another option is to power it via USB with a USB battery pack. Be careful which battery pack you choose. Some of these batteries will only continue to give current to a device if that device is pulling a significant amount of current. This transmitter does not always meet that threshold especially during periods of radio silence.

Another option is to use a 9V battery with a 5V regulator. Off of the regulator, attach the red and black wires of a micro USB cable. Take the plug end of the cable and connect it to the Feather. I’m using this method for another project at the moment and it’s working fine.

Happy Training

If you have any questions about the code or how to get things going, just let me know and I’ll try to address it. Also, if you have any ideas to make things better, let me know or take a stab at it yourself. I look forward to seeing what you guys make.



Leave a Reply