LowPowerLab Forum

Hardware support => Low Power Techniques => Topic started by: kobuki on September 26, 2015, 07:39:30 PM

Title: Using ListenMode as Wakeup timer
Post by: kobuki on September 26, 2015, 07:39:30 PM
I have  a wild idea for a robust wake-up facility without using WDT, using listen mode in a somewhat more "inventive" way. When tuning my projects for RSSI, especially my OOK transceiver lib, I realised that having a low RSSI threshold generates noise. 100% guaranteed. What you need to do is:

 - set RSSI threshold to the lowest possible value (highest sensitivity, maybe activating sensitivity boost as well)
 - set bandwidth to very high, like 0.5 MHz
 - set listen mode to wake on RSSI only
 - other parameters are probably arbitrary, could leave them to Moteino defaults or your own

Setting ListenIdle will determine how often the mote wakes up. Setting ListenIdleCoef to 231, ListenIdleResol to 0b11 makes it 1 minute which is perfect for a TH mote, for example. After waking up, radio needs to be set to normal working parameters. Of course values can be juggled around for more possibilities.
Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on September 26, 2015, 08:22:51 PM
That's a clever idea.  Are you proposing to connect the RSSI pin to D3?  in essence, it would give you up to a 63 second wake-up timer instead of just an up to 8 second wakeup timer.
Title: Re: Using ListenMode as Wakeup timer
Post by: kobuki on September 26, 2015, 08:28:30 PM
Yes, that might be necessary. The module wakes up the MCU via DIO0 pin change interrupt on payload ready and other events, but in this case it might not play a role. The DS is hinting at several DIO pins having to do with RSSI, one of them might be a good candidate. Needs RTFM'ing and testing.

EDIT: fixed pin name
Title: Re: Using ListenMode as Wakeup timer
Post by: TomWS on September 26, 2015, 09:19:24 PM
@kobuki, as I read your idea, you're basically using the ListenMode idle interval as a wake up timer, having set the RSSI sensitivity so high that you're virtually guaranteed that a wakeup will occur during the RX interval. 

Is this correct?  If so, I don't understand the references to the other D pins on the radio.

Tom
Title: Re: Using ListenMode as Wakeup timer
Post by: kobuki on September 26, 2015, 09:24:18 PM
Correct. But since this idea is "new" and associated modes that can cause an interrupt haven't been explored yet, I'm not completely sure we don't need the other DIO pins. I'm reading the manual now and it seems that enabling continuous mode, no preamble, no sync word matching will fire an interrupt on DIO0 and thus waking up the mote in its default Moteino configuration. OTOH, DIO2 is the demotulator output in cont. mode and is guaranteed to generate noise with my proposed setup, that I already know.
Title: Re: Using ListenMode as Wakeup timer
Post by: TomWS on September 26, 2015, 09:43:18 PM
But getting back to the proposal, ISTM if you set up the radio in ListenMode (normal 'Moteino' setup isn't relevant in this case) AND set up the parameters as you've suggested, then there may not be a need for a separate device to generate a 'wakeup' burst or even a WDT, the radio will wake up the Mote simply due to RF noise at a time interval that is programmed via the ListenIdle parameter.  If true, that seems to have worthwhile application in a number of cases.

Tom

Title: Re: Using ListenMode as Wakeup timer
Post by: kobuki on September 26, 2015, 09:53:50 PM
Yes. Exactly this is what I propose. Atmega WDT turned off, shaving ~4 uA off the power budget. No external WDT is needed, except for this multipurpose Swiss Army knife-like thing called RFM69 transceiver :)

'Moteino' setup is important for everyone wishing to save power on it, since it means no change in HW is needed to achieve what I propose. In its off-the-shelf config, it should still be able to run well below 10 uA. In that case it does count.
Title: Re: Using ListenMode as Wakeup timer
Post by: TomWS on September 26, 2015, 10:16:33 PM
'Moteino' setup is important for everyone wishing to save power on it, since it means no change in HW is needed to achieve what I propose. In its off-the-shelf config, it should still be able to run well below 10 uA. In that case it does count.
My use of  the phrase "Moteino setup" specifically refers to the radio settings established in the RFM69 library, which need to be changed to support ListenMode.

Tom
Title: Re: Using ListenMode as Wakeup timer
Post by: joelucid on September 27, 2015, 03:13:02 AM
Quote
Yes. Exactly this is what I propose.

This is a good idea! I doubt it's really necessary to use continuous mode or OOK. Simply setting Rssithresh to 255 will probably guarantee Rssi detection under any setting. You can map Rssi to dio0 so no HW mods required either.

You could use this as general purpose wake up timer. Not only would it be lower power than the wdt but also much more accurate.

One feature of the burst collection approach is that you completely avoid collisions due to the server controlled polling of nodes. Combining your trick with the burst collection mechanism you could get both the lower power consumption of your approach plus the synchronization via the server. That effectively gives each Moteino an accurate synchronized clock.

Since we now have a synchronized clock we can have all nodes schedule their rx Windows during the same second every 5 minutes and get standby power consumption on a Moteino without regulator operating at 8mhz using internal rc clock down to 1200 nA. Not so shabby.

Joe
Title: Re: Using ListenMode as Wakeup timer
Post by: kobuki on September 27, 2015, 07:50:37 AM
:)

Yeah, it simplifies a few things for your design, if it works reliably (I think it does). In listen mode, only the internal RC oscillator of the RFM69 is working, and it's probably as prone to frequency skew as any other. The module calibrates it on startup, but a forced calibration can be started any time. Felix's lib already has the function exactly for that. I guess a calibration cycle won't hurt every hour or so.

It would be nice to have an addition to the LPL lib (or in a separate one) that works similarly to the existing low-power support libraries, but instead of the internal Atmega WDT it uses the RFM69. I might even write it if you don't beat me to it ;)

BTW, it's kobuki, not kabuki :x (They've completely unrelated origins.)
Title: Re: Using ListenMode as Wakeup timer
Post by: TomWS on September 27, 2015, 08:06:26 AM
Combining your trick with the burst collection mechanism you could get both the lower power consumption of your approach plus the synchronization via the server. That effectively gives each Moteino an accurate synchronized clock.
I'll admit that I haven't finished my morning coffee, but I'm not quite getting how this Wakeup timer gets synchronized with the server.

Tom
Title: Re: Using ListenMode as Wakeup timer
Post by: joelucid on September 27, 2015, 08:51:11 AM
Quote
I'll admit that I haven't finished my morning coffee, but I'm not quite getting how this Wakeup timer gets synchronized with the server.

The assumption is that if you regularly recalibrate the radio's RC sensor like I did in this prototype (https://lowpowerlab.com/forum/index.php/topic,1269.msg8600.html#msg8600) you get a fairly accurate timer. Now you only need to periodically send a current timestamp to the nodes and they can maintain a synchronized clock fairly well.

In the above prototype I used the radio as timer to schedule the next RX window for all motes during the same 3 second window in a 5 min period instead of waking RX once every three seconds. However if I missed the burst the timing would become unaligned. However with the new method we can get the wakeup with certainty and simply start another 5 min listen mode just before the window opens.

Or as I said in my second post we could move to modified ACKs and just send system time during the ACK.
Title: Re: Using ListenMode as Wakeup timer
Post by: TomWS on September 27, 2015, 08:55:28 AM
Great!  Thanks for the explanation!

Tom
Title: Re: Using ListenMode as Wakeup timer
Post by: joelucid on September 27, 2015, 04:56:37 PM
This works well as expected. Attached is a quick prototype. Currently only supports delays up to 65 seconds (the radio doesn't support more natively, longer periods need to be pieced together).

Interestingly I need to wait until the third RSSI interrupt. I already receive two during the initial RX window which seems to indicate that the radio actually starts a second RSSI detection after deciding to stay in RX during the 1st RX window.

Just use like this for a 30 second sleep period:

   RFM69Listener::delay( radio, 30000 );
   reinitializeRadio();

reinitializeRadio should be your code to restore the Radio to it's normal condition.

Code attached.
Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on September 27, 2015, 05:15:20 PM
Great!  I gather you're using
radio.writeReg( REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_11 );
to map RSSI to DIO0?  That's a definite improvement over the earlier idea genesis, because with only two external interrupt pins on the ATMEGA328P, it's definitely better to keep one free for other purposes (like, for instance, connecting to a motion sensor).  Touché!   :)
Title: Re: Using ListenMode as Wakeup timer
Post by: TomWS on September 27, 2015, 05:35:34 PM
I don't know if I can deal with the 100% wasted code in:
Code: [Select]
static void delayIrq() 
{
return;
}
But, other than that, GOOD WORK!  Now go to sleep!

Tom
Title: Re: Using ListenMode as Wakeup timer
Post by: joelucid on September 27, 2015, 05:37:03 PM
Quote
I gather you're using
radio.writeReg( REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_11 );
to map RSSI to DIO0?

Yup, that's what that line does.
Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on September 27, 2015, 05:38:58 PM
Cool.  By the way, from an energy perspective, is it also better to use the RFM69 based wake-up timer method than the WDT, for cases where the delay is < 8 seconds?  i.e. maybe it should be the new default wakeup timer, except in cases where that interferes with something actively going on with the RFM69 radio.  I know, I know, RTFM....  IIRC, though, the answer would  be yes.
Title: Re: Using ListenMode as Wakeup timer
Post by: joelucid on September 27, 2015, 05:45:22 PM
Quote
I don't know if I can deal with the 100% wasted code

Oh, that's right, with the Arduino libs a detachInterrupt is enough since the default handler does nothing. I initially had some code in there I think  ;)
Title: Re: Using ListenMode as Wakeup timer
Post by: joelucid on September 27, 2015, 05:53:22 PM
Quote
is it also better to use the RFM69 based wake-up timer method than the WDT, for cases where the delay is < 8 seconds?

At about 2 seconds the 2 RX windows themselves cost about the same as the WDT. Additionally you need to execute the code to start listen mode, end it and reinitialize the radio. We'll should time that to see how much power it costs.

Oh, and Kobuki, I hereby officially award you with Joe's highly coveted Listen Mode Medal.
Title: Re: Using ListenMode as Wakeup timer
Post by: joelucid on September 27, 2015, 06:09:04 PM
Quote
detachInterrupt is enough

Actually it's not since you want to make sure to register the interrupt to the rising edge. But

Code: [Select]
attachInterrupt( RF69_IRQ_NUM, NULL, RISING);

works.
Title: Re: Using ListenMode as Wakeup timer
Post by: TomWS on September 27, 2015, 08:15:49 PM
Quote
I don't know if I can deal with the 100% wasted code

Oh, that's right, with the Arduino libs a detachInterrupt is enough since the default handler does nothing. I initially had some code in there I think  ;)
Sorry, I was being facetious. The 'return;' statement within an empty void function is unnecessary.  I guess I either need to elaborate or try to stop being funny (or both, or is it neither?)...

But, seriously, good work on testing this so quickly.

Thanks,
Tom
Title: Re: Using ListenMode as Wakeup timer
Post by: kobuki on September 28, 2015, 07:51:19 AM
Nice progress, Joe! And thanks for the medal, I'll put it in my virtual safe ;)

What you noted about the RSSI. Why do you receive 3 interrupts? Why isn't the chip waking up at the first? Or you just see it on the scope? Oh, and why the remapping? Isn't DIO0 signaling the state change with the default config (btw I don't know if you use a Tino proto or a Moteino)? Sorry for the many questions...
Title: Re: Using ListenMode as Wakeup timer
Post by: joelucid on September 28, 2015, 12:32:33 PM
Quote
What you noted about the RSSI. Why do you receive 3 interrupts?

The radio wakes the 328p three times with an RSSI until the selected time has passed. I would have expected 2 interrupts: one for the initial RX window right when listen mode is entered and one after the idle period. But I immediately get 2 during the first RX window and the the third at the correct  time.

Quote
Isn't DIO0 signaling the state change with the default config

You might want to check out the datasheet. All kinds of signals can be mapped to DIO0. In this case we don't want payloadready (which I use with normal listen mode), but RSSI detected.
Title: Re: Using ListenMode as Wakeup timer
Post by: kobuki on September 28, 2015, 12:55:47 PM
Hmm, it doesn't sound right. It can be circumvented by ignoring the bogus signals and then entering sleep mode, though. Haven't run your skecth yet, so it might not be a feasible solution.

I know about the mappings, but for the special purpose of external wakeup, I haven't fully explored their necessary settings yet. It seems from your code that you set RSSI IRQ for RX mode on DIO0, into which the module enters when waking itself up via its own internal RC timer to start RX mode for the defined period.
Title: Re: Using ListenMode as Wakeup timer
Post by: joelucid on September 29, 2015, 08:40:01 AM
Quote
It can be circumvented by ignoring the bogus signals and then entering sleep mode, though.

Sure. if you check my code I just call powerDown 3x - once for each interrupt. As I said two interrupts are completely expected. The second one during the first RX window is a bit surprising.

Quote
I know about the mappings, but for the special purpose of external wakeup

Nothing special for wakeup. the 328p wakes up on any interrupt. So by enabling interrupts and mapping a signal at the radio to DIO0 we'll get woken up by that signal, in this case "RSSI detected" which is active when RSSI has been detected as above threshold.
Title: Re: Using ListenMode as Wakeup timer
Post by: kobuki on September 29, 2015, 08:48:43 AM
As I said two interrupts are completely expected. ...

Why are 2 interrupts expected?

Nothing special for wakeup. the 328p wakes up on any interrupt. So by enabling interrupts and mapping a signal at the radio to DIO0 we'll get woken up by that signal, in this case "RSSI detected" which is active when RSSI has been detected as above threshold.

Not special for the 328p, but special use case of settings and interrupts for the RFM module, my original proposal which we're discussing right now. I thought that either in packet mode we might just get the same interrupt (remember that I suggested no sync word, no preamble), namely PayloadReady, or switching to another mode, eg. continuous mode + ook, we'd get it. BTW if it's indeed the case, I'm sure PayloadReady would fire only once until cleared. Would make life simpler and less quirks would be needed.
Title: Re: Using ListenMode as Wakeup timer
Post by: joelucid on September 29, 2015, 11:04:29 AM
Quote
Why are 2 interrupts expected?

Very simple: when you enter listen mode the radio immediately start an RX window. You get an interrupt for that window, but you want to wait for the second window to get the idle delay.

Quote
I thought that either in packet mode we might just get the same interrupt (remember that I suggested no sync word, no preamble), namely PayloadReady, or switching to another mode, eg. continuous mode + ook, we'd get it. BTW if it's indeed the case, I'm sure PayloadReady would fire only once until cleared. Would make life simpler and less quirks would be needed.

Oh, I see. You want to use OOK, fixed 1 byte packet length, no preamble, no sync word, etc. and then receive the noise as packet. Yeah, I don't know if that would work. In any case RSSI detection is faster than receiving a byte, so the RSSI approach is likely superior.
Title: Re: Using ListenMode as Wakeup timer
Post by: kobuki on September 29, 2015, 11:15:27 AM
Very simple: when you enter listen mode the radio immediately start an RX window. You get an interrupt for that window, but you want to wait for the second window to get the idle delay.

That's a bug in the RFM69, right?

Oh, I see. You want to use OOK, fixed 1 byte packet length, no preamble, no sync word, etc. and then receive the noise as packet. Yeah, I don't know if that would work. In any case RSSI detection is faster than receiving a byte, so the RSSI approach is likely superior.

No, I don't want to use OOK mode, but it's a possibility. All we want is some noise to trigger the interrupt. At the very high bitrate you've set in your test code, it would probably take around 50 uS to receive a byte, or maybe less. And if it works, there are no other tricks/circumventions needed. I will test it, I hopefully will have more time at the weekend.
Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on September 29, 2015, 11:31:22 AM
@Kobuki There's no waiting for a byte.  The RSSI is remapped to DIO0, and is thus directly connected to D2.  As soon as RSSI goes HIGH (which you would expect to be immediately given the deliberately oversensitive settings), the ATMEGA328P is woken up.  What could be faster than that? [ Sorry in advance for jumping in if you were referring to something else.]
Title: Re: Using ListenMode as Wakeup timer
Post by: joelucid on September 29, 2015, 11:47:07 AM
Quote
That's a bug in the RFM69, right?

I don't think so. The listen mode graphic in the datasheet shows that RX is first, followed by IDLE. In my view that also makes sense - I want to specify the duty cycle not a delay.

Quote
And if it works, there are no other tricks/circumventions needed.

You'll certainly also get two interrupts if it works.
Title: Re: Using ListenMode as Wakeup timer
Post by: kobuki on September 29, 2015, 12:15:44 PM
@Kobuki There's no waiting for a byte.  The RSSI is remapped to DIO0, and is thus directly connected to D2.  As soon as RSSI goes HIGH (which you would expect to be immediately given the deliberately oversensitive settings), the ATMEGA328P is woken up.  What could be faster than that? [ Sorry in advance for jumping in if you were referring to something else.]

Yeah, I know how it works. But I think in order to get around the bogus interrupt, we'd need to busy-wait it and only then enter power down mode - or find another mode of the RFM69 that's somehow not issuing bogus interrupts. IF the bogus int. is somehow triggered at the end of the first RX period, then it's certainly not a solution, since the RX period can be as long as 260 ms. (Yes, it's only baseless assumption without further testing.) And why I think busy-waiting would be better than simply entering powerdown multiple times is that it might be better for the coin cell, not dragging it up and down in a very short period. Plus, the multiple startups might take more power than waiting for a few dozen micros fully powered. And IF we busy-wait, we can try other solutions that take the same amount of cycles but are guaranteed to work without furher tricks.

To make sense of these assumptions, a good uA-meter would be required and a good DSO, neither of which I possess right now.
Title: Re: Using ListenMode as Wakeup timer
Post by: kobuki on September 29, 2015, 12:24:14 PM
Quote
That's a bug in the RFM69, right?

I don't think so. The listen mode graphic in the datasheet shows that RX is first, followed by IDLE. In my view that also makes sense - I want to specify the duty cycle not a delay.

Quote
And if it works, there are no other tricks/circumventions needed.

You'll certainly also get two interrupts if it works.

The associated drawings are a bit controversial (there are multiple ones), and it's not explicitly stated what starts the listen mode duty cycle. I tend to seek explicit statements in a technical document... But of course, your idea is very reasonable and supported by your experience. Based on that, 2 ints would be just fine. But we don't know why the 3rd one comes and exactly when. I'll also test it out later.
Title: Re: Using ListenMode as Wakeup timer
Post by: kobuki on October 11, 2015, 03:45:05 PM
@Joe: did you bring the idea any further in the meantime? Unfortunately I didn't have the time.

A little offtopic, but is your Tino project progressing, generally? It's been a long time you reported something :)
Title: Re: Using ListenMode as Wakeup timer
Post by: joelucid on October 12, 2015, 07:11:56 AM
Kobuki, further than working code?  :)
Title: Re: Using ListenMode as Wakeup timer
Post by: kobuki on October 12, 2015, 07:36:09 AM
Kobuki, further than working code?  :)

Sorry, I don't understand your question.

I was meaning to ask if you've made perhaps a configurable lib based on this idea for periodic wakeups, integrated the idea in your Tino succesfully and it's under testing, things like that. Since you haven't written anything about this cool little thing.

Did it help you in clarifying my original question?

EDIT: oh, and if you maybe found a solution to the multiple wake-up triggers solution.
Title: Re: Using ListenMode as Wakeup timer
Post by: joelucid on October 12, 2015, 09:09:42 AM
Quote
I was meaning to ask if you've made perhaps a configurable lib based on this idea for periodic wakeups, integrated the idea in your Tino succesfully and it's under testing, things like that. Since you haven't written anything about this cool little thing.

Yeah I had posted the code and it worked. I had it running on a Tino for some time. Haven't done much more than that though.

Rg Tino I'm still thinking about it. I've assembled a few and it's a pain. I think it would be best to start a Kickstarter campaign, see if one can get more than say 1k orders and then have them professionally assembled in China. I've been pretty busy with other stuff though so really not much progress recently.
Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on November 18, 2016, 11:02:17 AM
There may be an alternative to the OP that will get the same desired result.  The notion is this: From standby mode, map DIO0 to PlllLock prior to entering ListenMode.  Also, instead of setting the Rssi Threshhold low, set it maximally high.  Because PllLock will go high just once prior to entering RxMode, then by definition, you should receive an interrupt on DIO0 once every period of (TlistenRx + TlistenIdle).
Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on January 27, 2017, 12:45:07 PM
Just an unvetted idea (and this may be going overboard), but if one mapped DIO0 to ModeReady after the RFM69 enters into Stdby mode, as it of course does periodically while in Listen Mode, then DIO0 should go low the instant Stdby mode is left in order to transition into PllLock mode.  So, if one used that as the trigger to wake the atmega328p (which takes ~4uSec), which then immediately reset the RFM69, then perhaps one could avoid expending the energy that would otherwise be consumed in the PllLock phase plus the minimum 64uSec of Rx phase.

[Edit: It would, of course, require access to the RST pin on the RFM69, but that could be bodged on.]
Title: Re: Using ListenMode as Wakeup timer
Post by: joelucid on January 27, 2017, 02:29:59 PM
Quote
if one mapped DIO0 to ModeReady

You can't. ModeReady is only supported on DIO5 and DIO4. Other than that it's worth a try. BTW, I've found that if you have the RSSIThresh on 0 (never can be triggered) you can safely abort listen mode the instant PLLLock triggers. No need to wait through the entire RX period.

I haven't tried it, but I bet you could also set the RX period so short that it merely covers the time until PLLLock.

Joe
Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on January 27, 2017, 04:34:43 PM
You can't.

Good catch, and thanks for pointing that out.  By accident, I looked at Table 21 instead of Table 22.   ::)

Oh well, make that two bodge wires then instead of only one bodge wire.

Also, that's good info wrt setting RSSIThresh to 0.  With RSSIThresh on 0, maybe Listen Mode can be aborted even  before  PLLLock triggers?  I'm guessing that would be faster than  resetting the entire RFM69.

I'll give it a try.
Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on January 29, 2017, 01:26:11 AM
Well, from the looks of Figures 18, 19, and 21, if it's possible to abort immediately after PLLLock, and  if the figures are drawn more or less to scale (?), then most of the benefit will already be accrued by that alone.  The comparatively little time and energy that will be wasted is just a function of TS_OSC, which the datasheet defines as follows:
Quote
"The crystal oscillator wake-up time, TS_OSC, is directly related to the time for the crystal oscillator to reach its steady state. It depends notably on the crystal characteristics."
Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on January 30, 2017, 12:32:24 PM
I programmed an 8Mhz Moteino to turn-on a pin when Frequency Synthesis starts and another pin when PllLock goes high.  I did this by just having the Moteino read the RFM69 register values, so it's not as accurate as a fully DIO mapped setup, but I expect it's reasonably close enough as a first experiment.  Hooking those two pins to an oscilliscope (see attached scope shot) suggests that the length of time from the onset of Frequency Synthesis until PllLock is about 65uSec.  It is that time interval of wasted energy that the above idea would be targeting.
Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on January 30, 2017, 01:29:52 PM
If I set ListenCoefRx=1 and ListenResolRx=64uSec, then (see attached) Frequency Synthesis seems to run for about 128uSec before turning off.
Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on January 30, 2017, 01:43:54 PM
For completeness, I also tried setting ListenCoefRx=0, just to see what that would do.  See attached scope shot.  It doesn't appear to be useful.
Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on January 30, 2017, 03:09:43 PM
If I set ListenCoefRx=1 and ListenResolRx=64uSec, then (see attached) Frequency Synthesis seems to run for about 128uSec before turning off.

I think these settings are "good enough," and here's why: the DS says the current drain from keeping the RC oscillator active is typically 1.2uA.  I calculate that if one to were to program Listen mode so that it woke up the atmega328p once every 66.3secs (which is the longest interval that can be specified), then the equivalent incremental drain from the RFM69 is about 31nanoamps.  That's to say, the total drain from the RFM69 would be 1.231uA.  In other words, at least in this scenario,  further optimization wouldn't make much difference.

[Edit1:  Correction:  Actually, the ~16ma of current would run for about 185uSec, not 128uSec, because that's about how long it takes from the start for PllLock to go low.  That adjustment doesn't change the conclusion though.]

[Edit2: In addition, setting a higher bitrate and disabling AGC and AFC will make it shorter.  Interestingly, I just now tried increasing the bitrate to 300kbps and disabling both AGC and AFC, but doing so resulted in no reduction of the 185uSec time.  Apparently one can't get any shorter than that.]

Finished!   :)
Title: Re: Using ListenMode as Wakeup timer
Post by: joelucid on January 31, 2017, 01:10:38 PM
Cool! I use Listen mode with thresh of 0 for all my not actively listening nodes that don't have clock XTALs. Works very well and is a great improvement over the 4uA WDT.
Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on February 06, 2017, 11:33:09 PM
Unfortunately, I encountered a setback on implementing it for the atmega328p.  I'm finding that if ListenResolRx=64usec, then ListenCoefRx needs to be 2 or greater because otherwise the atmega328p doesn't seem to detect the interrupt.  So, unless someone knows of a workaround to that, it appears that in actual practice that is the shortest Rx window that can still trigger an interrupt with PllLock mapped to D2.
Title: Re: Using ListenMode as Wakeup timer
Post by: perky on February 07, 2017, 07:30:42 AM
Are you getting a pulse on the interrupt line longer than 1 MCU clock that the 328P is missing, and can you program the interrupt on the 328P to be edge sensitive rather than level sensitive? If it's programmed for level the interrupt might get missed. From the manual (p. 89):

"If edge or toggle interrupt is selected, pulses that last longer than one clock period will generate an interrupt. Shorter pulses are not guaranteed to generate an interrupt. If low level interrupt is selected, the low level must be held until the completion of the currently executing instruction to generate an interrupt."

Mark.
Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on February 07, 2017, 08:50:46 AM
For the code I'm using:
Code: [Select]
  attachInterrupt (0, wake, RISING); 
  EIFR = bit (INTF0);  // clear flag for interrupt 0

The MCU is running off the 8Mhz internal resonator, so that may be a factor as well.

The pulse is what's shown in the scope shot above.
Title: Re: Using ListenMode as Wakeup timer
Post by: perky on February 07, 2017, 10:08:28 AM
Interesting. I've seen behaviour on an xmega that was a bit curious, it claimed the pin change detection mechanism was asynchronous but it didn't work when selecting specific rising or falling edge mode, however it did work when I selected both edges and read the state of the pin in the ISR to determine which one it was. It was an oddity that I couldn't explain. Maybe try detecting both edges?

Mark.
Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on February 09, 2017, 02:13:42 PM
I think I'll try feeding it into the atmega328p's timer.  I would think that if atmega328p's timer can accurately count pulses from a 32,768 crystal oscillator, then it should also able to capture a  64usec PllLock pulse, since that lasts longer.
Title: Re: Using ListenMode as Wakeup timer
Post by: perky on February 09, 2017, 04:07:54 PM
I assume the both edges test didn't work then?
Mark.
Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on February 09, 2017, 04:26:53 PM
Wasn't sure how to do it.  Is it possible to assign two different ISR's (one for FALLING and one for RISING) to the same pin?  Is that how it's done?  Or do I use separate pins (one for RISING and the other for FALLING), but wire the two pins together?  Or something else?

Regardless, I'm thinking the timer approach might also be helpful for a somewhat different reason: when I'm setting the Listen Mode for fairly short cycles (64usec for Rx and about 100ms for idle), as I will for the low latency remote control listening, it might be tidier not to wake up the atmega328p on every cycle if nothing is happening just to have it increment a counter and go back to sleep.  Rather, maybe use the asynchronous timer's counting ability to wait 1000 or 10000 cycles or so before waking up the atmega328p with a timer interrupt so that it can measure the voltage and phone home.
Title: Re: Using ListenMode as Wakeup timer
Post by: perky on February 09, 2017, 05:45:19 PM
You can set the pin to interrupt on either edge:

attachInterrupt (0, wake, CHANGE);

I found with my xmega part this actually worked, but rising or falling modes didn't (still don't know why). If the logic is common maybe it will work for this too, it's a simple enough test as you're only trying to detect a transition.

Mark.

Edit: found the reason, the pin I was using has "limited asynchronous sense support", and that allows level and pin change interrupts but not rising or falling edge. Still confuses me though because the device did not wake up which it was supposed to do even if no interrupt was actually generated.

And more info, the 328P says that for the external interrupts "recognition of falling or rising edge interrupts on INT requires the presence of an I/O clock. Low level interrupt on INT is detected asynchronously". It doesn't mention pin change in that section, but the option is in the EICRA register section. If you are deep sleeping the device it'll have to wake up and start the IO clock first with rising or falling edges. Since it doesn't mention the change condition maybe that doesn't require the IO clock (?).
Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on February 09, 2017, 08:17:33 PM
You can set the pin to interrupt on either edge:

attachInterrupt (0, wake, CHANGE);


Thanks for clarifying that.  I tried it just now, but unfortunately CHANGE doesn't work any better than RISING or FALLING.  With any of them, it does occasionally, and seemingly at random, pick up the PllLock interrupt when ListenCoefRx=1 and ListenResolRx=64us.   However, it definitely misses the vast majority of them.  When I switch to ListenCoefRx=2, though, then it picks up every interrupt just as it should.

The issue is more significant if attempting a low latency listen mode, because there are simply many, many more ListenRx's happening (I'm hoping for 1 every 100ms), and it all adds up.  Reducing all those ListenRx's to ListenCoefRx=1 should reduce current consumption by somwhere up to half.

So, plan B is to hope that Listen Mode really does work as it should with ListenCoefRx=1.  However, because I can't utilize PllLock pulses which are that brief to wake the atmega328p, I'm hoping that feeding those PllLock interrupt pulses into the atmega328p's asynchronous timer will yet catch them, and thus indirectly wake the atmega328p after a programmed number of pulses are received if atmega328p hasn't already been awoken by receiving a packet while in Listen Mode.  Well, that's the theory anyway.   ::)

[Edit:  Actually, come to think of it, there is one other possibility as to why it's missing most of the PllLock interrupts when ListenCoefRx=1:  I have a lot of debug println statements that I haven't commented out yet.  Perhaps one of those is getting serviced when the PllLock interrupt briefly fires, and the interrupt flag clears before it finishes with the println's.  I'll do some housecleaning and see if that makes a difference.  Chances are it might!]
Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on February 12, 2017, 10:04:41 PM
Back to square one.  It turns out that commenting out the debug code didn't solve the problem after all.  So, I put pin 2 on a scope to see what's going on.  When ListenCoefRx=2, the pulse width on DIO0 is about 13uSec. 

When ListenCoefRx=1, there is no pulse at all.

[Edit: therefore, it would appear that the shortest (most energy efficient) setting for PllLock that still works is when ListenCoefRx=2.  It just is what it is.  ::)]

Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on February 13, 2017, 12:21:08 PM
I just now mapped DIO4 to PllLock to see what would happen.  When ListenCoefRx=2, I get a repeating pulse that's 62uSec wide.  However, when ListenCoefRx=1, I get no pulses.

I think that confirms it.  ListenCoefRx=2 is the shortest setting when ListenResolX is 64uSec.   :(
Title: Re: Using ListenMode as Wakeup timer
Post by: perky on February 13, 2017, 12:56:29 PM
OK, it wasn't missing pulses then - they just weren't there ;) This is useful work WhiteHare.
Mark.
Title: Re: Using ListenMode as Wakeup timer
Post by: joelucid on February 13, 2017, 05:34:50 PM
Yeah, it typically takes 80 uS to get pll locked according to the datasheet. So this isn't too surprising. Still very good to have it experimentally confirmed!
Title: Re: Using ListenMode as Wakeup timer
Post by: kobuki on February 25, 2017, 04:58:05 PM
Sorry guys, I haven't been following this thread all along. Could you outline the PLL lock method? What steps are involved? Maybe a short, working code fragment that says it all instead of explaining things again... Thanks.
Title: Re: Using ListenMode as Wakeup timer
Post by: Neko on March 25, 2017, 09:17:29 PM
This looks like a very useful technique for the project I am working on. Does anyone have experience with it? Is there more recent code than joelucid's original listen.cpp code?

Thanks.
Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on March 26, 2017, 12:13:19 PM
I'm using the basic notion.  It works reliably.  I think short of adding an ultra low power RTC, it's probably the best (= least current consuming) way to sleep your Moteino and still be able to wake it at a particular future time.  All the details of how to do it are in this thread.  Start by getting regular Listen Mode to work, and then you're 80% of the way there.
Title: Re: Using ListenMode as Wakeup timer
Post by: Neko on April 04, 2017, 10:15:31 PM
I'm using the basic notion.  It works reliably.  I think short of adding an ultra low power RTC, it's probably the best (= least current consuming) way to sleep your Moteino and still be able to wake it at a particular future time.  All the details of how to do it are in this thread.  Start by getting regular Listen Mode to work, and then you're 80% of the way there.

It's a little beyond my level, WhiteHare. I'm working hard to understand. (I've read the thread several times, and am studying the cpp file.) But I'm new to Moteino and at an intermediate level with Arduino. I do have Felix's Listener examples working, but am not sure how to go from there. Here's a really basic question, for example. In the cpp file, RFM69Listener.delay (and others) has as its first argument "RFM69& radio". What value do you set that to when you call the function? What would the call look like in my ino file?

Would there be a basic example of how to get a fixed delay using this method?
Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on April 05, 2017, 07:00:41 AM
You should probably ask the author.  I don't have any demo code.
Title: Re: Using ListenMode as Wakeup timer
Post by: Neko on April 07, 2017, 08:30:56 PM
I have it working now. Thanks.

From what I'm seeing (and some hints in this thread), it seems like the clock is not super accurate. About 1% variability among the moteinos I have. I need more like more like 0.25% accuracy in my application.

I do have a very accurate once-per-minute wakeup burst coming from the master node, however. Is there a way to use that to calibrate the clock (also hinted at earlier in the thread)? I thought about running a fixed delay (e.g. 58 sec), and then waking up and trying to count the exact time until the next wakeup burst using millis() (which is somewhat more accurate). But I wonder if there is a better way?
Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on April 07, 2017, 09:18:37 PM
JoeLucid did quite a bit of work on the topic of calibration and clock syncing.  He posted some general descriptions of his approach, as well as the results he was able to get.  I don't recall that he ever posted any demo code, but you might start with that.
Title: Re: Using ListenMode as Wakeup timer
Post by: Neko on April 07, 2017, 10:28:09 PM
Right. I found the thread. Lots of great ideas there, and I even understand about 20% of them!

My goal is to have 250 nodes send message to the gateway once per minute, each in its own 1/4-second time slot. I think the easiest way to do this is a variation on one of your posts in the thread:

1) The gateway starts a 1-minute cycle by a wakeup burst to all nodes.

2) Each node immediately sleeps for 250 ms times its ID#.

3) Each node then wakes up and sends its data to the gateway.

4) The gateway responds with the actual time since the burst.

5) The node can then adjust itself accordingly on the next round. After a round or two, the nodes should nicely avoid talking at the same time.

At least this seems like a good idea. I'm sure the problems will surface when I actually try to implement it...


Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on April 08, 2017, 02:53:47 AM
Sounds like an interesting approach.  Please do post on how it pans out for you!
Title: Re: Using ListenMode as Wakeup timer
Post by: Neko on April 18, 2017, 11:38:50 PM
Works quite nicely. All the elements are in place.
Title: Re: Using ListenMode as Wakeup timer
Post by: Neko on May 22, 2017, 11:55:16 PM
I'm using joelucid's radio.delay() code to time the responses of a number of nodes relative to a wakeup burst. 99.9% of the time it all works nicely, with the nodes hitting their mark within a few ms. But some of my moteino's hang after several hundred trials, requiring a power cycle to recover. It happens only on 4 out of seven nodes. The other 3 have gone for 10's of thousands of trials without a problem.

The nodes get stuck in the third instance of
        LowPower.powerDown( SLEEP_FOREVER, ADC_OFF, BOD_OFF );

I wonder if the 1st two of the three interrupts happen too fast, so that the MCU is not able to enter the second SLEEP mode before the second interrupt occurs. But that's just a guess.

Is there a way to avoid this? Should I be using the PLLLock method instead? Is it something related to the "stuck in listen mode (https://lowpowerlab.com/forum/low-power-techniques/stuck-in-listen-mode-listen-mode-bug-with-workaround/)" bug?
Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on May 23, 2017, 07:23:40 AM
Do the nodes which get stuck have additional flash memory chips on them, and the ones that don't get stuck don't have additional flash memory?  In the past I reported an apparent  bug which relates to that.  If you wire your DTR pin to ground on the nodes which have the problem, does the problem go away?  Which version of Arduino IDE are you compiling with?  If you compile using Arduino IDE 1.0.6, does the problem go away?  There is another fix which you might also try if those don't work, but it's more involved.  So, please report back which, if any, of the above solved your problem.

I use ListenMode as a wakeup timer all the time, and I've never had a problem with it failing.  Based on your description, it's almost impossible that it is the root of your particular problem.
Title: Re: Using ListenMode as Wakeup timer
Post by: Neko on May 23, 2017, 09:43:38 AM
Do the nodes which get stuck have additional flash memory chips on them, and the ones that don't get stuck don't have additional flash memory?  In the past I reported an apparent  bug which relates to that.

Some have SPI and some don't, so it doesn't seem to be related to that.

Quote
If you wire your DTR pin to ground on the nodes which have the problem, does the problem go away? 

Doesn't seem to help. I've had one failure already in the time I took to write this. You mean DTR on the 6-pin programming interface, right?

Quote
Which version of Arduino IDE are you compiling with? If you compile using Arduino IDE 1.0.6, does the problem go away?

I am using 1.6.4 on OSX (MacBook Pro). I can move to Windows and/or to 1.0.6.

Quote
There is another fix which you might also try if those don't work, but it's more involved.  So, please report back which, if any, of the above solved your problem. I use ListenMode as a wakeup timer all the time, and I've never had a problem with it failing.  Based on your description, it's almost impossible that it is the root of your particular problem.

That's encouraging. The failure always occurs just after the last SLEEP command. I use two radio.delay's in a row (one shorter than 262 ms, one longer). The failure is always on the first one.

Can you post or send the code you use for it? As I said, I am using joelucid's code from earlier in this thread. The only modification is that the last SLEEP of the three, and the ListenModeEnd, are moved to the main body of the code instead of staying in the cpp file.

Code: [Select]
radio.delayms(smallTime);
LowPower.powerDown( SLEEP_FOREVER, ADC_OFF, BOD_OFF );
radio.listenModeEnd();
Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on May 23, 2017, 10:03:55 AM
Try 1.0.6 on Windows next.  Compared to anything else, it's the least effort.
Title: Re: Using ListenMode as Wakeup timer
Post by: Neko on May 23, 2017, 12:35:09 PM
Version 1.0.6 on Windows still has trouble.

One interesting thing I notice is that I have 2 delays in succession. The first is many seconds long, but only has 262-ms resolution. The second delay is only a few ms to get to the exact desired time. No matter what order I do these in, the error occurs just after the short delay.
Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on May 23, 2017, 12:57:50 PM
I'll have to defer to someone else.  This doesn't sound like a problem I'm familiar with.
Title: Re: Using ListenMode as Wakeup timer
Post by: Neko on May 23, 2017, 06:59:19 PM
On the oscilloscope, it looks like the pulse at the end of the delay period simply doesn't get made. So the moteino gets stuck in the third SLEEP command.
Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on May 24, 2017, 07:56:16 AM
I'm using different homegrown code, so I can't help you with the library code.  However, at a basic level, it sounds as though either:
1.  Listen Mode was not in effect when you last went to sleep, or
2.  The DIO mapping changed.
If you want to debug it further, you might try checking for those conditions before going to sleep by looking at the corresponding register values.

Title: Re: Using ListenMode as Wakeup timer
Post by: Neko on May 24, 2017, 02:59:01 PM
1. I think Listen Mode is in effect. There are two 0.1-ms pulses on D2 about 2 ms apart at the start of every delay. Those are also there in the failed cases.

2. Perhaps. I'll try to check.

Would it be impolite to ask if you would share your homegrown code?

As I mentioned, the failures are happening with short (< 262 ms) delays. I'm currently testing with longer ones and it seems to be helping. In addition, I am going to add the 50 uS delay recommended by joelucid before turning off ListenMode.
Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on May 24, 2017, 06:11:57 PM
Well, since you have an oscilliscope, you should be able to easily confirm/refute #1 and/or #2 by seeing whether there's a periodic pulse coming in on D2.  If Listen Mode is enabled and DIO0 is mapped to D2, you should see that pulse arriving at the expected periodicity regardless of whether or not your Moteino is waking up or not.  Of course, you're really only interested in whether it continues to arrive when your Moteino should have woken up but instead seems to be in infinite sleep.  If it *is* arriving under those conditions, then something is wrong with the ISR.  If it isn't arriving, then it's #1 or #2.

My code is different.  It runs off a different DIO pin that's connected to D3.  You'd have to bodge a wire to make it work.  I can't offer to support it, so just believe me when I say: you're better off sticking to a standard library.  When I wrote my code, either there wasn't a library, or if there was, I didn't realize it existed.

All that said, I think I may have published some code blocks from it in this thread:  https://lowpowerlab.com/forum/projects/a-solar-supercap-powered-moteino/
Title: Re: Using ListenMode as Wakeup timer
Post by: Neko on May 24, 2017, 09:59:59 PM
Well, since you have an oscilliscope, you should be able to easily confirm/refute #1 and/or #2 by seeing whether there's a periodic pulse coming in on D2.  If Listen Mode is enabled and DIO0 is mapped to D2, you should see that pulse arriving at the expected periodicity regardless of whether or not your Moteino is waking up or not.  Of course, you're really only interested in whether it continues to arrive when your Moteino should have woken up but instead seems to be in infinite sleep.  If it *is* arriving under those conditions, then something is wrong with the ISR.  If it isn't arriving, then it's #1 or #2.

Exactly. It isn't arriving.

Quote
My code is different.  It runs off a different DIO pin that's connected to D3.  You'd have to bodge a wire to make it work.  I can't offer to support it, so just believe me when I say: you're better off sticking to a standard library. 

Heaven forfend! No bodging.

Quote
When I wrote my code, either there wasn't a library, or if there was, I didn't realize it existed.

All that said, I think I may have published some code blocks from it in this thread:  https://lowpowerlab.com/forum/projects/a-solar-supercap-powered-moteino/

Ok. I will search for it. Thanks much.
Title: Re: Using ListenMode as Wakeup timer
Post by: WhiteHare on May 25, 2017, 08:57:46 AM
Hopefully someone who actually uses the library will help you sort out your issue.  If you ever do solve it, be sure to post what it was for future users.

Good luck!
Title: Re: Using ListenMode as Wakeup timer
Post by: Neko on May 27, 2017, 04:06:53 PM
I haven't really solved the problem, but I have worked around it. When radio.delay is used to make delays that are less than 262 ms, then the crashes occur, as I said above, about once per 500 trials in about 1/3 of the nodes. When I increase the delay to be over 262 ms, then the crashing stops. I have no idea what the reason is.

I tried putting delayMicroseconds(128); in ListenModeEnd(), prior to:

  writeReg(REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_LISTENABORT | RF_OPMODE_STANDBY);
  writeReg(REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_STANDBY);

but this did not help on its own.