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.