While trying to debug a deadlock in my RFM69 library I noticed in the logging that I was getting a receive interrupt while putting bytes in the FIFO for transmission.
Register 0x49 - Value 0X00 - Bits 00000000
Register 0x4a - Value 0X00 - Bits 00000000
Register 0x4b - Value 0X00 - Bits 00000000
Register 0x4c - Value 0X00 - Bits 00000000
Register 0x4d - Value 0X00 - Bits 00000000
...
22:58:47.192 Received To 0X22 a 33 byte message hello world RFM69-915-02 10-58-47 CRC Ok True
The thread 0x6a8 has exited with code 0 (0x0).
22:58:48.334 Send-hello world RFM69-915-01 10-58-48
22:58:48.351 Send-Done
22:58:48.388 Received To 0X22 a 33 byte message hello world RFM69-915-02 10-58-52 CRC Ok True
22:58:48.462 Transmit-Done
The thread 0xde4 has exited with code 0 (0x0).
22:58:53.427 Send-hello world RFM69-915-01 10-58-53
22:58:53.445 Send-Done
22:58:53.556 Transmit-Done
22:58:57.382 Received To 0X22 a 33 byte message hello world RFM69-915-02 10-58-57 CRC Ok True
The thread 0x17c has exited with code 0 (0x0).
After re-reading the RFM69CW/RFM69HCW module datasheet (based on the Semtech SX1231/SX1231H) I realised my code for loading the FIFO could be more efficient.
SX1231 Register map FIFO
Based on the timing diagram I could remove the loop which loads bytes in the FIFO for transmission.
After stress testing with several client devices this appears to have reduced the scope of a receive interrupt to occur while a packet was being loaded into the FIFO for transmission. I now need to dig deeper into the timing around entering different operational modes and selectively enabling event interrupts.
After problems with interleaved interrupt handling in my Windows 10 IoT Core client I figured the AutoMode used by the plainRFM69 library might be worth investigation. My first Arduino client was based on the plainRFM69 library but had Interoperability issues.
For this attempt I also started with the minimal sample and modified the code to send and receive text messages.
/*
Copyright (c) 2014, Ivor Wanders, Bryn Lewis 2019
MIT License, see the LICENSE.md file in the root folder.
*/
#include <SPI.h>
#include <plainRFM69.h>
// slave select pin.
#define SLAVE_SELECT_PIN 10
// connected to the reset pin of the RFM69.
#define RESET_PIN 9
// tie this pin down on the receiver.
#define SENDER_DETECT_PIN A0
const uint8_t tx_buffer[] = "ABCDEFGHIJKLMNOPQRSTURWXYZ1234567890";
//const uint8_t tx_buffer[] = "abcdefghijklmnopqrstuvwxyz1234567890";
uint8_t rx_buffer[sizeof(tx_buffer)] = "";
plainRFM69 rfm = plainRFM69(SLAVE_SELECT_PIN);
void sender() {
uint32_t start_time = millis();
uint32_t counter = 1; // the counter which we are going to send.
while (true) {
rfm.poll(); // run poll as often as possible.
if (!rfm.canSend()) {
continue; // sending is not possible, already sending.
}
if ((millis() - start_time) > 1000) { // every 500 ms.
start_time = millis();
// be a little bit verbose.
Serial.print("Send:"); Serial.println(counter);
// send the number of bytes equal to that set with setPacketLength.
// read those bytes from memory where counter starts.
rfm.sendVariable(tx_buffer, counter);
counter++; // increase the counter.
if ( counter > strlen(tx_buffer))
{
counter = 1;
}
}
}
}
void receiver() {
uint32_t counter = 0; // to count the messages.
while (true) {
rfm.poll(); // poll as often as possible.
while (rfm.available())
{
uint8_t len = rfm.read(rx_buffer); // read the packet into the new_counter.
// print verbose output.
Serial.print("Packet Len:");
Serial.print( len );
Serial.print(" : ");
Serial.println((char*)rx_buffer);
}
}
}
void setup() {
Serial.begin(9600);
SPI.begin();
bareRFM69::reset(RESET_PIN); // sent the RFM69 a hard-reset.
//rfm.setRecommended(); // set recommended paramters in RFM69.
rfm.setPacketType(true, false); // set the used packet type.
rfm.setBufferSize(2); // set the internal buffer size.
rfm.setPacketLength(sizeof(rx_buffer)); // set the packet length.
rfm.setFrequency((uint32_t)909560000); // set the frequency.
rfm.setLNA(RFM69_LNA_IMP_200OHM, RFM69_LNA_GAIN_AGC_LOOP);
// p71, 3 preamble bytes.
rfm.setPreambleSize(16);
// p71, 4 bytes sync of 0x01, only start listening when sync is matched.
//uint8_t syncthing[] = {0xaa, 0x2d, 0xd4};
uint8_t syncthing[] = {0xd4, 0x2d, 0xaa};
rfm.setSyncConfig(true, false, sizeof(syncthing), 0);
rfm.setSyncValue(&syncthing, sizeof(syncthing));
rfm.dumpRegisters(Serial);
// baudrate is default, 4800 bps now.
rfm.receive();
// set it to receiving mode.
pinMode(SENDER_DETECT_PIN, INPUT_PULLUP);
delay(5);
}
void loop() {
if (digitalRead(SENDER_DETECT_PIN) == LOW) {
Serial.println("Going Receiver!");
receiver();
// this function never returns and contains an infinite loop.
} else {
Serial.println("Going sender!");
sender();
// idem.
}
}
I took the list register values and loaded them into a Excel spreadsheet alongside the values from my Windows 10 IoT Core application
First thing I noticed was the order of the three sync byes (Registers 0x2F, 0x30, 0x31) was reversed. I then modified the run method in the Windows 10 code so the registers settings on both devices matched. (I removed the PlainRFM69 SetRecommended call so as many of the default options as possible were used).
I also found an error with the declaration of the RegPacketConfig1DcFree enumeration (Whitening = 0b0100000 vs. Whitening = 0b01000000) which wouldn’t have helped.
Register 0x4c - Value 0X00 - Bits 00000000
Register 0x4d - Value 0X00 - Bits 00000000
...
17:55:53.559 Received 1 byte message A CRC Ok True
.17:55:54.441 Received 2 byte message AB CRC Ok True
.17:55:55.444 Received 3 byte message ABC CRC Ok True
.17:55:56.447 Received 4 byte message ABCD CRC Ok True
.17:55:57.449 Received 5 byte message ABCDE CRC Ok True
.17:55:58.453 Received 6 byte message ABCDEF CRC Ok True
The thread 0x578 has exited with code 0 (0x0).
.17:55:59.622 Received 7 byte message ABCDEFG CRC Ok True
.17:56:00.457 Received 8 byte message ABCDEFGH CRC Ok True
.17:56:01.460 Received 9 byte message ABCDEFGHI CRC Ok True
.17:56:02.463 Received 10 byte message ABCDEFGHIJ CRC Ok True
..17:56:03.955 Received 11 byte message ABCDEFGHIJK CRC Ok True
17:56:04.583 Received 12 byte message ABCDEFGHIJKL CRC Ok True
I did some investigation into that the plainRMF69 code and found the ReadMultiple and WriteMuliple methods reverse the byte order
void bareRFM69::writeMultiple(uint8_t reg, void* data, uint8_t len){
SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0)); // gain control of SPI bus
this->chipSelect(true); // assert chip select
SPI.transfer(RFM69_WRITE_REG_MASK | (reg & RFM69_READ_REG_MASK));
uint8_t* r = reinterpret_cast<uint8_t*>(data);
for (uint8_t i=0; i < len ; i++){
SPI.transfer(r[len - i - 1]);
}
this->chipSelect(false);// deassert chip select
SPI.endTransaction(); // release the SPI bus
}
void bareRFM69::readMultiple(uint8_t reg, void* data, uint8_t len){
SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0)); // gain control of SPI bus
this->chipSelect(true); // assert chip select
SPI.transfer((reg % RFM69_READ_REG_MASK));
uint8_t* r = reinterpret_cast<uint8_t*>(data);
for (uint8_t i=0; i < len ; i++){
r[len - i - 1] = SPI.transfer(0);
}
this->chipSelect(false);// deassert chip select
SPI.endTransaction(); // release the SPI bus
}
I won’t be able to use interrupt AutoMode clients with the EasySensors shields as the DIO2 pin is not connected but on the AdaFruit RFM69HCW Radio Bonnet 433MHz or 915MHz it is connected to GPIO24.
While doing yet more stress testing I noticed a couple of odd message go past and a long pause every so often when sending a message in the Visual Studio output window.
I have two Arduino devices sending addressed messages every (both individual and broadcast) to the Adafruit RFM69 HCW Radio Bonnet, on my two Windows 10 IoT Core devices every 100mSec. At the same time the windows 10 devices are sending each other a message every 5 seconds.
To help spot the pauses I added some code to mark any events where there was a significant gap. In this case ” is ASCII character for 0x22 the device address
21:10:30.746 Received To 34 a 23 byte message Hello World ---0x22:236 CRC Ok True
21:10:30.918 Received To 153 a 23 byte message Hello World ---0x99:236 CRC Ok True
21:10:31.399 Received To 34 a 23 byte message Hello World ---0x22:237 CRC Ok True
21:10:31.568 Send-hello world RFM69-915-01 09-10-31
21:10:31.580 Send-Done
21:10:31.592 Received To 34 a 33 byte message """"""""""""""""""""""""""""""""" CRC Ok True
RC-------------------------------------------
21:10:32.052 Received To 34 a 23 byte message Hello World ---0x22:238 CRC Ok True
21:10:32.225 Received To 153 a 23 byte message Hello World ---0x99:238 CRC Ok True
21:10:32.705 Received To 34 a 23 byte message Hello World ---0x22:239 CRC Ok True
There were also still some corrupted messages
21:10:30.746 Received To 34 a 23 byte message Hello World ---0x22:236 CRC Ok True
21:10:30.918 Received To 153 a 23 byte message Hello World ---0x99:236 CRC Ok True
21:10:31.399 Received To 34 a 23 byte message Hello World ---0x22:237 CRC Ok True
21:10:31.568 Send-hello world RFM69-915-01 09-10-31
21:10:31.580 Send-Done
21:10:31.592 Received To 34 a 33 byte message """"""""""""""""""""""""""""""""" CRC Ok True
RC-------------------------------------------
21:10:32.052 Received To 34 a 23 byte message Hello World ---0x22:238 CRC Ok True
21:10:32.225 Received To 153 a 23 byte message Hello World ---0x99:238 CRC Ok True
21:10:32.705 Received To 34 a 23 byte message Hello World ---0x22:239 CRC Ok True
It looks like if the base station receives a message as it is about to send a message the Rfm69Device_OnTransmit never gets called.
It also looks like every so often the transmitter gets stuck on one of Windows 10 devices effectively jamming the frequency.
Transmit stuck on
16:12:10.193 Received To 34 a 22 byte message Hello World ---0x22:65 CRC Ok True
16:12:10.360 Received To 153 a 22 byte message Hello World ---0x99:65 CRC Ok True
16:12:10.831 Received To 34 a 22 byte message Hello World ---0x22:66 CRC Ok True
16:12:10.998 Received To 153 a 22 byte message Hello World ---0x99:66 CRC Ok True
The thread 0x570 has exited with code 0 (0x0).
16:12:11.484 Send-hello world RFM69-915-01 04-12-11
16:12:11.494 Received To 34 a 22 byte message Hello World ---0x22:67 CRC Ok True
16:12:11.504 Send-Done
The thread 0x3a8 has exited with code 0 (0x0).
16:12:16.554 Send-hello world RFM69-915-01 04-12-16
16:12:16.566 Send-Done
16:12:16.660 Transmit-Done
T--------------------------------------------
16:12:16.736 Received To 153 a 22 byte message Hello World ---0x99:75 CRC Ok True
16:12:17.206 Received To 34 a 22 byte message Hello World ---0x22:76 CRC Ok True
16:12:17.374 Received To 153 a 22 byte message Hello World ---0x99:76 CRC Ok True
16:12:18.011 Received To 153 a 22 byte message Hello World ---0x99:77 CRC Ok True
Transmit stuck
16:12:07.591 Transmit-Done
16:12:07.880 Received To 153 a 23 byte message Hello World ---0x99:137 CRC Ok True
16:12:08.533 Received To 153 a 23 byte message Hello World ---0x99:138 CRC Ok True
16:12:08.839 Received To 17 a 24 byte message Hello World ----0x11:139 CRC Ok True
16:12:09.186 Received To 153 a 23 byte message Hello World ---0x99:139 CRC Ok True
16:12:09.493 Received To 17 a 24 byte message Hello World ----0x11:140 CRC Ok True
16:12:10.799 Received To 17 a 24 byte message Hello World ----0x11:142 CRC Ok True
The thread 0xc8 has exited with code 0 (0x0).
16:12:12.567 Send-hello world RFM69-915-02 04-12-12
16:12:12.589 Send-Done
16:12:12.681 Transmit-Done
16:12:16.510 Received To 17 a 33 byte message hello world RFM69-915-01 04-12-16 CRC Ok True
16:12:16.576 Received To 153 a 22 byte message Hello World ---0x99:75 CRC Ok True
16:12:17.025 Received To 153 a 23 byte message Hello World ---0x99:151 CRC Ok True
16:12:17.214 Received To 153 a 22 byte message Hello World ---0x99:76 CRC Ok True
16:12:17.331 Received To 17 a 24 byte message Hello World ----0x11:152 CRC Ok True
The thread 0xfa0 has exited with code 0 (0x0).
16:12:17.661 Send-hello world RFM69-915-02 04-12-17
16:12:17.680 Send-Done
16:12:17.772 Transmit-Done
16:12:17.851 Received To 153 a 22 byte message Hello World ---0x99:77 CRC Ok True
16:12:18.331 Received To 153 a 23 byte message Hello World ---0x99:153 CRC Ok True
16:12:18.489 Received To 153 a 22 byte message Hello World ---0x99:78 CRC Ok True
16:12:18.638 Received To 17 a 24 byte message Hello World ----0x11:154 CRC Ok True
16:12:18.985 Received To 153 a 23 byte message Hello World ---0x99:154 CRC Ok True
16:12:19.291 Received To 17 a 24 byte message Hello World ----0x11:155 CRC Ok True
16:12:19.638 Received To 153 a 23 byte message Hello World ---0x99:155 CRC Ok True
16:12:19.944 Received To 17 a 24 byte message Hello World ----0x11:156 CRC Ok True
16:12:20.291 Received To 153 a 23 byte message Hello World ---0x99:156 CRC Ok True
16:12:20.597 Received To 17 a 24 byte message Hello World ----0x11:157 CRC Ok True
Then as rfm69Device.SetMode(Rfm69HcwDevice.RegOpModeMode.Receive) hasn’t been called no messages are received until another message is sent.
It looks like a timing issue around access to the message fifo (I have that in a critical section) so I need todo some more debugging. Maybe purging the receive buffer