RFM69 not receiving when esp32 wakes up

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:

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:

#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 when 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 is like that when the ESP32 wakes up, the module's buffer is lost. I know that the RFM itself doesn't have a buffer. I want to read data when there are an interrupt in DIO0. I have tried using low-level programming, using the library functions to access the buffer directly and I am not able to.

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.

Sure because that buffer is not filled while the ESP is at sleep. The RFM itself doesn't have a buffer so if the ESP sleeps while the message is sent it won't know about it.

In teory, the esp32 wakes up when the rfm69 makes an interrupt on DIO0 pin that it’s connected to GPIO27 esp32 pin when recieve frame. My question is how can I get that using rh_rfm69 library.
Awake esp32 when interrupt irq occurs and then read that fifo.

Your code does nothing when waking up! You put the ESP to sleep at the end of the setup() routine. So when it wakes up it will start the code in the loop() but there is no code. But you have code in setup() that checks for input from the RFM69.

Are you really sure this code worked (with just removing the sleep code), I have serious doubts.