Project

General

Profile

Intermitent reception problems with JeeNode / RFM69CW

Added by fgomes almost 4 years ago

I have 2 JeeNodes with RFM69CW 915MHz from Moderndevice.com. One is simply transmitting sensor data every 5 seconds. The other is receiving this data and updating an LCD with it (and reporting by the serial port). No Acks are being used in this test. I have the receiver permanently powered, sending messages every 5 seconds. I’m finding that when I power on the receiver it receives a few messages from the transmitter, but then stops receiving more messages (the remaining functions still work, but doesn’t receive radio messages). If I restart the receiver it receives again some messages and then stops receiving more messages. I’ve another node acting as a sniffer and it receives every message during the test, so it confirms that the transmitter is transmitting. I’ve also found that when i left the receiver powered, it is able to receive some messages from time to time, for example during one test it received 5 consecutive messages when I powered it on, then it didn’t receive any message for 50 minutes (the transmitter is transmitting every 5 seconds), then it recovered and received a few more messages (17 consecutive messages). The RSSI in the receiver node when it receives is always very good, the nodes are physically close (RSSI between –27 and –37 dBm).

This occurred in the past with a node that was replaced and the problem was solved, so I’ve considered that it was a problem with that radio, but now it is occurring again with a new module I’ve just received, I’m starting to get worried about that. Do you have some clue to what could be the problem? Some additional tests I could do in order to figure the root cause of this problem?

Thanks!

Fernando


Replies (35)

RE: Intermitent reception problems with JeeNode / RFM69CW - Added by fgomes almost 4 years ago

I’ll try to answer to the previous questions:

I didn’t change the RSSI threshold, I’m using the lib exactly as downloaded. I will do this change in order to check the difference, but as far as I understand this will ‘only’ enable the reception of messages with a lower signal, and what I’m facing is the reduction of the observed signal, or am I misunderstanding your suggestion? Do you suspect that the RSSI identified by the receiver is wrong, and this is not a receiver reception problem but it is only rejecting the messages because it is not calculating the RSSI correctly?

The RSSI is printed immediately after the recvDone function returns true.

The Ack to the transmitter is seen by the sniffer when the receiver is not blocked, with a very high signal since they are side by side, I get RSSI values of around –10dBm. When the receiver blocks, I see in the sniffer the transmitted messages and their retries, without any ack. You can see below some example values from the test done this night, when the receiver is seeing –86 dBm, the sniffer is seeing –67dBm.

For the receiver code, here are the main pieces (for simplicity), if you need the complete code please let me know, i’ll attach it. The lcdRefresh function could take some milliseconds since it has to manage the blinking of values shown when they are in alarm, but it is a code without loops, the blinking is based on the millis() time each time it is called. The processData function just copy the received values to internal variables so it takes a very short time to run. The processAlarms function just compares 4 values against thresholds and change the alarm flags associated with each value according to that comparison, so it is also very short. The only peripheral used is a LCD using the I2C adapter from JeeLabs. I have introduced a delay of 5ms between the received message and sending the ack, otherwise I wasn’t able to see the Ack in the sniffer. The transmitter node waits 20ms for the Ack, so i think that this isn’t a problem.

#define RF69_COMPAT 1
#include
#include
#include

#define SERIAL_DEBUG 1

// Transmit cycle in seconds
#define TRANSMIT_CYCLE 2
#define TRANSMIT_TIMEOUT ((TRANSMIT_CYCLE*2+10)*1000)
#define RECOVER_TIMEOUT ((TRANSMIT_CYCLE*10+10)*1000)
#define SCREEN_WIDTH 16
#define SCREEN_HEIGHT 2

unsigned long lastRX;
unsigned long lastRecover;

PortI2C myI2C (1);
LiquidCrystalI2C lcd (myI2C);

typedef struct payload {
unsigned int sequence;
float hallEffectValue; l
float temperature;
float battVoltage;
} payload;

typedef struct {
unsigned int cycleTime;
long currentTime;
} replyPayload;

replyPayload replyMsg;
int last_rssi=999;
int last_afc, last_fei, last_lna;
void setup() {
Serial.begin(57600);
lcd.begin(SCREEN_WIDTH, SCREEN_HEIGHT);
lcdInit();
rf12_initialize(18, RF12_915MHZ, 212); // params are byte nodeId, byte freqBand, byte netGroup
replyMsg.cycleTime = TRANSMIT_CYCLE;
lastRX = lastRecover = millis();
}
void loop() {
lcdRefresh();
if (rf12_recvDone()) {
if(rf12_crc == 0) {
lastRX = lastRecover = millis();
last_rssi =
(RF69::rssi>>1);
last_afc = (RF69::afc);
last_fei = (RF69::fei);
last_lna = (RF69::lna >> 3);
processData();
delay(5);
if(RF12_WANTS_ACK) {
replyMsg.currentTime = millis();
rf12_sendStart(RF12_ACK_REPLY, &replyMsg, sizeof(replyMsg));
}
processAlarms();

Serial.print(“Time = ”);
Serial.println(millis());
Serial.print(“RSSI: ”);
Serial.println(last_rssi);
Serial.print(“AFC: ”);
Serial.println(last_afc);
Serial.print(“FEI: ”);
Serial.println(last_fei);
Serial.print(“LNA: ”);
Serial.println(last_lna);
Serial.print(“Get payload.sequence: ”);
Serial.println(transaction_count_value);
Serial.print(“Get payload.hallEffectValue: ”);
Serial.println(lp_value, 0);
Serial.print(“Get payload.temperature: ”);
Serial.println(tmp_value, 1);
Serial.print(“Get payload.battVoltage: ”);
Serial.println(bat_value);
Serial.println(“=”);
} else {
Serial.print(millis());
Serial.println(" NOISE/CORRUPTED MSG“);
}
}
if((millis()-lastRX) > TRANSMIT_TIMEOUT) {
// Alarm
sprintf(lcdData.alarmMsg, ”Sensor failed“);
lcdData.signalStrength = –999;
processAlarms();
}
if((millis()-lastRecover) > RECOVER_TIMEOUT) {
Serial.print(”Trying to recover RFM69");
replyMsg.currentTime = millis();
rf12_sendNow(0, &replyMsg, sizeof(replyMsg));
rf12_sendWait(0);
lastRecover = millis();
}

} //End of Loop

For running the RF12Demo at the receiver, what do you propose? Changing the transmitter and receiver code and send messages between them? Can you tell me what commands do you want to run?

Adding some additional info for the test made during the night (after swapping the hardware between the sniffer and receiver as I stated in the previous post), there were some blocking issues (4 in total) but they have recovered always when the receiver sent a message. When they occured the RSSI was very low (–82 dBm) but this morning it was normal again (–72dBm). The sniffer always get about –70dBm during all night, even when the receiver blocks. These are some of the values in the receiver:

At the start of the test:

Time = 10341
RSSI: –68
AFC: 0
FEI: 95
LNA: 3

Before the first failure (1:15 hours later):

Time = 4526623
RSSI: –86
AFC: 0
FEI: 199
LNA: 2

For the above message seen by the receiver with –86dBm, the values seen by the sniffer where the following:

Message from the transmitter seen by the sniffer:
RSSI –67
AFC: 0
FEI: 538
LNA: 4

Ack from the receiver seen by the sniffer:
RSSI: –10
AFC: 0
FEI: 538
LNA: 6

Returning to messages saw by the receiver:

Before the second failure (1:16 hours later):

Time = 4606408
RSSI: –83
AFC: 0
FEI: 199
LNA: 2

This morning (9:15 hours later):

Time = 33299373
RSSI: –74
AFC: 0
FEI: 362
LNA: 3

So after some issues occurred between 1:15 and 1:30 hours working, it continued to work ok until now.

Fernando

RE: Intermitent reception problems with JeeNode / RFM69CW - Added by JohnO almost 4 years ago

I will look at your data in a moment. Can you check how long your transmitter waits for an ACK before retransmitting.

RE: Intermitent reception problems with JeeNode / RFM69CW - Added by JohnO almost 4 years ago

fgomes wrote:
> I’ll try to answer to the previous questions:
>
> I didn’t change the RSSI threshold, I’m using the lib exactly as downloaded. I will do this change in order to check the difference, but as far as I understand this will ‘only’ enable the reception of messages with a lower signal, and what I’m facing is the reduction of the observed signal, or am I misunderstanding your suggestion?

My thoughts were that a borderline signal is received that moves the receiver centre frequency to a point where the next packet is clipped by the RSSI threshold. Since this follow on packet is not received the AFC has no opportunity to swing the centre frequency back again.

> Do you suspect that the RSSI identified by the receiver is wrong, and this is not a receiver reception problem but it is only rejecting the messages because it is not calculating the RSSI correctly?

I am considering lots of things: Is there a second device somewhere also sending an ACK? Is the transmitter not waiting long enough before transmitting again and corrupting the airwaves. Is a 912Mhz packet arriving from somewhere else before you have pulled the RSSI, LNA etc values .

> The Ack to the transmitter is seen by the sniffer when the receiver is not blocked, with a very high signal since they are side by side, I get RSSI values of around –10dBm. When the receiver blocks, I see in the sniffer the transmitted messages and their retries, without any ack. You can see below some example values from the test done this night, when the receiver is seeing –86 dBm, the sniffer is seeing –67dBm.
>
> For the receiver code, here are the main pieces (for simplicity), if you need the complete code please let me know, i’ll attach it. The lcdRefresh function could take some milliseconds since it has to manage the blinking of values shown when they are in alarm, but it is a code without loops, the blinking is based on the millis() time each time it is called. The processData function just copy the received values to internal variables so it takes a very short time to run. The processAlarms function just compares 4 values against thresholds and change the alarm flags associated with each value according to that comparison, so it is also very short. The only peripheral used is a LCD using the I2C adapter from JeeLabs. I have introduced a delay of 5ms between the received message and sending the ack, otherwise I wasn’t able to see the Ack in the sniffer. The transmitter node waits 20ms for the Ack, so i think that this isn’t a problem.

Understood.

> #define RF69_COMPAT 1
> #include
> #include
> #include
>
> #define SERIAL_DEBUG 1
>
> // Transmit cycle in seconds
> #define TRANSMIT_CYCLE 2
> #define TRANSMIT_TIMEOUT ((TRANSMIT_CYCLE*2+10)*1000)
> #define RECOVER_TIMEOUT ((TRANSMIT_CYCLE*10+10)*1000)
> #define SCREEN_WIDTH 16
> #define SCREEN_HEIGHT 2
>
> unsigned long lastRX;
> unsigned long lastRecover;
>
> PortI2C myI2C (1);
> LiquidCrystalI2C lcd (myI2C);
>
>
> typedef struct payload {
> unsigned int sequence;
> float hallEffectValue; l
> float temperature;
> float battVoltage;
> } payload;
>
> typedef struct {
> unsigned int cycleTime;
> long currentTime;
> } replyPayload;
>
> replyPayload replyMsg;
> int last_rssi=999;
> int last_afc, last_fei, last_lna;
>
> void setup() {
>
> Serial.begin(57600);
> lcd.begin(SCREEN_WIDTH, SCREEN_HEIGHT);
> lcdInit();
>
> rf12_initialize(18, RF12_915MHZ, 212); // params are byte nodeId, byte freqBand, byte netGroup
>
> replyMsg.cycleTime = TRANSMIT_CYCLE;
> lastRX = lastRecover = millis();
>
> }
>
> void loop() {
>
> lcdRefresh();
>
> if (rf12_recvDone()) {
> if(rf12_crc == 0) {
> lastRX = lastRecover = millis();
> last_rssi =
(RF69::rssi>>1);
> last_afc = (RF69::afc);
> last_fei = (RF69::fei);
> last_lna = (RF69::lna >> 3);
> processData();
> delay(5);
> if(RF12_WANTS_ACK) {
> replyMsg.currentTime = millis();
> rf12_sendStart(RF12_ACK_REPLY, &replyMsg, sizeof(replyMsg));

I wonder if it is worth waiting here until the ACK has been transmitted. Very unlikely to be an issue though.

> }
> processAlarms();
>
> Serial.print(“Time = ”);
> Serial.println(millis());
> Serial.print(“RSSI: ”);
> Serial.println(last_rssi);
> Serial.print(“AFC: ”);
> Serial.println(last_afc);
> Serial.print(“FEI: ”);
> Serial.println(last_fei);
> Serial.print(“LNA: ”);
> Serial.println(last_lna);
> Serial.print(“Get payload.sequence: ”);
> Serial.println(transaction_count_value);
> Serial.print(“Get payload.hallEffectValue: ”);
> Serial.println(lp_value, 0);
> Serial.print(“Get payload.temperature: ”);
> Serial.println(tmp_value, 1);
> Serial.print(“Get payload.battVoltage: ”);
> Serial.println(bat_value);
> Serial.println(“=”);
> } else {
> Serial.print(millis());
> Serial.println(" NOISE/CORRUPTED MSG“);
> }
> }
>
> if((millis()-lastRX) > TRANSMIT_TIMEOUT) {
> // Alarm
> sprintf(lcdData.alarmMsg, ”Sensor failed“);
> lcdData.signalStrength = –999;
> processAlarms();
> }
>
> if((millis()lastRecover) > RECOVER_TIMEOUT) {
> Serial.print(“Trying to recover RFM69”);
> replyMsg.currentTime = millis();
> rf12_sendNow(0, &replyMsg, sizeof(replyMsg));
> rf12_sendWait(0);
> lastRecover = millis();
> }
>
> } //End of Loop
>
> For running the RF12Demo at the receiver, what do you propose? Changing the transmitter and receiver code and send messages between them? Can you tell me what commands do you want to run?
Does the transmitter check the returned payload in the ACK
RF12Demo is able to send ACK but won’t return your millis payload.
I was thinking of replacing the receiver by RF12Demo, it can send the ACK’s (”0c") provided this is sufficient for the transmitter to carry on.

> Adding some additional info for the test made during the night (after swapping the hardware between the sniffer and receiver as I stated in the previous post), there were some blocking issues (4 in total) but they have recovered always when the receiver sent a message. When they occured the RSSI was very low (–82 dBm) but this morning it was normal again (–72dBm). The sniffer always get about –70dBm during all night, even when the receiver blocks. These are some of the values in the receiver:

This is very odd.

> At the start of the test:
>
> Time = 10341
> RSSI: –68
> AFC: 0
> FEI: 95
> LNA: 3
>
>
> Before the first failure (1:15 hours later):
>
> Time = 4526623
> RSSI: –86
> AFC: 0
> FEI: 199
> LNA: 2
>
> For the above message seen by the receiver with –86dBm, the values seen by the sniffer where the following:
>
> Message from the transmitter seen by the sniffer:
> RSSI –67
> AFC: 0
> FEI: 538
> LNA: 4
>
> Ack from the receiver seen by the sniffer:
> RSSI: –10
> AFC: 0
> FEI: 538
> LNA: 6
>
> Returning to messages saw by the receiver:
>
> Before the second failure (1:16 hours later):
>
> Time = 4606408
> RSSI: –83
> AFC: 0
> FEI: 199
> LNA: 2
>
> This morning (9:15 hours later):
>
> Time = 33299373
> RSSI: –74
> AFC: 0
> FEI: 362
> LNA: 3
>

Very very odd!

Do you have other 912Mhz devices around?

RE: Intermitent reception problems with JeeNode / RFM69CW - Added by fgomes almost 4 years ago

Thanks! For the transmitter side, ACK_TIME is 20ms:

static byte waitForAck() {

replyPayload* msg;

MilliTimer ackTimer;
while (!ackTimer.poll(ACK_TIME)) {
if (rf12_recvDone() && rf12_crc 0 && rf12_hdr (RF12_HDR_DST | RF12_HDR_CTL | NODE)) {
// see http://talk.jeelabs.net/topic/811\#post-4712
msg = (replyPayload*) rf12_data;
cycleTime = msg->cycleTime;
return 1;
}
set_sleep_mode(SLEEP_MODE_IDLE);
sleep_mode();
}
return 0;
}

The retransmission is delayed 100ms if ack failed. The RETRY_LIMIT is 5:

for(i=0; i<RETRY_LIMIT; i++) {
rf12_sleep(RF12_WAKEUP);
rf12_sendNow(RF12_HDR_ACK, &payload, sizeof payload);
rf12_sendWait(2);
byte acked = waitForAck();
rf12_sleep(RF12_SLEEP);
if (acked) {
break;
}
// Msg or Ack could fail due to noise, wait a few milliseconds in low power before retrying:
Sleepy::loseSomeTime(100);
}

Fernando

RE: Intermitent reception problems with JeeNode / RFM69CW - Added by fgomes almost 4 years ago

Thanks for you detailed analysis!

JohnO wrote:
> fgomes wrote:
> > I’ll try to answer to the previous questions:
> >
> > I didn’t change the RSSI threshold, I’m using the lib exactly as downloaded. I will do this change in order to check the difference, but as far as I understand this will ‘only’ enable the reception of messages with a lower signal, and what I’m facing is the reduction of the observed signal, or am I misunderstanding your suggestion?
>
> My thoughts were that a borderline signal is received that moves the receiver centre frequency to a point where the next packet is clipped by the RSSI threshold. Since this follow on packet is not received the AFC has no opportunity to swing the centre frequency back again.

Ok, I’ll try it later today

>
> > Do you suspect that the RSSI identified by the receiver is wrong, and this is not a receiver reception problem but it is only rejecting the messages because it is not calculating the RSSI correctly?
>
> I am considering lots of things: Is there a second device somewhere also sending an ACK? Is the transmitter not waiting long enough before transmitting again and corrupting the airwaves. Is a 912Mhz packet arriving from somewhere else before you have pulled the RSSI, LNA etc values .
>

I only have three nodes with 915MHz radios (receiver, transmitter, sniffer), all my other nodes are 868MHz, so as far as I know there is no other transmission in this frequency. Nevertheless, using SDR# I observe a small constant carrier always present at this frequency, and then the pulsating carrier when the nodes transmit.

> > if(RF12_WANTS_ACK) {
> > replyMsg.currentTime = millis();
> > rf12_sendStart(RF12_ACK_REPLY, &replyMsg, sizeof(replyMsg));
>
> I wonder if it is worth waiting here until the ACK has been transmitted. Very unlikely to be an issue though.
>

Ok, I’ll add it, just in case :)
> > For running the RF12Demo at the receiver, what do you propose? Changing the transmitter and receiver code and send messages between them? Can you tell me what commands do you want to run?
>
> Does the transmitter check the returned payload in the ACK
RF12Demo is able to send ACK but won’t return your millis payload.
> I was thinking of replacing the receiver by RF12Demo, it can send the ACK’s (“0c”) provided this is sufficient for the transmitter to carry on.
>
I could patch the transmitter to ignore the payload

>
> Do you have other 912Mhz devices around?

Nop, as stated above, as I am in Europe I normally use 868 or 433 radios. Currently I have 3 JeeNodes SMD with 915MHz radios from Moderndevice, all used in this test (transmitter, receiver and sniffer) and these are the only radios I have for this frequency band. The other radios I have at home are 868MHz RFM69HW and RFM12B devices, and of course some remote controls for the garage door and other ‘standard’ wireless devices (433 and 868 MHz).

Best regards

Fernando

RE: Intermitent reception problems with JeeNode / RFM69CW - Added by JohnO almost 4 years ago

Hi Fernando,

Do you handle sleep differently in your sniffer versus your receiver? I ask because the observed RSSI reported by a ATMega328 that just woken from sleep is worse than one that is always awake. I have put this down to the delay in the processor waking up delaying the grabbing of the RSSI value from the radio card.

I have posted on the phenomenon before when I was exploring low power options but it hasn’t been fully explored.

RE: Intermitent reception problems with JeeNode / RFM69CW - Added by fgomes almost 4 years ago

Hi John

I only put the ATMEGA sleeping in the transmitter. The receiver and the sniffer don’t sleep, since they are not battery powered I didn’t optimize their power consumption. I’ll try the other tips you gave me, lowering the RSSI threshold to see if it behaves better.

In the meantime I tried a different approach, I don’t know if this can give us some clue to the issue. With the most problematic node pair in the previous tests I changed the RF part of the code to use the LowPowerLab lib instead of the JeeLib (I kept the JeeLib for all the non RF functions, like LCD, Sleepy, etc). And the finding was that the RSSI kept stable during all the test (about 8 hours), both in the receiver and in the sniffer, and similar in both. The rest of the receiver code was kept and working, updating the LCD with the values received from the transmitter.

The other finding was that the signal level seen in the receiver for the transmitter messages, both in the same position as in the previous tests (8 meters away with some walls in between) is similar to the RSSI I saw in the sniffer in the previous test (between –68 and –71 dBm), and now stable and equal in both the receiver and sniffer. But the RSSI saw by the sniffer or the receiver for a transmitter node close to it is now (using LowPowerLab lib) “only” about –25dBm, where in the same tests using the JeeLib the RSSI when the nodes are side by side was better than –10dBm (I even saw –6dBm in some of the messages). Does this makes any sense? Any different AGC configuration, since the signal when the transmitter is far is the same, it seems that it isn’t the transmission power that is different, but the dynamic sensitivity is different. The LowPowerLab lib doesn’t have implemented the reading of the radio registers in the interrupt handler as you did, but I could add them in order to compare if you think it could help.

Best regards

Fernando

RE: Intermitent reception problems with JeeNode / RFM69CW - Added by JohnO almost 4 years ago

Hi Fernando,

Interesting results with the LowPowerLab library, this suggests to me that we have some issue on our library to look at. The actual RSSI value is highly dependant on the instant that is collected and should be viewed only as comparative between nodes built with the same library. I am interested in seeing any issues in jeelib resolved since that is the library I am familiar with but I don’t really have the bandwidth to get up to speed with the LowPowerLab library.

RE: Intermitent reception problems with JeeNode / RFM69CW - Added by JohnO almost 4 years ago

Are you willing to post your full jeelib version code for the transmitter, receiver and sniffer?

RE: Intermitent reception problems with JeeNode / RFM69CW - Added by JohnO almost 4 years ago

Hi Fernando,

I have had a thorough trawl through theRF69 code over the last couple weeks and dug out a bug and enhanced the packet length verification section.
If you ever have time to give the branch another try I would welcome your feedback.

(26-35/35)