Author Topic: Real time RSSI measurement broken RFM69CW?  (Read 27091 times)

WhiteHare

  • Hero Member
  • *****
  • Posts: 1296
  • Country: us
Re: Real time RSSI measurement broken RFM69CW?
« Reply #75 on: February 12, 2016, 01:35:11 PM »
Here's a tentative plan on how to implement Perky's suggestion for sleeping while the RSSI measurement is taken.  Use the above methods to figure out the period of the RSSI measurement (by noticing how often it updates).  Using that information, then on the next RSSI update, put *everything* to sleep except for the radio.  Then, sometime *after* the *next* RSSI measurement is taken, wake-up the atmega and read the latched RSSI value from the radio.  That value will have been measured while the atmega and everything else was asleep, and thus it is the measurement we want.  Obviously, the timing of the wakeup has to be precise so as to not read an RSSI that was latched after the wakeup has happened.

I'm tempted to rely on an external interrupt to wake the atmega rather than the atmega's internal clock, if only because of the atmega's proximity to the radio.   I'm not sure what to use for that, though.  Any suggestions?

perky

  • Hero Member
  • *****
  • Posts: 873
  • Country: gb
Re: Real time RSSI measurement broken RFM69CW?
« Reply #76 on: February 12, 2016, 04:46:25 PM »
Could you just map RSSI onto DIO0 and wake it up with that? Something like this:

Map RSSI to DI0
Put into RX mode
Immediately go to sleep
Wake up with RSSI rising edge
Immediately read RSSI register


WhiteHare

  • Hero Member
  • *****
  • Posts: 1296
  • Country: us
Re: Real time RSSI measurement broken RFM69CW?
« Reply #77 on: February 12, 2016, 05:12:51 PM »
Excellent idea!

WhiteHare

  • Hero Member
  • *****
  • Posts: 1296
  • Country: us
Re: Real time RSSI measurement broken RFM69CW?
« Reply #78 on: February 12, 2016, 09:34:54 PM »
Given that RSSI threshhold is set to 0xFF, it turns out that once RSSI goes HIGH, it simply stays high.  i.e. it can't be used to signal that there's a new RSSI value to read, unless an RX restart has occured, which temporarily sets RSSI back to zero.  It takes about 6.8ms between initiating an RX restart and RSSI going HIGH, so the new plan is to initiate an RX Restart, immediately put the atmega to sleep, and then wait for the RSSI to wakeup the atmega, at which point read the RSSI value.  The only question is whether the RSSI value will have been resampled again between initiating the atmega wake-up and being able to read the RSSI value.  If so, the RSSI value that's read may be polluted.  This is where knowing 1. the period of RSSI resamplings, and 2. how long it takes the atmega to wakeup, and 3. how long it takes the atmega to go into powerdown sleep will help.  So, those three things are next to measure.



« Last Edit: February 13, 2016, 11:47:10 AM by WhiteHare »

WhiteHare

  • Hero Member
  • *****
  • Posts: 1296
  • Country: us
Re: Real time RSSI measurement broken RFM69CW?
« Reply #79 on: February 13, 2016, 11:47:15 AM »
OK, I measured the time between RSSI updates as 1.5ms, so that's a tight constraint.  The update interval is very consistent.  So, the atmega will need to fully wake-up from powerdown and read the RSSI in less time than that.  However, IIRC, at 8mhz the atmega will take longer than that.

WhiteHare

  • Hero Member
  • *****
  • Posts: 1296
  • Country: us
Re: Real time RSSI measurement broken RFM69CW?
« Reply #80 on: February 13, 2016, 01:48:45 PM »
Good news!  It turns out that if you do an Rx Restart, then the very first RSSI measurement that results from the Rx Restart will latch for more than 8ms.  After that, and before the next such Rx Restart, the RSSI will update about every 1.5ms. 

I altered the earlier code to record RSSI only when there's a change in RSSI value.  Then, after adding timestamps, the pattern becomes clear:

Code: [Select]
---------------------------------------------------------------------
0.0. RSSI=-120
0.1. RSSI=-123, deltaT=9208uSec
0.2. RSSI=-122, deltaT=1576uSec
0.3. RSSI=-125, deltaT=1528uSec
0.4. RSSI=-121, deltaT=1504uSec
0.5. RSSI=-125, deltaT=1576uSec
---------------------------------------------------------------------
0.0. RSSI=-126
0.1. RSSI=-125, deltaT=8624uSec
0.2. RSSI=-124, deltaT=1520uSec
0.3. RSSI=-123, deltaT=1520uSec
0.4. RSSI=-124, deltaT=1576uSec
0.5. RSSI=-125, deltaT=1512uSec
---------------------------------------------------------------------
0.0. RSSI=-124
0.1. RSSI=-125, deltaT=8672uSec
0.2. RSSI=-124, deltaT=1576uSec
0.3. RSSI=-121, deltaT=1512uSec
0.4. RSSI=-124, deltaT=1520uSec
0.5. RSSI=-125, deltaT=1576uSec
---------------------------------------------------------------------
0.0. RSSI=-127
0.1. RSSI=-123, deltaT=8624uSec
0.2. RSSI=-126, deltaT=1520uSec
0.3. RSSI=-125, deltaT=1560uSec
0.4. RSSI=-124, deltaT=1528uSec
0.5. RSSI=-124, deltaT=1520uSec
---------------------------------------------------------------------


An 8ms window should be wide enough for a Moteino to wake from deep powerdown and read the latched RSSI before it changes.

« Last Edit: February 13, 2016, 02:23:56 PM by WhiteHare »

WhiteHare

  • Hero Member
  • *****
  • Posts: 1296
  • Country: us
Re: Real time RSSI measurement broken RFM69CW?
« Reply #81 on: February 16, 2016, 12:33:28 AM »
I've run across an unexpected problem, which is that when I map DIO0 to RSSI, it will trigger the interrupt on D2 (interrupt 0 on the atmega328p) almost immediately.  It doesn't matter whether I attached the interrupt at RISING, FALLING, CHANGE, or LOW: the outcome is the same.  Because of this problem, I can't  get the atmega328p into powerdown sleep.  This problem does *not* manifest if I map DIO0 to PayloadReady, as Felix's library does.

What's especially odd is that if I read the RSSI flag (i.e. bit 3 in RegIrqFlags1 (0x27)), it is LOW when I expect it to be, and it goes HIGH when I expect it should.  It does not appear  to be jumping around.

I am mystified as to what is going on.  Has anyone else here run across this issue? 

[Edit: Adding a pulldown resistor does appear to "solve" the problem, but apparently 10K is too low a value, because now RSSI *never* seems to trigger, as opposed to all-the-time without a pulldown resistor.  What would be a good ohm value to use?]
« Last Edit: February 16, 2016, 02:39:09 AM by WhiteHare »

perky

  • Hero Member
  • *****
  • Posts: 873
  • Country: gb
Re: Real time RSSI measurement broken RFM69CW?
« Reply #82 on: February 16, 2016, 07:02:32 AM »
That's curious, 10k is quite high really and you'd expect a driver to source current to drive it high, sx1231h can sink and source at least 1mA on its digitil outputs according to the spec.

Can you poll the D2 pin instead of using an interrupt to see whether it's the interrupt code that's not working properly?

I can imagine when selecting the RSSI on DIO0 that there could be a positive going glitch as this is done with a binary mux in the radio, binary values can transition through other states while it settles and temporarily mux through a high. You'll most likely see that on a 'scope and it might trigger an edge detection in the interrupt logic. You might consider the following procedure:

disabling interrupts
map RSSI (could cause spurious edge detection)
clear the interrupt flag
re-enable interrupts

Mark.
 

WhiteHare

  • Hero Member
  • *****
  • Posts: 1296
  • Country: us
Re: Real time RSSI measurement broken RFM69CW?
« Reply #83 on: February 16, 2016, 10:09:14 AM »
I've been mapping RSSI to DIO0 only once, and that is in the "setup()" function.

I just now physically severed the pulldown resistor, so now we're back to square one.

After shifting from Rx-Idle into Rx-Read mode,  if I wait for RSSI to go high by running the code
Code: [Select]
while (!(digitalRead(D2))) {}
then RSSI appears to go high after about 32-40 microseconds.  That's the same as what I get if I do attach the interrupt.  That's far too fast, because it takes longer than that just for the PLL to lock.

On the other hand, if I instead wait for RSSI to go high by running the code
Code: [Select]
while (!(radio.readReg(0x27) & 0x08)) { }  //wait for RSSI to go high
then RSSI appears to go high after close to 7000 microseconds, which is also pretty much exactly the same amount of time it takes for RxReady to go HIGH.  I'm assuming this wait time is correct.  Note that I'm first setting the radio to idle mode, waiting for ModeReady, then putting the radio into Rx mode and then recording a timeStamp of when that occurs so as to measure the length of time to RSSI going high.  An RxRestart would be *much* faster, but in this case I don't want faster.  Indeed, I want it as slow as possible to give plenty of time for putting the atmega into deep powerdown sleep mode.

WhiteHare

  • Hero Member
  • *****
  • Posts: 1296
  • Country: us
Re: Real time RSSI measurement broken RFM69CW?
« Reply #84 on: February 16, 2016, 11:08:56 AM »
Argh.  Looks as though the connection between DIO0 and D2 came loose.  In the course of repairing it just now, I apparently nuked the radio (maybe an ESD).   :'(

perky

  • Hero Member
  • *****
  • Posts: 873
  • Country: gb
Re: Real time RSSI measurement broken RFM69CW?
« Reply #85 on: February 16, 2016, 11:13:53 AM »
OK, interesting result. Just thinking, but I had a problem some time back that I didn't really get to the bottom of when going from standby mode to rx mode it would fail to receive the next packet properly - this was pretty odd. In that case an RSSI interrupt was generated but no sync address match. If I put the radio to sleep rather than standby that problem went away. This could be related, I think idle mode is mapped to standby mode in the RadioHead library, could you change it to map to sleep mode instead? There could be an issue here with the way the radio resets when entering rx mode after from standby.
Mark

Edit: Nuking things always happen when you least want it to happen (which is never), hope you fix it soon.
« Last Edit: February 16, 2016, 11:15:24 AM by perky »

WhiteHare

  • Hero Member
  • *****
  • Posts: 1296
  • Country: us
Re: Real time RSSI measurement broken RFM69CW?
« Reply #86 on: February 16, 2016, 12:53:48 PM »
Thanks for the encouragement.   :)

So as to continue, I just now hooked up a factory fresh Moteino with the regular RFM69HW and wire antenna using Felix's FTDI connector.  So, this is a little different, because Antenna is not shorted to ground, it has a wire antenna, and its voltage regulator is still intact.  On the plus side, though, is that the hardware hasn't been monkeyed with, and so I don't expect anything will come loose anytime soon.  Also, all of what follows should be easily reproducible by anyone reading this.

Here's the TL;DR summary: with this setup there is a disparity between the results that come from just reading the D2 pin versus attaching an interrupt to the D2 pin.

Using:
Code: [Select]
while (!(digitalRead(D2))) {}  // Wait for RSSI to go HIGH

the RSSI flag doesn't appear to go high until about 6968uSeconds after putting the RFM69HW into Rx Mode:


Code: [Select]
---------------------------------------------------------------------
RSSI=-116, rssiFlagRising=6968uSec
RSSI=-118, rssiFlagRising=6968uSec
RSSI=-117, rssiFlagRising=6968uSec
RSSI=-115, rssiFlagRising=6968uSec
---------------------------------------------------------------------


However, if I attach an interrupt instead to D2 and attempt to get the atmega328p to enter powerdown sleep, what I get instead is:

Code: [Select]
---------------------------------------------------------------------
RSSI=-118, rssiFlagRising=12uSec
RSSI=-118, rssiFlagRising=16uSec
RSSI=-118, rssiFlagRising=16uSec
RSSI=-118, rssiFlagRising=12uSec
---------------------------------------------------------------------
RSSI=-115, rssiFlagRising=12uSec
RSSI=-115, rssiFlagRising=16uSec
RSSI=-115, rssiFlagRising=16uSec
RSSI=-115, rssiFlagRising=16uSec
---------------------------------------------------------------------
RSSI=-116, rssiFlagRising=16uSec
RSSI=-116, rssiFlagRising=16uSec
RSSI=-116, rssiFlagRising=12uSec
RSSI=-116, rssiFlagRising=16uSec
---------------------------------------------------------------------
RSSI=-117, rssiFlagRising=16uSec
RSSI=-117, rssiFlagRising=16uSec
RSSI=-117, rssiFlagRising=12uSec
RSSI=-117, rssiFlagRising=16uSec
---------------------------------------------------------------------

Obviously, that is a dramatic difference.

The code I'm using to attach the interrupt, powerdown, and wake up, is Nick Gammon's "Sketch J" ( http://www.gammon.com.au/power), which I  simply repackaged as "sleepNow()":

Code: [Select]
#include <avr/sleep.h>

void wake ()
{
  // cancel sleep as a precaution
  sleep_disable();
  // precautionary while we do other stuff
  detachInterrupt (0);
 
}  // end of wake


void sleepNow ()
{
  // disable ADC
  ADCSRA = 0; 
 
  set_sleep_mode (SLEEP_MODE_PWR_DOWN); 
  sleep_enable();

  // Do not interrupt before we go to sleep, or the
  // ISR will detach interrupts and we won't wake.
  noInterrupts ();
 
  // will be called when pin D2 goes HIGH 
  attachInterrupt (0, wake, RISING);
  EIFR = bit (INTF0);  // clear flag for interrupt 0
 
  // turn off brown-out enable in software
  // BODS must be set to one and BODSE must be set to zero within four clock cycles
  MCUCR = bit (BODS) | bit (BODSE);
  // The BODS bit is automatically cleared after three clock cycles
  MCUCR = bit (BODS);
 
  // We are guaranteed that the sleep_cpu call will be done
  // as the processor executes the next instruction after
  // interrupts are turned on.
  interrupts ();  // one cycle
  sleep_cpu ();   // one cycle

  } // end of sleepNow()

The only difference between the first and second sets of results is that I replaced:
Code: [Select]
while (!(digitalRead(D2))) {}  // Wait for RSSI to go HIGH

with

Code: [Select]
sleepNow();


If anyone has a better way to handle the interrupt scenario, please post a link and I'll try it instead.  Normally Gammon's code works just fine for me, but just not now when DIO0 is mapped to RSSI.  What's clear is that the atmega328p never even fully gets into deep powerdown sleep, because if it did, it would take about 2.1ms (at 8Mhz) just to wake up.
« Last Edit: February 16, 2016, 01:04:21 PM by WhiteHare »

WhiteHare

  • Hero Member
  • *****
  • Posts: 1296
  • Country: us
Re: Real time RSSI measurement broken RFM69CW?
« Reply #87 on: February 16, 2016, 01:34:00 PM »
In my experimental setup (before the connection between DIO0 and D2 became loose), I did notice some noise on the D2 pin (see first attachment).

By mapping PllLock onto the D3 pin, and running another o-scope probe to that, I was able to determine that the big spike on D2 exactly coincineded with PllLock  going HIGH (see second attachment).  There, D2 is in yellow, and D3 is in blue.

As a workaround, I tried waiting until after PllLock went high before invoking SleepNow(), but the end result was basically the same, just delayed by the amount it waited for PllLock to go HIGH.  So, something else besides just that PllLock spike is in play, maybe something too brief for my scope to capture but yet still able to trigger an interrupt (assuming that's even possible).

By the way, the experimental setup was being run off a battery and with no voltage regulator.
« Last Edit: February 16, 2016, 02:05:47 PM by WhiteHare »

WhiteHare

  • Hero Member
  • *****
  • Posts: 1296
  • Country: us
Re: Real time RSSI measurement broken RFM69CW?
« Reply #88 on: February 16, 2016, 01:47:10 PM »
Anyhow, that nasty voltage spike was there on literally every cycle that took the RFM69 from idle-mode into Rx-mode (see attachment).

So, this is just a data dump.  I didn't anticipate this roadblock, and I'm really not sure where to take it from here.  One idea that might work (I haven't tried it) is to map RxReady onto DIO4, wire that to D3, and then (hopefully) attach an interrupt to that for wake-up purposes.  The RFM69HW has a DIO4, which is the only pin that RxReady can be mapped to.  Unfortunately, the RFM69CW from the OP doesn't have a DIO4 on it.  Aside from that, or maybe making another attempt at adding a pulldown resistor, I'm out of ideas.  If there were a way to squelch or prevent the voltage spikes (?) or whatever it is that's prematurely triggering the interrupt, that would of course be worth trying.  However, I'm not sure how to approach doing that, as this is all pretty far afield and more or less where the road ends, at least for me.

Hopefully something in the above rings a bell for someone on how to proceed.

« Last Edit: February 16, 2016, 04:39:03 PM by WhiteHare »

WhiteHare

  • Hero Member
  • *****
  • Posts: 1296
  • Country: us
Re: Real time RSSI measurement broken RFM69CW?
« Reply #89 on: February 16, 2016, 05:12:13 PM »
I think I found something which may inform what's going on.  If I disconnect DIO0 from D2 but run the code above anyway (the version that is  using the interrupt attachment), the result is:

Code: [Select]
---------------------------------------------------------------------
RSSI=-127, rssiFlagRising=32uSec
RSSI=-127, rssiFlagRising=32uSec
RSSI=-127, rssiFlagRising=24uSec
RSSI=-127, rssiFlagRising=24uSec
---------------------------------------------------------------------
RSSI=-127, rssiFlagRising=32uSec
RSSI=-127, rssiFlagRising=32uSec
RSSI=-127, rssiFlagRising=32uSec
RSSI=-127, rssiFlagRising=32uSec
---------------------------------------------------------------------
RSSI=-127, rssiFlagRising=32uSec
RSSI=-127, rssiFlagRising=24uSec
RSSI=-127, rssiFlagRising=24uSec
RSSI=-127, rssiFlagRising=32uSec
---------------------------------------------------------------------
RSSI=-127, rssiFlagRising=32uSec
RSSI=-127, rssiFlagRising=32uSec
RSSI=-127, rssiFlagRising=32uSec
RSSI=-127, rssiFlagRising=32uSec
---------------------------------------------------------------------

It makes sense that RSSI=-127, because PllLock hasn't yet gone high.  So, the pregnant questions are:
1.  Why wasn't RSSI=-127 when DIO0 was wired to D2?  After all, it triggered at nearly the same time.  My hypothesis is there must have been noise travelling from D2 into DIO0, and then into the radio.
2.  Why does the interrupt trigger at all?  Nothing is coming from DIO0 to trigger D2.  Because there is no pulldown or pullup resistor, D2 is  just a floating pin, so it must be triggering off whatever noise happens to be on D2.  And whatever that noise is, it seems to hit the RISING threshhold fairly consistently at about 24-32uSec after putting the RFM69 into Rx Mode.

So, if I disconnect more wires from the radio one by one, and rerun the code, perhaps I'll narrow it down to the wire or wires which are causing D2 to trigger at the 24-32uSec mark, and that, then, would be a likely suspect for the noise.

[Edit: OK, so I next severed the wire that was connecting DIO3 to D3 (where D3 was using the default 00 mapping to FifoFull.  Wow, the results sure did surprise me:

Code: [Select]
---------------------------------------------------------------------
RSSI=-117, rssiFlagRising=24uSec
RSSI=-119, rssiFlagRising=32uSec
RSSI=-120, rssiFlagRising=32uSec
RSSI=-122, rssiFlagRising=32uSec
---------------------------------------------------------------------
RSSI=-121, rssiFlagRising=32uSec
RSSI=-119, rssiFlagRising=32uSec
RSSI=-116, rssiFlagRising=32uSec
RSSI=-115, rssiFlagRising=32uSec
---------------------------------------------------------------------
RSSI=-116, rssiFlagRising=32uSec
RSSI=-119, rssiFlagRising=32uSec
RSSI=-118, rssiFlagRising=24uSec
RSSI=-119, rssiFlagRising=32uSec
---------------------------------------------------------------------
RSSI=-119, rssiFlagRising=32uSec
RSSI=-118, rssiFlagRising=32uSec
RSSI=-115, rssiFlagRising=32uSec
RSSI=-124, rssiFlagRising=32uSec
---------------------------------------------------------------------
RSSI=-114, rssiFlagRising=24uSec
RSSI=-118, rssiFlagRising=32uSec
RSSI=-117, rssiFlagRising=32uSec
RSSI=-121, rssiFlagRising=24uSec
---------------------------------------------------------------------
RSSI=-118, rssiFlagRising=24uSec
RSSI=-116, rssiFlagRising=24uSec
RSSI=-121, rssiFlagRising=32uSec
RSSI=-120, rssiFlagRising=32uSec
---------------------------------------------------------------------

Now RSSI is showing noise again!   WTF?  How does that make any sense?  FifoFull should have been false, so presumably DIO3 was acting like a ground to D3, which was configured as an input, and therefore high impedance, at least to DC (but maybe not high impedance to high frequency noise?).   Is that a possible explanation?]
« Last Edit: February 16, 2016, 05:56:35 PM by WhiteHare »