Computing stuff tied to the physical world

Posts Tagged ‘LowPower’

New solar setup

In Hardware on May 15, 2012 at 00:01

Time for another experiment, this time combining my small solar panel with the 3.4 mAh Lithium battery which seems to work so well. The circuit I’m going to try is as follows:

JC s Grid page 16

Here’s the construction, cozily attached to the back of the solar cell:

DSC 3128

Same solar cell, I think it can supply up to 4.5V @ 1 mA in full sunlight.

The tricky bit is that the rechargable lithium cell needs to be treated with care. For maximum life, it needs to be hooked up to a voltage source between 2.8V and 3.2V, and the charge current has to be limited.

Note that the 1 kΩ resistor is put in series with the battery not only to charge it, but also when taking charge out of it. Seems odd, but that’s the way the datasheet and examples show it. Then again, with a 10 µA current draw the voltage drop and losses are only about 10 mV. A diode bypass could be added later, if necessary.

The diode after the regulator has the nice effect of dropping the 3.3V output to an appropriate value, as well as blocking all reverse current flow. There is no further circuitry for the regulator, since I don’t really care what it does when there is too much or too little power coming from the solar cell. Let’s assume it’s stable without caps.

It all looks a bit wasteful, i.e. linearly regulating the incoming voltage straight down to 3.3V regardless of PV output levels and discarding the excess. But given that this little 3V @ 3.4 mAH battery has already supported a few days of running time when fully charged, maybe it’s still ok.

I’ll let this charge for a day or two.

Watching it go down

In AVR, Hardware, Software on May 13, 2012 at 00:01

Now that there’s low-power vccRead() code to measure the current power supply voltage, we can finally get a bit more valuable info from the radioBlip sketch, which sends out one packet per minute.

So here’s a new radioBlip2 sketch which combines both functions. To support more test nodes, I’m adding a byte to the payload for a unique node ID, as well as a byte with the measured voltage level:

Screen Shot 2012 05 09 at 18 28 02

As a quick test I used a JeeNode without regulator, running off an electrolytic 1000 µF cap, charged to 5V via a USB BUB, and then disconnected (this is running the RFM12B module beyond its 3.8V max specs, BTW):

DSC 3127

Here’s a dump of the received packets:

    L 16:56:32.032 usb-A600dVPp OK 17 1 0 0 0 1 209
    L 16:57:35.859 usb-A600dVPp OK 17 2 0 0 0 1 181
    L 16:58:39.543 usb-A600dVPp OK 17 3 0 0 0 1 155
    L 16:59:43.029 usb-A600dVPp OK 17 4 0 0 0 1 134
    L 17:00:46.323 usb-A600dVPp OK 17 5 0 0 0 1 115
    L 17:01:49.431 usb-A600dVPp OK 17 6 0 0 0 1 98
    L 17:02:52.314 usb-A600dVPp OK 17 7 0 0 0 1 82
    L 17:03:55.016 usb-A600dVPp OK 17 8 0 0 0 1 66
    L 17:04:57.526 usb-A600dVPp OK 17 9 0 0 0 1 50

Or, more graphically, as voltage – showing 8 minutes before the sketch runs out of juice:

Screen Shot 2012 05 09 at 19 06 19

This consumes only marginally more power than without the VCC measurements: the original radioBlip sketch lasted 1 minute longer under similar conditions, i.e. one extra packet transmission.

Improved VCC measurement

In AVR, Software on May 12, 2012 at 00:01

As shown in this post, it is possible to read out the approximate level of VCC by comparing the internal 1.1 V bandgap with the current VCC level.

But since this is about tracking battery voltage on an ultra-low power node, I wanted to tinker with it a bit further, to use as little energy as possible when making that actual supply voltage measurement. Here’s an improved bandgap sketch which adds a couple of low-power techniques:

Screen Shot 2012 05 09 at 15 42 39

First thing to note is that the ADC is now run in noise-canceling-reducing mode, i.e. a special sleep mode which turns off part of the chip to let the ADC work more accurately. With as nice side-effect that it also saves power.

The other change was to drop the 250 µs busy waiting, and use 4 ADC measurements to get a stable result.

The main delay was replaced by a call to loseSomeTime() of course – the JeeLib way of powering down.

Lastly, I changed the sketch to send out the measurement results over wireless, to get rid of the serial port activity which would skew the power consumption measurements.

Speaking of which, here is the power consumption during the call to vccRead() – my favorite graph :)

SCR41

As usual, the red line is the integral of the current, i.e. the cumulative energy consumption (about 2300 nC).

And as you can see, it takes about 550 µs @ 3.5 mA current draw to perform this battery level measurement. The first ADC measurement takes a bit longer (25 cycles i.s.o. 13), just like the ATmega datasheet says.

The total of 2300 nC corresponds to a mere 2.3 µA average current draw when performed once a second, so it looks like calling vccRead() could easily be done once a minute without draining the power source very much.

The final result is pretty accurate: 201 for 5V and 147 for a 4V battery. I’ve tried a few units, and they all are within a few counts of the expected value – the 4-fold ADC readout w/ noise reduction appears to be effective!

Update – The latest version of the bandgap sketch adds support for an adjustable number of ADC readouts.

Not long enough

In Hardware on May 9, 2012 at 00:01

My second solar setup did not fare well:

DSC 3086

Started during the day, with the supercap charged up in bright daylight behind a window, it was able to power the JeeNode for about 16 hours – and then in the middle of the night it gave up:

    L 02:36:44.743 usb-A600dVPp OK 17 30 4 0 0
    L 02:37:48.074 usb-A600dVPp OK 17 31 4 0 0
    L 02:38:51.402 usb-A600dVPp OK 17 32 4 0 0
    L 02:39:54.725 usb-A600dVPp OK 17 33 4 0 0

Times are in UTC and we’re in the CEST time zone, so this was two hours later – i.e. around 4:30 AM.

I left it there for another few days, but unfortunately once dead this setup never recovers. The main reason for this is probably that the RFM12B starts up in a very power hungry mode (well, relatively speaking anyway) with a 0.6 mA current consumption – because it starts with the crystal oscillator enabled.

Maybe the self-leakage of the supercap was still too high, and would be (much) lower after a few days in the mostly-charged state, so I’m not ruling out using supercaps just yet. But as it stands, not getting through even a single night is not good enough – let alone being used in darker spots or on very dark winter days.

More experimentation needed!

How low can it go?

In AVR, Hardware on May 7, 2012 at 00:01

While experimenting with various alternate power sources for a JeeNode, I was curious as to just how low it could go in terms of voltage and still function as a simple wireless transmit node.

Made the following mods to push things a bit more than usual:

  • adjusted the fuses to set the brownout level to 1.8V iso 2.7V (efuse: 0×06)
  • changed the RFM12B’s low-battery level to 2.2V iso 3.1V (rf12_control: 0xC040)
  • removed the voltage regulator from a JeeNode, and keep just the electrolytic cap
  • changed the radioBlip sketch to run at 8 MHz, i.e. 16 MHz clock % 2

This is the same setup as with the Tiny Lithium discharge setup described a few days ago, BTW.

Here’s the JeeNode-under-test (JUT?) – the cap I used here is again 100 µF:

DSC 3070

One pair of wires is from the power supply, the other from the multimeter.

And then it’s just a matter of hooking it up to a power supply and gradually lowering the supply voltage.

And the result is … 3.0, 2.9, 2.8, 2.7, 2.6, 2.5, 2.4, 2.3, 2.2, 2.1, 2.0, 1.9, 1.85 Volt still works!

Anything lower than that and the sketch stops sending out packets once a minute – but then again, that’s probably just the brownout detector of the ATmega kicking in!

To get it back up, I re-connected the power supply at 2.1 V and the node started its blips again… lower didn’t work, my hunch is that the RFM12B’s clock circuit needs that slightly higher voltage level to start oscillating.

Measuring VCC via the bandgap

In AVR, Hardware, Software on May 4, 2012 at 00:01

The ATmega’s (and ATtiny’s for that matter) all have a 10-bit ADC which can be used measure analog voltages. These ADC’s are ratiometric, meaning they measure relative to the analog reference voltage (usually VCC).

On a 5V Arduino, that means you can measure 0..5V as 0..1023, or roughly 5 mV per step.

On a 3.3V JeeNode, the measurements are from 0 to 3.3V, or roughly 3.3 mV per step.

There’s no point connecting VCC to an analog input and trying to measure it that way, because no matter what you do, the ADC readout will be 1023.

So can we figure out what voltage we’re running at? This would be very useful when running off batteries.

Well, there is also a “bandgap reference” in each ATmega/ATtiny, which is essentially a 1.1V voltage reference. If we read out that value relative to our VCC, then a little math will do the trick:

  • suppose we read out an ADC value “x” which represents 1.1V
  • with 5V as VCC, that value would be around 1100 / 5000 * 1023 = 225
  • whereas with 3.3V as VCC, we’d expect a reading of 1100 / 3300 * 1023 = 341
  • more generally, 1100 / VCC * 1023 = x
  • solving for VCC, we get VCC = 1100 / x * 1023

So all we have to do is measure that 1.1V bandgap reference voltage and we can deduce what VCC was!

Unfortunately, the Arduino’s analogRead() doesn’t support this, so I’ve set up this bandgap demo sketch:

Screen Shot 2012 04 22 at 21 44 43

Sample output, when run on a JeeNode SMD in this case:

Screen Shot 2012 04 22 at 21 47 20

There’s a delay in the vccRead() code, which helps stabilize the measurement. Here’s what happens with vccRead(10) – i.e. 10 µs delay instead of the default 250 µs:

Screen Shot 2012 04 22 at 21 51 15

Quite different values as you can see…

And here’s the result on an RBBB with older ATmega168 chip, running at 5V:

Screen Shot 2012 04 22 at 21 53 44

I don’t know whether the 168′s bandgap accuracy is lower, but as you can see these figures are about 10% off (the supply voltage was measured to be 5.12 V on my VC170 multimeter). IOW, the bandgap accuracy is not great – as stated in the datasheet, which specifies 1.0 .. 1.2V @ 25°C when VCC is 2.7V. Note also that the bandgap reference needs 70 µs to start up, so it may not immediately be usable when coming out of a power-down state.

Still, this could be an excellent way to predict low-battery conditions before an ATmega or ATtiny starts to run out of steam.

Trying to measure capacitor leakage

In Hardware on Apr 7, 2012 at 00:01

Capacitors have a “leakage current”, i.e. when you charge them up fully, the leakage current will cause them to slowly lose that charge. I was wondering about this in the context of an ultra-low power JeeNode, which has a 10 µF buffer cap right after the voltage regulator. Does its leakage affect battery lifetimes?

Time to do a quick test – I used the 47 µF 25V cap included with JeeNode kits these days:

DSC 2981

So how do you measure leakage currents, which are bound to be very small at 3.3V? Well, you could charge up the cap and then insert a multimeter in series in its most sensitive range. This multimeter goes down to 0.1 µA resolution, although its accuracy is specified as 1.6 % + 5 digits, so the really low values aren’t very precise.

A simpler way is to use the RC time constant as a basis. The idea is that a real-world cap can be treated like a perfect cap (which would keep its charge forever) plus a resistor in parallel. That resistor merely “happens” to be situated inside the cap.

What I did was charge the cap from a 3x AA battery pack which was just about 4.0V, then disconnect the battery and watch the discharge on the oscilloscope:

SCR02

As you can see, it took 500 seconds for the charge in the capacitor to drop by some 2.5V – note the exponential decay, which matches the assumption that the leakage comes from a fixed resistance.

Can we derive the leakage from this? Sure we can!

The formula for RC discharge is:

    T = R x C

Where T (in seconds) is the time for the cap to discharge by 63.2 percent, R is the discharge resistor (in ohms), and C is the capacitor size (in farads).

Above, it took 500 seconds to drop from 3.98 V to 1.48 V, which by pure accident is almost exactly 63.2 %, so T = 500 and C = 0.000,047 – giving us all the info needed to calculate R = 500 / 0.000,046 = 10638298 ≈ 10.6 MΩ.

Using ohm’s law (E = I x R), that means the leakage current at the start is 4 V / 10.6 MΩ = 0.376 µA.

The good news is that such a result would not be of any concern with ultra-low power JeeNodes – the regulator + ATmega + RFM12B use an order of magnitude more than that, even when powered down.

But the bad news is that this result is in fact completely bogus: to measure the charge, I placed the oscilloscope probe over the cap, and it happens to have 10 MΩ internal resistance itself. So basically the entire discharge behavior shown above was caused by the probe i.s.o. the capacitor’s own leakage!

So it looks like I’ll need a different setup to measure real leakage, which is probably in the nanoamp range…

75 days and counting

In AVR, Hardware on Mar 30, 2012 at 00:01

The JeeNode Micro based on the ATtiny84 is getting more and more use around here. One of the ways it can be powered is via a CR2032 coin cell on its back:

I’ve got one with the radioBlip sketch running here, to see how long it will last on a single coin cell.

Well… today it passed the 75-day mark – celebration time!

Onwards!

Can’t be done

In Hardware on Jan 27, 2012 at 00:01

As you may know from posts a short while ago, I’ve been working on creating an ultra-low power supply, providing just enough energy to a JeeNode or JeeNode Micro to let it do a little work, report some data over wireless, and then go to sleep most of the time.

I even designed a PCB for this thing and had a bunch of them produced:

Screen Shot 2012 01 25 at 01 57 45

The good news is that it works as intended and that I’ll be using this circuit for some projects.

The bad news is that they won’t be available as kits in the shop. Ironically, this was the first time where I actually had a batch of kits all wrapped up and ready to go, ahead of time.

But the reality is that I can’t pull it off. For two different reasons:

  • The circuit is connected to live AC mains @ 230 VAC and that means there is a serious risk if you build this stuff, try it out, and then hurt yourself because of some mistake. And even after that, there is the risk that the whole circuit is not properly protected, exposing these voltages (even just humidity and condensation).

  • The other risk is that once everything works, it gets built-in for permanent use and becomes part of your house. What if it gets wet or malfunctions for some other reason, and your house burns down?

As supplier, I’d be liable (rightly so, BTW – there is no excuse for selling stuff which might be dangerous).

The hardest part of all is that even if an accident has nothing to do with this Low-power Supply, I still have to prove that this stuff is safe under any circumstance and that it complies with all regulations!

I’m not willing to go there. Life’s too short and I don’t have the pushing power to go through it all.

Having said this, I do intend to use this supply myself and create all sorts of nodes for use here at JeeLabs. Because I know the risks, I know which failsafe features have been built into the supply, and I’m ok with it:

DSC 2894

The design is available in the Café, to document what I’ve done and for others to do whatever they like with it.

I’m not happy about this decision, in fact I hate it. I’m really proud of finding out that it is possible to create sensor nodes which run off just 12 mW of AC mains power. But the right thing to do is to stop here.

Putting the JNµ to sleep

In AVR, Hardware, Software on Jan 18, 2012 at 00:01

The Sleepy::loseSomeTime() code in the Ports library was never tested on a JeeNode Micro. Turns out that only a minor library difference kept it from working (the arduino-tiny library has its own version of millis(), etc):

Screen Shot 2012 01 14 at 23 55 34

So now, the JNµ can be put to sleep as well. Here’s the jouleTest sketch I used, tweaked to run on the JNµ as well:

Screen Shot 2012 01 14 at 23 55 09

And sure enough, about once every 10 seconds it shows that familiar packet-transmit current consumption:

SCR88

The blue line is the AC-coupled supply voltage, a 3x AA Eneloop battery pack in this case. It supplies about 3.8V, but when running off a 1000 µF cap, it looks like this continues to work down to 1.8V (well below the RFM12B’s minimum 2.2V specs) – although with only about half the transmit power by then.

This current use fingerprint is almost identical to the ATmega328 running this same code. Not surprising really, since it’s the RFM12B which determines most of the power consumption, not the ATmega vs ATtiny difference.

Onwards!

Another AA booster

In Hardware on Jan 16, 2012 at 00:01

Out of curiosity, I’ve been doodling around with the AS1323 boost regulator chip, as suggested by someone in the comments. It’s not super efficient, but it does claim an extraordinarily low quiescent current of 1.6 µA.

Hooking up such a tiny chip is quite a challenge:

DSC 2856

The trouble is that this stuff can’t be spread out too much – the specs say that both input and output caps have to be within 5 mm of the chip. So I tied it to a pcb – mostly for stability – and then wired everything up around it.

Without any load, this thing operates in quite an efficient mode:

SCR81

The yellow trace is the voltage drop across a 10 Ω low-side resistor, the blue trace is the output, but AC coupled, i.e. showing only the ripple voltage.

The red line is the math function to integrate total power use in Coulombs – more on that later.

If you look at the top overview graphs, you can see the current blips which are over 160 ms apart, i.e. this thing is activating only 6 times a second. And each current pulse lasts only about 150 µs. The peak current on the input side, i.e. drawn from the battery, is about 12.5 mA.

Let’s put a 1 kΩ load on the 3.3V output line:

SCR83

I’ve adjusted the scale a bit. The switcher is now operating at about 11 KHz. The peak current drawn is almost 18 mA, but note also that the current never drops to 0 anymore – the baseline of that yellow trace is 2 divisions down from the top, so that’s about 6 mA (as expected, since the load is always drawing current).

Now let’s push it and change the output load to 100 Ω, i.e. about 33 mA @ 3.3V. To make that work, I had to change the input sense resistor to 1 Ω:

SCR84

The baseline for the yellow trace is now halfway, same as for the blue line.

I also added a third probe, the green line monitors output voltage, which is indeed steady at 3.3V (both red and green lines are based at the bottom of the screen). Note the huge peak current draw on the battery: over 290 mA!

Let’s try to understand what’s going on in this last case. First of all, with a 1 Ω sense resistor, a 190..290 mA current draw creates a voltage drop of around 0.25V – which means the battery voltage isn’t really reaching the switching regulator. The battery was measured to be at 1.37V, so the switcher is getting only about 1.1V on average. The datasheet says that it will only be 70..75% efficient on such an input voltage, when generating the 3.3V output.

The 100 Ω output load draws about 33 mA. That’s at 3.3V, so a perfect step-up regulator would need to draw 3x as much when running off 1.1V, i.e. 100 mA. A 70% efficient switcher would draw about 150 mA (0.70 x 150 ≈ 100). What I’m seeing here is more like a 40% efficient switching result (0.40 x 250 = 100) – hm, not sure why…

The other way to determine average current consumption, is to do some Coulomb counting…

In the first screenshot, each blip uses about 900 nanocoulombs (the red line rises 4.5 divisions over the entire width of of the screen). With 6 blips per second, we use 5.4 µC each second, i.e. 5.4 µA average current draw (not quite the 1.6 µA I expected, but still very impressive for an unloaded step-up regulator).

The second graph is trickier. We need to figure out the Coulombs increase per repetitive cycle. My guess would be around 820 nC. Multiply by the switching frequency of 11.25 KHz, and you get 9.2 mC per second, i.e. 9.2 mA average battery current to deliver about 3.3 mA @ 3.3V.

Gotta be a bit careful here. It turns out that the battery (which is a bit old), still delivers 1.44V at this lower power level. Also, since I’m using a 10 Ω current sense resistor in this case, there’s 92 mV wasted in that resistor. That leaves about 1.35V going in. A perfect switcher would draw 3.3V / 1.35V * 3.3mA = 8.07 mA. We’re pulling 9.2 mA, which is about 87% efficiency. That seems a bit optimistic, since the AS1323 doesn’t really go much further than 80%. Oh well, there are probably several measurement errors in my quick and dirty test setup.

For the third case with the 100 Ω load, I end up with a figure of 215 mC/s, i.e. an average current draw of 215 mA. Better than before but still under 50% efficiency.

One more datapoint: with a 100 kΩ load, the switching frequency goes to 120 Hz, while still using about 800 nC per cycle, i.e. ≈ 100 µC per second, or 100 µA. Again, pretty good for what is essentially a 33 µA load @ 3.3V – even if all these estimates are off by perhaps 25%.

So this chip might work quite well for bursty ultra-low power contexts such as a mostly-sleeping JeeNode!

Low-power blink test

In Hardware, Software on Jan 8, 2012 at 00:01

Here is a new snoozeBlink sketch which can run off the new experimental 12 mW Low-power Supply:

Screen Shot 2011 12 28 at 14 48 03

It does all the right things to start off in low-power mode and puts the ATmega to sleep, even as the LED blinks!

The LED is a normal red LED with a forward voltage of about 1.6V and with a 470 Ω series resistor. The result:

SCR03

(lots of noise because I’m using the default 1:10 probe and the scope at its most sensitive 1 mV/div setting)

Voltage over the 100 µF reservoir cap in blue, current consumption in yellow. You can see the startup dip when the cap reaches about 6V, then the 2s wait, and then the LED blink at about 2 Hz with a 10% duty cycle. There’s not much energy to spare – the reservoir cap doesn’t even get a chance to fully re-charge between blinks.

After about 4 seconds, I turned off the power to find out what would happen. Yet there’s still enough energy left to get two more full blinks, and then an aborted blink as the reservoir cap voltage drops below 3V.

Note how the power consumption is just 3 mA while the LED is turned on. The ATmega itself is hardly ever running (the very brief 10 mA peaks got filtered out in this scope capture).

It can even be made to flash with a 26 mA LED current (omitting the resistor) for 16 ms @ 2 Hz. In this case the reservoir cap voltage varied from 9.4 to 4.4 V, again leaving very little energy to spare. Maybe one day this can be refined to drive a TRIAC, which needs very frequent but brief pulses (a BT137, BTA312, or L6004L3?).

But there’s actually something extra-ordinary going on with that power-up sequence – let’s investigate:

SCR04

The BIG surprise? This is running on a standard JeeNode with standard bootstrap – no power-up troubles at all!

Let me try and interpret everything happening in that last image:

  • the initial very high blip (over 25 mA) is the JeeNode’s on-board 10 µF capacitor charging up
  • the 65 ms @ 3.2 mA is the clock startup delay, as defined by the default fuse setting
  • up to this point, the reservoir cap has lost some 2V of its charge
  • the next blip is the boot loader passing control immediately to the sketch (!)
  • then there’s the 32 ms loseSomeTime() call in setup(), with the ATmega finally powered down
  • the last blip at the right-end side of the screen puts the RFM12B into low-power sleep mode

So what’s going on, and above all why is the boot loader problem gone, after all that trouble it gave me before?

The only explanation I can think of lies in the one change I made since then: I’m now using OptiBoot v4.4 … and it probably does the right thing, in that it skips the boot loader on power-up and only goes through a boot-loader sequence on reset. This is the well known ladyada fix. I guess my previous boot loader setup wasn’t using that.

This is really good news. It means you just need a recently-flashed ATmega and you can continue to use the normal FTDI upload mechanism while fooling around with this ultra low-power stuff. Even the 10 µF cap and regulator on the JeeNode can be left in when powering it from the new Low-power supply.

ISP Programmers – part 2

In AVR, Hardware on Jan 5, 2012 at 00:01

In yesterday’s post, I presented my latest ISP programmers, based on the isp_repair2 sketch.

I made a few small improvements to that sketch:

  1. the RFM12B is powered down at the end, so that the unit only consumes a few µA’s once done
  2. the programming rate has been improved by getting rid of those horribly slow digitalWrite() calls, etc.
  3. updated RF12demo and OptiBoot to the latest version (v8 and v4.4, respectively)

Furthermore, I switched from the funky switches to plain jumpers, with the following layout:

Isp pins

Another change is that the default with no jumpers is now to burn RF12demo w/ OptiBoot for use with a 16 MHz resonator – this is a good default for JeeNodes, JeeNode USB’s, and JeeNode SMD’s. To select the other options, just hook this up to USB, change the jumpers, and watch the serial output report on reset.

This is the output with no jumpers and no target board attached:

Screen Shot 2011 12 28 at 11 49 57

This is the output after a normal programming cycle (again, the default case, no jumpers installed):

Screen Shot 2011 12 28 at 11 50 15

Programming takes only a few seconds. Note that this programmer is fully self-contained and includes its own LiPo battery, so all you need to do is press the 6 pins on the ISP header pads. The neat thing is that due to the normally-discharged cap on the target board, the brief power dip caused by touching the ISP pads will generate a hardware power-on reset in the programmer, which then immediately starts its programming cycle.

So the the whole workflow is now as follows:

  • grab this thing – and let’s call it a “Portable ISP Programmer” (PIP!)
  • press the pins against the ISP header of the unit to be re-flashed
  • watch the initial LED blink on the programmer as it comes out of reset
  • wait 2..3 seconds
  • watch the second LED blink, indicating that it has successfully completed programming

There is no power switch, since the programmer enters total power down when done. To re-charge, plug the programmer into a USB port and wait for the “charge” LED to turn off. Note that pressing the reset button also works, but that it adds a small boot loader delay before the isp_repair2 sketch gets started.

This has become so convenient, that I can now take any old JeeNode lying around here, and reset it to a well-known state in just a few seconds, before re-using it for some project or experiment.

ISP programmers

In AVR, Hardware on Jan 4, 2012 at 00:01

ISP (re-)programming is going to become more important in the future, so I’ve built a few more of these:

DSC 2844

The problem was to come up with a robust way to connect to the target board, but I think I’ve found a solution:

DSC 2843

Take a 4-pin header, slightly enlarge the holes in the plastic, and then gently-but-forcefully press a couple of Pogo pins in there. I’m using the type with a large head with sharp edges. Here’s the whole assembly:

DSC 2839

After that, it’s a matter of attaching all the wires and tying / glueing things together:

DSC 2841

These units are all refurbished ones with a defective radio, since that’s not needed here.

DSC 2840

The ZIP straps hold the battery and wires in place. The hot glue does the rest:

DSC 2842

These programmers are considerably more effective than you might think – tomorrow, I’ll explain why…

Scheduler power optimization

In Software on Jan 2, 2012 at 00:01

Last year’s post showed how a packet transmission w/ ACK reception works out in terms of power consumption. It also uncovered a fairly large “power consumption bug”, with the scheduler idling only 0.1s at a time, causing the ATmega to exit power-down mode through its watchdog far more often than necessary.

Here’s the relevant code in the general-purpose Scheduler class in Ports.cpp:

Screen Shot 2011 12 21 at 19 00 38

And here’s what I ‘m going to change it to, to optimize and stay powered-down much longer:

Screen Shot 2011 12 21 at 19 00 10

This changes the wake-up period from 30 times per second, to roughly once every 8s, with blips like this:

SCR58

My interpretation of this picture, is that the ATmega on this JeeNode needs a whopping 10 mA of power for 50 µs once every eight seconds to keep going. That 1 ms “lead-in” at < 1 mA is probably clock startup, or something.

This current draw is the same as before (this capture was with PIR installed). But instead of 1800 wake-ups per minute, there will now be 10 or so. This will reduce the power consumption from 2,000 µC to roughly 10 µC!

Does that mean the Room Node will now last 200 times longer on a single battery? Unfortunately, no. With these low-power games, the weakest link determines total battery life. In this case, there’s a PIR sensor which has to be constantly on, drawing about 50 µA. That’s 3,000 microcoulombs per minute.

But still, this little optimization should add quite a bit to the lifetime of a battery:

  • old: 3000 (PIR) + 130 (radio) + 600 (estimated) ATmega/regulator + 2,000 (scheduler) = 5730 µC/min
  • new situation, again per minute: 3,000 + 130 + 600 + 10 = 3740 µC/min

If you’re wondering what “microcoulombs/minute” means: that’s just current, so rescaling it to µC/s (i.e. µA’s), we get: old ≈ 96 µA, new = 63 µA. With a 2000 mAh 3x AA battery pack, that’s 2.5 vs 3.6 years of run time.

Note that these values are fairly optimistic. With motion in the room, there will be more than one packet transmission per minute. I have yet to see the real-life battery life of these room nodes, although right now it’s looking quite good: the nodes I have around here have been working for many months – 2012 will tell!

But either way, that change of just a few lines of C code should add about 50% to the battery life. Crazy, eh?

Anatomy of a Room Node transmission

In Hardware on Dec 30, 2011 at 00:01

Now that my analysis capabilities have improved, it thought it’d be interesting to see the power consumption profile of a Room Node, running the roomNode.ino sketch. Here’s an annotated capture of a motion event:

Annotated room packet

The yellow line is the current consumption of the entire room node. I’ve added some annotations, although there are still a few things I’m not so sure about, such as the 2.5 ms delay between SHT readout and XMIT start.

The red line is the integral of the yellow line, i.e. the total amount of energy consumed as time progresses. It took about 3 ms between the end of the packet transmission and the first ACK packet header byte coming in – this thumb-twitching with the receiver enabled accounts for about 1/3rd of the power consumption!

There is almost always room for improvement with this sort of stuff. The closer you look, you more you find things to optimize. For example, I noticed that there were blips every 32 mS or so (it’s slightly irregular):

SCR54

This is zoomed in on both axes. The noise level is a bit higher, perhaps due to the 2 mV/div setting of the scope.

That’s over 1 ms @ 0.8 mA, at about 30 times per second on average. I don’t know what it is – it’s not the PIR sensor, which was removed during this measurement. Not a lot of energy per blip, but it does add up: ≈ each uses 1.1 µC, i.e. some 2,000 µC per minute. Whereas the first screen shows that a transmission takes only 130 µC.

So there you go: vampire power at microwatt levels!

Update – Ah, wait – of course! – it’s the Scheduler class in the Ports library! When idling, it lets time pass in steps of 0.1s (or rather 96 ms), and there’s no other way to do this than with 32 and 64 ms watchdog timer steps. I told you – there are no show-stoppers in this game, it works on logic and insight, all the way down!

Finished Low-power Supply

In Hardware on Dec 28, 2011 at 00:01

The Low-power Supply described previously on this weblog now has a PCB – and it’s about as small as a JNµ:

DSC 2827  Version 2

Here’s an assembled unit, ready for testing and hooked up to power a JeeNode (w/ disabled bootstrap):

DSC 2831

And here’s the whole test setup I had to create to check this thing out:

DSC 2830

Lots of stuff involved, including high-voltage probe and 230V isolation transformer (to the right, out of view).

Here’s a demonstration of how it works – summarized as one elaborate scope capture:

SCR42

Green is the mains voltage (235 Vrms), purple is the charge building up on the 100 µF reservoir capacitor, yellow is the regulated output, and blue is the JeeNode’s current consumption (measured as voltage drop over 10 Ω). Note how some of the voltages measured here differ more by than four orders of magnitude!

Anyway, that zoomed-in image is the clear signature of the second 8-byte RFM12B packet transmission. Current consumption varies from 23 to 26 mA. It’s a relatively coarse image, since it has been zoomed in 4,000 times.

The 3.3V supply level is reached ≈ 2s after power-up, with another 2.5s needed to fully charge the reservoir cap. You can see from the purple dips that this supply could sustain at least one packet transmit per second.

No surprises here, but it’s good to see that the PCB design works as intended. Next step: implement deep sleep on the ATtiny84 – hopefully this’ll take just some minor adjustments to the Sleepy::loseSomeTime() code.

Meet the Low-power Supply

In Hardware on Dec 18, 2011 at 00:01

Now that everything is working, I want to have a ready-to use printed circuit board for it. Came up with this:

Screen Shot 2011 12 09 at 18 34 14

It’s tiny – about 48 x 12 mm – even though it’s based entirely on through-hole parts. The idea is to build it up, add wires, and then encapsulate the whole thing in heat-shrink tubing to reduce the number of contact points.

It can not be repeated enough: when tied to AC mains, the ENTIRE circuit carries AC mains voltage levels!

I have a couple of configurations in mind (see yesterday’s post for the schematic):

  • with C1 a 10 nF X2 cap and C4 replaced by a wire, this delivers an average of 0.3 mA on 230 VAC mains
  • with C1 a 22 nF X2 cap and C4 replaced by a wire, this delivers an average of 0.3 mA on 115 VAC mains
  • with both C1 and C4 22 nF caps, this supplies 0.3 mA on 230 VAC with no direct connection to AC mains
  • with C1 and C4 replaced by a wire, this supply can be used with 10..24V DC in – which is great for testing
  • with C1 and C4 each replaced by a 220 kΩ resistor, and R1 by a 1N4007 diode, this becomes a somewhat less efficient (but lower-profile) resistive version, again delivering up to 0.3 mA at 230 VAC

With C4 replaced by a wire, this circuit will have its “GND” output tied directly to the “N” input. This is important when powering the AC current monitor, which needs to have one side of its shunt at 0V relative to AC mains.

Note that no matter what, even with C1 and C4 both included, faults can develop in this circuit which cause the “low voltage” output of the circuit to end up directly tied to an AC mains “live” line. This is not, and will never be, a “safe” circuit. It can only be used safely while enclosed in a plastic box, with no contacts or parts sticking out.

In all cases, the on-board regulator will be activated once the input voltage rises to about 6V. This is the key to being able to power up a JeeNode or JeeNode Micro with their on-board RFM12B module.

A power supply which draws 12 mW!

In Hardware on Dec 17, 2011 at 00:01

It’s been a challenge to get all the bits of the AC current monitor ready, but the last hurdle has now been taken.

In a nutshell: the AC current monitor is a small unit based on a JeeNode Micro, which periodically broadcasts information about the current consumption of an attached appliance. It’s hooked up to 230V, so it’d be a bit silly to run it off batteries. It would be equally silly if it were to draw lots of power, and since it has to be permanently on, I wanted to get its power consumption really, really low – under 0.1 Watt. That goal has now been reached.

According to this calculator, the following setup draws only 12 mW @ 230V and will supply 0.3 mA @ 3.3V:

DSC 2821

Here is the schematic:

Screen Shot 2011 12 09 at 02 54 33

It’s a transformer-less capacitive power supply, combined with an LT1121 low-power 3.3V linear regulator. C4 can be omitted. This regulator has a shutdown pin, which is tied to the input voltage via a voltage divider. As a result, the output of this supply switches on only once the 100 µF reservoir capacitor has charged up to 6V (it’ll continue charging to 12V, at which point the zener diode kicks in). Here is the power-up behavior w/o D2, and no load:

SCR85

The blue line is the voltage over the reservoir cap, and the yellow line is the regulated output. If you look very closely, you can even see the 50 Hz cycles “pumping up” the reservoir once every 20 milliseconds.

By itself, this isn’t good enough yet to drive my test JeeNode (no bootstrap, brief wakeup activity every 10s):

SCR90

Very odd behavior, as the regulator and the RFM12B start pulling more current than is coming in, preventing the output from ever reaching more than 1.8 V (I used a 470 µF reservoir cap in this test).

The final trick was to add a diode from the regulator output to the shutdown pin. This positive feedback causes the regulator to very quickly snap out of shutdown mode. So once the reservoir cap reaches about 6V, the regulator switches on, at which point the shutdown pin is quickly pulled high to finish the job and keep it on:

SCR96

This is running from 150 VAC using the new AC power box. At lower voltages, the trickle current becomes too weak to reliably turn on. At 230V, on the other hand, the whole startup process is even quicker and very robust.

I have not yet been able to measure the power draw of this supply. Due to its design it will always draw the same amount (predicted to be 12 mW), regardless of load. The feed capacitor (C1) is a 10 nF X2 type.

Here’s the final proof – a JeeNode, powering up in a few seconds and sending out a test packet every 10 seconds:

SCR99

Many thanks to martynj – his weblog comments and great suggestions by email made this result possible.

Good – now I can sprinkle dozens of these around the house and still use no more than one Watt extra!

Developing a low-power sketch

In AVR, Software on Dec 13, 2011 at 00:01

As you’ll know if you’ve been reading this weblog for more than a few nanoseconds, I put a lot of time and effort into making the ATmega-based JeeNode use as little power as possible – microwatts, usually.

In the world of ultra-low power, the weakest link in the chain will determine whether your sketch runs days, weeks, months, or years… low power can be a surprisingly elusive goal. The last microoulombs are the hardest!

But it’s actually quite easy to get some real savings with only a little effort. Here are some things to avoid:

  • Don’t optimize in the wrong place – it’s tempting to start coding in a way which seems like a good idea in terms of power consumption, although more often than not the actual gains will be disappointing.

  • Don’t leave the lights on – the ATmega is amazingly easy to power down, which instantly reduces its consumption by several orders of magnitude. Make sure you do the same for every major power consumer.

  • Don’t just sit there, waiting – the worst thing you can do in terms of power consumption is wait. Unfortunately, that’s precisely what the Arduino runtime’s delay() and delayMicroseconds() calls do.

Ok, with this out of the way, I’ll describe a very simple way to get power consumption down – and hence battery lifetimes up (waaay up in fact, usually).

The trick is to use a convenience function from JeeLib (a.k.a. the Ports library). It’s in the “Sleepy” class, and it’s called loseSomeTime(). So if you have this in your code:

    delay(100);

… then you should replace it with this:

    Sleepy::loseSomeTime(100);

You also need to include the following code at the top of your sketch to avoid compilation and run-time errors:

    #include <JeeLib.h>

    ISR(WDT_vect) { Sleepy::watchdogEvent(); }

As the name indicates, the timing is not exact. That’s because the ATmega is put into a power down mode, and then later gets woken up by the watchdog timer (this is hardware, part of the ATmega). This timer can be several percent off, and although the milliseconds timer will automatically be adjusted by loseSomeTime(), it won’t be as accurate as when updated by the crystal or the ceramic resonator often used as system clock.

The second issue with the watchdog is that it can only delay in multiples of ≈ 16 ms. Any call to loseSomeTime() with an argument less than 16 will cause it to return immediately.

Furthermore, loseSomeTime() can only work with argument values up to 60,000 (60 seconds). If you need longer delays, you can simply create a loop, i.e. to wait 120 minutes in ultra-low power mode, use this:

    for (byte i = 0; i < 120; ++i)
      Sleepy::loseSomeTime(60000);

One last aspect of loseSomeTime() to be aware of, is that it will abort if an interrupt occurs. This doesn’t normally happen, since the ATmega is shut down, and with it most interrupt sources. But not all – so if loseSomeTime() returns prematurely, it will return 0. Normally, it returns 1.

The trade-off of loseSomeTime() is power consumption (system clock and timers are shut down) versus accuracy.

But the gains can be huge. Even this simple LED blink demo will use about 10 mA less (the ATmega’s power consumption while running at 16 MHz) than a version based on delay() calls:

    void loop () {
      digitalWrite(4, 1);
      Sleepy::loseSomeTime(250);
      digitalWrite(4, 0);
      Sleepy::loseSomeTime(250);
    }

To reduce this even further, you could shorten the blink ON time as follows:

    void loop () {
      digitalWrite(4, 1);
      Sleepy::loseSomeTime(50);
      digitalWrite(4, 0);
      Sleepy::loseSomeTime(450);
    }

The LED may be somewhat dimmer, but the battery will last 10x longer vs. the original delay() version.

Battery-powered operation isn’t hard, you just have to think a bit more about where the energy is going!

RFM12B low-power startup

In AVR, Hardware on Dec 8, 2011 at 00:01

The startup saga continues. Too many inter-related issues, I need to simplify…

Before tackling the power-ramp startup scenario, i.e. starting up a JeeNode (or JeeNode Micro) on a slowly-charging capacitor, I wanted to make absolutely certain that the sketch is set up to get the best low power mode as quickly as possible after a hardware power-on reset.

Time to create a test setup:

DSC 2816

This is a JeeNode running off 3.6 .. 3.9 V battery power, driving a MOSFET plug using this sketch:

Screen Shot 2011 11 30 at 17 08 54

In other words: power up for 2.5 seconds, power down for 0.5, then rinse and repeat. The JeeNode sitting upright at the bottom right is the Device Under Test (DUT). It’s a JeeNode without regulator, with a little test board to pass the ground connection through a 10 Ω resistor. This lets me measure current (or rather: voltage drop) as well as the voltage of the power supply.

Here is the behavior of a standard ATmega, with standard fuses and a sketch to init & power down the RFM12B:

SCR36

There’s a 1.5s startup delay as the boot loader listens for incoming commands, before it passes control to the current sketch. The lower half of this screen shot shows that point, i.e. right when the sketch is given control. Within about 250 µs, the RFM12B is put to sleep. The vertical scale is 2 mA/div (Ohm’s law, 10 Ω resistor).

Note the time scale: the lower portion is zoomed in 1000x w.r.t. the top.

After lots of experimentation, with the boot loader disabled, I managed to get startup a lot quicker, using a lot less energy. The code used was as follows (with these fuse settings: EXT = 0×06, HIGH = 0xDB, LOW = 0xC2):

Screen Shot 2011 11 30 at 18 22 47

Here is a screenshot with all the traces properly labeled and with measurement units added:

SCR50

Note again the horizontal time scale (top left). Here’s how to identify the different portions of these graphs:

  • the first blip is when the ATnega comes out of power-on reset
  • the second blip is for the rf12_initialize() and rf12_sleep() calls
  • the third blip is the first time loop() is run, which then quickly goes to sleep again

The big surprise (and disappointment) here, is the time between blips 1 and 2, where the average current consumption is about 0.75 mA (between the white cursor lines). This is caused by the RFM12B starting up (a bit irregularly) with the crystal oscillator enabled, instead of in power down.

The problem is that the RFM12B can’t be accessed in the first 30 ms or so after power up (probably because it’s still busy getting out of its own hardware reset). That’s a shame, since the ATmega can go to sleep in ≈ 250 µs.

The point of this all, is to make a JeeNode (or JNµ) start up with a capacitor powered from AC mains, using as low a current trickle as possible. But unless I can find a way to shut that RFM12B down very early on, it looks like a 1 mA or so trickle will be needed to overcome this initial power “hogging” behavior.

I’m not (yet?) willing to throw more hardware at the problem, but that would be one way to work around it: use an I/O pin and a MOSFET to power the RFM12B, after the voltage is high enough to be able to overcome this dip.

In the previous post, I managed to get a JeeNode started with what I though was a 10 µA trickle, but it now looks like I was off by two orders of magnitude in those tests. It’s easy to lose track of details while making changes!

Conclusion: an AC mains power supply with 1 mA trickle is an option, but I’m not ready to give up … yet!

RF12 power optimization

In AVR, Hardware, Software on Dec 1, 2011 at 00:01

Here’s a small evolutionary change to the RF12 driver, to squeeze one more drop of power consumption out of it.

This is the code for which I’m trying to optimize power consumption:

Screen Shot 2011 11 19 at 11 31 16

The Sleepy::loseSomeTime() call is the big power saver. It puts the ATmega into a total power down mode, except for the watchdog timer, which is used to get it back out of this comatose state. So we’re sleeping for 10 seconds.

Around it are the rf_sleep() calls needed to put the RFM12B into low-power mode as well.

And lastly, the rf12_sendWait(3) call does something pretty nifty: it puts the ATmega into full power down mode between each byte sent to the RFM12B while transmitting. This requires a non-standard fuse setting in the ATmega – it only works with a ceramic resonator or the internal clock oscillator, not with a crystal: wake up out of power down within a few clock cycles.

The most efficient mode turns out to be with the ATmega running at 8 MHz off the internal RC oscillator (which starts up really fast). With default Arduino’ish settings, you have to use mode 2, i.e. a less extreme power down mode so it can wake up fast enough.

Here’s one complete transmission of a 8-byte payload (scope details to follow tomorrow):

SCR33

Each vertical division is 5 mA current draw (the voltage drop across a 10 Ω series resistor). You can see the ATmega turn on, drawing 5 .. 9 mA, and the RFM12B in transmit mode consuming about 23 mA.

The red line is pretty advanced stuff: it integrates the current over time – which is equivalent to the amount of charge consumed. At the end of the trace, this leads to a result of 7.22 microcoulombs per packet sent. One way to interpret this (thanks, Jörg – see comments), is that you could send one packet per second on an average current of less than 8 µA (hm, I think that should be 80 µA).

The “blips” are when the ATmega wakes up and feeds another byte to the RFM12B. In detail (edited image):

SCR16

These blips take about 32 µS @ 5 mA, which is what it takes to communicate with the RFM12B on the SPI bus at 2 MHz. The reason is that the RFM12B supports a 2.5 MHz maximum SPI rate (it turns out that this limitation only applies for data read from the RFM12B module).

The blips repeat 18 times, every 162 µS. Why 18? Well, an RF12 data transmission looks as follows:

RF12 packets

That’s 9 bytes of overhead, plus the 8 payload bytes, plus a trailing interrupt to shut down the RFM12B once the transmission is over.

For completeness – in case you think I can’t count blips: there’s one more activity peak at the start. That’s the call to rf12_canSend(), to check that the RFM12B is ready to start a transmission (which then takes 250 µs to start).

This is probably the limit of what you can push out of power savings with an ATmega (or ATtiny) and an RFM12B. Well, apart from: 1) sending less data, 2) increasing the transmit data rate, or 3) decreasing transmitter power.

When re-using the same code with “rf12_sendWait(2)” and running with normal fuse settings at 16 MHz using a ceramic resonator, it uses only slightly more charge – 7.70 µC, i.e. 7% more. So while this was a nice exercise, it’s not really a major improvement.

All in the name of nanowatt yak power s(h)aving…

All power-up puzzles solved?

In AVR, Hardware on Nov 30, 2011 at 00:01

As reported in a recent post, there were startup problems when powered from a 0.4 mA trickle-fed capacitor.

In short: it didn’t work…

The problem with a trickle-feed supply is not that the voltage level will ramp up very slowly (the brown-out detector and power-on reset circuitry should be able to handle that). The problem is that the circuit needs to draw less current than the trickle at all times – because otherwise the capacitor won’t ever reach its full charge level.

One problem was the MCP1702 voltage regulator, which has a large current draw before the input voltage reaches 3.3V where it can start regulating. So I removed the regulator, and created a setup which limits the capacitor charge to around 3.8V – thinking that without the regulator, the ATmega would at some point start up and immediately put itself and the RFM12B into sleep mode, letting the supply voltage rise a bit further.

Strangely enough, it didn’t work at all. I kept seeing a start-up spike of several milliamps. Here’s the current consumption on power-up (the scope shows the voltage over a 10 Ω resistor in series with the power supply):

DSC 2796

That’s over 10 milliamps, for well over a second – Huh?

And then it finally dawned on me: the boot loader! The ATmega is set to look for an upload right after power-up or reset, which is what the boot loader is all about. Guess what it does: look for incoming commands on the serial port for roughly one second, before passing control to the main sketch stored in the ATmega.

Clearly, the boot loader is running at full power. Whoops!

So the first conclusion is that in this context, we can’t use a boot loader. The solution is to change the high fuse from 0xDA to 0xDB with an ISP programmer. It’ll make it harder to upload code, but there’s no other way.

Great. I thought that would solve the problem. But that’s not all. The default fuse settings also cause the ATmega to wait for 65 milliseconds on power-up. This is for crystals to get up to a stable oscillation. Unfortunately, that means the ATmega is spending 65 ms in a higher-power mode on startup.

So I changed the fuses to use the 1K / 14 CK startup mode (power-up / reset). The way I read this, it means that the ATmega will power-up after 1024 + 14 clock cycles once it comes out of hardware reset, and after 1024 clock cycles when coming out of sleep mode.

Furthermore, the divide-by-8 prescaler fuse bit needs to be set, because the ATmega will power up with a 2.7 V supply voltage (the BOD level). At that level, running at 16 MHz is way out of spec, and no doubt very unreliable.

So all in all, the following fuse settings are required:

  • BOD level = 2.7V, i.e. don’t power up before the supply has reached 2.7V
  • enable ÷ 8 pre-scaler on startup (can be disabled in software later)
  • make the clock start up in low-power 1K / 14 CK mode
  • disable the boot loader, jump immediately to the main sketch

Here is the power consumption with these changes (note the 40x X scale and 5x Y scale differences):

DSC 2798

There’s still a 0.65 mA current draw during start-up. Unfortunately, this one is nasty: it’s caused by the RFM12B module, which powers up in this mode. Best thing I can do is put the RFM12B to sleep as soon as possible, but that can’t happen before the ATmega has started up fully. So basically, there’s a 0.65 mA current draw which we can’t get rid of (other than adding extra circuitry to control the RFM12B’s power – but see also below).

What this means, is that I’ll have to settle for a 1 mA trickle feed supply for now. It’s enough to keep charging the buffer cap, and this way things ought to finally get past that power-up hurdle.

And guess what? It works!

DSC 2801

The cap charges until the supply reaches 2.7V, then the ATmega snaps out of reset and puts the RFM12B to sleep.

The interesting thing now, is to check whether that MCP1702 current anomaly on startup really was a problem. So I switched back to a standard JeeNode, and tried it with the above fuse settings.

Hey, it still works! So we could go back to a 12V zener charging a 100 µF cap. This puzzle has come full circle!

More good news – it looks like there is a sneaky way to avoid the 0.65 mA power-up current draw of the RFM12B: make the ATmega start up at 1.8V instead of 2.7V – the RFM12B isn’t pulling much current at that level. So if we turn it off right away then the RFM12B will be put to sleep before it gets a chance to draw too much current.

Does this work? You bet. Here is by far the craziest low-power setup I’ve ever been able to get going:

DSC 2803

That’s a 100 µF cap charged using a 10 µA trickle. You can see the 1.8V bump where the ATmega kicks in, inits the RFM12B, puts it to sleep, and later on sends 2 packets. This is a standard JeeNode, but with special fuse settings:

  • internal 8 MHz RC oscillator, fastest startup
  • don’t enter the boot loader
  • brown-out level is set to 1.8V

The fuse settings are: extended = 0×06, high = 0xDB, low = 0xC2.

Fascinating how everything affects everything, eh?

UpdateI’m having some doubts about this last result. Will need to triple-check my calculations on this one. That last report is most definitely incorrect, there’s no way to get the RFM12B to start up with a 10 µA trickle – it starts up with the crystal oscillator active, which means that it’ll draw at least 0.6 mA until put to sleep.

Ultra low power supply

In Hardware on Nov 27, 2011 at 00:01

This is another post about my quest for an ultra low power supply for the JeeNode and JeeNode Micro, directly connected to AC mains (and hence dangerous, I can’t stress that enough).

To reiterate: the goal is to create a supply using at most 0.4 mA for powering a device at roughly 2.5 .. 3.5 V. With a capacitive transformer-less circuit, this should lead to a 230V power drain of under 0.1 W.

The zener diode approach doesn’t work for voltages under 6V. Low voltage zeners are too leaky.

Neither does a low-power linear regulator – maybe – driven from say a 12V zener + cap. It probably draws too much current on power-up.

A possible solution was mentioned in a 2008 article by Bob Chao, titled “Voltage clamp circuits for ultra-low-voltage apps”. It’s based on a special type of MOSFET called an “EPAD”.

There’s a chip called the ALD111933 (scary name!) which includes two of these. Here are some specs:

Screen Shot 2011 11 17 at 16 46 14

So its gate threshold is very strictly specified as 3.3V, and it can only drain just a few milliamps. Still plenty for me, though. Another design limit is that the device only supports up to 10V between source and drain.

Here’s what I have in mind as my next attempt for the ultra low power supply:

JC s Doodles page 24

The 9.1V zener will have no more than 10 µA of leakage, and the leakage of the MOSFET is negligible as long as the supply voltage remains under 3.3V. Which means all the surplus current can be used by the JeeNode – at last!

Note that there are no other voltage levels of this thing, so there’s not much leeway for charge on the capacitor to drop during high power use, i.e. packet transmission. I can think of two ways to improve on that: go back to a 470 µF cap, which will hold more charge, or add an extra diode in the MOSFET’s gate to increase the voltage level at which it triggers. Either way, I think this circuit ought to finally give me that constant trickle to keep going!

I’ve ordered the necessary parts. To be continued…

The beat goes on

In Hardware on Sep 4, 2011 at 00:01

Today, a milestone was reached:

    $ jeemon examples/driver-demo/
    15:45:01.975 RF12demo config usb-A700fdxv RF12-868.5
    reading:RF12-868.5.3:radioBlip:ping = 493295
    reading:RF12-868.5.3:radioBlip:age = 365
    ^C

That’s nearly half a million packets, one every 64 seconds, all on a single LiPo battery charge:

Screen Shot 2011 09 03 at 15 51 53

The setup is very simple. A 1300 mAh LiPo battery (I just picked one up in a camera shop with a convenient size), attached to a JeeNode USB:

At 3.94 V the battery is still far from dead, so it’ll probably stay alive for quite a bit longer…

The sketch running on this node is:

Screen Shot 2011 09 03 at 16 14 28

(looks like I had lost the low-power stuff in the “radioBlip” code, now fixed on GitHub)

Lots of low-power nodes are holding out nicely here at JeeLabs, by the way. There are about half a dozen permanent room nodes, and with the latest roomNode sketch they just keep going. Some are running on 3x AA rechargeable EneLoop batteries, others use 3x AAA with even less juice, and all of them have been running with just a single charge since the beginning of this year.

JeeNode with a 32 KHz crystal

In AVR, Hardware on Jun 28, 2011 at 00:01

Another experiment: running a JeeNode on its internal 8 MHz RC clock while using the crystal input to run timer 2 as an RTC. This would allow going into a very low-power mode while still maintaining a much more accurate sense of time.

To this end, I modified a JeeNode SMD, by replacing the 16 MHz resonator with a 32 KHz crystal:

Dsc 2599

I didn’t even bother adding capacitors, these are probably not needed with this crystal (same as on the RTC Plug) since there is probably enough parasitic capacitance already.

The tricky part is the code, since the ATmega is now running in a not-so-Arduino-like mode. Could almost have used OptiBoot with this setup, but the only internal RC clock build for it is the LilyPad, which has an ATmega168.

I ended up using the ISP programmer. IOW, I now compile for “LilyPad w/ 328″ and then bypass the bootstrap and serial-upload. Less convenient, but it works.

Here’s a quick test sketch which writes a dot on the serial line exactly once a second:

Screen Shot 2011 06 24 at 15.51.49

So this setup is working. It draws 4.10 ma, consistent with the recent current measurements: slightly less than with the 16 MHz resonator pre-scaled by two.

In idle mode, current use drops to 1.71 mA, not bad!

Now let’s power down with just the timer running as real time clock. There’s a special “power save” mode which does just that. The difference is that timer 0 will now be off, so there won’t be interrupts waking up the ATmega every 1024 µs (as side-effect, the millis() function will start to lose track of time):

Screen Shot 2011 06 24 at 16.15.04

A small adjustment is needed to make sure the serial port is finished before we go into low-power mode, hence the call to delay(3).

Hm, power consumption is still 0.67 mA – quite a bit, given that we’re really powering down most of the time.

Ah, wait. I forgot to turn off the radio. Doing that brings the reading down to 0.15 mA – and I forgot to turn off the ADC and other sub-systems. Now we’re down to … 0.05 mA, while still printing dots:

Screen Shot 2011 06 24 at 16.39.15

Note that these 1 second interrupts are very accurately timed, more so even than with the standard 16 MHz resonator. This could be used to perform time-domain tricks on the wireless side, i.e. waking up just in time whenever a “scheduled” packet is expected to come in – as described in yesterday’s post.

There’s probably more left to try. The delay is running on full power, waiting for the serial output to clear the USART. It could be done while in idle mode, for example. Anyway… that entire delay becomes superfluous when we stop sending out debugging output over the serial port.

So there you have it – a JeeNode running at ≈ 8 MHz, with a precise 32,768 Hz pulse feeding timer 2, in a way which supports low-power sketches while maintaining an accurate sense of time.

Wanna make a clock?

Current measurements

In AVR, Hardware on Jun 26, 2011 at 00:01

Wanted to check a few things w.r.t. current consumption of a JeeNode. The old way of doing this was a bit inconvenient, so I made a new test setup:

Dsc 2597

(old one on the left, new one on the right)

Sturdier, no need to disconnect the multimeter to short it out, and most importantly: high-side current sensing! That’s quite important, because multimeters can add a small voltage drop when used in current measurement mode, and that voltage drop will affect the serial I/O on the FTDI pins when placed in the GND line. Silly me, should have been on the PWR line all along!

The back side of the new connector is trivial:

Dsc 2598

The multimeter attaches to the top pins, bent apart for easy connection. The jumper shorts it out so this contraption can still be used when the multimeter is turned off.

Ok, time for some simple measurements:

  • ATmega full speed, doing nothing: 6.84 mA
  • ATmega full speed, with the RFM12B receiver on: 18.42 mA
  • ATmega powered down, only the RFM12B receiver on: 11.53 mA
  • ATmega full speed, with the RFM12B tranmitter on: 29.92 mA

Idle mode is a simple way to reduce power consumption without changing the logic of the code. It turns the MPU off until an interrupt occurs. Basically, you’re telling it “I’ve got nothing to do until something new happens”. It’s a pretty safe change, and well worth doing in any idle loop which isn’t directly polling I/O pins. The ATmega’s current consumption is slashed by more than half:

  • ATmega in idle mode, doing nothing: 2.80 mA

Another way to reduce power consumption, is to slow down the clock at which everything takes place, by setting the “clock pre-scaler”:

  • ATmega @ 16 MHz, doing nothing: 6.84 mA (as before)
  • ATmega @ 8 MHz, doing nothing: 4.35 mA
  • ATmega @ 4 MHz, doing nothing: 2.96 mA
  • ATmega @ 2 MHz, doing nothing: 2.02 mA
  • ATmega @ 1 MHz, doing nothing: 1.55 mA
  • ATmega @ 500 KHz, doing nothing: 1.28 mA
  • ATmega @ 250 KHz, doing nothing: 1.16 mA
  • ATmega @ 125 KHz, doing nothing: 1.09 mA
  • ATmega @ 62.5 KHz, doing nothing: 1.06 mA

Diminishing returns, clearly. Note that lowering the system clock in this way is not necessarily the best choice – getting something done N times faster and then powering down completely might be more efficient (see below).

One thing to watch out for: don’t go below 4 Mhz if you want to be able to use the RFM12B, or the processor will be too slow to process each byte.

When combining this, we get:

  • ATmega @ 4 MHz in idle mode, doing nothing: 1.48 mA
  • ATmega @ 62.5 KHz in idle mode, doing nothing: 1.03 mA

The advantage of this approach is that the clock is still running on the 16 MHz resonator (which probably draws most of that remaining current), so you’re still able to keep track of time – just more slowly.

A different approach is to go into real low power mode, and use the watchdog to get back out of this comatose state. The watch dog timer is less accurate, but depending on your application that may not be an issue.

Here’s the current consumption with the ATmega alternately in full speed and in power down mode:

  • ATmega 16 ms @ 16 MHz / 16 ms powered down, doing nothing: 3.49 mA
  • ATmega 8 ms @ 16 MHz / 16 ms powered down, doing nothing: 2.31 mA
  • ATmega 4 ms @ 16 MHz / 16 ms powered down, doing nothing: 1.39 mA
  • ATmega 2 ms @ 16 MHz / 16 ms powered down, doing nothing: 0.80 mA
  • ATmega 1 ms @ 16 MHz / 16 ms powered down, doing nothing: 0.46 mA

That last one does about the same amount of work as when running constantly @ 1 MHz, but with a third of the power consumption. Here is the corresponding sketch:

Screen Shot 2011 06 24 at 13.45.56

And it will continues to scale downward:

  • ATmega 100 µs @ 16 MHz / 16 ms powered down, doing nothing: 90.4 µA

Which still represents 100,000 active processor cycles per second…

And lastly, let’s take it into power down and run for just 1 ms per second, i.e. 0.1% of the time. I can’t measure this with the multimeter, because the power use jumps up every second, but the comatose period draws a mere 6.8 µA, which is consistent with what has been reported several times before (the watchdog is still active, and so is the brown-out detector).

Still running on LiPo

In Hardware on May 21, 2011 at 00:01

A while back, a post on this weblog described a simple setup I had running to see how long the radioBlip.pde sketch would keep running on a single LiPo battery.

Here’s the setup again:

That’s a 1300 mAh battery, and the test sketch on it sends out an incrementing counter approximately once a minute (I extended the counter to 4 bytes, instead of the 2 bytes used in the original sketch).

It’s still going strong, i.e. this sketch has been running for 9 months on a single battery charge so far.

The counter is now at about 350,000 and I’ve determined that packets actually go out every 64 seconds, so that puts the counter at about 260 days. There’s a gap there, because the node was once reset some two weeks after being started for the first time.

So with some 275 days of running time, we can deduce that the average power consumption of this node has to be under (1300 * 1000) µAh / (275 * 24) h = 197 µA. This assumes that the battery would be empty, which it isn’t yet – so we know the average current must be lower (a lot lower, probably). Unfortunately, I didn’t include logic to measure and send out the LiPo voltage, which would be a good indicator of how far the LiPo battery actually is. The good news: a check with my multimeter shows the battery to still supply a whopping 3.985 V!

Anyway – I wouldn’t be surprised to get at least 4 times as much runtime, i.e. 3 years, out of this setup (which would translate to 50 µA average current draw).

Sooo… just hang around for another few years, and I’ll let you know!

GLCD on battery power

In Hardware on Nov 27, 2010 at 00:01

I’m going to switch to a different type of graphic LCD once the next batch of Graphic Boards arrives. Instead of a white-on-black type, the new GLCD will be a blue-on-sort-of-blueish color:

Dsc 2356

The reason for this is that it is still quite readable without the backlight:

Dsc 2358

There is a solder jumper on the Graphics Board, to choose between powering the backlight continuously via PWR, or having it powered under software control, via the not-often-used IRQ pin. This not only lets you turn the backlight on and off, but even dim it under software control, because the IRQ pin supports PWM, i.e. analogWrite().

The above display draws about 280 µA without backlight right now, which means it will keep running for over a month on a single AA cell, using the AA Power Board. There are probably ways to reduce that current consumption further, as I’m not doing anything yet with the ST7565′s standby and other low-power modes.

And although it may not be practical for a permament display, this definitely is useful for something I’d like to have around and use on a regular basis. By sending it stuff to display over wireless, this setup can support what is quickly becoming my favorite mode of operation here at Jee Labs: no wires cluttering my desk!!!

Sending data TO remote nodes

In Software on Oct 31, 2010 at 00:01

Yesterday’s post described an easy way to get some data from remote battery-powered nodes to a central node. This is the most common scenario for a WSN, i.e. when reading sensors scattered around the house, for example.

Sometimes, you need more reliability, in which case the remote node can request an “ACK” and wait (briefly) until that is received. If something went wrong, the remote node can then retry a little later. The key of ACKs is that you know for sure that your data packet has been picked up.

But what if you want to send data from the central node TO a remote node?

There are a couple of hurdles to take. First of all, remote nodes running on batteries cannot continuously listen for incoming requests – the RFM12B receiver draws more than the ATmega at full power, it would drain the battery within a few days. There is simply no way a remote node can be responsive 100% of the time.

One solution is to agree on specific times, so that both sides know when communication is possible. Even just listening 5 ms every 500 ms would create a fairly responsive setup, and still take only 1% of the battery as compared to the always-on approach.

But this TDMA-like approach requires all parties to be (and remain!) in sync, i.e. they all need to have pretty accurate clocks. And you have to solve the initial sync when powered up as well as when reception fails for a prolonged period of time.

A much simpler mechanism is to let the remote take the initiative at all times: let it send out a “poll” packet every so often, so we can send an ACK packet with some payload data if the remote node needs to be signaled. There is a price: sending a packet takes even more power than listening for a packet, so battery consumption will be higher than with the previous option.

The next issue is how to generate those acks-with-payload. Until now, most uses of the RF12 driver required only packet reception or simple no-payload acks. This is built into RF12demo and works as follows:

Screen Shot 2010 10 30 at 20.17.37

That’s not quite good enough for sending out data to remote nodes, because the central JeeLink wouldn’t know what payload to include in the ACK.

The solution is the RF12demo’s “collect mode”, which is enabled by sending the “1c” command to RF12demo (you can disable it again with “0c”). What collect mode does, is to prevent automatic ACKs from being sent out to remote nodes requesting it. Instead, the task is delegated to the attached computer:

Screen Shot 2010 10 30 at 20.17.48

IOW, in collect mode, it becomes the PC/Mac’s task to send out an ACK (using the “s” command). This gives you complete control to send out whatever you want in the ACK. So with this setup, remote nodes can simply broadcast an empty “poll” packet using:

    rf12_sendStart(0, 0, 0);

… and then process the incoming ACK payload as input.

It’s a good first step, since it solves the problem of how to get data from a central node to a remote node. But it too has a price: the way ACKs are generated, you need to take the round-trip time from JeeLink to PC/Mac and back into account. At 57600 baud, that takes at least a few milliseconds. This means the remote node will have to wait longer for the reply ACK – with the RFM12B still in receive mode, i.e. drawing quite a bit of current!

You can’t win ‘em all. This simple setup will probably work fine with remotes set to wait for the ACK using Sleepy::loseSometime(16). A more advanced setup will need more smarts in the JeeLink, so that it can send out the ACK right away – without the extra PC round-trip delay.

I’ll explore this approach further when I get to controlling remote nodes. But that will need more work – such as secure transmissions: once we start controlling stuff by wireless, we’ll need to look into authorization (who may control this node?), authentication (is this packet really from who it says it is?), and being replay-proof (can’t snoop the packet and re-send it later). These are all big topics!

More on this some other time…

Simple RF12 driver sends

In AVR, Software on Oct 30, 2010 at 00:01

(Whoops… this post got mis-scheduled – fixed now)

Yesterday’s post illustrates an approach I’ve recently discovered for using the RF12 driver in a very simple way. This works in one very clear-cut usage scenario: sending wireless packets out periodically (without ACK).

Here’s the basic idiom:

Screen Shot 2010 10 29 at 13.01.24

What this does is completely ignore any incoming data, it just waits for permission to send when it needs to, and then waits for the send to complete by specifying “2″ as last arg to rf12_sendStart().

No tricky loops, no idle polling, everything in one place.

With a few lines of extra code, the RFM12B module can be kept off while not used – saving roughly 15 mA:

Screen Shot 2010 10 29 at 13.07.11

And with just a few more lines using the Sleepy class, you get a low-power version which uses microamps instead of milliamps of current 99% of the time:

Screen Shot 2010 10 29 at 13.09.03

Note the addition of the watchdog interrupt handler, which is required when calling Sleepy::loseSomeTime().

The loseSomeTime() call can only be used with time ranges of 16..65000 milliseconds, and is not as accurate as when running normally. It’s trivial to extend the time range, of course – let’s say you want to power down for 10 minutes:

Screen Shot 2010 10 29 at 13.11.16

Another point to keep in mind with sleep modes, is that it isn’t always easy to keep track of time and allow other interrupts to wake you up again. See this recent post for a discussion about this.

But for simple Wireless Sensor Network node scenarios, the above idioms will give you a very easy way to turn your sketches into low-power mode which can support months of operation on a single set of batteries.

Update – it looks like the above RF12_sleep() arguments are completely wrong. They should be:

  • rf12_sleep(N) turns the radio off with a wakeup timer enabled if N is 1..127
  • rf12_sleep(0) turns the radio off
  • rf12_sleep(-1) turns the radio back on

This list matches what is documented on the wiki page.

Reporting motion

In AVR, Software on Oct 21, 2010 at 00:01

Yesterday’s post presented a new sketch which did everything the old sketch did, except report motion. The reason was that the requirements for reporting motion are quite different from the rest: it has to be reported right away – using ACKs, time-outs, and retries to make sure this message is properly received.

The latest version of roomNode.pde now adds the missing logic. And it does indeed get a lot messier – doubling the total number of lines in the source code.

Here is the new loop() code:

Screen Shot 2010 10 19 at 22.37.41

The key change is that there is now a check for “pir.triggered()” which will be called outside all normal scheduling actions. Note that this code is still using scheduler.pollWaiting(), so the code is still spending most of its time in power-down mode.

Except that now, we’re also setting up a pin-change interrupt for the PIR sensor:

Screen Shot 2010 10 19 at 22.40.16

The new code to handle these PIR triggers is as follows:

Screen Shot 2010 10 19 at 22.42.14

So instead of folding this complicated case into the rest of the code, when a PIR trigger goes off, we now simply send that packet out and wait for the ACK, repeating it a few times if necessary. The normal measurement and reporting tasks are not affected by any of this, other than that the measurement scheduling is postponed a bit to avoid triggering another report right away.

The new PIR motion sensor turns out to be quite convenient, because it has an on-board trimpot to set the re-trigger timeout. As long as motion is detected more often than this threshold, the PIR output will remain 1, so there is no need to play tricks in software to avoid constant triggers. We’ll get one pin change for the start of motion, and another one when no motion has been detected for a preset amount of time.

Having said that, I’ve implemented a similar re-triggerable one-shot mechanism in software anyway, because my older nodes use the ELV PIR sensor, which send out a pulse for each motion trigger. So all ON pulses within 30 seconds of each other get coalesced into one.

To illustrate that the system is still doing almost nothing most of the time, I added a debug mode which prints a “.” on each iteration of loop(). In normal Arduino sketches, this would cause an incessant stream of characters to be printed out, but in this sketch there are just a few:

Screen Shot 2010 10 19 at 22.12.35

Motion detection now works more or less independently of the normal measure / report tasks.

There are still some rough edges, but I expect this new code to perform considerably better in terms of battery lifetime already. The dreaded battery rundown problem when the central node is not reachable should be gone. All that remains are a few attempts (I’ve set it to 5) whenever the PIR sensor turns on or off. In both cases the ACK has to be received within 10 milliseconds – after that the sketch enters power-down mode again.

The new code should also make it much easier to add sensor types (switches, hall-effect, 1-wire, barometer).

FWIW, this code needs 8238 bytes (without serial I/O), so it’ll still easily fit in an ATmega168. Without SHT11 (which uses floating point) that drops to 5682 bytes, including the RF12 driver. How’s that for a WSN node!

New roomNode code

In AVR, Software on Oct 20, 2010 at 00:01

It’s time to start putting the pieces together now: sensor readout, scheduling of measurements and packet sends, and low-power mode. Looks like the code in the Ports and RF12 libraries is now making this easier than ever.

There’s a new roomNode.pde sketch which illustrates the whole shebang. At 145 lines, it’s a bit too long to include here in full, but I’ll show some of the interesting pieces.

Note that this version implements everything except motion reporting, which is a bit more complex.

Following the good ol’ top-down tradition, first the setup() and loop() code:

Screen Shot 2010 10 19 at 14.06.12

It starts the measurement loop, which then keeps itself running periodically. The report activity is started every once in a while. Note also the “now” variable, which will make it easier to use 2-byte ints in the logic which will decide later about when to report motion, etc.

The measurement code depends completely on what sensors are supported, and is pretty straightforward:

Screen Shot 2010 10 19 at 14.10.36

No surprises, we just have to be careful to do things in an energy-efficient manner. All the readings end up in the “payload” struct.

And here’s the reporting code:

Screen Shot 2010 10 19 at 14.14.24

Here’s some sample output on the serial port:

Screen Shot 2010 10 19 at 14.18.17

I still need to add the logic for motion detection, but with the new scheduling capabiltities, I expect that extra complexity to stay within a small portion of the code – unlike the current rooms.pde sketch, where everything seems to affect everything else.

The best part? My multimeter stays mostly under 60 µa, i.e. the low-power logic is automatically kicking in!

Room Node – next steps

In AVR, Software on Oct 19, 2010 at 00:01

First of all: thanks to everyone who commented on the recent posts, both online and by direct email. Fantastic feedback, lots of ideas, and several valuable corrections.

In yesterday’s post, I agonized about how hard it is to track time in some sort of reasonably continuous way when most of it is spent in comatose state. Fortunately, a Room Node won’t need that awareness very much. I just wanted to show how things get complex in terms of watchdogs running-but-not-yet-expired, and multiple interrupt sources.

For the next version of the rooms.pde sketch, my plan of attack is to simply ignore the issue. The watchdog will be used for guaranteed wake-up, while PIR motion detection and radio reception interrupts will simply cause the millis() clock to lose time, occasionally.

For ACKs, I’m going to start simple and wait for up to 2 milliseconds in idle mode, before resuming lower-power options again. One interesting suggestion was to slow down the clock while doing so (through the system clock pre-scaler), but that has to be done with care because a slower-running ATmega will also respond more slowly to RF12 driver interrupts – and there is not that much slack there.

Here’s the updated Scheduler class, now included in the Ports library:

Screen Shot 2010 10 18 at 22.54.27

Only a minor extension on the API side: by using pollWaiting() instead of poll(), you can tell the system to enter low-power mode until the next scheduled task. If another interrupt pre-empts this wait cycle, then it’ll break out of power-down mode and go through the loop and re-enter the low-power state the next time around.

The other change I’m currently testing is that a few Scheduler functions can be called from interrupt code, so this provides a way for interrupt code to safely schedule, resume, or cancel a task “via the main thread”.

This is the tiny change needed to make the schedule.pde demo energy efficient:

Screen Shot 2010 10 18 at 23.01.24

However, because it now uses the watchdog, you also need to add the following boilerplate to the sketch:

ISR(WDT_vect) { Sleepy::watchdogEvent(); }

The demo now draws 25 µA when I remove the LEDs.

So here’s the deal: if you can manage to write all your code is such a way that it never calls delay() – or delayMicroseconds() with large values – and instead uses this Scheduler-with-tasks approach, then you’ll get a fairly low power usage almost for free… i.e. without having to do anything else! (just don’t forget to turn the radio on and off as needed)

The code has been checked into subversion, and is also available as ZIP archive – see the Ports info.

Update – more changes checked in to better handle watchdog vs other interrupts.

Tracking time in your sleep

In AVR, Software on Oct 18, 2010 at 00:01

No, this isn’t a story about bio-rhythms :)

One of the challenges I’ll be up against with Room Nodes is how to keep track of time. The fact is that an ATmega is extraordinarily power efficient when turned off, and with it a JeeNode – under a few microamps if you get all the little details right. That leads to battery lifetimes which are essentially only determined by self-discharge!

But there are two problems with power off: 1) you need to be 100% sure that some external event will pull the ATmega out of this comatose state again, and 2) you can completely lose track of time.

Wireless packets are of no use for power-down mode: the RFM12B consumes many milliamps when turned on to receive packets. So you can’t leave the radio on and expect some external packets to tell you what time it is.

Meet the watchdog…

Fortunately, the ATmega has a watchdog, which runs on an internal oscillator. It isn’t quite as accurate, but it’ll let you wake up after 16 ms, 32ms, … up to 8 seconds. Accuracy isn’t such a big deal for Room Nodes: I don’t really need to know the temperature on that strict a schedule. Once every 4 .. 6 minutes is fine, who cares…

There’s a Sleepy class in the Ports library, which manages the watchdog. It can be used to “lose time” in a decently accurate way, and will use the slowest watchdog settings it can to get it out of power-down mode at just about the right time. To not disrupt too many activities, the “millis()” timer is then adjusted as if the clock had been running constantly. Great, works pretty well.

It’s not enough, though.

As planned for the next implementation, a Room Node needs to sleep one minute between wakeups to readout some sensors, but it also needs to wake up right away if the motion sensor triggers.

One solution would be to wake up every 100 ms or so, and check the PIR motion sensor to see whether it changes. Not perfect, but a 0.1s delay is not the end of the world. What’s worse though is that this node will now wake up 14,400 times per day, just to check a pin which occasionally might change. This sort of polling is bound to waste some power.

Meet the pin-change interrupt…

This is where pin-change interrupts come in, They allow going into full power-down, and then getting woken up by a change on any of a specified set of pins. Which is perfect, right?

Eh… not so fast:

Screen Shot 2010 10 17 at 22.05.30

Q: What time is it when the pin-change occurred?

A: No idea. Somewhere between the last watchdog and the one which will come next?

IOW, the trouble with the watchdog is that you still don’t really track time. You just know (approximately) what time it is when the watchdog fires again.

If the watchdog fires say every 8 seconds, then all we know at the time of a pin-change interrupt, is that we’re somewhere inside that 8s cycle.

We can only get back on track by waiting for that next watchdog again (and what if the pin change fires a second time?). In the mean time, our best bet is to assume the pin change happened at the very start of the watchdog cycle. That way we only need to move the clock forward a little once the watchdog lets us deduce the correct moment. FYI: everything is better than adjusting a clock backwards (timers firing again, too fast, etc).

Now as I said before, I don’t really mind losing track of time to a certain extent. But if we’re using 8-second intervals to get from one important measurement time to the next, i.e. to implement a 1-minute readout interval, then we basically get an 8-second inaccuracy whenever the PIR motion detector triggers.

That’s tricky. Motion detection should be reported right away, with an ACK since it’s such an important event.

So we’re somehere inside that 8-second watchdog cycle, and now we want to efficiently go through a wireless packet send and an ACK cycle? How do you do that? You could set the watchdog to 16 ms and then start the receiver and power down. The reception of an ACK or the watchdog will get us back, right? This way we don’t spend too much time waiting for an ack with the receiver turned on, guzzling electrons.

The trouble is that the watchdog is not available at this point: we still want to let that original 8-second cycle complete to get our knowledge of time back. Remember that the watchdog was started to get us back out in 8 seconds, but that it got pre-empted by a pin-change.

Let me try an analogy: the watchdog is like throwing a ball straight up into the air and going to sleep, in the knowledge that the ball will hit us and wake us up a known amount of time from now. In itself a pretty neat trick to keep track of the passage of time, when you don’t have a clock. Well, maybe not for humans…

The scenario that messes this up is that something else woke us up before the ball came down. If we re-use that ball for something else, then we have lost our way to track time. If we let that ball bring us back into sync, fine, but then it’ll be unavailable for other timing tasks.

I can think of a couple solutions:

  • Dribble – never use the watchdog for very long periods of time. Keep waking up very frequently, then an occasional pin-change won’t throw us off by much.

  • Delegate – get back on track by asking for an ack which tells us what time it is. This relies on a central receiving node (which is always on anyway), to tell us how to adjust our clock again.

  • Fudge it – don’t use the watchdog timer, but go into idle mode to wait for the ack, and make that idle period as short as possible – perhaps 2 ms. IOW, the ACK has to reach us within 2 milliseconds, and we’re not dropping into complete powerdown during that time. We might even get really smart about this and require that the reply come back exactly 1 .. 2 ms after the send, and then turn off the radio for 1 ms, before turning it on for 1 ms. Sounds crazy, until you realize that 1 ms of radio time uses as much energy as 5 seconds of power down time – which adds up over a year! This is a bit like what TDMA does, BTW.

All three options look practical enough to consider. Dribbling uses slightly more power, but probably not that much. Delegation requires a central node which plays along and replies with an informative ack (but longer packets take longer to receive, oops!). Fudging it means the ATmega will be in idle mode a millisec or two, which is perhaps not that wasteful (I haven’t done the math on that yet).

So there you go. Low power stuff isn’t always trivial, once you start pushing for the real gains…

Room Node battery life

In AVR, Hardware on Oct 6, 2010 at 00:01

The current Room Node sketch only gets 1..2 months of life out of a 3x alkaline AA battery pack. Not enough – by far – for practical use around the house.

The good news is that it’s almost entirely a software issue. There have been JeeNodes running for many months now, some up to 10 months, so there is no hardware limitation to achieve such lifetimes.

In fact, I’d like to push it a bit further and see how long one could run a Room Node off a single rechargable AA battery using the AA Power board. If it’s not that long, I could still opt for the 3x AA pack.

Let’s estimate the idle current draw of a JeeNode first.

The big consumer is the PIR sensor. I recently switched to a new one, because it only needs 3.3V and because of its low current draw. Note that the PIR motion sensor is the only component in the Room Node which should not be disabled during sleep: the whole point is to be able to detect motion at all times, after all. Also, a PIR sensor needs time to stabilize, in the order of a minute, so turning it on briefly is no option.

Here’s the good news:

Dsc 2077

That’s 41 µA idle current.

The JeeNode draws ≈ 3.3 µa, let’s round it up to 4 µA.

The SHT11 draws 2..5 µW, let’s round it up to 2 µA.

So total idle draw is 47 µA.

As it turns out, transmissions consume a neglegible amount of current – if the frequency of transmission is 5 minutes, for example (i.e. 288x per day). The motion detection is different, this needs to go out as soon as there is motion, but this probably won’t happen more than a dozen times a day, on average).

For a transmission, the RFM12B needs to be on for about 2 ms, at which point it draws around 25 mA. With 2 ms once every 300 seconds, that’s a duty cycle of 1:150000, i.e. under 2 µA when averaged out.

So let’s round up and assume that the average current draw of a Room Node is 50 µA @ 3.3V.

A 3x AA battery pack of 2500 mAh would last 50,000 hours, i.e. over 5 years if we ignore the self-discharge rate … assuming that the low-power code is perfect, that is!

Now for the AA Power Board lifetime estimate. At very low current levels, the efficiency of the LTC3525 regulator is 75..80%, according to the datasheet. But first, we need to estimate the current draw. Keep in mind that the power source will be 1.2 .. 1.3V, so we basically need a 3-fold step up. Let’s calculate the input current draw, assuming 1.2V in, 3.3 V out @ 50 µA, and 75% efficiency:

input current = 50 x 3.3 / 1.2 / 0.75 = 183 µA

With an Eneloop battery, I’ll assume it has 1900 mAh capacity, and loses 15% of its charge in two years. Let’s assume that it’ll be used no more than 2 years, and that it lost that 15% charge right at the beginning. Then this is effectively nothing more than a 1600 mAh battery.

Ok, how long can it power a JeeNode plus Room Board?

lifetime = 1600 / 0.183 = 8743 hours = 364 days

So all in all this setup should be able to run just about one year off a single rechargable AA battery. Note that there was some rounding in several places in these calculations, so these estimates are probably a bit conservative.

One year battery life… that’s in fact exactly what I was hoping for!

Now the “only” remaining challenge is to optimize the “rooms.pde” sketch enough to make this happen.

Poor Henry

In Hardware on Oct 2, 2010 at 00:01

The new AA Power Board is working very nicely, but it turns out that the ferrite-core inductor is a little fragile.

This is the 10 micro-Henry inductor core, as it should be:

Inductor

… and this is what happened to one of the shipments “all the way” to the UK:

Sje 3911

(photo courtesy Steve Evans – great close-up!)

Whoops, not good!

This happened to two of the five boards shipped as part of a “5-pack”, where I placed all the boards together in a single plastic bag, along with the metal AA clips. The fact that the inductor is placed near the outside edge also probably doesn’t help…

I’ll package the boards differently from now on. But if you got these boards, please check them and let me know if they got damaged (they may still work, depends a bit on the breakage) – I’ll send out replacements for any bad boards out there, of course.

Live and learn!

Room Node mount?

In Hardware on Sep 21, 2010 at 00:01

I’m still searching for ideas to mount a JeeNode with a Room Board, a.k.a. as a “Room Node”. Now that the AA Power Pack lets me get rid of two of the 3 AA’s, I’m sort of hoping to bump into some new and practical options.

How about this position, against the ceiling?

Dsc 1957

The PIR motion sensor is placed above an empty spot between the JeeNode and the AA Power board. It’ll need to be wired up in that position, of course.

The shapes are still agonizingly unsuited for placement into a corner, but then again… it’s a lot better than with the 3x AA battery pack! Here’s the whole setup again, in close-up:

Dsc 1958

The trick will be to cover it up properly, here’s a first trial using my favorite foam-board as prototyping tool:

Dsc 1960

That’s 6.5 cm wide, btw. Any less, and the battery holder will poke into it and make it wobble.

Does it look good? I don’t know. I think I could live with a slanted 6.5 x 20 cm white strip along the ceiling, with a little PIR peeking out in the middle (and a small hole for the LDR + temperature/humidity sensor).

Next challenge is to come up with a mounting bracket for this darn thing. Perhaps 3D-printed? Two triangles on the end or something? If they slant slightly inwards, they would cast a shadow and not draw much attention…

It all needs to be properly detachable, since this thing runs on battery power. I could stick two little solar panels on the surface to get a warm fuzzy environmental feeling… but I doubt they’ll capture enough energy in that position.

Anyway – I’m happy to have a fresh option to think about. We’ll see…

Lots of AA’s

In Hardware on Sep 20, 2010 at 00:01

C’mon, admit it… you’ve got a pile of discarded AA’s somewhere in your drawers as well:

Dsc 1950

With all the JeeNodes and room nodes I’ve been trying out around here – and the modest results with the rooms.pde sketch w.r.t. battery life so far, I’ve gone through all these much faster than I would have liked to:

Dsc 1949

Went through over 60 here at Jee Labs, in the past year or so. So much for the environment!

Enough is enough. I’m switching to the Apple charger with the Eneloop NiMh’s. And with the new AA Power board, it looks like a single AA cell per node might be enough.

But wait! Are all those AA cells really empty? Time to find out!

Since the AA Power board is so efficient, I though it’d be interesting to see how many of those “dead” AA cells are truly empty. Note that the AA Power board can pull juice out of a battery and generate 3.3V even when it’s supplying less than half its original voltage:

Dsc 1946

So let the battle begin: which cells really can no longer drive a JeeNode as wireless test node?

The result surprised me quite a bit. These 10 were completely dead:

Dsc 1948

But the rest – which is ALL the batteries shown in the first picture – still worked!

This doesn’t mean that any of these batteries will last very long. But still – they drive the JeeNode and its on-board RFM12B transmitter well enough to send out a fresh packet once a second. Which means that even with an output voltage less than 1.1V, they are still able to a briefly deliver a 80 mA peak current once a second (i.e. 3x the current required @ 3.3V) !

Hmm, now what … charge an Eneloop with all that residual energy, perhaps? :)

AA power options

In Hardware on Sep 19, 2010 at 00:01

The new AA Power board is a pretty darn flexible little board, if I may say so myself. Its switch regulator draws very little current itself, 7..30 µA depending on the input voltage. The input voltage range is approx 1.0 .. 5.5V, to be able to start up, but it will drain the power source all the way down to 0.4V if it can, pulling every last bit of juice out of regular AA batteries.

But the AA Power board is also capable of providing a pretty decent amount of current when needed. This is essential for the on-board wireless radio of the JeeNode, but it even works with heavier loads than that:

Dsc 1942

That’s an Arduino-compatible JeeNode with an LCD Plug and a 2×16 character LCD with backlight – all running off a single 1.2V AA NiMH battery!

The maximum current depends on the input voltage. It is guaranteed to be at least 60 mA from a 1V supply, going up to 140 mA from a 1.8V supply. Note that the input current can be much more than that – drawing 60 mA at 3.3V means the battery may have to deliver about 200 mA at 1V to make it happen. A clever little power regulator it is – a producer of energy it is not!

There a several ways to connect the AA Power board with a JeeNode:

  • inline, feeding the PWR pin with 3.3V (this will be dropped some 30..50 mV by the on-board regulator of the JeeNode itself, with no ill effects)
  • in piggy-back mode, with an AA cell inserted in the battery clips (alkaline or NiMh)
  • as a shield on top of the JeeNode, again with an AA cell inserted

There’s also a fourth way to use this board: leave off the battery clips, and connect a battery between any PWR and GND pins on the JeeNode itself (or use the battery holes) – this requires a solder jumper on the AA Power board.

The flexibility of the regulator means that you can connect any power source between 1.0 and 5.5V to PWR and GND, just as you would with a stand-alone JeeNode. Whatever it is, the +3V pin will carry the essential 3.3V level.

There is one issue to beware of: when PWR is connected to BAT+ via the solder jumper, then do not hook up a second power source at the same time. The most common case is probably: when a battery is connected to PWR, do not connect an FTDI adapter such as the BUB, because it’ll put 5V on the PWR pin … and the battery (or the BUB!) probably won’t like it.

The PWR pin can in fact be used in four different modes:

  • normal – it’s higher than 3.3V and the on-board regulator brings it down to 3.3V for the +3V pin – this would be the case with 3 to 8 AA’s, for example (no need for an AA Power board)
  • boosted – it’s lower than 3.3V and it’s used to feed the AA Power board – in this case the on-board regulator does nothing (and could be omitted)
  • parallel – the PWR pin is connected directly to the +3V pin – this can be used with the AA Power board to make sure the PWR pin also carries power (always 3.3V), in case some plugs expect a supply voltage on the PWR pin
  • floating – the PWR carries no power – this is the case when the AA Power board is used without solder jumper (default case)

The important point here is that the PWR pins do not necessarily carry a higher voltage than the +3V pins. It might be more (normal), less (boosted), the same (parallel), or none (floating). Not every JeePlug can be used with each mode of operation, so be careful to check.

Tomorrow, I’m going to fool around with a bunch of batteries :)

AA mounting options

In Hardware on Sep 18, 2010 at 00:01

As promised yesterday, here is some more info on how to use the new AA Power board.

You’ve already seen the “inline” mode, using an Alkaline cell this time:

Dsc 1932

The second main mounting option is in piggy-back mode, flipped over and mounted on the back of a JeeNode:

Dsc 1939

This can be done either with regular male header pins (1×6 and 2×4, or 3×4), or with extra long pins which will stick out the front of the JeeNode as normal header pins:

Dsc 1938

Doing so requires some care, because once these two boards are soldered back-to-back, you can’t reach everything anymore. Disassembling such a sandwich later is tricky.

Note that you can stand the whole assembly on empty AA battery clips, but once a battery is inserted, this becomes unstable because the round battery sticks out:

Dsc 1940

With AAA clips and the much thinner (and weaker) AAA battery, it turns out that the whole construction does stand upright, but the size and position of the clips gives it limited stability when adding plugs on top.

There is a third option – use the AA Power board on top of a JeeNode with stacking headers, i.e. like a “shield”:

Dsc 1953

There is not that much room, but the 4 port headers can still be used. Note that the AA Power board needs to be mounted upside down in this case, i.e. with the SMD components and the silk screen facing down towards the JeeNode. Here’s another view of this shield-style option:

Dsc 1951

Coming up… a description of the full range of power connections supported by this little magician.

Long live the AA battery!

In Hardware on Sep 17, 2010 at 00:01

The AA Power board announced yesterday just arrived:

Dsc 1931

And it looks like it does indeed perform exactly as expected. Here’s the ripple:

Screen Shot 2010 09 16 at 13.41.07

That’s with the 1.6 mA LED load, i.e. a 75 µs cycle / roughly 13 KHz – this was as predicted: at light loads, the recharge frequency can reach down into the audible range. But it’s highly unlikely to be noticable due to the tiny size of the inductor, which after all is not built to act as a loudspeaker :)

Here’s the “AAv1″ fully mounted for powering a JeeNode via the FTDI connector:

Dsc 1934

(there’s no charge circuit here, I’m just using an externaly-recharged battery as power source)

And here’s the whole setup in actual use:

Dsc 1935

Works like a charm. Runs just fine with the “rooms” and “radioBlip” sketches, and wireless just works – as before.

Quiescent current draw is about 20 µA when powered this way. That goes down to 10 µA when used with two cells @ 2.4V, and down to an amazing 7 µA when powered from a 3V source (a CR2032 ought to work nicely!). Above 3.3V, the circuit becomes just a tad less efficient when it switches into step-down mode, drawing about 30 µA all the way up to 5.5V.

Great, now we’re starting to get into some serious low-power options.

Tomorrow, I’ll describe other ways to use this new AA Power board…

Meet the AA Power board

In Hardware on Sep 16, 2010 at 00:01

Remember the recent post about running a JeeNode off a single battery?

Dsc 1897

That was 9 days ago, and that LED shown above is still lit. It’s not a huge accomplishment, because the LED draws only about 1.6 mA and is very dimly lit, but still. Over two hundred hours of operation time, and the rechargeable battery I used (this one) is still going. It started off at 1.35V and is now at a decent 1.22V level.

Assuming a 70% efficiency (at such low voltages, it probably won’t be much higher than that), and an average of 1.3V getting boosted to 3.3V, the power consumption over this period is … scribble, scribble … 1.6 * 3.3 / 1.3 / 0.7 * 216 = 1253 mAh, i.e. about two thirds of the total capacity of this one-cell AA battery.

Not too shabby. Even without power-down tricks, just by entering idle mode in all the busy loops, an ATmega328P will draw less than 1.6 mA when running at 16 MHz on 3.3V (which is slightly overclocked, but it works just fine). Idle mode is very nice, because you don’t have to play any serious low-power tricks, you just have to tell the ATmega: I have nothing to do right now, take it easy until the next interrupt occurs.

In other words: using only the simplest of all the low power tricks, a JeeNode can run about two weeks off a single AA battery (less, if you have power-hungry peripheral chips connected, of course).

Try running an Arduino Duemilanove off a 9V battery, or even a 4x AA battery pack. Fine board, but it sure ain’t low power…

Anyway, I’ve decided to design an AA Power board for this little power magician:

Screen Shot 2010 09 15 at 21.20.21

It’s not specific to the JeeNode, but it was of course designed to be a particularly good match for it:

  • the width of the board is exactly the same as JeeNodes and all the JeePlugs
  • it can be attached in-line, i.e. like an FTDI board/cable
  • it can be used in piggy-back mode, i.e. attached to the back of a JeeNode
  • or use it in shield mode, i.e. on top of a JeeNode with stacking headers
  • it has mounting holes (since there is plenty of room on this thing)
  • the board can be fitted with either AA battery clips, or AAA battery clips
  • or attach external batteries to it: one, two, three (even four, if NiMh) … you decide!

Whatever the power source is, this board will either boost or step-down the voltage as needed. The efficiency will be up to 95%, depending on load and supply voltage. But in any case, it’ll be way more efficient than any linear voltage regulator, including the one on the JeeNode.

One AA is smaller than 3 or 4, obviously, so a JeeNode with this AA Power board will also fit into smaller places.

In case you insist on using 3x or 4x AA’s, then you’lll still benefit from a much higher conversion efficiency, and the ability to run the batteries down until they are completely empty. In other words: they will last longer!

Now it’s just a matter of waiting to find out whether I did all my homework properly, and got the connections, traces, and physical dimensions right.

Running off a single AA battery

In Hardware on Sep 6, 2010 at 00:01

The other day, I found the LTC3525 – an interesting little (yes, tiny!) boost regulator chip, which might be a pretty good power source for low-power JeeNodes.

Couldn’t resist – had to try it…

Here’s a test setup using my favorite foam-board as base, with one AA battery driving a test LED:

Dsc 1897

(hard to see, but that LED is indeed on)

Did I mention that the whole thing uses tiny parts? It did take some patience…

Dsc 1898

Tests show that it will regulate any input voltage from 0.8V .. 5.5V to 3.3V @ 60..200 mA depending on the input voltage. And with 70..90% efficiency, even in the 10′s of µA current consumption range. I’ve verified that it will indeed down-regulate when fed > 3.3V, which makes it very flexible.

The quiescent current draw of this circuit appears to be around 20 µA on a 1.3V input.

So it looks like this could work out nicely:

Dsc 1899

My hunch is that this thing could last 6 months for a room node. Maybe more, but with a 6-pack of AA batteries plus charger, who cares?

Hmm, might be worth designing a little board for…

Sleepy class

In AVR, Software on Sep 4, 2010 at 00:01

To make it simpler to experiment with the very low-power states of the ATmega on the JeeNode, I’ve moved some code to the Ports library.

It’s all wrapped up into a new “Sleepy” class:

Screen Shot 2010 09 03 at 14.07.54

See the powerdown_demo.pde and radioBlip.pde sketches for examples of use.

This class is documented in the Café:

Screen Shot 2010 09 03 at 14.23.39

FWIW, I’m also evaluating the Redmine system as a way to bring the code repository, Café docs, issue tracker, and Talk forums all into one context:

Screen Shot 2010 09 03 at 14.24.50

That site is still experimental, so I’m not making it public yet. The one missing feature holding me back is that Redmine does not have a good spam prevention mechanism, such as Akismet. At least last time I looked. But all in all, this would be a great way to provide a place to describe projects, fill in the documentation, and track all code changes and bugs collaboratively. If you’d like to have a sneak preview, or want to have a place to describe your project, or perhaps would like to help with the fairly gigantic task of getting a good documentation section going, please email me.

I’ve started copying over some content, but it’s going to take a while before everything has been brought over and adjusted. Both the old and the new system use Markdown, but there are always them pesky little details…

Anyway, back to the topic at hand – enjoy the low-power options, and please consider sharing your explorations, findings, and inventions in the Talk discussion forums.

JeeNode goes solar

In Hardware on Sep 3, 2010 at 00:01

Now that ultra low-power options are coming into reach for JeeNodes, lots of new scenarios can be explored.

The most obvious one is probably a solar-powered JeeNode … so meet the latest new node #5 at Jee Labs:

Dsc 1875

It also uses a 0.47 F supercap, same as yesterday, but now hooked up to a small 4.5 V solar cell (which can only deliver a few mA in bright sunlight), and a Schottky diode between the solar cell and the capacitor.

Here’s the “power supply” in more detail:

Dsc 1876

As you can see, the solar cell is tiny. A few square cm’s only. In fact, it takes quite some time for it to charge the supercap to acceptable levels. I had to place the cell in moderately bright sunlight for about half an hour to get to a 4 Volt charge. It was inching along, taking several seconds per 0.01 V increase.

To avoid losing all that charge right away in the power-up cycle, I modified the ATmega’s fuses to start in 258 clock cycles after power down, and to start up within 4.1 msec after reset. That way it will start up as quickly as possible at all times. The 258 CK setting is particularly nice, because it means the ATmega can get out of total power down within about 16 µs, fast enough to respond to a byte RX/TX interrupt from the RFM12B!

Does it work? Check it out: after connecting the JeeNode with the “radioBlip.pde” sketch pre-loaded… away it went – sending one packet every 60 seconds as node 5:

    OK 5 1 0
    OK 5 2 0
    OK 5 3 0
    OK 5 4 0

While exposed to the current partly-sunny / partly-cloudy light levels, the voltage on the supercap is still increasing. This is good – it means there’s a surplus of solar energy, even with these transmissions going on. That extra energy will be crucial if this thing is to last through the night…

If everything works out, this little Arduino-compatible bugger could well be the first JeeNode to become completely autonomous and transmit wirelessly… forever!

Time will tell :)

Sending packets without battery

In AVR, Hardware, Software on Sep 2, 2010 at 00:01

Here’s a fun experiment…

After yesterday’s improved power-down current results, I wanted to find out how much power it really takes to send out a bunch of small packets. No acks, just periodically sending out a packet and sleeping.

Trouble is, I didn’t want to wait for a battery to run down, since that would take months or even years. Bit long to get results for this weblog, eh?

So instead, I used this little chap:

Dsc 1873

It’s a super-capacitor which can handle up to 5.5V and has a capacity of 0.47 Farad! That’s like putting a thousand 470 µF caps in parallel. Amazing stuff, in an even more amazingly small package.

Here’s a JeeNode, fitted with this new power source, to give you an idea of just how small this thing is:

Dsc 1874

The next step was to design a small sketch to test this. Here’s what I came up with:

Screen Shot 2010 08 29 at 11.57.38

Some of the code left out for brevity. Full source code can be found here.

What this demo does is send out a packet with a 2-byte payload, then sleep for approximately 1 second, then send again, etc. Until power runs out.

Sure enough, packets started coming in every second:

    OK 4 0 0
    OK 4 1 0
    OK 4 2 0
    OK 4 3 0
    [...]

I expected it to send out say 100 packets or so, before the charge in the 0.47 F supercap would run out.

Guess how far it went…

    [...]
    OK 4 178 28
    OK 4 179 28
    OK 4 180 28
    OK 4 181 28

That’s packet number … clickety, clickety … 28 * 256 + 181 = 7349 !!!

In other words, the JeeNode was able to send out well over 7000 packets, i.e. two hours of packets sent once a second.

This is fantastic. I think the secret – apart from the 3 µA powerdown mode – is that the RFM12B + RF12 driver require very little time to start up, send off a packet, and go back to sleep again. There is no ACK involved, the RFM12B is hardly ever in reception mode.

With real-world use, I expect power requirements to be considerably higher. First of all, a Room Board will draw around 50 µA, due to the on-board PIR sensor. And second, I’m going to want to use ACKs for at least the motion detector reports, so that the system has a robust mechanism for reporting motion whenever it is detected. This means putting the RFM12B in receive mode for a few milliseconds, waiting for the ACK. And repeating this process a few times if that ACK isn’t immediately received.

But still … over 7000 packets without a battery!

Update – with one packet per 5 seconds, the charge lasted 4523 packets, i.e. just over 6:15.

Update #2 – with one packet per 60 seconds, 771 packets got sent out, that’s 12:51 hours … looks like the self-discharge of the supercap is eating up the remaining energy.

Sleep!

In AVR, Software on Sep 1, 2010 at 00:01

The “powerdown_demo.pde” sketch in this recent post draws 20 µA, which surprised me a bit…

A while back, I got it down to a fraction of that, by turning off the brown-out detector (BOD) through a fuse bit on the ATmega. That’s a little circuit which prevents the ATmega from coming out of reset and doing anything if the voltage is too low.

As it turns out, you can turn off the BOD in software, but only for sleep mode. The reasoning being that there’s no point in protecting the processor from going berserk while it’s not doing anything in the first place…

Well, my code to turn off the BOD was wrong. You have to do this right before going to sleep. Here’s the updated powerdown_demo.pde sketch:

Screen Shot 2010 08 28 at 12.50.18

(correction – I mixed up my bits: change “PINB |= …” to “PINB = …” or “PORTD ^= …”)

The result?

Dsc 1872

Now we’re cookin’ again!

Another LiPo option

In Hardware on Aug 21, 2010 at 00:01

The other day, I found a Lithium battery in a local shop, which has just about the right size and properties for use with a JeeNode USB:

Dsc 1818

Found it here, for €9 … so it won’t break the bank.

The nice bit, apart from its size, is that it is fully enclosed and isolated, with two contacts which are easy to solder:

Dsc 1819

Do read that warning, and then proceed anyway :)

What you see above, is the battery with a bit of solder applied to each terminal. Next, I attached some wires:

Dsc 1820

I used two-sided tape to permanently fasten the battery to the JeeNode USB’s back side. Note that the headers were already soldered on, with all the extruding pins clipped to get a slightly flatter surface:

Dsc 1821

The ground wire didn’t need insulation after all, since it connects right next to where the battery is. The positive wire was connected to PWR on port 3, to leave the PSI header free if it ever needs to be hooked up later.

And that’s all there is to it:

Dsc 1822

There is no switch to disconnect the LiPo, so the JeeNode USB can run down the battery if it’s not running a good power-saving sketch. But who needs a switch anyway, when you can do it in software, right? Just upload this:

Screen Shot 2010 08 16 at 01.23.09

When run, the JeeNode will power off completely. This code has been added as “powerdown_demo.pde” sketch in the Ports library.

For proper use, sketches running on a LiPo-powered JeeNode USB should periodically measure the current LiPo voltage via the ADC6 pin, which is tied to a voltage divider. For this to work, the voltage should not have dropped below about 3.4V, so that the ATmega still gets a properly regulated 3.3V as AREF to compare with. The voltage on ADC6 is always half the voltage on the PWR pin. So what every sketch needs to do, is to occasionally measure the voltage, and once it reaches 3.4V, shut down completely using something like the above code.

So there it is – another JeeNode, ready to go … to recharge it, I just plug it into USB!

New AA battery option

In Hardware on Aug 19, 2010 at 00:01

Today might be a good day to set aside your dislike of Apple for a moment…

There is a new battery pack + charger option on the market:

Dsc 1816

In Europe, this combination costs €29.95, and it gets you 6 rechargable batteries plus a charger.

The specs are what make this thing particularly interesting for low-power battery-powered devices:

  • each NiMH AA cell holds 1900 mAh charge (rumored to be rebranded Sanyo Eneloops)
  • the batteries are reported to retain at least 70% of their charge for 2 years
  • battery lifetime is reported as being at least 10 years (with recharges, of course)
  • the charger drops to 30 mW “vampire” power draw once the batteries are charged

To start with the latter: I’ve verified it. When charging, there’s a small yellow LED and it draws less than 4 watts. When done, the LED turns green, and power consumption drops to 0.18W. Then, after 6 hours, the LED goes off and the power consuption drops to… zero! At least on the very sensitive SBC-500 I used.

This is a very big deal!

It means you can permanently leave these chargers plugged in, with a few spare AA’s. No cost, no waste – simply a way to keep a couple of cells fully charged and ready to go.

It’s also perfect for JeeNodes, using the standard 3x AA battery holder:

Dsc 1817

That’s 4.1V when fully charged. And JeeNodes will work with them all the way down to 3.3V, i.e. 1.1V per cell. Also, unlike LiPo batteries, running NiMH batteries down won’t do them any harm.

At last, I can stop wasting alkaline batteries… I’m probably going to replace all of them in the months ahead!

Going for gold with the BMP085

In Software on Jun 30, 2010 at 00:01

The recent post about adding some battery savings logic got a lot of mileage out of a very simple change – more than 10x lower average power consumption.

Warning: getting power consumption down can be an addictive puzzle!

Jörg Binkele was very helpful, and sent me a scope image, measuring the voltage drop over a 10 Ω resistor in the power line (before the regulator). Here are the first 5 seconds after powering up:

Jeenode Start tb0

As expected, the node settles into a very low power mode most of the time, with an occasional blip once a second. FYI: one vertical division is 10 mA. The little horizontal bar at both ends is probably the trigger level.

One small surprise was the startup behavior. Well, that first 18 mA bump is really a very simple bug: in the first second when the timer is running and being polled, the node is not in low-power mode. Aha, of course – my power-down logic is at the end of loop(). Ok, trivial to change – just move the end of loop() to the beginning:

Screen Shot 2010 06 24 at 11.11.51

Yup, that seems to get rid of the 1 second hump @ 18 mA. Great. I don’t have an explanation yet for the initial 1.5 seconds, but I suspect that the RF12 driver is waiting in rf12_initialize() – there is still some oddness with RFM12B initialization after power-up. Oh well – that’ll be for another day.

But now it gets interesting – I told you it’s addictive! – the image above shows that each blip is ≈ 75 msec @ 18 mA. That’s when both the ATmega and the RFM12B are turned on.

Wait a minute. Why so long? Sure, the BMP085 needs to measure temperature and pressure, and that takes several tens of milliseconds. But why keep everything else running full throttle? There’s no need.

So I rearranged the core loop a bit, in a way where all major delays would be done with as much of the node’s hardware turned off as possible (bmp085demo.pde):

Screen Shot 2010 06 24 at 19.06.55

Here is the result, again courtesy of Jörg – and then annotated:

Detail Power use

There’s lots of info here. Please note that the time scale is 25 times more detailed than the first scope image. The fun part is that you can essentially tie each power level to a line of code.

For example, the first hump is when the timer hasn’t yet reached 1000 milliseconds (since the watchdog can only take steps of at least 16 ms), so the node waits. But since it uses idle mode i.s.o. normal mode, power levels are about half of what an ATmega usually consumes. With almost no effect on the code. All we’re doing is switch off to wait for the next timer interrupt – that’s 50% of easily obtained savings.

Then there are two medium peaks when the ATmega starts the BMP085 measurements, and in between it drops back to power-down levels. Then we waste some power sending results out on the serial port (this could be removed). Lastly, when it’s time to transmit the readings, we switch on the radio, make sure it gets its job done, and then loop, again in power-down mode with the watchdog to keep us going.

If you look very closely, you can even see how long the BMP085 is busy with measuring temperature (about 4ms) and pressure (roughly 20 ms). Exactly according to specs.

The blip on the first screen is about 4 divisions on the second screen, and as you can see, the node is now asleep most of that time. That’s probably another 10-fold improvement. I wouldn’t be surprised if this node will now run a year or so on one set of AA batteries. And it’s still reporting once a second.

The moral is: match your reasoning to measured facts, and you can get a lot of power savings. Each case will be different, but it’s not rocket science.

Thanks Jörg, but please don’t send any more scope shots … I need to kick this addiction again! ;)

(Reminder: last day of the June special in the shop!)

A small improvement to rf12_sendStart()

In Software on Jun 21, 2010 at 00:01

The RF12 driver has a function called rf12_sendStart() which – you guessed it – is used to start sending out a new wireless packet.

Yesterday’s post was about battery savings, which I implemented by going into a power-down state right after sending out a new data packet.

That code included this little detail:

Screen Shot 2010 06 20 at 03.50.41

The reason for this is that the RF12 driver works mostly on an interrupt basis – i.e. in the background. Without the delay, the node would power down before the packet had actually been sent out. Then, when waking up, the transmission would fail due to the transmitter underrun caused by this logic.

By simply waiting a bit, the interrupts can continue to take place, and all the bytes will get sent to the RFM12B and from there into the airwaves.

Totally by chance, an EtherCard software problem was reported on the Jee Labs discussion forum, which turns out to be related to this very same issue. Sure enough, adding the “delay(5);” fixed that problem as well.

This felt a bit unsatisfactory as solution, so I’ve extended the rf12_sendStart() function to support a “synchronous mode”. The change is backwards compatible, i.e. the default behavior of rf12_sendStart() hasn’t changed.

Now, if you pass 1 as fourth argument, rf12_sendStart() will wait for the packet transmission to actually complete before returning to its caller. In general, calling rf12_sendStart() in sync mode is probably a good idea. Sync mode can be used for sending data packets as well as acknowledgement packets.

So the above code can be replaced by this single line:

Screen Shot 2010 06 20 at 04.02.11

This simplifies the bmp085demo.pde sketch slightly, and it also solves the problem that the EtherCard library may occasionally lock out interrupts on the SPI bus a bit too long to keep the RF12 driver running.

The code and documentation have been updated.

Onwards!

Battery savings for the Pressure Plug

In AVR, Hardware, Software on Jun 20, 2010 at 00:01

Reducing power consumption is fairly tricky, as you can see in the many previous posts about this topic. And to be honest, I haven’t quite gotten to the point where I want to be with the Room Board. My first “major” (ahem) setup with about a dozen nodes around the house didn’t quite go as I had hoped. Most batteries were empty within a month. A few nodes are still going, but those are hooked up to power adapters…

I’d like to revisit this issue and try to improve things a bit. To make the rooms sketch perform better, and also to make the code structure a bit clearer. The current rooms code is quite complex and hard to follow.

But before messing with the rooms.pde sketch, let’s tackle something simpler: the wireless sensor node based on the Pressure Plug, as described here, and then simplified here. I’ll use that last version as starting point.

The first point to note is that to get a substantial first power reduction, you have to focus on the portion of the code where it’s spending most of the time. Which, in the case of “bmp085demo”, is here:

Screen Shot 2010 06 17 at 01.55.06

That’s right: it’s waiting for the next second to “happen”. And even with a slow’ish sensor such as the BMP085 at maximum resolution, it’s spending more than 90% of its time there… waiting!

I’ll use an approach which might be a bit surprising: let’s not change any of the current logic. The idea is that once we’ve done our thing for the current second, we can go into low power mode, as long as we make sure to get back to normal operating conditions in time for the next second.

So what we’re going to do is add some code to the end of the loop() function. It’s functionally equivalent to adding it at the start, since loop(), eh, loops – but I think it makes a better point.

The end of loop() used to look as follows:

Screen Shot 2010 06 17 at 02.01.01

I’m changing it to this:

Screen Shot 2010 06 17 at 01.43.00

IOW, at this stage all the hard work has been done. We wait a bit for all interrupt-driven I/O to complete (serial and RF12). And then we need to figure out how much time remains until the next second. The power saving happens by spending that time in power off mode.

But this requires some preparation. When inducing a comatose state like this, you have to make absolutely sure that something is still able to get you out of coma and back up and running again. This is what the ATmega’s “watchdog” is for: we set it up to wake us up in 16 milliseconds, just before entering sleep mode. And then we keep doing that until it’s almost time to take another reading. The actual watchdog interrupt handler does nothing, btw – all we want is to get back out of power down.

Note that the radio also needs to be turned off and back on again. It’s the biggest power consumer when enabled. Turning it off and going into power down mode is what lets us go from a tens-of-milliamps current drain to a tens-of-microamps current drain.

All the logic for this is located in the loseSomeTime() function, which was adapted from a slightly different version in the rooms.pde sketch:

Screen Shot 2010 06 17 at 01.42.33

And that’s about it. The average power consumption of this sensor node will go down by an order of magnitude. It’ll still be 1..2 mA, but it’s a major improvement: this node should now run 2..3 months on AA batteries. The source code for bmp085demo.pde has been updated.

I’d like to stress that such gains require very little effort for many types of sketches. All you have to do is figure out where the sketch is spending most of its time, and deal with just that part of the code. Getting into yet lower power consumption levels would require more work.

Using LiPo batteries

In Hardware on May 29, 2010 at 00:01

The latest revision of the JeeNode USB includes a LiPo battery charge circuit:

Screen Shot 2010 05 22 at 13.45.15

The “+5V” pin is the incoming pwoer from the USB bus, it goes directly to the MAX1555 LiPo charger. From there, the PWR line is fed, so this will normally be at 4.2V when no battery is attached. That PWR voltage in turn is fed to the on-board 3.3V regulator for the ATmega and RFM12B.

This design was chosen because it lets you very easily add a LiPo battery: simply attach it between PWR and GND. There are no switches or switch-over issues: plug-in to charge, then use unplugged as needed.

I’m going to use the Carrier Board as example, and I’m going to use a LiPo battery from SparkFun, which comes with a polarized JST plug already attached. Here is the matching socket:

Dsc 1486

What we need is a spot where this socket can be soldered on. Ah, here it is, on the PWR/SER/I2C connector:

Dsc 1487

The trouble is that the pins are not 0.1″ apart as needed here, and that the socket won’t be usable if mounted sideways. So I cut off the plastic tabs and bent the wires a bit differently (taking care not to bend too much, because they break very easily):

Dsc 1484

The result fits perfectly on the Carrier Board, with the whole setup in turn fitting very nicely in the ABS box:

Dsc 1485

I’m using an 850 mAh LiPo cell.

One point to note is that the charge current from the MAX1555 is fixed at 280 mA. The rule for LiPo battery is to charge them at no more than 1C, i.e. a 850 mAh cell shouldn’t be charged with more than 850 mA. So in this case, we’re fine, with an estimated charge time of 3..4 hours for a fully discharged battery.

IOW, don’t use this setup with LiPo batteries smaller than 300 mAh or so.

Another thing to avoid with LiPo batteries is to discharge them below about 3V. You can check rf12_lowBat() from the RF12 library once in a while. It reports when the voltage at the RFM12B drops below 3.1V, i.e. around 3.2 .. 3.3V on the LiPo. Once this happens, power down the ATmega + radio to avoid draining the battery any further.

Why all the fuss? Because LiPo batteries can burn and explode, when improperly handled. There’s a lot of energy in there, and at some point things can exceed the design limits. Search for “lipo explode” on YouTube…

There are really only two issues: 1) the short-circuit discharge current can be extremely high (20C, i.e. 17 Amps with the above unit!), so short circuits and polarity reversals must be avoided at all times. And 2), charging should be done with the proper circuitry, such as the one in the JeeNode USB.

Why use LiPo’s? Well, they are very compact for the amount of energy they store, they can be recharged over and over again, and they have a very low self-discharge rate (i.e. long shelf life when not used).

When used properly, LiPo batteries are a great way to power JeeNodes, etc.

Lithium node

In Hardware on Jan 23, 2010 at 00:01

The 3.6 long-life / low-current OmniCel lithium batteries just came in.

Say hello to the latest room node at Jee Labs:

DSC_0944.jpg

Colorful, eh? ;)

The battery is connected directly to +3V and GND, i.e. after the voltage regulator, since its operating voltage is an excellent match for the ATmega and RFM12B.

No motion sensor was needed for where this node is going (and I didn’t have any left anyway), so that reduces the current draw by some 40 µA. Average should be somewhere around 200 µA – as mentioned before, this can no doubt be optimized further.

Since there are no motion triggers, this node will only send one or two packets per minute – the battery should last well into 2011, according to the specs.

Unless the receiver is turned off and this thing starts re-transmitting all the time. I really need to fix that flaw…

For a fun enclosure, check out the Airwick post by Szymon Kobalczyk on the Jee Labs discussion forum.

Sleep mode fix

In AVR, Software on Jan 20, 2010 at 00:01

The Rooms sketch (latest code here) had problems with the sleep mode added about a month ago:

Screen shot 2010-01-17 at 14.05.55.png

The first value is the current consumption in µA.

For some reason or other, the node would stop working and enter a permanent-on mode, drawing over 7 mA and draining the battery in a matter of days. Not good.

It seems to be related to the way the power down mode was implemented. To get absolutely rock bottom power draw, I was using the RF12′s watchdog timer. The ATmega watchdog time draws slightly more current and isn’t quite as configurable.

I’ve now reverted to using the ATmega watchdog anyway. Here is the modified logic:

Screen shot 2010-01-18 at 12.09.39.png

The watchdog is set to interrupt every 16 milliseconds, constantly. When the node is powered down, this will wake it up again. What the new loseSomeTime() code does, is simply to power down a couple of times, until the target delay time has been reached. There is some inaccuracy in these timings since the watchdog timer is free-running, but this should not matter too much when waiting for a second or so.

The new code has been running fine for over a day on six nodes. Here’s a sample from my power tracker:

Screen shot 2010-01-19 at 16.56.22.png

That’s 110 µA right now, 265 µA in the last minute, and 230 µA in the last hour.

At around 250 µA average, the power consumption is a bit higher than before, but my main concern is first to get the nodes running reliably. Even @ 250 µA, the AA batteries should last several months.

The average power down current draw is 110 µA/sec, 40 µA of which is due to the PIR sensor. The total current draw while transmitting is around 29 mA – during reception it’s about half, i.e. 14 mA. Still, due to the very brief on-times, this current consumption averages to only about 400 µA during 1 second for a normal send + ack sequence. Under optimal RF conditions, the long-term average consumption of a node will be under 150 µA. I’m confident that further optimizations could reduce this to well under 100 µA.

But there is one known flaw, which can be observed to happen once in a while: the nodes always wait for an ack in full-power mode, i.e. with the receiver on. This will normally be within milliseconds, but if the connection is flakey or if the central node is unresponsive, then nodes can spend a great deal of time in full-power mode. This needs to be fixed one day.

I’ve started re-flashing all the room nodes and replacing their dead batteries, here at Jee Labs – let’s see how it goes this time around.

Power tracker – software

In AVR, Software on Dec 22, 2009 at 00:01

Yesterday’s post described a small circuit to track power consumption of JeeNodes to help optimize sketches for minimal power consumption.

Let’s put that circuit to use, with a bit of software to measure actual power consumption. The basic idea is to continuously measure current and then integrate these measurements to determine the sum of all power consumption intervals, regardless of levels.

The reason for this is that we’re not really interested in current draw but in the amount of charge consumed by the JeeNode. As far as the battery is concerned, drawing 1 mA for 1 hour is the same as drawing 100 µA for 10 hours (in the ideal case, anyway). The fancy way to say this is that we need to measure Coulombs, not Amps. Or rather micro-Coulombs, i.e. µC. That’s really easy once you realize that 1 µA is the same as 1 µC per second. Or to put it differently again: 1 mAh = 3600 mC. So a 1000 mAh battery is really nothing but a 3600 C charge.

Ok, back to the problem at hand: measuring average current draw per second.

Here is a simple sketch which does all the auto-ranging and integration:

Screen shot 2009-12-19 at 19.34.25.png

It reports averaged power drain in µA/sec (the second value is the number of samples per second). The 10% correction which I had to apply in my setup could be due to a number of factors – most likely it’s due to resistor tolerances (they are all 5%).

Here’s an interesting case with the latest rooms node:

Screen shot 2009-12-19 at 20.01.21.png

As you can see, the baseline power drain is a fantastically low 56 µA/sec in this case, but once or twice a minute it goes up to 14 mA/sec for several seconds. Not sure what’s going in here – need to investigate (now that I can!).

It would be nice to automatically detect the baseline, i.e. the average low-level sleep consumption, and things like the peak current and the percentage of the total consumption caused by such peaks. Extending the software to handle this is more work.

With slightly more elaborate software, it will be possible to place the power measurement plug between the measuring JeeNode and the JeeNode under test, and then leave it alone. A 1-day or 1-week average should give an excellent estimate of battery lifetimes.

Power consumption tracker

In Hardware on Dec 21, 2009 at 00:01

After the recent battery life estimation and refinement posts, I wanted to create a more permanent and more automated setup for monitoring the total power consumption of JeeNodes. I expect to be repeating these power usage optimizations regularly, with new sketches.

Here’s the idea. A little interface to let one JeeNode (or Arduino, whatever) monitor the power consumption of another. This ought to provide a fairly accurate measurement within a day or so.

First the schematic:

Screen shot 2009-12-19 at 16.27.09.png

This is a “low-side” current meter. In fact there are two of them in series, one with a 60 mA range, the other with a maximum range of about 1 mA. So this setup can measure up to 60 mA with approximately 1 µA resolution at the lower end. These ranges could easily be changed by adjusting the 5 Ω (2x 10 Ω) and 270 Ω resistors.

The low range resistor has a forward-biased diode, which limits the total voltage drop over it to under about 0.6V. This means that the total voltage drop over the measurement circuit will stay under 1V for currents up to 60 mA. With a 5V supply, that leaves about 4V to be supplied to the JeeNode being tested – more than enough headroom for the 3.3v regulator to do its thing.

Note that there is a drawback to low-side current sensing: the “ground” level supplied to the test circuit isn’t really ground. It’s floating “somewhere” above zero, and what’s worse is that the actual level will depend on the amount of current drawn. But in this case it doesn’t really matter, since the test circuit isn’t connected to anything else anyway (we’re doing all this to measure a battery-power wireless system, after all).

Two op-amps are used to amplify the 0 .. 0.3V signals 10 times. A neat trick: the low range op-amp (on the right) nicely compensates for the floating reference level from the high-range resistor by using that as reference for its negative input. So basically, these two op-amps generate two analog voltages in the total range of 0 .. 3.3V. I picked the OPA2340 CMOS op-amps because they can operate at 3.3V and can output rail-to-rail voltages. They also happen to draw very little current.

Here’s a custom-made JeePlug with all the above components:

DSC_0867.jpg DSC_0872.jpg

Note: I don’t know what got into me while building this plug, but the pins on the port connector are all reversed. So I’m forced to plug this thing in the other way around. Doh!

This is only half the story. Tomorrow: the software side of power tracking.

Update – for a very nice current metering setup, see also David Jones’ µCurrent adapter.

Battery life – refinement

In AVR, Hardware, Software on Dec 19, 2009 at 00:01

Yesterday’s post described how to estimate the battery life of a JeeNode running the “rooms” sketch with the SHT11, ELV PIR, and LDR sensors. To summarize:

  • the code started out using 370 µA average current, i.e. roughly 7 months on 3 AA cells
  • of these, 200 µA were caused by the 1-second periodic wakeup “blip”
  • another 120 µA were due to the actual measurements and packets sent every 30 seconds
  • and finally, the remaining 50 µA come from the PIR + JeeNode current draw in sleep mode

Yesterday’s post was also about reducing that 200 µA blip consumption to somewhere around 20 µA.

Today, let’s tackle the other power “hog”: the 300 ms @ 12 mA spike. Here is that pattern again:

b1.png

The high peak at the end is the RF transmission of a packet, followed by a “knee” during which the node is waiting for the ack packet in RF receive mode.

Note that the main power drain is NOT caused by wireless communication!

This period of over 300 milliseconds is when the ATmega is polling the SHT11, waiting for a fresh reading. Twice in fact: once for the temperature and once for the humidity measurement.

So the explanation is very simple: we’re polling and waiting in full-power mode. Quelle horreur!

The fix requires a small modification to the SHT11 driver in the Ports library. Instead of a fixed delay, it needs to be extended to allow using an arbitrary function to waste some time. Here’s the modified code:

Screen shot 2009-12-18 at 01.00.53.png

A new second arg has been added, specifying an optional function to call instead of delay(). The code remains backward compatible, because this argument defaults to zero in Ports.h:

Screen shot 2009-12-18 at 01.02.45.png

So now all we need to do is define a delay function which goes into real power down mode for a little while:

Screen shot 2009-12-18 at 01.52.23.png

… and then adjust the two measurement calls to use this function:

Screen shot 2009-12-18 at 01.05.08.png

Does all this make a difference? You betcha:

b2.png

That’s a substantial fraction of a second in which the ATmega will draw considerably less than 12 mA. How much less? Let’s expand the vertical scale:

b3.png

Most of the time, the voltage is around 50 mV, i.e. 1 mA over 47 Ω. That’s the SHT11 current draw while active. There are two measurements – so everything behaves exactly as expected!

A couple of quick wake-ups remain, to check whether the SH11 measurement is ready. And so does the wireless TX/RX peak, of course. Here is an isolated snapshot of that RF activity (200 mV/div and 4 ms/div):

b4.png

Approximate current draw: TX = 35 mA, RX = 20 mA. Total time is about 10 ms.

Looks like we’ve reduced the power consumption of this once-per-30-second spike by perhaps 90%. As a result, the node now consumes about 20 (blip) + 20 (spike) + 50 (sleep) = 90 µA on average. Even with much smaller 800 mAh AAA cells, the battery life of these low-power nodes should now be over a year.

There are several conclusions to take home from this story, IMO:

  1. The biggest drain determines battery lifetimes.
  2. Measuring actual current profiles always beats guessing.
  3. A simple USB storage scope is plenty to perform such measurements.

If I had followed my hunches, I’d no doubt have spent all my time on getting the current draw of packet transmissions down – but as these experiments show, their effect on power drain is minimal.

There are more optimizations one could explore. There always are. But the gains will be limited, given that the ELV PIR sensor consumes 30..40 µA, and that it needs to be on at all times anyway, to be able to detect motion.

Sooo… end of story – for now :)

All source changes checked in. The entire rooms sketch still compiles to under 8 Kb of code.

Battery life estimation

In AVR, Hardware, Software on Dec 18, 2009 at 00:01

To get an indication of battery power drain, I measured the voltage drop over a 47 Ω resistor in series with the 5V supply, using a JeeNode with Rooms Board and the latest version of the “rooms” sketch.

Here’s the blip I see, once a second (100 mV/div and 20 msec/div):

on-time-1.png

That’s a 40 msec pulse of about 5 mA, in other words: 5 mA during 4 % of the time, which averages out to around 200 µA current draw continuously. Not bad, but not stellar either: it’s 4 times the sleep mode current.

Every once in a while, a much longer and bigger spike shows up:

occasional-peak.png

Which looks like roughly 350 msec @ 12 mA.

Let’s assume the big one is a real transmission. It sort of fits: the spike at the end is a brief transmission at ≈ 35 mA total, followed by a 20-ish mA period of reception (waiting for the ack to come in).

Very roughly speaking, the area of that extra spike at the end is about the same as the 5-to-10 mA step at the start of this period. So as an estimate, we’re consuming about 12 mA during 350 msec – let’s round down to 300 msec.

Let’s also assume these bigger current patterns happen every 30 seconds, when the node is reporting changed values (everything other than motion gets reported at that rate in the latest “rooms” sketch).

So 1% of the time (300 ms every 30s), power consumption is 12 mA. This averages out to 120 µA continuous current consumption.

In other words: a JeeNode running this latest rooms sketch with the SHT11 and ELV-PIR sensors, is consuming roughly 200 (blip) + 120 (spike) + 50 (sleep) = 370 µA.

Using a 2000 mAH 3-cell AA battery, this should lead to a 225-day lifetime – over 7 months.

Can we do better? Sure.

It’s basically a matter of figuring out what’s going on during those 40 and 350 msecs, respectively. Interestingly, more can be gained by improving non-transmitting “blips” than twice-a-minute high-power RF packet exchanges.

Do those 40 ms @ 5 mA every second look a bit suspicious? Yep – that’s the “idling” power level. What happens is that I was a bit too pessimistic in the time spent in sleep mode. This was the code:

Screen shot 2009-12-17 at 00.51.26.png

Looks like this is about 40 ms off, and so the code ends up waiting for the 1 sec timer to expire… in idle mode!

Let’s change this to end up closer to the desired time:

Screen shot 2009-12-17 at 02.59.16.png

Here’s the new blip (different scales):

better-blips.png

We’re down from 40 to 10 msec blips – tada!

That translates to an average 50 µA current draw from the blips, bringing the total down to 220 µA. Which translates to a 375-day battery life: over a year!

Now we’re cookin’ … but could we do even better? Sure.

Note that only the 2 ms spike at the end of the 5 mA blip is the actual active period. The time up to then we’re just waiting in idle mode – and wasting power.

We could shorten the sleep timer to 994 ms, since we don’t care whether readings are taken exactly 1 second apart. Now the RFM12B-based watchdog timer will wake us up just 2 ms short of the target time. And sure enough, the 5 mA blip is down to around 3 ms – shown here with an even further expanded time scale:

final-blip.png

But that’s silly. We’re tweaking a millisecond timer, and we’re not even interested in an “exact” 1000 ms cycle in the first place! It makes much more sense to just use the RFM12B wakeup timer to get us close to that 1 second cycle, and then immediately take a measurement. Here’s the corresponding code change in periodicSleep():

Screen shot 2009-12-17 at 02.35.36.png

Does this make a difference? Definitely:

best-blip.png

One final remark: the above battery lifetime estimates do not take into account the increased power consumption when motion is detected and more packets are sent (up to once every 5 seconds). On the plus side, when no light / temperature / humidity changes happen, the packet frequency will drop further, to once-a-minute.

The above changes have been checked into the source code repository.

Update – I just found out that the DSO-2090 scope has a high-pass low-pass filter option:

smooth.png

Sure wish I’d found out about that feature sooner… it’s so much more informative: the initial ramp is probably the clock starting up, and the little peak could well be the LDR pull-up during ADC conversion!

Rooms sketch, reloaded

In AVR, Hardware, Software on Dec 16, 2009 at 00:01

With the new easy transmission mechanism and the low power logic implemented, it’s time to revisit the “rooms” sketch, which I use for all my house monitoring nodes based on the Room Board.

I’ve wrapped the code used in POF 71 a bit further, with these two extra functions:

Screen shot 2009-12-15 at 22.25.44.png

With this, the main loop becomes very simple – even though it will now power down the RFM12B and the ATmega328 whenever there’s nothing to do for a while:

Screen shot 2009-12-15 at 22.25.57.png

The lowPower() and loseSomeTime() code is still the same as in POF 71 – this is where all the hardware low-power trickery really takes place:

Screen shot 2009-12-15 at 22.24.57.png

Note that these need an “#include <avr/sleep.h>” at the top of the sketch to compile properly.

I’ve also disabled the pull-up resistor on the LDR while not measuring its value. This drops power consumption by over 100 µA, depending on actual light levels.

A quick measurement indicates that power consumption went down from 20 mA to some 50 µA (much of that is probably the PIR sensor). These are only approximate figures, because my simplistic multi-meter setup isn’t really measuring the charge (i.e. integrated current draw), just the current draw while in sleep mode.

These changes have been checked into the repository as “rooms.pde”.

This code isn’t perfect, but since “perfection is the enemy of done” I’ll go with it anyway, for now. One difference with the original rooms sketch is that the motion sensor is not read out as often so brief motion events might be missed. Another issue with this code is that if the central node is off, a lot of re-transmissions will take place – without the node going into sleep mode in between! IOW, a missing or broken central node will cause all remote nodes to drain their batteries much faster than when things are properly ack’ed all the time. Oh well, let’s assume this is a perfect world for now.

With these levels of power consumption, it’s finally possible to run room nodes on battery power. I’ll use some 3x AAA packs, to see what sort of lifetime this leads to – hopefully at least a couple of months.

Will report on this weblog when the batteries run out … don’t hold your breath for it ;)

Update – I just fixed a power-down race condition, so this code really goes back to sleep at all times.

Low power mode again

In AVR, Software on Dec 9, 2009 at 00:01

After yesterday’s Wireless Light Sensor was announced, I wanted to push a bit more on the low-power front.

The POF described two simple tricks to get the power consumption from 19 to 3 mA, roughly. It turns out that a single extra step will get the idle consumption down to some 20 µA. That doesn’t mean we’re getting a 15-fold battery lifetime increase, because I’m measuring the current at idle time but not accounting for the brief periods of high-current activity which also occur. But it’s a major reduction in power consumption.

Here’s how … but this requires going a bit deeper into some low-level AVR/ATmega chip features.

First, here are some utility functions we’re going to need:

Screen shot 2009-12-08 at 10.04.31.png

The lowPower() routine disables the ADC subsystem and then enters the specified low-power mode in the ATmega. Once it resumes, the ADC subsystem setup will be restored to its previous state.

The loseSomeTime() does just what is says on the box: go into comatose mode for a more-or-less controlled amount of time. The trick is to activate the RFM12B watchdog just before passing out. This leads to larger power savings than we would have with the ATmega’s watchdog, btw – and it’s easier to implement.

The complication is that we risk losing all track of time. It’s a bit hard for an ATmega to count heartbeats when its heart has stopped beating – not only are there no beats, it’s also stripped of its counting abilities while in coma…

So instead, we estimate just how long we’ve been away from the watchdog time chosen for the RFM12B, and correct the milliseconds timer built into the Arduino. That’s what the “timer0_millis” stuff above is about. It will not be quite as accurate as before, but that’s probably acceptable for a sensor node like this one.

The last issue is that we need an indication about how long we can go comatose. I’ve added a “remaining()” member to the MilliTimer class to obtain this information.

Now, all the pieces are in place to change the code in the Wireless Light Sensor from this:

Screen shot 2009-12-08 at 10.14.23.png

.. to this:

Screen shot 2009-12-08 at 10.15.53.png

So there you have it. Most of the time between each measurement once a second, the node will now go into a very low-power mode of around 20 µA. My current measurement tools are inadequate to measure exactly what amount of charge is being consumed, which is what this is really about. So accurate battery lifetime calculations are not yet possible – but I expect it to be in the order of months now.

I’ve updated the Wireless Light sensor POF to point to this post and include this trick.

Ligthy power save

In AVR, Software on Jul 5, 2009 at 00:01

Getting the power consumption down of yesterday’s “Lighty” example turns out to be quite a challenge.

One thing to do is to separate out the logic for enabling the different sensors, and extending it to also support disabling all of them:

Picture 3.png

Powering down completely works best when all internal peripherals are also turned off, as implemented in the following code:

Picture 4.png

Now the trick is to enable some interrupt source to take us out of this deep sleep phase again. This could be the ATmega watchdog, but the radio watchdog uses even less power, so here’s how to stay off for about 4 seconds:

Picture 5.png

So far so good. This disables all power consuming sensors and internal circuits, preps the radio to wake us up in 4 seconds, powers off, and then reverses the whole process.

Bug there is a bug in all this – somewhere… From some earlier experiments, I would have expected to see a power draw of a few microAmps with this code. But for some reason, it never drops below 2.7 mA, i.e. still “burning” 1/10th of full power!

I haven’t been able to figure out yet where these milliamps are going :(

For the sake of argument, let’s assume this works properly. Then the next problem will come up, which is that measuring and sending packets every 4 seconds drains more power than I’d like to. It takes several milliseconds to measure all readings and send out a packet. But who needs readings every 4 seconds?

So the solution to this is to just sleep a bit longer, using the 4-sec wakeups to quickly read-out some sensors, and calculate their averages. Here’s is the final loop of the power-saving “LightySave” sketch:

Picture 8.png

This will integrate readings for 75x 4 seconds, i.e. 5 minutes, and then send out a single packet. Note how the power-hungry radio module is only enabled at the very last moment. All we have to do is make sure it’s ready to send, then send one packet, then wait again until the send is complete.

Then the loop restarts, sleeping in low-power mode, etc.

Only issue is to find out where the 2.6 mA are going! I’ll try to figure this out, and will post here once fixed …

New RF12 sleep support

In AVR, Software on May 23, 2009 at 00:01

The RF12 driver has been extended to support power down as well as wake-up.

This example uses the RFM12B wake-up timer to generate an interrupt in about 1 second, then powers down, then leaves the radio off once power is back up:

Picture 3.png

That last call is important, because otherwise if the system happens to power up due to some other trigger, then the wake-up interrupt may happen later and cause problems. This way, regardless of why the system came back up, we make sure that the RFM12B wake-up interrupt stays off. The radio is still off at this point.

The argument to rf12_sleep() is a time value, in units of 32 ms. The maximum value is 127, i.e. 4 about seconds between wake-ups. If you need longer sleep times, change the logic to go back to sleep right away until the proper amount of time has elapsed.

To turn the radio back on, use “rf12_sleep(-1)” to start listening to packets again after the next rf12_recvDone() poll. Since the RFM12B consumes a fair amount of power, it’s best to wait with this right until you’re ready to send out a packet.

Here is the new code, which is now included in the updated RF12 driver:

Picture 1.png

The RF12 driver software is available over here or as ZIP, this is an Arduino-compatible library.

Power consumption – more savings

In AVR, Hardware, Software on May 16, 2009 at 00:01

Let’s get that JeeNode power consumption down

The no-savings baseline from two days back was 10 mA, with a few simple measures getting it down to 1.31 mA, i.e. waiting in idle mode with the pre-scaler set to 64 and turning the RFM12B clock off.

It turns out that the ATmega328 is quite a bit more power efficient in that mode, the same sketch consumes 0.67 mA, i.e. half that of an ATmega168. Great – that’s an easy gain. Unfortunately it doesn’t carry over as much to power down mode: 125 µA versus 137 µA. There is still some unexplained power use there – maybe some of the circuits need to be turned off explicitly, or some more output pins floated.

Anyway, the next idea to go beyond 1.31 mA is to use the watchdog timer for idling away in power down mode. The basic code structure will be as follows:

Picture 1.png

Ooh, wait – turns out that there is a simpler way, which doesn’t require changing the main application logic after all. We can let the watchdog generate an interrupt without resetting the system. Here’s the code I ended up with after some experimentation:

Picture 2.png

Note the added dummy watchdog interrupt routine. Without it, the code apparently enters a nasty infinite loop when the watchdog fires, which is hard to get out of – even after a hardware reset.

Usage: 139 µA while waiting – 99% of the time. Great.

The code can actually be streamlined a bit – simply leave the watchdog running to pull the processor out of power down mode once a second:

Picture 4.png

But there’s more. The ADC can be disabled to reduce the power drain even further:

Picture 5.png

Now usage drops to 24 µA while waiting. Cool.

One last change is to disable the brown-out detection, which in turn disables the internal voltage reference. Changing the high fuse from 0xDD to 0xDF drops total power usage to a diminutive 6.8 µA. Perfect.

So there you have it – 1500 times less power usage!

Update – see the discussion in this post for a change which gets this down to 3.7 µA …

Update 2 – changed the low fuse from 0xFF to 0xEE, i.e. 64 µs start-up i.s.o. 1+64 ms (ok for resonator, not ok for a crystal). This will help get the power up duration down once I start looking into it.

Power consumption – subtle bugs

In AVR, Software on May 15, 2009 at 00:01

Yesterday’s code has several bugs:

Picture 2.png

As already mentioned, a delay is needed to let the serial data leave the USART before the pre-scaler change messes up the clock and baudrate. But there are also two other serious problems:

  • the “limit = millis() + …” expression will overflow and fail (after about 49 days)
  • the “millis() == limit” condition can “miss a beat”, leading to an almost-infinite loop

Both bugs can be fixed by carefully rewriting the code:

Picture 1.png

The differences are subtle, but essential. Without it, the loop will get stuck within just a few seconds of starting the sketch. With the above fixes it’ll run properly forever… I think.

Power consumption – baseline

In AVR, Software on May 14, 2009 at 00:01

Ok, first step in lowering JeeNode power consumption is to establish a baseline.

Here is the original code, the first few lines of the loop that is – the rest is the actual sensor readout and calculations, which take about 10 milliseconds:

Picture 1.png

Usage: 9.80 mA (slightly different from yesterday’s post, hooked up to USB from now on).

First change is to make the delay loop explicit:

Picture 2.png

Usage: 10.05 mA – no idea why it’s slightly higher. Anyway 10 mA will be used as baseline – this is the current drawn before any power-saving measures are introduced.

First step: lower power use by putting the processor in idle mode while it’s waiting for the next readout time. Included “avr/sleep.h” and changed the loop to be as follows:

Picture 4.png

Usage: 5.58 mA – it works, cool!

Next idea is to lower the system frequency, but only while waiting – so that readout, processing, and serial I/O remain unaffected:

Picture 5.png

Usage: 1.99 mA – whee! But there is a small gotcha – the system now goes into slow mode before the serial port has finished transmitting. A “delay(3)” at the end (or start!) of the loop is needed to fix this.

For comparison: with just the pre-scaler and no idle mode, usage is 2.15 mA – so the bulk of the savings comes from slowing down the system clock. Idle mode saves roughly 10% at lower frequencies.

One more important saving is possible due to the onboard RFM12B radio module, which powers up with its 10 MHz crystal clock running. Adding a bit more code to access the radio and disable its clock lowers power usage from 1.99 mA to 1.31 mA.

So these three simple measures combined already lead to a 7.5-fold power reduction: “waiting” a bit more carefully and turning off the RFM12B. All without affecting the main application code in any way.

As for the bottom line: putting the processor in power down (from which this code won’t ever wake up) uses 137 µA – and removing the MPU chip brings it to 17 µA. Note that with 140 µA average usage, a JeeNode can run for two years on 3 standard AA batteries.

It ‘s possible to reduce the power consumption from 1.31 mA to the µA range by powering down the processor and using the watchdog timer to wake it up – but that requires another set of changes to code and fuses – stay tuned…

Update – see this more recent post for additional details.

Power consumption

In AVR, Hardware on May 13, 2009 at 00:01

This contraption:

Measuring power draw

… when connected as follows:

Measuring power draw

… makes it easy to measure the supply current, with a BMP085 pressure sensor hooked up in this case:

Measuring power draw

Just under 10 milliamps, as you can see. That’s just the JeeNode running the BMP085 demo at 16 MHz, sending a new reading over the serial port every second. The RF12 module has not been turned on.

If the JeeNode is to be used for a WSN, then it will have to get its power consumption down. Way down, in fact…