Skip to main content

You are here

rf12_canSend() RSS check always true

11 posts / 0 new
Last post
rf12_canSend() RSS check always true

I have been trying to debug some intermittent connectivity issues and have my logic analyzer hooked up to a JeeNode n5 talking to a JeeNode v6. One thing I've noticed is that in the rf12_canSend() code it checks to make sure the "air is clear" by attempting to check the RSSI bit of the RFM12B status word. if (rxstate == TXRECV && rxfill == 0 && (rf12_byte(0x00) & (RF_RSSI_BIT >> 8)) == 0) { rf12_xfer(RF_IDLE_MODE); // stop receiver ... Note. Not only is the code only sending one byte and I think all transaction have to be a word, but rf12_byte doesn't take the SPI slave select line low so byte is sent to no device on the bus. What we're seeing here is RF_IDLE_MODE RF_RECEIVER_ON // rf12_recvDone because first rf12_canSend returns 0 00 sent to nobody // rf12_canSend test RF_IDLE_MODE // rf12_canSend success RF_XMITTER_ON // starting transmit

Two questions up for discussion

  • Should the code be removed entirely or updated to do an actual command word?
  • Why turn the receiver on at all before attempting a transmit? It is only on for 6us and the only possible outcome is that it gets a sync byte in those 6us. The odds of that seem extremely low.

Wow, good work. My guess is that we may need to stew on this until jcw finishes his one month watchdog.


Ooh, good catch. The way things are coded now, I agree that this check probably doesn't do anything useful.

It's still a good idea to get "listen-before-send" going, IMO. It means that nodes try not to disrupt an ongoing transmission. That doesn't have to be a perfect solution - if it covers most cases, then that in itself can improve band utilization. Note that the task is not to receive a preamble or a valid data byte, only to find out wether any sort of 868 MHz signal is being received (could be an unrecognized format, including OOK). The RSSI bit flags signal strenght, and is independent of the signal encoding method.

What I don't know, is how long the receiver has to be on to be able to detect RSSI. If that's a few ms, then this mechanism would be a bit expensive: turn on receiver, wait a few ms, then read out the RSSI bit. But I suspect that the receiver doesn't need very long to actually set RSSI. Trouble is, it'll take some tricky testing to figure this out, I'm afraid. I'll think about how to improve on this.

One last comment: rf12_canSend() is still needed, even though the RSSI check doesn't work. It also prevents the code from starting a transmission while a proper packet is being received.


Hey you're not supposed to be here, go enjoy your time off! I agree about the listen-before-send concept but it doesn't appear that the RFM gives us any indication of if it is actually receive-capable.

In my case, my RFM was sleeping with the standard rf12_sleep(RF12_SLEEP) command with this sort of code: rf12_sleep(RF12_WAKEUP); while (!rf12_canSend()) rf12_recvDone(); rf12_sendStart(0, outbuf, len); rf12_sendWait(1); rf12_sleep(RF12_SLEEP); The datasheet says it takes 250uS to start the receiver which occurs on the first call to rf12_recvDone(). A 16MHz ATmega can loop a heck of a lot faster than 250uS so the status check always will have the RSSI field cleared. That's what I thought happens. However in this case where I'm just waking up from RF12_SLEEP (crystal oscillator has been shut down), the time to turn on the receiver is tOscStartup + tRecvStartup. tOsc is 1-5ms according to the datasheet, and 2.9-3ms in my measurement. So when waking from sleep to transmit, I'm not really sure how to tell when it is ok to check RSSI levels. The only way I can tell how long the startup takes is timing a dead sleep to transmitter turn on where the interrupt signals it is ready for data.

I was playing with this all day yesterday to learn more about how the RFM12 works. In my case, I never need to receive and knowing that the RSSI check will return 0 for the first 1-5ms after receiver turn on I just removed it completely. Also knowing that the radio takes 3ms to start up, I changed my code to wake the RFM as soon as I know I'm going to have data to send, then go about collecting other data I'll include (battery level) and build the packet. Doing so shaved close 1ms off the time I spend in IDLE waiting for the first interrupt. BEHOLD (1ms divs)!

Waking the radio immediately before rf21_sendStart()

Waking the radio early

I've also shortened the preamble down to 16 bits just to play with that, which is why the transmitter is on a slightly smaller amount of time in the second image.


Does anyone know if we ever fixed this: 'rf12_canSend() RSS check always true'.


Good question John!

I am using a word transfer reading the status register in CanSend() since a long time (without seeing this thread), but have now noticed that the reading is useless because it comes too short after activating the receiver.

And I am experiencing another problem with CanSend(). If a lot of rf 'noise' is present (or, as in my case, the antenna design is not perfect), the RSSI bit is always set and while( CanSend() ); is looping until the watchdog resets the controller. I have fixed this with an additional timeout. If the while loop is left due to timeout (~20ms), I just start sending.

Seems there is still some work necessary on the driver...

BR, Jörg.


This applies to the case when the RFM12B has only just been brought out of sleep mode, right?


@jcw, good question...
I see this in an application with a pcb antenna (single LiFeYPO4 cell monitor). In the shorter version for 60Ah cells the antenna is also shorter and has a much worse form. On this pcb I use the same software as on the longer 100Ah one and I see a lot of watchdog resets due to the CanSend() loop not coming to an end. If I increase the RSSI threshold by one step, it works also for this pcb version. And all this is also heavily dependant on the number of other modules in the nearer neighborhood. So it seems to have something to do with 'RF noise'.
Not so easy to debug though, because it nearly never happens on the workbench but only in the 'real' environment...
To answer your question, yes, the module wakes up every 20s to send a new status message and this is where CanSend() is used.


No, the big bug is that rf12_byte() doesn't assert chip select (bitClear(SS_PORT, cs_pin)) so it isn't sending data to anyone. Therefore rf12_byte() always returns 0, and this

0 & (RF_RSSI_BIT >> 8)) == 0

Is always true. I was suggesting just removing the check on the basis that "If it never did anything for the past 2 or 3 years, I think it is safe to go without it". Since I've made that suggestion, we now know that the DRSSI bit has such a tremendous lag (at least a millisecond), that replacing the code with working code would likely produce false positives and fail to indicate the proper state of "the air".


sorry for hijacking this thread with my very special problem due to badly designed hardware (antenna).

What yo say is:
- using rf12_byte() is absolutely wrong because it does not assert chip select
- using rf12_xfer() would cure this but does not work due to too slowly reacting DRSSI bit
- So the lib should at least be corrected by just removing this code until a better solution is found.

Agreed. This would not give the false feeling that this code could work at all under different circumstances (as JCs question suggests).


Yeah that sums it up pretty well. The DRSSI actually would be asserted for a small window at the beginning of the packet. There's 5 bytes of preamble so the DRSSI would be asserted and the other checks would still be false for about half that. This assumes that the incoming transmission is above the set level, which also isn't always the case. So yes there could be some benefit to checking it, but considering it hasn't been functional and we still see great performance I believe it isn't worth the effort.

But yeah the option would be to either replace it with rf12_xfer(0x0000) & RF_RSSI_BIT or remove it. It isn't hurting anything right now though so it isn't a tremendous issue.

Premium Drupal Themes by Adaptivethemes