Author Topic: 2-Way RFM69 Radio Communication  (Read 4206 times)

gfvalvo

  • NewMember
  • *
  • Posts: 7
  • Country: us
2-Way RFM69 Radio Communication
« on: November 30, 2016, 10:33:39 PM »
Hi All. I have a rather involved RCM69 radio question. I'll try to be concise as possible. I have two nodes communicating with each other.

NODE1 - Adafruit Huzzah ESP8266 + FeatherWing RFM69 Radio module "shield"
NODE2 - Adafruit Feather 32u4 with built-in RFM69 Radio module.

They are both running sketches based on the basic TX and RX Example Code here:
https://learn.adafruit.com/adafruit-feather-32u4-radio-with-rfm69hcw-module/using-the-rfm69-radio

Operation is as follows:

NODE1 is the master. It sends a data packet to NODE2 and checks for an ACK. It then goes into Receive mode and waits in a 2000 ms loop listening for a reply packet from NODE2. If it gets one, it sends an ACK.
The process then repeats with NODE1 sending its next packet.

NODE2 is the slave. It listens for a packet from NODE1 and sends an ACK. It then delays for 250 ms before sending its own reply packet and listening for an ACK. Finally, it goes back to listening for the next packet from NODE1.

So, after all that, here's my question -- Why is the 250 ms delay before sending the reply packet necessary in NODE2's sketch? The code for both NODE1 and NODE2 is shown below. I've found that without the 250 ms delay NODE1 never receives the reply packet from NODE2. Even 200 ms doesn't seem to work. I'm not even sure if the delay is required because NODE2 isn't ready to send or NODE1 isn't ready to listen.

Any words of wisdom will be appreciated.

Greg

NODE1 CODE:
Code: [Select]
#include <RFM69.h>    //get it here: https://www.github.com/lowpowerlab/rfm69
#include <SPI.h>

#define NETWORKID     100  // The same on all nodes that talk to each other
#define NODE1        1    // The unique identifier of this node
#define NODE2      2    // The recipient of packets

#define FREQUENCY     RF69_915MHZ
#define ENCRYPTKEY    "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes!
#define IS_RFM69HCW   true // set to 'true' if you are using an RFM69HCW module

#define SERIAL_BAUD   115200
#define WAIT_TIME 2000

#ifdef ARDUINO_AVR_FEATHER32U4
  #define RFM69_CS      8
  #define RFM69_IRQ     7
  #define RFM69_IRQN    4  // Pin 7 is IRQ 4!
  #define RFM69_RST     4
  #define LED           13
  #define LED_ON        HIGH
  #define LED_OFF       LOW
  char node1[] = "Node 1 = FEATHER32U4";

#elif defined(ARDUINO_ESP8266_ESP12)
  #define RFM69_CS      2
  #define RFM69_IRQ     15
  #define RFM69_IRQN    digitalPinToInterrupt(RFM69_IRQ )
  #define RFM69_RST     16
  #define LED           0
  #define LED_ON        LOW
  #define LED_OFF       HIGH
  char node1[] = "Node 1 = ESP8266";

#else
  #error Unrecognized Board
#endif

typedef struct {
  char dataMessage[20];
  uint16_t packetnum;
} dataStructure;

dataStructure txPacket = {
  "Hello from NODE 1",
  0
};

uint16_t packetnum = 0;  // packet counter, we increment per xmission

RFM69 radio = RFM69(RFM69_CS, RFM69_IRQ, IS_RFM69HCW, RFM69_IRQN);

void setup() {
  Serial.begin(SERIAL_BAUD);
  delay(2000);
  Serial.println();
  Serial.println();
  Serial.print("RFM69 NODE 1 - "); Serial.println(node1);
 
  // Hard Reset the RFM module
  pinMode(RFM69_RST, OUTPUT);
  digitalWrite(RFM69_RST, HIGH);
  delay(100);
  digitalWrite(RFM69_RST, LOW);
  delay(100);

  // Initialize radio
  radio.initialize(FREQUENCY, NODE1, NETWORKID);
  if (IS_RFM69HCW) {
    radio.setHighPower();    // Only for RFM69HCW & HW!
  }
  radio.setPowerLevel(31); // power output ranges from 0 (5dBm) to 31 (20dBm)
 
  radio.encrypt(ENCRYPTKEY);
 
  pinMode(LED, OUTPUT);
  digitalWrite(LED,LED_OFF);
  Serial.print("\nTransmitting at ");
  Serial.print(FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
  Serial.println(" MHz");
}


void loop() {
  uint32_t now;
  dataStructure rxPacket;
  Serial.print("Sending Packet # "); Serial.println(packetnum);
  txPacket.packetnum = packetnum++;
   
  if (radio.sendWithRetry(NODE2, (uint8_t *) &txPacket, sizeof(dataStructure))) { //target node Id, message as string or byte array, message length
    Serial.println("Received an ACK");
    Blink(LED, 50, 3); //blink LED 3 times, 50ms between blinks
  } else {
    Serial.println("No ACK Received");
  }
 
  Serial.flush();
  now = millis();
  while(1) {
    if (radio.receiveDone()) {
      memcpy((void *)&rxPacket, (void *)radio.DATA,  sizeof(dataStructure));
      Serial.print("Received Packet From: [");Serial.print(radio.SENDERID);Serial.print("] ");
      Serial.print(rxPacket.dataMessage); Serial.print(" - "); Serial.println(rxPacket.packetnum);
      if (radio.ACKRequested())
      {
        radio.sendACK();
        Serial.println("- ACK sent");
      }
    }
    if (millis() - now >= WAIT_TIME) {
      break;
    }       
    yield();
  }
}

void Blink(byte PIN, byte DELAY_MS, byte loops)
{
  for (byte i=0; i<loops; i++)
  {
    digitalWrite(PIN,LED_ON);
    delay(DELAY_MS);
    digitalWrite(PIN,LED_OFF);
    delay(DELAY_MS);
  }
}


NODE2 CODE
Code: [Select]
#include <RFM69.h>    //get it here: https://www.github.com/lowpowerlab/rfm69
#include <SPI.h>

#define NETWORKID     100  // The same on all nodes that talk to each other
#define NODE1        1   
#define NODE2      2   

#define FREQUENCY     RF69_915MHZ
#define ENCRYPTKEY    "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes!
#define IS_RFM69HCW   true // set to 'true' if you are using an RFM69HCW module

#define SERIAL_BAUD   115200

#ifdef ARDUINO_AVR_FEATHER32U4
  #define RFM69_CS      8
  #define RFM69_IRQ     7
  #define RFM69_IRQN    4  // Pin 7 is IRQ 4!
  #define RFM69_RST     4
  #define LED           13
  #define LED_ON        HIGH
  #define LED_OFF       LOW
  char node2[] = "Node 2 = FEATHER32U4";

#elif defined(ARDUINO_ESP8266_ESP12)
  #define RFM69_CS      2
  #define RFM69_IRQ     15
  #define RFM69_IRQN    digitalPinToInterrupt(RFM69_IRQ )
  #define RFM69_RST     16
  #define LED           0
  #define LED_ON        LOW
  #define LED_OFF       HIGH
  char node2[] = "Node 2 = ESP8266";

#else
  #error Unrecognized Board
#endif

typedef struct {
  char dataMessage[20];
  uint16_t packetnum;
} dataStructure;

dataStructure replyPacket = {
  "Reply from Node 2",
  0
};

RFM69 radio = RFM69(RFM69_CS, RFM69_IRQ, IS_RFM69HCW, RFM69_IRQN);

void setup() {
  Serial.begin(SERIAL_BAUD);
  delay(2000);
  Serial.println();
  Serial.println();
  Serial.print("RFM69 Node 1 - "); Serial.println(node2);
 
  // Hard Reset the RFM module
  pinMode(RFM69_RST, OUTPUT);
  digitalWrite(RFM69_RST, HIGH);
  delay(100);
  digitalWrite(RFM69_RST, LOW);
  delay(100);

  // Initialize radio
  radio.initialize(FREQUENCY, NODE2, NETWORKID);
  if (IS_RFM69HCW) {
    radio.setHighPower();    // Only for RFM69HCW & HW!
  }
  radio.setPowerLevel(31); // power output ranges from 0 (5dBm) to 31 (20dBm)
 
  radio.encrypt(ENCRYPTKEY);
 
  pinMode(LED, OUTPUT);
  digitalWrite(LED, LED_OFF);
  Serial.print("\nTransmitting at ");
  Serial.print(FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
  Serial.println(" MHz");
}


void loop() {
  uint32_t now;
  dataStructure rxPacket;
  if (radio.receiveDone()) {
    memcpy((void *)&rxPacket, (void *)radio.DATA,  sizeof(dataStructure));
    Serial.print("Received Packet From: [");Serial.print(radio.SENDERID);Serial.print("] ");
    Serial.print(rxPacket.dataMessage); Serial.print(" - "); Serial.println(rxPacket.packetnum);
    if (radio.ACKRequested())
    {
      radio.sendACK();
      Serial.println("- ACK sent");
    }
   
 
    delay(250);  // <<<<<<<----------- NODE 1 WILL NOT RECIEVE THIS NEXT REPLY PACKET WITHOUT THIS DELAY ????????? ------------------
    Serial.println("Sending Reply");
    replyPacket.packetnum = rxPacket.packetnum;
    if (radio.sendWithRetry(NODE1, (uint8_t *) &replyPacket, sizeof(dataStructure))) { //target node Id, message as string or byte array, message length
      Serial.println("Received an ACK");
      Blink(LED, 50, 3); //blink LED 3 times, 50ms between blinks
    } else {
      Serial.println("No ACK Received");
    }
  }
}

void Blink(byte PIN, byte DELAY_MS, byte loops)
{
  for (byte i=0; i<loops; i++)
  {
    digitalWrite(PIN, LED_ON);
    delay(DELAY_MS);
    digitalWrite(PIN, LED_OFF);
    delay(DELAY_MS);
  }
}

sslobodyan

  • NewMember
  • *
  • Posts: 1
  • Country: ua
Re: 2-Way RFM69 Radio Communication
« Reply #1 on: December 05, 2016, 05:45:37 AM »
Maybe problem in Blink(LED, 50, 3); //blink LED 3 times, 50ms between blinks ? Node2 waits for node1 blinking?

RoSchmi

  • NewMember
  • *
  • Posts: 23
  • Country: de
Re: 2-Way RFM69 Radio Communication
« Reply #2 on: December 05, 2016, 09:24:57 AM »
Another reason can be that you did not specify the "retries" and "retryWaitTime" parameter in the sendWithRetry call. So I think that eventually the method will take falsely the return message in some way as an ACK. Perhaps it will work if you set the "retryWaitTime" to maybe 50 or 100 ms.
« Last Edit: December 05, 2016, 09:27:12 AM by RoSchmi »

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: 2-Way RFM69 Radio Communication
« Reply #3 on: December 05, 2016, 02:01:24 PM »
So, after all that, here's my question -- Why is the 250 ms delay before sending the reply packet necessary in NODE2's sketch? The code for both NODE1 and NODE2 is shown below. I've found that without the 250 ms delay NODE1 never receives the reply packet from NODE2. Even 200 ms doesn't seem to work. I'm not even sure if the delay is required because NODE2 isn't ready to send or NODE1 isn't ready to listen.
That's a very good question, adafruit should be able to answer that since it's their code.
I see adafruit pads their code with very generous delays which is very weird. You should NOT need any kind of delays like that.
Even the sendWithRetry() should just work without additional params - you can still specify delay and retries but the default params are tuned to work with the default library settings.
I would take this to adafruit's forums and ask them since it's their hardware behaving like this with their sketches. Maybe that's the answer - the delays are needed so the feather can run :)

gfvalvo

  • NewMember
  • *
  • Posts: 7
  • Country: us
Re: 2-Way RFM69 Radio Communication
« Reply #4 on: December 05, 2016, 09:01:45 PM »
The problem was the Blink() function. Got rid of that and the 250 ms delay is no longer needed. Delay() is evil. Thanks for the suggestion @sslobodyan.