Dropped Packets with High RSSI

Started by Aerokeith, July 02, 2025, 02:06:45 AM

Aerokeith

I've been testing some new PCBs that use Sparkfun RFM69HCW modules, and am seeing some strange behavior. I have a single transmitter sending 61 byte packets at a very low fixed rate, between 1 and 10 pkts/sec. The single receiver (eventually will be 4) is receiving most packets correctly, with a RSSI of -31dBm when the boards are close together. But every 5-30 packets or so, one (and only one) packet is entirely dropped. I'm measuring the time between received packets to confirm that it's a single packet drop. The packet drop rate doesn't seem to depend on the receiver RSSI (distance).

Configuration:
Teensy 4.0 MCU (SPI CS on pin 10; Interrupt on pin 2)
Both the transmitter and receiver call setCS(10); setHighPower(); and set300KBPS();

I can't tell if the issue is on the transmitter or receiver side. Since I'm sending packets so slowly, I assume I'm not overrunning the transmit rate, although I don't know how to check that the transmitter is ready (apparently it's not canSend()), or if the send() operation has successfully completed (???).

On the receiver side I'm using receiveDone() to check for packet receipt, and then I read the RSSI immediately afterwards to confirm that it looks good.

Can anyone suggest additional tests to help isolate the issue? Thanks!

Felix

Circuit wise, if all is good, and it looks like you know what you're doing, there are 3 things I'd explore to try to narrow this down:

- Unless your application requires so for some very specific reason, I would drop back from 300kbps to the library default. And see if the same behavior persists.
- Number 2 is the obvious elephant in the room, which runs at some insane speeds for such a small micro board. If you have the ability, to try one with another board,
- Analyze the spectrum with a freeze feature to capture sporadic fast packets or used frequencies that might be near or on top of your channel. It's rare, and usually more in a dense urban or industrial setting that stray frequencies jam your own traffic, and perhaps that could be the case.

Aerokeith

I tried dropping back to the default data rate, but no change in the behavior.
As for #2, I can try testing with my original prototype, which has much greater spacing between the Teensy MCU and the radio module.
But I don't have a spectrum analyzer. In any case, I'm in a pretty rural area. By the way, I check the RSSI on the transmitter side right before each packet is transmitted, and it's a steady -128dBm.
It's just so odd that it's always one packet dropped, never two in a row.

Felix

The receiver should be in receive mode, that's accomplished by calling receiveDone() and not doing something else in between.
When you say slowly, you must mean frequency, not data rate - which you maxed out at 300kbps. Hence, I suggest taking different approaches to change variables in the equation and observe when the behavior stops or changes, then you're close to the problem.

Aerokeith

Quotethe receiver should be in receive mode, that's accomplished by calling receiveDone() and not doing something else in between.
Yes, that's what I'm doing.

By "slowly" I mean that I'm sending packets [calling send() ] at a low rate of only a few times a second. I haven't yet found a way to determine if the transmitter is ready to send another packet, so I'm relying on fixed timing.

Quotewhich you maxed out at 300kbps.
I commented out the call to set300KBPS() on both the sender and receiver side but that didn't make a difference.

Yes, I understand basic debugging techniques. I'm just looking for additional variables to try.

Aerokeith

Felix,
I ran a new test with a different method, and this time found that dropping back to the default bitrate considerably reduced the packet drop rate. The drop rate is also reduced if the transmitter and receiver are move further apart (they were only inches apart originally).

At the default bitrate, I see an effective data throughput of about 57 Kbps. Unfortunately, this is a bit too slow for my application, which needs about 70 Kbps. Can you please tell me how to adjust the rate? I searched through the forum but couldn't find a clear answer.

I haven't yet had time to run a test to see if interference from the MCU is the culprit.

Thanks, Keith

Felix

See definition for RFM69::set300KBPS().
Adjust for 100 or the lowest you need to achieve your requirement:
Datasheet is here.


Aerokeith

Can you please confirm that these are the correct settings for BitRate=100 Kbps?

void set100KBPS() {
  writeReg(0x03, 0x01);  //REG_BITRATEMSB: 100kbps (0x0140, see DS p20)
  writeReg(0x04, 0x40);  //REG_BITRATELSB: 100kbps (0x0140, see DS p20)
  writeReg(0x19, 0x49);  //REG_RXBW: 200kHz (DccFreq=010b, RxBwMant=01b/20, RxBwExp=001b)
  writeReg(0x1A, 0x89);  //REG_AFCBW: 200kHz (DccFreqAfc=100b, RxBwMantAfc=01b/20, RxBwExpAfc=001b)
  writeReg(0x05, 0x06);  //REG_FDEVMSB: 100khz (0x0668)
  writeReg(0x06, 0x68);  //REG_FDEVLSB: 100khz (0x0668)
  writeReg(0x29, 240);   //set REG_RSSITHRESH to -120dBm
  writeReg(0x37, 0b10010000); //DC=WHITENING, CRCAUTOOFF=0
  //                ^^->DC: 00=none, 01=manchester, 10=whitening
}

Also, if I want to use two transmitters operating in close proximity (~2m apart), do I need to offset the center frequencies by more than RxBw?
Thanks!

Felix


Aerokeith

A quick initial test indicates that it works well enough. More testing to come.

Any thoughts on the second question?

Felix

They should work just as well at 2m apart.
You want the center frequency to match as much as possible. In reality it will vary from module to module by some amount, which is OK.

Aerokeith

I think I'm getting closer to identifying the root cause of my "dropped packets" issue. The link is very reliable, with essentially no packet drops, if I continuously transmit packets by calling send() in a tight loop. But as soon as I add any delay between calls to send(), the packet loss rate jumps up. My guess is that during the delays the RFM module is switching to RX mode to listen for incoming packets. And then on the next call to send() maybe there's some kind of glitch when switching back to TX mode that corrupts the packet. Or maybe this is happening on the receiver side?

I've tested the difference between "continuous-transmit" and "periodic transmit" modes a couple of different ways, and get consistent results: continuous-good, periodic=bad. In periodic-transmit mode, the size of the delay between calls to send() doesn't seem to matter, although I haven't yet tried very small delays to see where the breakpoint is.

In my application i have dedicated transmit-only and receive-only nodes. Is there a way I can force the module to remain in either TX or RX mode?

Note that in my application, the delay between calls to send() are important. I use the elapsedMillis library to "pace" the calls to send(), allowing the CPU to perform other tasks during the delays.

Regarding the question I asked about center frequencies: I will have two transmitters in close proximity, and each transmitter will be sending data to two receivers located slightly further away. I plan to use different center frequencies for each transmitter [using setFrequency()] and I was asking about the necessary frequency separation.

Felix

I applaud your perseverence, it pays off.
The send() will just modulate the packet then switch the radio in STANDBY mode, it cannot be left in TX mode or it would continuously modulate the carrier and not only eat up a lot of current, but also block the channel, it would be a terrible waste.
One call to receiveDone() will check if there is data received and if not it places the radio in RX mode, it eats around 15mA, but it stays there, it's needed if you expect an incoming packet at any undetermined time, once a packet is received it will read the packet and go into STANDBY mode.
A call to receiveBegin() just forces the RX mode regardless (this is called by receiveDone())

So i misunderstood initially - you definitely want comfortable separation if you transmit in parallel. I call for 300kbps if you have the room and don't need many channels tight together. Even 1mhz if there is no concern. Too much will start suffering if the antennas tuning frequency is very sharp, but 1mhz should be just fine with most antennas, and in your case at very short range a few db missed because of slight antenna mismatch is no concern.

Aerokeith

QuoteI applaud your perseverence, it pays off.
Thanks, it's really important that I get this working in within the next week.

Your message describes the normal operations of send() and receiveDone(), which I think I understand reasonably well. But I don't see any clues that would help me find or fix the problem. Maybe I should describe what I'm doing (in my test code) in more detail to see if it gives you any ideas of new things to try:

Transmit
The main loop calls send() every 100ms to send a 61 byte packet where the first byte contains a packet sequence number that is incremented every iteration. The bit rate is 100 Kbps.

Receive
The main loop repeatedly calls receiveDone() to check for a received packet, with no delays within the loop. If a packet is received, the packet sequence number is checked to see if there's a gap in the expected sequence. Errors are reported, but no other processing is performed (for this test).

It's pretty simple, but doesn't work correctly (no packet drops) until the transmit-side delay is reduced to less than the duration of a single packet (~6ms).
In this condition, send() is being called before the last bits of the previous packet have been transmitted. That's normal, I know. But when the delay is increased, send() is called when the previous transmission is completed (which I assume turns off the transmitter). So I'm guessing that there's some sort of delay in turning the transmitter back on such that the RFM module isn't fully ready to transmit the first bits of the packet, which get corrupted. I tried adding a setMode(RFM_MODE_TX) before the call to send() but that had no effect.

Any better ideas?


Aerokeith

Sorry to bug you. Can you at least confirm that the approach I'm using should work, and that it's not unusual? I keep looking for something stupid I've done, but no luck so far.