LowPowerLab Forum

Hardware support => Low Power Techniques => Topic started by: Neko on March 28, 2017, 10:25:41 AM

Title: Pulse counter with ListenMode delay
Post by: Neko on March 28, 2017, 10:25:41 AM
Hi all,

Sorry for the wall of text. Iím new to the whole Moteino world (but having fun working with them) and could use some help on a project.

I have 250 switches, and I need to record how many times they are closed during each minute. The recordings last for months at a time. I currently have a custom interface that connects via wires to each switch. Works great.

The question is can I do this wirelessly? I was envisioning a low-power Moteino node with a magnetic reed switch on it that gets placed near a magnet. I was thinking a CR123 or equivalent so that the batteries would last for about a year.

The reed switch generate an interrupt that wakes the node out of sleep and increments a counter. Then put the node back to sleep. The switches can trip up to about 20,000 times a day at rates of up to 3/sec.

Reporting the counts to the base every minute seems harder. Where can I get a signal every minute to trigger a transmission of the counts? As I understand it, when the node is in low power sleep, there is no accessible timer running, so when the node wakes up, it has no idea how much time has gone by. There has to be some sort of independent timing signal provided to trigger at 1-minute intervals.

From scouring the forums for a couple of weeks, I think I see a few possibilities. Not sure if these are workable or if there are other better solutions.

1. A realtime clock (AB1815) set to give a wakeup once per minute. The nice thing about this is that I could have the gateway tell each node exactly when during the minute to transmit. That way only one node is trying to transmit during any given 240 ms period.
2. Put a 32768 Hz watch crystal on the oscillator pins. Iím told this would allow Timer 2 to run during sleep. But I donít know if this would cause a prohibitive increase in power consumption. I think with this, and a bit of programming, one could again arrange for the nodes to each transmit during a different 240-ms slot.
3. A less accurate clock, like a TPL5010. Approximately once per minute is good enough for the data recording (the gateway can interpolate). But now the nodes are independently timed and will collide about once in 50 tries. They would have to retry when the line wasnít busy.
4. Listen Mode. Have the gateway send wakeup signals. My understanding of Listenmode is shaky, but it seems the gateway can send a signal that wakes up only 1 node at a time. The node would report its counts, and the gateway would move on to the next node. Even better would be having the node sleep for most of the minute (58 seconds) and then only go into listen mode a second or two just before it expected a message. But this would again require a timing signal, so back to #1, 2 or 3.

If someone could steer me in the right direction, I'd much appreciate it.
Title: Re: Pulse counter
Post by: perky on March 28, 2017, 11:31:59 AM
There can be an independent timer running, namely the watchdog timer. This can be used to wake the node up after a certain time. Do some searching on the low power sleep library as to how it is used. This isn't that accurate though, but you might be able just to transmit your packet at an interval asynchronously and leave the gateway in permanent receive, you'll get some clashes every now and then but you'll send the data on the next packet anyway. If there's a relatively long time between packets and you can live with the inaccuracy of the data or packet loss you might not need to use timeslots.

Title: Re: Pulse counter
Post by: Neko on March 28, 2017, 12:03:50 PM
This where  I get stuck, Mark. I get that if I sleep for 8 seconds and wake up from sleep, I know it has been 8 sec, more or less, since sleep started.  But if an interrupt comes in from the switch in the middle of that 8 seconds, I also wake up. How do I tell how long I've been sleeping? Can I re-enter that original sleep bout and pick where I left off? I thought by going back to sleep after an interrupt, I restart the 8-sec timer. And now I have. No idea when the minute is up. Hence my question about external timing signals.
Title: Re: Pulse counter
Post by: perky on March 28, 2017, 01:30:00 PM
Each interrupt source, including the watchdog interrupt, has it's own separate ISR. So you can set a flag in that ISR to determine whether that source fired. You don't have to set the watchdog timer when going back to sleep, you can selectively do that based on whether the watchdog ISR has fired.

So in the watchdog ISR set a flag and increment your time elapsed counter. Just prior to going back to sleep (after you've determined there's nothing else to do), do something like this:

1) Disable global interrupts
2) Check the watchdog ISR flag, if set clear the flag and reset the watchdog timer.
3) check no other inturrupts have happened that would normally wake it up. If they have goto 5), else goto 4)
4) go to sleep (which will re-enable global interrupts)
5) Re-enable global interrupts

So with this a pin interrupt might wake the MCU, and once you've dealt with that you can go back to sleep if the watchdog hadn't fired. The watchdog will fire at some point, but then you'll reset it when you go back to sleep because the flag was set.

Title: Re: Pulse counter
Post by: Neko on March 28, 2017, 02:01:26 PM
Sounds good. I was using LowPower.powerDown to sleep. I guess I'll need to learn more about things at a lower level to do this.
Title: Re: Pulse counter
Post by: fabiocer on June 20, 2017, 07:27:29 AM
Hi All,
I am trying to do something like that but with an higher frequency. It's a trip counter for drills. As you probably know the life time of a ball bearing is rated in million of complete turns.
So, to make some tests in term of lifetime, I have to count the total revolutions. The speed of the motor may vary from 2,000 to 12,000 /15,000 RPM.
I think that the best solution is to use a dedicated low power 16-bit counter and periodically read it.
I write because I tried some "energy harvesting" from the magnet, and I have found really interesting result. With a coil of 1,000 turn of 0,08mm wire, I obtained up to 30mA on a 3,3 Voltage Reg.
I can give you more details if this is interesting for you.
We are also now trying some commercial inductors in order to study the result.
The idea is for sure useful for the Neko project. I can only suggest to use minimun 12 magnets, one every 30 degrees of the circunference. If the speed is lower than 1 turn per second, you need more spikes in order to charge a Cap. Of course the magnets have to be alternate (north-south orientation).
Title: Re: Pulse counter
Post by: perky on October 10, 2017, 06:57:49 PM
You definitely want to use an asynchrously clocked timer for that, interrupts are going to be too fast.

Title: Re: Pulse counter
Post by: Neko on November 02, 2017, 11:52:46 PM
I finally have a nice solution now for the timing of the nodes, using listenMode.delay() written a while back by joelucid.

The idea is to have each node wake up and send its report to the gateway within its designated time-slot, so that they don't step on each other. Currently, Node ID N gets the slot that is 100*N ms from the start of the minute.

When the node starts up, it has no idea what time it is, so it simply sends its report. The gateway then responds with the time between now and the start of the node's next slot. So if node 20 wakes up 24785 ms into the minute, the gateway tells it to wait for 62000-24785 ms. The node goes into listenmode.delay() for that time, before it wakes up again and reports.

One wrinkle is that the RFM69's clock, which is used for listenmode.delay, is in error by a up to 2% from the gateway's clock, so the node will wake up early or late on the next round. But each time it does, since the gateway gives it a report on how far off it was, after 2 or 3 cycles, the node can then compensate for the error and easily hit the mark within a ms or 2.

With this method, there is no wakeup burst from the gateway. The only listenMode command used is delay(), which has gone for over 1,000,000 cycles so far without a problem. With Felix's help, the current consumption is down to 3 uA during sleep (plus the current for the sensor), which means about 12 uA average during a cycle. Not bad.