Yesterday’s optimisation was able to achieve an estimated 60-fold power consumption, by turning on the radio only when a packet is predicted to arrive, and going into a deep sleep mode for the rest of the time.
That does work, but the problem is that the sending node isn’t sending out a packet every 3 seconds. Sometimes no packet is sent because there is nothing to report, and sometimes a packet might simply be lost.
Yesterday’s code doesn’t deal with these cases. It merely waits after proper reception, because in that case the time to the next packet is known and predictable (to a certain degree of accuracy). If a packet is not coming in at the expected time, the sketch will simply continue to wait indefinitely with the radio turned on.
I tried to somewhat improve on this, by limiting the time to wait when a packet does not arrive, turning the radio off for a bit before trying again. But that turns out to be rather complex – how do you deal with uncertainty when the last known reception is longer and longer ago? We can still assume that the sender is staying in its 3s cycle, but: 1) the clocks are not very accurate on either end (especially the watchdog timer), and 2) we need a way to resync when all proper synchronisation is lost.
Here’s my modified loop() code:
And here’s the slightly extended snoozeJustEnough() logic:
Yes, it does work, some of the time – as you can see in this slow scope capture:
Four of those blips are working properly, i.e. immediate packet reception, drop in current draw, and then display update. Two of them are missed packets (probably none were sent), which are again handled properly by turning the receiver off after 150 ms, instead of waiting indefinitely.
But once that first packet reception fails, the next try will be slightly too late, and then the receiver just stays on for the full 3 seconds.
And that’s actually just a “good” example I picked from several runs – a lot of the time, the receiver just stays on for over a dozen seconds. This algorithm clearly isn’t sophisticated enough to deal with periodic packets when some of ’em are omitted from the data stream.
I can think of a couple of solutions. One would be to always send out a packet, even just a brief empty one, to keep the receiver happy (except when there is packet loss). But that seems a bit wasteful of RF bandwidth.
The other approach would be to implement a Phase Locked Loop in software, so that the receiver tracks the exact packet frequency a lot more accurately over time, and then gradually widens the receive window when packets are not coming in. This would also deal with gradual clock variations on either end, and if dimensioned properly would end up with a large window to re-gain “phase lock” when needed.
But that’s a bit beyond the scope of this whole experiment. The point of this demonstration was to show that with extra smarts in the receiving node, it is indeed possible to achieve low-power periodic data reception without having to keep the receiver active all the time.
Update – With the following timing tweak, everything works out a lot better already:
The receiver is now staying in sync surprisingly well – it’s time to declare victory!
I haven’t looked at your entire code, but it appears on the surface that you could cut your power quite a bit more by turning off the rf12b before you spend the 35ms to show the newly received power info.
I think you’re right. Will look into it, thanks.
Long ago I worked for an active RF tag company. What you are talking about is one of the central issues in their system design. To optimize power and RF BW I think the best tradeoff is to force transmit of a short “sync” packet, not necessarily every time slot, but after some number of missing packets. That number depends on the accuracy of your local and remote clocks.
“clocks are not very accurate on either end” …Maybe I haven’t been paying enough attention- is this intended to be a symmetric peer-peer network of all battery-powered jeenodes, or is it a client-server where all the battery nodes talk to a central, mains-powered, internet-connected device which might even have NTP-based time?
I haven’t decided what hardware to use on either end, to be honest… so, yes, one side can probably be made very stable.
Are you sure using a precision timer like
http://docs.macetech.com/doku.php/chronodot
Wouldn’t allow for that accurate measurement of time. Accuracy within a few seconds a year should be enough -especially if you code something in the packet to update the time between nodes.
That way you could straight up tell the node “is it time for a packet?” – “is there one there (yes/no)” ” if you don’t see anything for “x” nanoseconds go to sleep” or “receive the data”.
I want one of those chronodots for my bulb dial clock sooo bad. When is sparkfuns;s free day again?
There are many sources of accurate timing info. While having one of these on one side would be fine, I wouldn’t want to add that cost to every remote note. I’m more inclined to transmit something stable on a periodic basis.
Even with accurate clocks on each end, over time there will be drift. You could send a clock update along with the data on each valid burst of info. Or the receiving end could send a packet back acknowledging a valid transfer and updated clock info. Accounting for the delay in transmitting, your clocks would never be out of sync by more than the last valid update.
@jcw About your final code: you are still using the constant to decrease the waiting time in case of single or multiple failure to communicate, right? I would just get a global variable, which would be reset to a constant after every successful communication and increase by the same constant every time when it is not. Then value of the constant could be decreased a lot (30 vs 150ms), I think.
About clocks. Some time ago you were discussing getting a bit more expensive but much better RTC – “Precision Time, anyone?” from 21 Jan’12. Have you decided to do NOT go for it ??? That chip DS3231 is very sweet, because could be used to wake up from deep sleep… I would really like to have such an option. To be “precise” :), I would not go for a standard RTC plug, sorry.
Sorry, the previous message was a bit less polished language wise … I really like the idea and try to improve it.
Another point/question: Do we really need a scope to do such a timing tests. I would guess, that just printing millis() over serial would serve pretty OK, right? The introduced extra delay should not be huge.
Just trying to avoid another expense ;)