[solved] attiny13a sleep mode - high current consumption

Hi,

I've an attiny13a (9.6MHz, BOD 2.7V) put to sleep but it draws 20µA (without the LDO). I've connected nothing else but 3.3V power (HT7333). I find this really surprising because my Pro Minis waste 5-6µA while sleeping.
Here's how I put it to sleep:

#include <avr/sleep.h>
#include <util/delay.h>

void setup() {
  DDRB  = 0b000001; // all but PB0 INPUT, want to use PB0 ...
  PORTB = 0b000000; // all LOW
}

void loop() {
sleepNow();
}

void sleepNow() {
  {
//    BODCR |= (1<<BODS)|(1<<BODSE);       //Disable Brown Out Detector Control Register 
    ACSR |= (1<<ACD);   //Analog comparator off
    ACSR = ADMUX = ADCSRA = 0;
  }

  WDTCR |= (1<<WDP3) ;      //Watchdog set for about 4 seconds
  
  // Enable watchdog timer interrupts
  WDTCR |= (1<<WDTIE);
  sei(); // Enable global interrupts 
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_mode();
  sleep_disable();
}

Btw. the BOD-constants are not set (Arduino 1.6.9, MicroCore core by MCUdude) and I could not find the example, I stumbled upon some time ago, how to assign values to registers in C. I would like to define the constants myself BODCR is 0x30.

Thanks & best

The register names are supposed to be supplied by the compiler. He can probably hack in the missing define, but it's curious that it's an issue.

You have the part where you disable the BOD commented out - it's wrong anyway, even if the register defines were in, though, see section 7.5.1 and 7.2 of the datasheet - there's a special sequence you need to use to write to that register.

DrAzzy:
The register names are supposed to be supplied by the compiler.

They are for the t13A...

grep -d BODCR *.h

File avr\iotn13a.h:
#define BODCR _SFR_IO8(0x30)

grep -d BODS *13*.h

File avr\iotn13a.h:
#define BODSE 0
#define BODS 1

The t13 does not have a Brown-Out Detector Control Register. The register at 0x30 is "Reserved".

The board entry is very likely configured for the t13 (not-A).

I made an issue for it.

terraduino, try changing this line to attiny13a, and do the power consumption measurements again. If the power consumption drops, I'll add this fix to the core :slight_smile:

Hi all,

I changed L26 in boards.txt and the constants work. However, I cannot compile anymore avrdude: AVR Part "attiny13a" not found. :wink:

@DrAzzy Thanks, my mistake. I was wrong to rely in the correctness of the original code sample.

I've made some changes, i.e. added BOD, but still 20µA.

#include <avr/sleep.h>
#include <util/delay.h>

#define BODCR _SFR_IO8(0x30)
#define BODSE 0
#define BODS 1


void setup() {
  DDRB  = 0b000001; // all but PB0 INPUT, want to use PB0 ...
  PORTB = 0b000000; // all LOW
}

void loop() {
sleepNow();
}

void sleepNow() {
  {
    ACSR |= (1<<ACD);   //Analog comparator off
    ACSR = ADMUX = ADCSRA = 0;
  }

  WDTCR |= (1<<WDP3) ;      //Watchdog set for about 4 seconds
      
    
  // Enable watchdog timer interrupts
  WDTCR |= (1<<WDTIE);
  sei(); // Enable global interrupts 
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);

  BODCR |= (1<<BODS)|(1<<BODSE);
  BODCR |= (1<<BODS);
  BODCR &= ~(1<<BODSE);
    
  sleep_mode();
  sleep_disable();
}

Did I misunderstand the BOD-instruction?

Thanks for your help & best

If you made the change @hansibull described then this is not needed (and should produce a warning)...

#define BODCR _SFR_IO8(0x30)
#define BODSE 0
#define BODS 1

Are those lines still needed?

  cli();  // No interrupts; timed sequence
  BODCR = (1<<BODS) | (1<<BODSE);
  BODCR = (1<<BODS);
  sei();  // Enable global interrupts or we never wake
  // Sleep now!

terraduino:
Hi all,

I changed L26 in boards.txt and the constants work. However, I cannot compile anymore avrdude: AVR Part "attiny13a" not found. :wink:

If it's getting to where it calls avrdude, it's compiling, but not able to upload.

It needs another entry in the avrdude.conf for the 13a to be able to upload.

I've added a new entry to the avrdude.conf file and edited the boards.txt file. Please give it a try!

EDIT:
It's the classic avrdude.conf related issue. Arduino IDE doen't want to use the custom avrdude.conf file when uploading. I'm on the case..

EDIT2:
Issue fixed! Please give it a go :slight_smile:

#define BODCR _SFR_IO8(0x30)
#define BODSE 0
#define BODS 1

Are those lines still needed?

The latest commit now compiles code for an ATtiny13A, so the code sines above is now included in the iotn13a.h file, and are not needed in the sketch.

The trick was to compile for an ATtiny13A, but upload to an ATtiny13.

Thanks a lot for the update, it does work without the explicit definitions of BODCR and the like.

@CodingBadly Thank you for the code sample, it does work. The current while sleeping now is lower than what my DMM can measure :wink:
Btw. a second #define produces a warning only when the second #define is different from the first.

Best

Thank you for the follow up.

Hi @terraduino , can you post the final code you used for this. I am also trying to reduce the power consumption of ATTiny13A to near zero but I can only get ~ 2.3uA using WDT while ATTiny85 goes down till 0.2 uA while sleep.
I am not an expert on AVRs and hence did not understand the conversation on this thread properly.

Thanks for your help

Hi,

Here is the code I use:

#include <avr/sleep.h>

#ifdef __AVR_ATtiny13__

  #define SLEEP_FOREVER  128
  #define SLEEP_016MS    (period_t)0
  #define SLEEP_125MS    (1<<WDP1) | (1<<WDP0)
  #define SLEEP_250MS    (1<<WDP2)
  #define SLEEP_500MS    (1<<WDP2) | (1<<WDP0)
  #define SLEEP_1SEC     (1<<WDP2) | (1<<WDP1)
  #define SLEEP_2SEC     (1<<WDP2) | (1<<WDP1) | (1<<WDP0)
  #define SLEEP_4SEC     (1<<WDP3)
  #define SLEEP_8SEC     (1<<WDP3) | (1<<WDP0)

#endif /* ifdef __AVR_ATtiny13__ */


  // without that empty declaration, I got some problems with my other code. Maybe you don't need that.
  ISR(WDT_vect) {
  }


  void sleepNow(byte b) {
    {
      ACSR |= (1 << ACD); //Analog comparator off
      ACSR = ADMUX = ADCSRA = 0;
    }

    if (b != SLEEP_FOREVER) {
      WDTCR |= b;    //Watchdog
      // Enable watchdog timer interrupts
      WDTCR |= (1 << WDTIE);
    }
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);

    cli(); // No interrupts; timed sequence
    sei(); // Enable global interrupts or we never wake
    sleep_mode();
    sleep_disable();
  }


  // calling in loop() for example: sleepNow(SLEEP_1SEC);

Give it a try and post back if it works for you too.
Best

Hi @terraduino, I tried your code but I still get a sleep current of 2.3 uA.
The code you posted isnt very different in what it does from what you originally asked here apart form disabling ADC, isnt it? Disabling ADC did not affect current consumption for me. Was there something you were able to do to bring down the consumption?

Typical current consumption of common AVR WDT is about 4uA. 2.3uA is suspicious for ATTiny13A with WDT enabled and 0.2uA unbelievable for ATTiny85.

Well, I cant claim that my DMM is very accurate so if it is showing 4uA as 2.3 uA , it might be possible. But then on the same DMM I am able to get a 0.2 uA on ATTIny85. I tried that when I saw the post by a gentleman here . He also claims that the sleep current is of that order.

I'm sure my DMM isn't the most accurate. Everything below 20uA is "very low" for me :wink:
Btw. the datasheet supports @Smajdalf statement, see Table 18-1 on page 118.

@vks007
Note that most of my Attiny13a are used in combination with reed switch or PIR. Hence, the WDT is disabled and current consumption is lower.

Thanks @terraduino. You may be right on that. Although I haven't been able to get sleep working on my ATiny13A without WDT. I tired several times but maybe I am missing something. Although my current project does require WDT so its okay but do you mind posting a code for t13a without WDT?