pouriap / TinyRF

A small Arduino library for using 315MHz / 433MHz RF modules with ATtiny13 and other low-memory microcontrollers.
GNU General Public License v3.0
64 stars 11 forks source link
315mhz 433mhz arduino arduino-library attiny attiny13 rf-module

TinyRF

A small Arduino library for generic 315MHz / 433MHz RF modules.

The transmitter code is small in size making it suitable for microcontrollers with limited memory. Namely the ATtiny13, or other ATtiny chips. But Arduino and other AVR MCUs are also supported.

433MHz / 315MHz cheap ebay RF modules

Features

Transmitter MCU support: ATtiny13 or any other microcontroller you can program with Arduino IDE.

Receiver MCU support: The receiver code needs more RAM and FLASH memory so it's not possible to use ATtiny13 as the receiver. It is recommended to use an Arduino as receiver because it has sufficient speed, RAM and FLASH memory. ESP8266 and ESP32 are also supported. You can even use an ATtiny85 as the receiver! (see ATtiny85 Receiver)

Arduino IDE support: Arduino IDE 1.6.0 and higher.

How to install the library

Usage notes:

Transmitter sketch:

#include "TinyRF_TX.h"

void setup(){
  // transmitter default pin is pin #2. You can change it by editing Settings.h
  setupTransmitter();
}

void loop(){

  const char* msg = "Hello from far away!";

  //send function accepts an array of bytes as first argument
  //second argument is the length of the array
  send((byte*)msg, strlen(msg));

  //make sure there's at least a TX_DELAY_MICROS delay between transmissions
  //otherwise the receiver's behavior will be undefined
  delayMicroseconds(TX_DELAY_MICROS);

  // you can provide a third argument to send a message multiple times
  // this is for reliability in case some messages get lost in the way
  // when sending multiple messages make sure you call getReceivedData() frequently in the receiver 
  // the receiver has a circular FIFO buffer, if you send too many messages and/or if they are
  // too long previous messages will get overwritten in the buffer
  // you can change the buffer size in settings.h
  // it is socially more responsible to use fewer repetition to minimize your usage of the bandwidth
  sendMulti((byte*)msg, strlen(msg), 5);

  delayMicroseconds(TX_DELAY_MICROS);

}

Receiver sketch:

#include "TinyRF_RX.h"

// the pin which will be connected to receiver module
// this pin has to support EXTERNAL interrupts
// on Arduino and similar boards this is pin 2 & 3
// on Digispark pro it's pin 3 & 9
// on ESP it's all GPIO pins except GPIO16, but using a pin that doesn't have an 
// alternate function such as pin 12-14 is recommended
uint8_t rxPin = 2;

void setup(){
  Serial.begin(115200);
  //make sure you call this in your setup
  setupReceiver(rxPin);
}

void loop(){

  const uint8_t bufSize = 30;
  byte buf[bufSize];
  uint8_t numLostMsgs = 0;
  uint8_t numRcvdBytes = 0;

  // number of received bytes will be put in numRcvdBytes
  // if sequence numbering is enabled the number of lost messages will be put in numLostMsgs
  // if you have disabled sequence numbering or don't need number of lost messages you can omit this argument
  uint8_t err = getReceivedData(buf, bufSize, numRcvdBytes, numLostMsgs);

  // the receiver has a circular FIFO buffer
  // if getReceivedData() isn't called frequently enough then older messages will get overwritten
  // so make sure the frequency at which you send messages in your tx code is slower than the frequency
  // at which you call getReceivedData() in your rx code to prevent that
  // specially when you are using sendMulti()
  // duplicate messages that are sent using sendMulti() will stay in the buffer until you read the first one
  // you can change the buffer size in settings.h

  if(err == TRF_ERR_NO_DATA){
    return;
  }

  if(err == TRF_ERR_BUFFER_OVERFLOW){
    Serial.println("Buffer too small for received data!");
    return;
  }

  if(err == TRF_ERR_CORRUPTED){
    Serial.println("Received corrupted data.");
    return;
  }

  // if sequence numbering is enabled and you use the sendMulti() function for sending a message
  // multiple times then getReceivedData() will return TRF_ERR_SUCCESS only once
  // all the duplicate messages will be automatically ignored
  // this means all you need to do is check if the return code is TRF_ERR_SUCCESS
  // these are non-repeated, crc-valid messages
  if(err == TRF_ERR_SUCCESS){

    Serial.print("Received: ");

    for(int i=0; i<numRcvdBytes; i++){
      Serial.print((char)buf[i]);
    }

    Serial.println("");

    if(numLostMsgs>0){
      Serial.print(numLostMsgs);
      Serial.println(" messages were lost before this message.");
    }

  }

}

How to reduce memory usage?

If you're running out of memory here are a few TinyRF-specific and general hints:

Using ATtiny85 as receiver

You can use ATtiny85 as the receiver but you have to be careful in order to not run out of RAM. Specifically you have to reduce the buffer size in Settings.h (TRF_RX_BUFFER_SIZE) to a smaller value such as 16. The buffers you use in your code for storing data should also be as small as possible.

Other similar low memory microcontrollers are not tested but should work given they have enough RAM and FLASH memory available.

For convenience I have included another library in the release page called TinyRF_85 which has the buffer size reduced. You can install it alongside the normal TinyRF library and include it whenever you want to use an ATtiny85 or similar microcontroller as receiver. This way you don't have to keep changing the buffer size in Settings.h every time you use a low memory MCU.

How to use without Arduino?

In order to make the library easy to use for Arduino users I have written the library with Arduino functions such as digitalWrite() and delayMicroseconds(). The optimizer automatically takes care of them and they don't add an overhead (tested with ATtiny13 + MicroCore). If you want to use it in a pure C AVR project you'll have to replace the functions yourself.

How to change settings:

Transmitter pin number and other settings are defined in Settings.h instead of being set programatically in order to save program space. To find out which settings are available and what they do take a look at Settings.h.

Feel free to create an issue if you encountered any bugs or problems