RFM69HCW with Xiao ESP32s3

Has anyone used the RFM69HCW with XIAO ESP32S3?
I have the RFM95W working with the LoRa library, but I cannot get the RFM69HCW to work with any library "RadioLib, RadioHead, LowPowerLab" so far!

//define the pins used by the transceiver module
#define ss D6
#define rst D7
#define dio0 D5

Which of the three radios RFM69HCW, RFM95W and RFM69 do you actually want to discuss?

For fruitful results when requesting help on this forum, members recommend to read and follow the directions in the "How to get the best out of this forum" post.

Hint: RadioHead: RH_RF69 Class Reference

RFM69HCW

looking at ESP32-S3_Pin_Reference GPIO5 6 and 7 should be OK

using a pair of RFM69HW modules connected to ESP32 ran File>Examples>Radiohead>RF68>rf69_client and rf69_server setup with connections

RH_RF69 rf69(5, 27);  // ESP32 (CS and INIT)

not used the RFM69 on a ESP32S3 but have used a RFM95 LoRa module on a ESP32-S3-DevKitC-1 using the following connections

// ESP32S3 VSPI connections
// ESP32S3 SCK pin GPIO12  to RFM95_pin SCK
// ESP32S3 MISO pin GPIO13  to RFM95_pin MISO
// ESP32S3 MOSI pin GPIO11  to RFM95_pin MOSI
// ESP32S3 pin GPIO 10   to RFM95 SS
// ESP32S3 pin GPIO8   to RFM95 Reset
// ESP32S3 pin GPIO9   to RFM95 DIO0 

Yes, I can get the RFM95w to work with the Xiao boards! I would like to get the RFM69HCW to work with the XIAO boards as well. I have tried to use the RadioHead: RH_RF69 Class but I get this error:

c:\Users\chris\OneDrive\Documents\Arduino\libraries\RadioHead\RH_ASK.cpp: In member function 'void RH_ASK::timerSetup()':
c:\Users\chris\OneDrive\Documents\Arduino\libraries\RadioHead\RH_ASK.cpp:533:23: error: too many arguments to function 'hw_timer_t* timerBegin(uint32_t)'
  533 |     timer = timerBegin(0, 80, true); // Alarm value will be in in us
      |             ~~~~~~~~~~^~~~~~~~~~~~~
In file included from C:\Users\chris\AppData\Local\Arduino15\packages\esp32\hardware\esp32\3.1.0\cores\esp32/esp32-hal.h:98,
                 from C:\Users\chris\AppData\Local\Arduino15\packages\esp32\hardware\esp32\3.1.0\cores\esp32/Arduino.h:36,
                 from c:\Users\chris\OneDrive\Documents\Arduino\libraries\RadioHead/RadioHead.h:1556,
                 from c:\Users\chris\OneDrive\Documents\Arduino\libraries\RadioHead/RHGenericDriver.h:9,
                 from c:\Users\chris\OneDrive\Documents\Arduino\libraries\RadioHead/RH_ASK.h:9,
                 from c:\Users\chris\OneDrive\Documents\Arduino\libraries\RadioHead\RH_ASK.cpp:6:
C:\Users\chris\AppData\Local\Arduino15\packages\esp32\hardware\esp32\3.1.0\cores\esp32/esp32-hal-timer.h:35:13: note: declared here
   35 | hw_timer_t *timerBegin(uint32_t frequency);
      |             ^~~~~~~~~~
c:\Users\chris\OneDrive\Documents\Arduino\libraries\RadioHead\RH_ASK.cpp:534:25: error: too many arguments to function 'void timerAttachInterrupt(hw_timer_t*, void (*)())'
  534 |     timerAttachInterrupt(timer, &esp32_timer_interrupt_handler, true);
      |     ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\Users\chris\AppData\Local\Arduino15\packages\esp32\hardware\esp32\3.1.0\cores\esp32/esp32-hal-timer.h:50:6: note: declared here
   50 | void timerAttachInterrupt(hw_timer_t *timer, void (*userFunc)(void));
      |      ^~~~~~~~~~~~~~~~~~~~
c:\Users\chris\OneDrive\Documents\Arduino\libraries\RadioHead\RH_ASK.cpp:535:5: error: 'timerAlarmWrite' was not declared in this scope; did you mean 'timerWrite'?
  535 |     timerAlarmWrite(timer, 1000000 / _speed / 8, true);
      |     ^~~~~~~~~~~~~~~
      |     timerWrite
c:\Users\chris\OneDrive\Documents\Arduino\libraries\RadioHead\RH_ASK.cpp:536:5: error: 'timerAlarmEnable' was not declared in this scope; did you mean 'timerAlarm'?
  536 |     timerAlarmEnable(timer);
      |     ^~~~~~~~~~~~~~~~
      |     timerAlarm

exit status 1

Compilation error: exit status 1

Here is the code that I am using:

#include <SPI.h>
#include <RH_RF69.h>

// Singleton instance of the radio driver
//RH_RF69 rf69;
//RH_RF69 rf69(15, 16); // For RF69 on PJRC breakout board with Teensy 3.1
//RH_RF69 rf69(4, 2); // For MoteinoMEGA https://lowpowerlab.com/shop/moteinomega
//RH_RF69 rf69(8, 7); // Adafruit Feather 32u4

RH_RF69 rf69(D6, D7);

void setup() 
{
  Serial.begin(9600);
  while (!Serial) 
    ;
  if (!rf69.init())
    Serial.println("init failed");
  // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM (for low power module)
  // No encryption
  if (!rf69.setFrequency(915.0))
    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(14, true);

  // 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);
}


void loop()
{
  Serial.println("Sending to rf69_server");
  // Send a message to rf69_server
  uint8_t data[] = "Hello World!";
  rf69.send(data, sizeof(data));
  
  rf69.waitPacketSent();
  // Now wait for a reply
  uint8_t buf[RH_RF69_MAX_MESSAGE_LEN];
  uint8_t len = sizeof(buf);

  if (rf69.waitAvailableTimeout(500))
  { 
    // Should be a reply message for us now   
    if (rf69.recv(buf, &len))
    {
      Serial.print("got reply: ");
      Serial.println((char*)buf);
    }
    else
    {
      Serial.println("recv failed");
    }
  }
  else
  {
    Serial.println("No reply, is rf69_server running?");
  }
  delay(400);
}


Connections:

RFM69HCW:   Xiao ESP32S3:
MISO               D9
MOSI               D10
SCK                 D8
NSS                 D6
RESET            D7
DIO0                D5

Those are several different errors, all due to the choice of MCU and board definition. The page I linked in post #2 suggests that the library author has not tested it with the ESP32S3, and that the library is not compatible with that MCU/board definition.

Is there a library that you could suggest? Thanks

No, sorry. I recommend checking the library docs for MCU compatibility before choosing the MCU.

That code compiles OK for me, using version 2.0.14 of Expressifs core with the XIAO ESP32S3.

I don't use newer versions of Expressifs core due to incompatibilities with some established libraries.

1 Like

looks like you are attempting to compile a version of the Radiohread library which has not been updated to ESP32 core V3
remove the Radiohead library and install the latest version from RadioHead Packet Radio library for embedded microprocessors

1 Like

Horace,
Thank you so much this worked and has saved my bacon!

thanks this also worked

I am now able to upload without Error and the boards start up and the RFM69HCW intit and the "setFrequency" does not fail but when it sends the data it is not sending, or the server is not receiving. Here is the sketch's I am using:
Server:

#include <SPI.h>
#include <RH_RF69.h>

RH_RF69 rf69(D6, D7);

void setup() 
{
  Serial.begin(9600);
  while (!Serial) 
    ;
  if (!rf69.init())
    Serial.println("init failed");
  // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM (for low power module)
  // No encryption
  if (!rf69.setFrequency(915.0))
    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(14, true);

  // The encryption key has to be the same as the one in the client
  uint8_t key[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
                    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
  rf69.setEncryptionKey(key);
  
#if 0
  // For compat with RFM69 Struct_send
  rf69.setModemConfig(RH_RF69::GFSK_Rb250Fd250);
  rf69.setPreambleLength(3);
  uint8_t syncwords[] = { 0x2d, 0x64 };
  rf69.setSyncWords(syncwords, sizeof(syncwords));
  rf69.setEncryptionKey((uint8_t*)"thisIsEncryptKey");
#endif
}

void loop()
{
  if (rf69.available())
  {
    // Should be a message for us now   
    uint8_t buf[RH_RF69_MAX_MESSAGE_LEN];
    uint8_t len = sizeof(buf);
    if (rf69.recv(buf, &len))
    {
//      RH_RF69::printBuffer("request: ", buf, len);
      Serial.print("got request: ");
      Serial.println((char*)buf);
//      Serial.print("RSSI: ");
//      Serial.println(rf69.lastRssi(), DEC);
      
      // Send a reply
      uint8_t data[] = "And hello back to you";
      rf69.send(data, sizeof(data));
      rf69.waitPacketSent();
      Serial.println("Sent a reply");
    }
    else
    {
      Serial.println("recv failed");
    }
  }
}


Client:

#include <SPI.h>
#include <RH_RF69.h>

// Singleton instance of the radio driver
//RH_RF69 rf69;
//RH_RF69 rf69(15, 16); // For RF69 on PJRC breakout board with Teensy 3.1
//RH_RF69 rf69(4, 2); // For MoteinoMEGA https://lowpowerlab.com/shop/moteinomega
//RH_RF69 rf69(8, 7); // Adafruit Feather 32u4

RH_RF69 rf69(D6, D7);

void setup() 
{
  Serial.begin(9600);
  while (!Serial) 
    ;
  if (!rf69.init())
    Serial.println("init failed");
  // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM (for low power module)
  // No encryption
  if (!rf69.setFrequency(915.0))
    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(14, true);

  // 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);
}


void loop()
{
  Serial.println("Sending to rf69_server");
  // Send a message to rf69_server
  uint8_t data[] = "Hello World!";
  rf69.send(data, sizeof(data));

  delay(1600);

/*  
  rf69.waitPacketSent();
  // Now wait for a reply
  uint8_t buf[RH_RF69_MAX_MESSAGE_LEN];
  uint8_t len = sizeof(buf);



  if (rf69.waitAvailableTimeout(500))
  { 
    // Should be a reply message for us now   
    if (rf69.recv(buf, &len))
    {
      Serial.print("got reply: ");
      Serial.println((char*)buf);
    }
    else
    {
      Serial.println("recv failed");
    }
  }
  else
  {
    Serial.println("No reply, is rf69_server running?");
  }
  */
  delay(400);
}


After more testing I see that the sender hangs on:

rf69.send(data, sizeof(data));

It will print Serial.println("Sending to rf69_server"); once and that's it.
Also, I get a "36" in the Serial monitor on both the sending code and the receiving code which I have no idea what this is.
I am thankful for all the help!

I suggest to turn off the encryption on both ends.

After doing that, and recompiling/uploading, post the code, along with complete serial monitor output produced by both the sender and receiver.

Hint: it is ALWAYS best to start with one or more of the basic library examples, and make sure those work, before rolling your own.

Sending Code:

#include <SPI.h>
#include <RH_RF69.h>

// Singleton instance of the radio driver
//RH_RF69 rf69;
//RH_RF69 rf69(15, 16); // For RF69 on PJRC breakout board with Teensy 3.1
//RH_RF69 rf69(4, 2); // For MoteinoMEGA https://lowpowerlab.com/shop/moteinomega
//RH_RF69 rf69(8, 7); // Adafruit Feather 32u4

RH_RF69 rf69(D6, D7);

void setup() 
{
  Serial.begin(9600);
  while (!Serial) 
    ;
  if (!rf69.init())
    Serial.println("init failed");
  // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM (for low power module)
  // No encryption
  if (!rf69.setFrequency(915.0))
    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(14, true);

  // 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);
}


void loop()
{
  Serial.println("Sending to rf69_server");
  // Send a message to rf69_server
  uint8_t data[] = "Hello World!";
  rf69.send(data, sizeof(data));

  rf69.waitPacketSent();
  // Now wait for a reply
  uint8_t buf[RH_RF69_MAX_MESSAGE_LEN];
  uint8_t len = sizeof(buf);

  if (rf69.waitAvailableTimeout(500))
  { 
    // Should be a reply message for us now   
    if (rf69.recv(buf, &len))
    {
      Serial.print("got reply: ");
      Serial.println((char*)buf);
    }
    else
    {
      Serial.println("recv failed");
    }
  }
  else
  {
    Serial.println("No reply, is rf69_server running?");
  }
  delay(400);
}

Receiving code:

#include <SPI.h>
#include <RH_RF69.h>

RH_RF69 rf69(D6, D7);

void setup() 
{
  Serial.begin(9600);
  while (!Serial) 
    ;
  if (!rf69.init())
    Serial.println("init failed");
  // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM (for low power module)
  // No encryption
  if (!rf69.setFrequency(915.0))
    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(14, true);

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

void loop()
{
  if (rf69.available())
  {
    // Should be a message for us now   
    uint8_t buf[RH_RF69_MAX_MESSAGE_LEN];
    uint8_t len = sizeof(buf);
    if (rf69.recv(buf, &len))
    {
//      RH_RF69::printBuffer("request: ", buf, len);
      Serial.print("got request: ");
      Serial.println((char*)buf);
//      Serial.print("RSSI: ");
//      Serial.println(rf69.lastRssi(), DEC);
      
      // Send a reply
      uint8_t data[] = "And hello back to you";
      rf69.send(data, sizeof(data));
      rf69.waitPacketSent();
      Serial.println("Sent a reply");
    }
    else
    {
      Serial.println("recv failed");
    }
  }
}

Sending Serial Monitor:

ESP-ROM:esp32s3-20210327
36
Sending to rf69_server

Receiving Serial monitor:

ESP-ROM:esp32s3-20210327
36

The "36" is not emitted by your program. It is probably from the boot sequence.

It is generally a good idea to have a program identify itself on the serial monitor, in setup().

I understand but I still get "36" I wonder if it is an error code of some kind via the library