Phipps Electronics

Order within the next 

FREE SHIPPING OVER $199

50,000+ ORDERS

WORLDWIDE SHIPPING

SSL SECURED

ATtiny85 Sleep Modes Tutorial – Save More Power

Contents

Continue from where you left on the ATtiny85 sleep modes tutorial to be able to save more power.

Introduction

Last time, Basic Coding taught you how to code for the ATtiny85 sleep modes. However, you may have observed you were only having minimal power savings. With this, you should learn how to optimize your power saving setup. You’ll learn this here in this blog.

Why You're not Saving Enough Power

There are several factors you have to consider why you’re not saving enough power during sleep mode and they are listed below.

  1. You’re not powering down unused peripherals or blocks on your MCU.
  2. You’ve failed to disable unused clock sources to peripherals especially on Idle mode.
  3. You’re wasting power on unnecessary I/O port functions.

Disable or Power Down Unused Peripherals or Blocks

You should be able to power down peripherals that you don’t use during sleep, such as the one’s below:

ADC—You can easily power off the ADC using the library and statement below. Note that the ADC is enabled by default and can still be enabled even during power down.

				
					#include <avr/io.h>

    // Turn OFF ADC to save power
    ADCSRA &= ~(1 << ADEN);

				
			

Comparator – Disable the Comparator through the library and statement below if it is enabled.

				
					#include <avr/io.h>

// Disable the analog comparator by setting the ACD bit in ACSR
ACSR |= (1 << ACD);
				
			

3. BOD or Brown-out Detect Circuit. – The brown-out detect circuit can be disabled through the option fuses. You may use AVRDUDESS for this. Some revisions of ATtiny85 (version C) can have their BOD disabled by software through assembly routines. You can search for a Lowpower library for this.

4. Internal Voltage Reference – This block can be disabled by disabling the ADC, Comparator, and BOD circuit.

5. Watchdog Timer—If enabled, the watchdog timer can be disabled in code through the library and statements below. You can also disable it through the option fuses.

				
					#include <avr/wdt.h>

// Disable the watchdog timer
wdt_disable();
				
			

Disable Clocks to Unused Peripherals

You may disable clocks on unused peripherals by utilizing the Power Reduction Register (PRR). You can disable clocks to Timer0/1, the USI, and ADC peripherals by writing a one to their corresponding PRR bit register. Note that the ADC should be disabled before shutting it down. Disabling clocks to peripherals is particularly useful on Idle sleep and active modes. You usually don’t need to use PRR in power down mode since the oscillator is alrady stpped in this mode.

ATtiny85 Sleep Mode PRR Register

Don't Waste Power on your Ports

Don’t waste precious power on these critical lines, be they analog or digital ports. Most importantly, and obviously, don’t drive resistive loads during sleep, as this will incur additional current.

ATtiny85 Sleep Mode Don't Drive resistive loads

On input ports, some digital input ports can have their input buffers still turned on on certain sleep mode setups. With this, it’s important for that input to have a defined value and not keep it floating. Not doing so can increase your circuit’s overall current. Put a pull-up resistor or activate an internal pull-up for this.

You also can’t ignore the input analog ports when using the ADC since some ports are multiplexed with digital pins. Because of this, it’s better to forcefully disable the digital input buffers on that port. Having an undetermined analog voltage on that pin can result in additional current because of the digital input buffer. Disable that digital buffer using the Digital Input Disable Register (DIDR0).

ATtiny85 Sleep Mode DIDR0 register
ATtiny85 Sleep Mode Tutorial Disable Digital Input Buffer DIDR0

Testing with Optimized Power Savings Setup

Wake Up with User Intervention (Button Press)

Last time, you tried waking up your MCU by pressing a button. However, power savings can only go up to 300uA. Why? It’s because the ADC is still enabled. Fortunately, the other peripherals (such as the comparator) and some fuses (such as the Watchdog and BOD) are not enabled by default. Below is an improved and optimized version of the code.

				
					#include <avr/sleep.h>
#include <PinChangeInterrupt.h>


#define BUZZER PB3
#define BUTTON PB4


void setup() {
  // put your setup code here, to run once:
  pinMode(BUTTON, INPUT_PULLUP);
  pinMode(BUZZER, OUTPUT);

  // Turn OFF ADC to save power
  ADCSRA &= ~(1 << ADEN);


  // Sleep Mode
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);

  // Set Change on Interrupt Pin
  attachPCINT(digitalPinToPinChangeInterrupt(BUTTON), PinChangeDet, FALLING);

}

void loop() {
  // put your main code here, to run repeatedly:


  // Enable Sleep
  sleep_enable();

  // Sleep upon startup Zzzz..
  sleep_cpu();

  // Unsleep here... must wake-up on pin change interrupt
  sleep_disable();

  // Door Melody Chime
  chime();

}

void PinChangeDet(void) {
  // do nothing... must wake up the MCU
}

void chime(void)
{
  byte i;
  for(i=0;i<10;i++)
  {
    digitalWrite(BUZZER, HIGH);
    delay(100);
    digitalWrite(BUZZER, LOW);
    delay(100);
  }
}


				
			

With this code, you can go down to almost a fraction of a micro ampere. With proper setup (such as a lower supply voltage – 3.0V and lower oscillator value – 1 MHz), you should ideally be able to go down up to 0.2uA.

Periodic Wake Up Using a Watchdog Timer

The same goes for the periodic wakeup using the watchdog timer. However, note that the watchdog timer incurs a small amount of current that can add to the power down current.

				
					#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/wdt.h>

#define LED PB3

void setup() {

  pinMode(LED, OUTPUT);

    // Set Watchdog Timer to trigger every 1 second
    WDTCR |= (1 << WDCE) | (1 << WDE); // Enable Watchdog Timer configuration mode
    WDTCR = (1 << WDP2) | (1 << WDP1) | (1 << WDP0); // Set timeout to 1 second
    WDTCR |= (1 << WDIE); // Enable Watchdog Timer interrupt

    sei(); // Enable global interrupts

    // ADC is enabled by default
    // Turn OFF ADC to save power
    ADCSRA &= ~(1 << ADEN); 

    // Set the sleep mode to power-down
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);

}

ISR(WDT_vect) {
    // Watchdog Timer interrupt service routine (ISR)
    // This code will run every time the Watchdog Timer triggers
  
    // Turn ON LED
    PORTB ^= (1 << PB3);
    
}

void loop() {

    // Put the MCU into sleep mode
    sleep_enable();
    sleep_cpu(); // Enter sleep mode

    // The MCU will continue here after waking up
    sleep_disable(); // Disable sleep mode
  
}

				
			

With this code, you can go down up to approximately 6uA, considering that the Watchdog timer is running during power down mode. You’ll see this reading when the scale is brought down to 50uA scale max from the video below.

Hope you’ve learned a lot on this ATtiny85 Sleep Mode Tutorial 🙂

SUBSCRIBE FOR NEW POST ALERTS

Subscribe to be the first to know when we publish a new article!
List Subscriptions(Required)

POPULAR POSTS

Scroll to Top