Author Topic: ESP32 can't read FIFO from RFM69 when esp32 wakes up  (Read 1697 times)

Fran13

  • NewMember
  • *
  • Posts: 2
ESP32 can't read FIFO from RFM69 when esp32 wakes up
« on: May 12, 2021, 10:43:27 AM »
Description:
Hello community. I have been stuck in a problem for a long time and after an intensive search I have not come up with any solution.

I'm using the RadioHead RFM library and RH_RF69 library to enable communication between Atmega32u4 and ESP32. The situation is the following:

As node:

1- Atmega32u4 wakes up every 60 seconds and reads sensors data.
2- Atmega32u4 sends data over RFM69HCW and goes to sleep again.

As Gateway:

1- Esp32 is in deep sleep mode and the setup for RFM69HCW is done.
2- If data is received by RFM69, then ESP32 will wake up by DIO0 connected to GPIO27 pin from ESP32 and received data will be stored in ESP32.

In a simple RadioHead_RawDemo_RX and RadioHead_RawDemo_TX  examples, without going to sleep, works properly.

When using energy saving mode, the frames are sent but not processed by ESP32 (server). Sometimes when I restart esp32 server i can see the first frame received (using a Logic Analyzer and Logi 2 - Saleae) but ESP32 never wake up again. But normally, if esp32 is not in an eternal sleep, the ESP32 wakes up caused from ext0 wakeup when I receive a message it wakes up but then the  condition if(rf69.available ()) is always false and I am not able to read the message from the buffer.

Feather32u4 code:
Code: [Select]
char radiopacket[20];

byte u8_watchdog_counter = 0;

RH_RF69 rf69(RFM69_CS, RFM69_INT);

// Class to manage message delivery and receipt, using the driver declared above
RHReliableDatagram rf69_manager(rf69, MY_ADDRESS);

void setup()
{
  Serial1.begin(115200);
  pinMode(RFM69_RST, OUTPUT);
  digitalWrite(RFM69_RST, LOW);
  // manual reset
  digitalWrite(RFM69_RST, HIGH);
  delay(10);
  digitalWrite(RFM69_RST, LOW);
  delay(10);

  if (!rf69_manager.init())
  {
    Serial1.println("RFM69 radio init failed");
    while (1)
      ;
  }
  Serial1.println("RFM69 radio init OK!");
  // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM (for low power module)
  // No encryption
  if (!rf69.setFrequency(RF69_FREQ))
  {
    Serial1.println("setFrequency failed");
  }

  // If you are using a high power RF69 eg RFM69HW, you *must* set a Tx power with the
  // ishighpowermodule flag set like this:
  rf69.setTxPower(20, true); // range from 14-20 for power, 2nd arg must be true for 69HCW

  // The encryption key has to be the same as the one in the server
 
  uint8_t key[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
                   0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
  rf69.setEncryptionKey(key);

  pinMode(LED, OUTPUT);

  Serial1.print("RFM69 radio @");
  Serial1.print((int)RF69_FREQ);
  Serial1.println(" MHz");
  Serial1.flush();
}

void loop()
{
  Watchdog.sleep(2000);
  u8_watchdog_counter++;
  if (u8_watchdog_counter >= 30 || u1_pin_changed)
  {
    radiopacket[0] = 0x30 + MY_ADDRESS;
    radiopacket[1] = 0x31;
    rf69.send((uint8_t *)radiopacket, strlen(radiopacket));
    rf69.waitPacketSent();
    u8_watchdog_counter = 0;
Blink(LED, 40, 3);
  }
  rf69.sleep();
}
ESP32 code: 
Code: [Select]
#include <SPI.h>
#include <RH_RF69.h>
#include <RHReliableDatagram.h>

/************ Radio Setup ***************/

// Change to 434.0 or other frequency, must match RX's freq!
#define RF69_FREQ 434.0

// who am i? (server address)
#define MY_ADDRESS 1

#if defined(ESP32)                     // ESP32 feather w/wing
#define RFM69_RST 26                   // same as LED
#define RFM69_CS 33                    // "B"
#define RFM69_INT 27                   // "A"
#define LED 13
#endif

RTC_DATA_ATTR int bootCount = 0;
// Singleton instance of the radio driver
RH_RF69 rf69(RFM69_CS, RFM69_INT);

// Class to manage message delivery and receipt, using the driver declared above
RHReliableDatagram rf69_manager(rf69, MY_ADDRESS);

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

// Dont put this on the stack:
uint8_t msg_recived[] = "Recived";
// Dont put this on the stack:
RTC_DATA_ATTR uint8_t buf[RH_RF69_MAX_MESSAGE_LEN];

void setup()
{
  pinMode(12, OUTPUT);
  pinMode(LED, OUTPUT);
  digitalWrite(12, LOW);
  Serial.begin(115200);
  delay(1000);
 
  esp_sleep_enable_ext0_wakeup(GPIO_NUM_27, 1); //RFM69 makes an interrupt on GPIO 27 on ESP32
  ++bootCount;
  Serial.println("Boot number: " + String(bootCount));
  print_wakeup_reason();

  radio_RFM69_setup();
  /*CODE*/
 
  if (esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_EXT0)
  {
    Serial.println("ESP_SLEEP_WAKEUP_EXT0");
  }

  if (rf69.available())
  {
    Serial.println("MSG:");
    // Wait for a message addressed to us from the client
    uint8_t len = sizeof(buf);
    uint8_t from = 13;
    if (rf69.recvfromAck(buf, &len, &from))
    {
      buf[len] = 0; // zero out remaining string

      Serial.print("Got packet from #");
      Serial.print(from);
      Serial.print(" [RSSI :");
      Serial.print(rf69.lastRssi());
      Serial.print("] : ");
      Serial.println((char)buf[1]);

      if (buf[1] == 0x31)
      {
        Blink(12, 40, 3);
      }
    }
  }

  /*END LOOP*/

  ///*GO SLEEP*///////
  Serial.println("Going to sleep now");
  delay(1000);
  Serial.flush();
  esp_deep_sleep_start();
}

void loop()
{
}


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

void print_wakeup_reason()
{
  esp_sleep_wakeup_cause_t wakeup_reason;

  wakeup_reason = esp_sleep_get_wakeup_cause();

  switch (wakeup_reason)
  {
  case ESP_SLEEP_WAKEUP_EXT0:
    Serial.println("Wakeup caused by external signal using RTC_IO");
    break;
  case ESP_SLEEP_WAKEUP_EXT1:
    Serial.println("Wakeup caused by external signal using RTC_CNTL");
    break;
  case ESP_SLEEP_WAKEUP_TIMER:
    Serial.println("Wakeup caused by timer");
    break;
  case ESP_SLEEP_WAKEUP_TOUCHPAD:
    Serial.println("Wakeup caused by touchpad");
    break;
  case ESP_SLEEP_WAKEUP_ULP:
    Serial.println("Wakeup caused by ULP program");
    break;
  default:
    Serial.printf("Wakeup was not caused by deep sleep: %d\n", wakeup_reason);
    break;
  }
}

void radio_RFM69_setup()
{
  if (!rf69_manager.init())
  {
    Serial.println("RFM69 radio init failed");
    while (1)
      ;
  }
  // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM (for low power module)
  // No encryption
  if (!rf69.setFrequency(RF69_FREQ))
  {
    Serial.println("setFrequency failed");
  }
   // If you are using a high power RF69 eg RFM69HW, you *must* set a Tx power with the
   // ishighpowermodule flag set like this:
   rf69.setTxPower(20, true); // range from 14-20 for power, 2nd arg must be true for 69HCW

   // The encryption key has to be the same as the one in the server

  uint8_t key[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
                   0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
  rf69.setEncryptionKey(key);
}
The fact is that the wakeup_reason detects me that it has been produced by ESP_SLEEP_WAKEUP_EXT0, but rf69.available () (which in the loop did work) is now always false. It seems that while the ESP32 is waking up it is just when the module receives the frame and that is why it is lost. I have tried using low-level programming using the library functions to access the buffer directly using readFifo()... but without success.

Also trying to read and write RFM69HCW registers without being victorious.

I would appreciate if someone, who understands or something similar has happened, could give me a hand.

Thanks.