-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Poor reception with RFM69HWC #16
Comments
Which frequency of chip? I wonder if you run into #13 I never got word back from testing of that, but an overflow in the frequency could affect the results. Can you try that branch? |
I'm using 434mHz modules, so a 32bit overflow is probably not the issue. |
By the way, thanks for responding....
Edit; put the table in triple backticks for monospace and added some spaces for alignment. |
Thanks for providing comparison!
I think the difference (ignoring some register that I think don't matter) boils down to:
The difference isn't that large, just multiply the register with 61 to get the frequency in Hz; 433999994 for plainRFM, 433750016 for radiohead. You could use setFrequency with One thing that does stand out to me is the SyncValues; Another; In this comparison, the baudrates are vastly different, with 4.8kb/s vs 250kb/s, that means transmissions take a pretty significant different duration, if there's any (periodic) interference in the environment plainRFM would be much more affected by that, you could try running When I developed this library years ago I only really tested with three radios and short ranges. That project (not on github) used the following in the initialization; this->rfm->setRecommended(); // set recommended paramters in RFM69.
this->rfm->setPacketType(true, true); // set the used packet type.
this->rfm->setBufferSize(this->buffer_size); // set the internal buffer size.
this->rfm->setPacketLength(64); // set the packet length.
this->rfm->setFrequency(this->frequency); // set the frequency.
this->rfm->setNodeAddress(this->kernel->getPlatformAddress());
this->rfm->setBroadcastAddress(PLATFORM_ADDRESS_BROADCAST);
this->rfm->baud153600();
this->rfm->setPreambleSize(10);
// tell the RFM to represent whether we are in automode on DIO 2.
this->rfm->setDioMapping1(RFM69_PACKET_DIO_2_AUTOMODE);
// set pinmode to input.
pinMode(this->dio2_pin, INPUT);
// Tell the SPI library we're going to use the SPI bus from an interrupt.
SPI.usingInterrupt(this->dio2_pin);
// hook our interrupt function to any edge.
attachInterrupt(this->dio2_pin, interrupt_RFM, CHANGE);
// start receiving.
this->rfm->receive(); I only needed like 3 meters of range and for that it seemed to work well. But it's like 10 years ago, so I probably forgot countless weeks of frustration trying to get it to work reliably ;) Hope this gives you some pointers on what you could try and what the differences are. Remember that |
Thank you for all of this informaiton. I tried just changing just the baud rate as you recommended ("baud(300000)"), but that resulted in no messages being recieved. So I moved writeRegister() to make it a public function, and just set registers to match the settings in Radiohead as follows.
With those settings reception is good but I get random messages (see below). It's not missing any packets (despite the "packetloss" messages), so I guess I am in a pretty noisy environment. I have CRC checking turned off and there are no sync words so I think using those features would get rid of some of the mess. Unfortunately, this is all the work I can do today. I'll post more progress soon. Packet (4): 146 |
Without both of these, you have nothing that will prevent noise from being decoded as data. Especiall with I'm still surprised that you didn't get reliable reception with lower baud rates, I recall testing lower baudrates and getting reasonably reliable reception through multiple concrete walls, but that environment likely had very little background noise. |
Got stuck today trying to write my own writeRegister routine (so I can use plainRFM69 unaltered). Seems simple but I could not get this to work: void writeRFM69Register(uint8_t RFM_Reg, uint8_t RFM_Val) { //write a byte to a radio register.
pinMode(SLAVE_SELECT_PIN, OUTPUT);
SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0)); // gain control of SPI bus
digitalWrite(SLAVE_SELECT_PIN, LOW);
SPI.transfer(0x80 | (RFM_Reg & 0x7F));
SPI.transfer(RFM_Val);
digitalWrite(SLAVE_SELECT_PIN, HIGH);
SPI.endTransaction(); // release the SPI bus
} So I gave up and used the function in bareRFM69.cpp. Is there a reason for it to be a private function? I changed the RSSI threshold and got perfect transmission and reception within a range of register values from 0x50 to 0x78. Next I will implement CRC and syncwords. |
Hmm, sure looks like that should work... no real reason it's a private function, just never needed to be public before. I haven't used this chip in years, so my memory on all of these things is a bit hazy.
Nice, glad you're getting it working. |
Just one more appeal for help, I think. I found that the automode and interupt systems would not work for me (I'm working toward something that will use interrupts and SPI elsewhere). So what I need is to just poll an interrupt pin (DIO0) to see if a message has come in, and if so, read it. I've got that working, and I now have a much simplified radio interface that just uses functions to read and write to the radio registers, to reset the radio, and to fill and read the FIFO. I've taken these functions out of plainRFM69 and I have my own versions in the main sketch. It all works so long as I still create an instance of plainRFM69 with: plainRFM69 rfm = plainRFM69(SLAVE_SELECT_PIN); BUT...If I don't create the instance, then the code compiles and runs but there's no communication with the radio -- all register reads come back as 0xFF. So I'm trying to find the magic button that gets pushed when creating an instance. Any ideas? In case you are wondering why I don't just keep the instance...I'm coding for a device that will have lots of non-programmer as users, and I'm trying to keep the overhead low. The fewer libraries to download and update the better. Thanks again for all of your help. Here's the sketch in case it is useful to others: /*
* Modified from code by Ivor Wanders
* MIT License, see the LICENSE.md file in the root folder.
*/
#include <SPI.h>
#include <Arduino.h>
#include <plainRFM69.h>
// slave select pin.
#define SLAVE_SELECT_PIN 8
// connected to the reset pin of the RFM69.
#define RESET_PIN 7
#define LED_RFID 43 // (PA27) Pin to control the LED indicator.
#define RADIO_INT 9 //
// define serial com parameters
#define Serial SerialUSB // SerialUSB
//create instance of plainRFM69 = why is this necessary???
plainRFM69 rfm = plainRFM69(SLAVE_SELECT_PIN);
uint32_t counter = 0; // to count the messages.
bool gotMessage = 0;
void setup(){
pinMode(RADIO_INT, INPUT);
Serial.begin(9600);
SPI.begin();
blinkLED(LED_RFID, 3, 200);
delay(3000);
Serial.println("POWER ON!!");
radioReset(RESET_PIN); // send the RFM69 a hard-reset.
//settings rendered by rfm.setRecommended(), with modifications
radioWriteRegister(0x18, 0x08); //Set regLNA to turn on LnaZin and have gain set by the internal AGC loop
radioWriteRegister(0x2D, 0x04); //4 LSB for preamble bytes. default = 3; MSB defaults to 0
radioWriteRegister(0x2E, B10011000); //Sync on; FifoFillCondition = 0; 3 sync bytes, no tolerance
radioWriteRegister(0x2F, 0x2D); // Sync value: Set to arbitrary value - same across network
radioWriteRegister(0x29, 0x64); //setRSSIThreshold (trial & error)
radioWriteRegister(0x6F, 0x30); //setContinuousDagc 0 0
radioWriteRegister(0x02, 0x01); //set DataModul to one to turn on guassan filter
radioWriteRegister(0x3C, 0x7F & 15 ); //FIFO threshold; first bit zero -> TX when fifo over threshold. other bits = threshold (need to experiment)
radioWriteRegister(0x19, 0xE0); //Channel filtering?? DccFreq = B010; RxBwMant = B10, RxBwExp = B101
radioWriteRegister(0x1A, 0xE0); //Channel filtering?? DccFreqAfc = B111, RxBwMantAfc = B01, RxBwExpAfc = B000
radioWriteRegister(0x13, 0x1A); //setPALevel...
radioWriteRegister(0x11, 0x7F); //setPALevel: power almost at max
radioWriteRegister(0x07, 0x6C); //Frequency MSB for 434,000,000 Mhz
radioWriteRegister(0x08, 0x80); //Frequency MidSB for 434,000,000 Mhz
radioWriteRegister(0x09, 0x00); //Frequency LSB for 434,000,000 Mhz
//Settings from radioHeand and trial & error.
radioWriteRegister(1, 4);
radioWriteRegister(3, 0);
radioWriteRegister(4, 0x80);
radioWriteRegister(5, 0x10);
radioWriteRegister(6, 0);
radioWriteRegister(0x23, 0x0);
radioWriteRegister(0x24, 0xBE);
radioWriteRegister(0x25, 0x40); //RFM69_DIO_MAPPING
radioWriteRegister(0x27, 0xD8);
radioWriteRegister(0x30, 0x1);
radioWriteRegister(0x31, 0x1);
radioWriteRegister(0x32, 0x1);
radioWriteRegister(0x2F, 0x3D);
radioWriteRegister(0x37, 0xD0); //packet config, Variable length, whitening on, CRC on
radioWriteRegister(0x38, 0x20); //RFM69_PAYLOAD_LENGTH
//Final settings
radioWriteRegister(0x3D, 0); //no interpacket delay, no auto RX restart, no AES (encryption)
radioWriteRegister(0x3C, 0x01); //minimum package threshold
radioWriteRegister(0x3B, B00000000); //Automode setting - turn it off
radioWriteRegister(0x5A, 0x55); // RFM69_TEST_PA1: Normal mode and Rx mode
radioWriteRegister(0x5C, 0x70); //RFM69_TEST_PA2: Normal mode and Rx mode
radioWriteRegister(0x01, B00010000); //set to receiver mode
radioDumpRegisters(); // view all registers
delay(5);
}
void loop(){
char choose = 'R'; //Change to something other than "R' before loading to transmitter
if (choose == 'R'){
Serial.println("Going Receiver!");
receiver();
// this function never returns and contains an infinite loop.
} else {
Serial.println("Going sender!");
sender();
// idem.
}
}
void sender(){
uint32_t counter = 0; // the counter which we are going to send.
uint8_t tx_buffer[13]; //buffer is 1 more than message. First byte is length
//Send 12 numbers but change the 11th one each time...
tx_buffer[12] = 1; tx_buffer[1] = 2; tx_buffer[2] = 3; tx_buffer[3] = 4;
tx_buffer[4] = 5; tx_buffer[5] = 6; tx_buffer[6] = 7; tx_buffer[7] = 8;
tx_buffer[8] = 9; tx_buffer[9] = 0; tx_buffer[10] = 1; tx_buffer[11] = 2;
while(true){
delay(2000);
tx_buffer[11] = counter;
tx_buffer[0] = 12;
Serial.print("Send:");Serial.println(counter);
radioWriteRegister(0x01, B00000100); //First Set mode register to receive mode
//(0b010<<5) + (0b110<<2) + (0b11) = B01011011
radioWriteRegister(0x3B, B01011011); //set to automode - start transmitting when FIFO level is above the thresshold
radioWriteFIFO(tx_buffer, 12);
radioWriteRegister(0x01, B00000100); // Back to recieve mode.
counter++; // increase the counter.
blinkLED(LED_RFID, 3, 200);
}
}
void receiver(){
uint8_t rx_buffer[66] = {0};
uint32_t* rx_counter = (uint32_t*) &rx_buffer;
while(true){
delay(1000);
uint8_t rd = digitalRead(RADIO_INT);
Serial.println(rd);
if(rd) {
SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0)); // gain control of SPI bus
digitalWrite(SLAVE_SELECT_PIN, LOW);
//this->chipSelect(true); // assert chip select
//SPI.transfer((RFM69_FIFO % RFM69_READ_REG_MASK));
SPI.transfer((0 % 0x7));
uint8_t len = SPI.transfer(0);
//len = len > (max_length-1) ? (max_length-1) : len; //Contain max value of len
for (uint8_t i=0; i < len; i++){
rx_buffer[i] = SPI.transfer(0);
}
digitalWrite(SLAVE_SELECT_PIN, HIGH);
SPI.endTransaction(); // release the SPI bus
Serial.print("Received Packet ("); Serial.print(len); Serial.println("): ");
for (byte i=0; i<len; i++) {
Serial.print(rx_buffer[i]); Serial.print(" ");
}
Serial.println();
gotMessage = 0;
}
}
}
void blinkLED(uint8_t ledPin, uint8_t repeats, uint16_t duration) { //Flash an LED or toggle a pin
pinMode(ledPin, OUTPUT); // make pin an output
for (int i = 0; i < repeats; i++) { // loop to flash LED x number of times
digitalWrite(ledPin, LOW); // turn the LED on (LOW turns it on)
delay(duration); // pause again
digitalWrite(ledPin, HIGH); // turn the LED off (HIGH turns it off)
delay(duration); // pause for a while
} // end loop
} // End function
void radioReset(uint8_t pin){ // function to send the RFM69 a hardware reset.
pinMode(pin, OUTPUT);
digitalWrite(pin, HIGH);
delayMicroseconds(150); // pull high for >100 uSec
pinMode(pin, INPUT); // release
delay(10); // wait 10 milliseconds before SPI is possible.
}
void radioWriteRegister(uint8_t reg, uint8_t data){
SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0)); // gain control of SPI bus
digitalWrite(SLAVE_SELECT_PIN, LOW);
//this->chipSelect(true); // assert chip select
//SPI.transfer(RFM69_WRITE_REG_MASK | (reg & RFM69_READ_REG_MASK));
SPI.transfer(0x80 | (reg & 0x7F)); // send write instruction (high byte = 1)
SPI.transfer(data);
digitalWrite(SLAVE_SELECT_PIN, HIGH);
//this->chipSelect(false);// deassert chip select
SPI.endTransaction(); // release the SPI bus
}
uint8_t radioReadRegister(uint8_t reg){
uint8_t foo;
SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0)); // gain control of SPI bus
digitalWrite(SLAVE_SELECT_PIN, LOW);
//SPI.transfer((reg % RFM69_READ_REG_MASK));
SPI.transfer(reg % 0x7F); //use modulo of 0x7F to ensure read instruction (high byte of address = 0)
foo = SPI.transfer(0);
digitalWrite(SLAVE_SELECT_PIN, HIGH);// deassert chip select
SPI.endTransaction(); // release the SPI bus
return foo;
}
void radioWriteFIFO(uint8_t *buf, uint8_t len){
for(byte i = 0; i < len; i++) {
Serial.print(buf[i]); Serial.print(" ");
}
Serial.println();
//uint8_t* r = reinterpret_cast<uint8_t*>(buffer);
SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0)); // gain control of SPI bus
digitalWrite(SLAVE_SELECT_PIN, LOW); // assert chip select
//SPI.transfer(RFM69_WRITE_REG_MASK | (RFM69_FIFO & RFM69_READ_REG_MASK));
SPI.transfer(0x80); //high bit = 1 to indicate write instruction - reg address is 0x00 for FIFO
for (uint8_t i=0; i < len ; i++){
// Serial.print("Writing to FIFO: "); Serial.println(r[i]);
SPI.transfer(buf[i]);
}
digitalWrite(SLAVE_SELECT_PIN, HIGH); // deassert chip select
SPI.endTransaction(); // release the SPI bus
}
void radioDumpRegisters() { //View all radio registers
uint8_t val;
for (int i = 0; i <= 0x3d; i++) {
Serial.print("0x");
Serial.print(i, HEX);
Serial.print(": 0x");
val = radioReadRegister(i);
Serial.println(val, HEX);
}
int j = 0x58;
Serial.print("0x");
Serial.print(j, HEX);
Serial.print(": 0x");
Serial.println(radioReadRegister(j), HEX);
j = 0x5A;
Serial.print("0x");
Serial.print(j, HEX);
Serial.print(": 0x");
Serial.println(radioReadRegister(j), HEX);
j = 0x5C;
Serial.print("0x");
Serial.print(j, HEX);
Serial.print(": 0x");
Serial.println(radioReadRegister(j), HEX);
j = 0x6F;
Serial.print("0x");
Serial.print(j, HEX);
Serial.print(": 0x");
Serial.println(radioReadRegister(j), HEX);
j = 0x71;
Serial.print("0x");
Serial.print(j, HEX);
Serial.print(": 0x");
Serial.println(radioReadRegister(j), HEX);
}
edit; added |
Cool, I'm glad you're getting it all working!
Absolutely, thanks for sharing your code. I think the missing bit is the The |
I'm running example scripts with an RFM69HWC. The code works but I am getting only intermittant reception with communication between two radios running on modified M0 arduinos. When I use the radiohead library reception is perfect (so the hardware is OK). But I would prefer to use plainRFM69 so I can have control over interrupts. I just can't figure out what I need to do to get the transmission to work properly. I've got a high power version of the radio, and I've tried several variations on rfm.setTxPower(14, true), but there's no effect on reception. I will note that touching one of the antennas improves reception, which imples hardware issues. But again, everything works with the example scripts in radiohead. I'm just wondering if there's some incompatibility with RFM69HWC that I'm unaware of.
The text was updated successfully, but these errors were encountered: