1

I want to use an ATtiny as data logger for the opening and closing of a door/window. For that I am using a reed-switch. Since I want to run it from a 3V coin battery, long term power consumption is crucial. Therefore the ATtiny (currently 13A) is in system down mode most time and is only listening to Pin-Change-Interrupts. Depending on the state of the reed-switch the power consumption differs in an order of magnitude.

  • switch open: 0.1µA
  • switch closed: 74.5µA
  • my Multimeter has a tolerance of ±0.1µA

This is a difference of an order of magnitude. But it is plausible as the datasheet of the ATtiny13A states in chapter 10 that a GPIO pin can only be pulled up and is otherwise dangling. The pull-up resistor is somewhere between 20k and 50k as stated in chapter 18.2.

So in my setup the pin is pulled up and the reed-switch is grounded.

How can I reduce the power consumption in the case where the switch is closed?

Alternatively: Can I somehow revert the state of the switch, as windows and doors are closed most of the time?

The MCU is running with the 128kHz internal Clock with CKDIV8 so practically running @ 16kHz.

The minimum viable code:

/*
  3V0               SW0
   |     |     |     |
 -----------------------
 |                     |
 |                     |
 |      ATtiny13A      |
 |                     |
 |                     |
 -----------------------
   |     |     |     |
               TX   GND
 */

#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <iso646.h>
#include <stdbool.h>
#include <util/delay.h>


#define BIT_SET( PORT, BIT_FIELD ) PORT |=  BIT_FIELD
#define BIT_CLR( PORT, BIT_FIELD ) PORT &= ~BIT_FIELD

#define TX_PIN          PB4
#define SW0_PIN         PB0
#define INT0_MASK       PCINT0


// MARK: - POWER

static void power_down(void) {
    BIT_SET(GIFR, _BV(PCIF));       // Clear interrupt signal
    BIT_SET(GIMSK, _BV(PCIE));      // Pin Change Interrupt Enabled
    sleep_enable();
    sleep_cpu();                    // Enter sleep mode
    sleep_disable();
    BIT_CLR(GIMSK, _BV(PCIE));      // Pin Change Interrupt Disabled
}



ISR(PCINT0_vect) {}



// MARK: - Setup

static void setup(void) {
    cli();

    // Set up output pins
    DDRB = _BV(TX_PIN);
    BIT_CLR(PORTB, _BV(TX_PIN));

    BIT_SET(PORTB, _BV(SW0_PIN));        // pull up interrupt pins
    BIT_SET(PCMSK, _BV(INT0_MASK));   // set PCINT0 to trigger interrupt
    BIT_SET(GIFR, _BV(PCIF));       // Clear interrupt signal
    BIT_SET(GIMSK, _BV(PCIE));      // Pin Change Interrupt Enabled
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);

    sei();
}



static void loop() {
    BIT_SET(PORTB, _BV(TX_PIN));
    _delay_ms(1);
    BIT_CLR(PORTB, _BV(TX_PIN));

    power_down();
}



int main(void) {
    setup();

    while (true) {
        loop();
    }
}
  • To be honest, your figures sound far too high. See ATtiny85: Power consumption vs clock speed You should be able to get down to 200 nA - please post your code and schematic. – Nick Gammon Jan 31 '17 at 10:05
  • 1
    Once the switch is closed, set the pin to INPUT. Once in a while, revert to INPUT_PULLUP and, if still closed, go back to INPUT to save battery. You can use the watchdog as a low-power timer for this periodic polling. – Edgar Bonet Jan 31 '17 at 10:35
  • 75µA at 3V means the pull-up resistor is 40k. Which is pretty much what's specified in the datasheet. You could switch to a NC reed-switch. So you pin will only be pulled LOW when the door is open, not closed. Depending on how long the door can be open, this could still be a less than ideal solution. – Gerben Jan 31 '17 at 14:14
  • @NickGammon: you are right. I had the WDT running which draws 5µA. – Kwasmich Jan 31 '17 at 21:50
1

I'm tempted to suggest two reed switches (one NO and the other NC). Then depending on the window state you change to use the switch which gives you the lowest drain (you could use a spare couple of pins to activate one or the other).

Failing that, you can just sleep when the switch is open (the low-power condition) and if it is closed use the watchdog timer to check it from time to time (in other words, drop the power to the switch while asleep). The WDT only uses around 5 µA so that isn't too bad (the coin battery probably self-discharges at about that rate anyway). That would be a lot better than a constant drain of around 70 µA.

I've got an ATtiny85 sitting in my hallway flashing an LED every couple of seconds. I can't recall when I replaced the battery, possibly once since I made it two years ago.

  • This is a brilliant idea. I didn't even know there are different types of reed switches. And there are also 3 pin ones wich are NC and NO at once. I'll try that out. – Kwasmich Feb 1 '17 at 19:43
2

The additional 80uA drain is almost certainly coming from the pull-up resistor being shunted to ground though the reed switch.

https://www.wolframalpha.com/input/?i=(3+volts)+%2F(50k+ohm)+in+uA

As suggested by @Edgar Bonet, one way to greatly reduce this drain is to disable the pull-up immediately when you wake from the pin going low. At this point it is possible for the pin to stay low even if the switch is no longer grounding the pin, so you need to periodically check it using a watchdog.

  1. Wake from pin going low pin change interrupt
  2. Disable pull-up (stops current flowing though resistor)
  3. Do your logging operation.
  4. Enable a watchdog wake up
  5. Go back to sleep.

At this point you can wake either from (1) a watchdog or (2) pin change if the pin goes high again.

If you wake from a pin change...

  1. re-enable the pull-up
  2. disable the watchdog
  3. go back to sleep

If you wake from the watchdog...

  1. re-enable the pull-up.
  2. if the pin is high now, disable the watchdog and go back to sleep.
  3. if the pin is low, disable the pull-up and leave the watchdog running and go back to sleep.

The watchdog timer on this part should only use single digits of uA while running, and it should only need to be running while the switch is grounding the pin. You can set the watchdog timeout to be quite long- on the order of seconds even, to reduce the frequency you wake to check with the pull-up (and therefore the net power used, at the cost of latency for detecting pin changes). The main downside to this strategy is that you can miss activations that happen inbetween your watchdog wake-ups, so for example if the pin goes low and then you set the watchdog for 8 seconds, and then the pin changes high and then low again during the next 8 seconds, it is possible (but not assured) that you could miss the second event, so set the watchdog timeout to be short enough that you will not miss consecutive events that you care about (you might not care if the door is opened twice in the same minute anyway).

Also, as noted by the famous @nick gammon, you might be able to get lower than 5uA when sleeping without the watchdog. Check to make sure you are disabling everything in the power register and that all unused pins are in input mode (these will be disabled when sleeping as long as there is not a pin change interrupt on them). There are lots of googleable articles on minimizing ATTINY power during sleep.

You also mentioned that your dominant case is that the switch is closed rather than opened. Since this is the higher-power case with the current switch consider using a normally open switch rather than normally closed one if possible.

Finally, if you just want simplicity and you only care about events of a minimum duration (saym then door much be open for at least 1/2 second to be noticed), then you can skip the pin change interrupt completely and only use an always-running watchdog to wake periodically and very quickly enable the pull-up and check for the desired pin state, and then disable the pull-up and go back to sleep. You should be able to do this in less than a dozen cycles so the net power usage should be almost as low as the watchdog timer drain by itself.

  • or connect the switch to the high side and use an external pull-down resistor how would this help? If the switch is closed most of the time, there will be a current coming from vcc, though the switch, through the pull-down to ground. It's the same as the other solution, except that you swapped the resistor and switch. Or am I missing something. – Gerben Jan 31 '17 at 19:12
  • @Gerben True, true. Mixed up reasoning fixed now. Thanks! – bigjosh Jan 31 '17 at 19:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.