Reducing Battery Power Consumption for Digispark ATtiny85

Introduction: Reducing Battery Power Consumption for Digispark ATtiny85

About: Arduino addict

or: Running an Arduino with a 2032 coin cell for 2 years.

Using your Digispark Arduino Board out of the box with an Arduino program it draws 20 mA at 5 volt.

With a 5 volt power bank of 2000 mAh it will only run for 4 days.

Step 1: Reducing Supply Voltage by Using a LiPo Battery

Using a LiPo battery with 3.7 volt as supply your Digispark board draws only 13 mA.

With a battery of 2000 mAh it will run for 6 days.

Step 2: Reduce CPU Clock

If you do not use USB connection, heavy math or fast polling in your program, reduce the clock speed. E.g. the heavy polling infrared receiving library IRMP runs well at 8 MHz.

At 1 MHz your Digispark draws 6 mA. With a battery of 2000 mAh it will run for 14 days.

Step 3: Remove the on Board Power LED and Power Regulator

Disable the power LED by breaking the copper wire that connects the power LED to the diode with a knife or remove / disable the 102 resistor.

Since you are using a LiPo battery now, you can also remove the on board power regulator IC. First lift the outer pins with the help of a solder iron and a pin. Then solder the big connector and remove the regulator. For small regulators, use much solder and heat up all 3 pins together, then remove it.

At 1 MHz and 3.8 volt your Digispark now draws 4.3 mA. With a battery of 2000 mAh it will run for 19 days.

Step 4: Disconnecting the USB D- Pullup Resistor (marked 152) From 5 Volt (VCC) and Connect It to USB V+

This modification is compatible with all1.x versions of the micronucleus bootloader. If you already have a new 2.x bootloader on your board, you must upgrade to one the 2.5 versions with "activePullup" in its name. The easiest way to do this, is to install the new digispark board package and burn the bootloader with the recommended (!!!not the default or aggressive!!!) version.

Break the copper wire on the side of the resistor that points to the ATtiny.
This disables the USB interface and in turn the possibility to program the Digispark board via USB. To enable it again, but still save power, connect the resistor (marked 152) directly to the USB V+ that is easily available at the outer side of the shottky diode.
The diode and its correct sides can be found by using a continuity tester. One side of this diode is connected to pin 8 of the ATtiny (VCC) and Digispark 5V. The other side is connected to the USB V+.
Now the USB pullup resistor is only activated if the Digispark board is connected to USB e.g. during programming.

The latter 2 steps are also documented here.

At 1 MHz and 3.8 volt your Digispark now draws 3 mA. With a battery of 2000 mAh it will run
for 28 days.

Step 5: Use Sleep Instead of Delay()

Instead of long delays you can use power saving CPU sleep. Sleeps can last from 15 milliseconds to 8 seconds in steps of 15, 30, 60, 120, 250, 500 milliseconds and 1, 2, 4, 8 seconds.

Since startup time from sleep is 65 milliseconds with the factory digispark fuse settings, only delays bigger than 80 ms can be replaced by sleep.

During sleep your Digispark draws 27 µA. With a 200 mAh button cell 2032 it will sleep for 10 month.

To be correct, the Digispark must at least wake up every 8 seconds, running for at least 65 milliseconds and drawing around 2 mA current. This leads to an average current of 42 µA and 6 month. In this scenario it makes almost no difference if your program runs for 10 milliseconds (every 8 seconds).

The code for using sleep is:

#include <avr/sleep.h><br>#include <avr/wdt.h><br>volatile uint16_t sNumberOfSleeps = 0;
extern volatile unsigned long millis_timer_millis;

void setup() {
  sleep_enable();
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // deepest sleep mode
  ...
}

void loop(){
...
  sleepWithWatchdog(WDTO_250MS, true); // sleep for 250 ms
...
  sleepWithWatchdog(WDTO_2S, true); // sleep for 2 s
...
}

/*
 * aWatchdogPrescaler can be 0 (15 ms) to 3(120 ms), 4 (250 ms) up to 9 (8000 ms)
 */
uint16_t computeSleepMillis(uint8_t aWatchdogPrescaler) {
    uint16_t tResultMillis = 8000;
    for (uint8_t i = 0; i < (9 - aWatchdogPrescaler); ++i) {
        tResultMillis = (tResultMillis / 2) + 65; // + 65 for the startup time
    }
    return tResultMillis;
}

/*
 * aWatchdogPrescaler (see wdt.h) can be one of
 * WDTO_15MS, 30, 60, 120, 250, WDTO_500MS
 * WDTO_1S to WDTO_8S
 */
void sleepWithWatchdog(uint8_t aWatchdogPrescaler, bool aAdjustMillis) {
    MCUSR = 0; // Clear MCUSR to enable a correct interpretation of MCUSR after reset
    ADCSRA &= ~ADEN; // disable ADC just before sleep -> saves 200 uA
    // use wdt_enable() since it handles that the WDP3 bit is in bit 5 of the WDTCR register
    wdt_enable(aWatchdogPrescaler);
    WDTCR |= _BV(WDIE) | _BV(WDIF); // Watchdog interrupt enable + reset interrupt flag -> needs ISR(WDT_vect)
    sei();         // Enable interrupts
    sleep_cpu();   // The watchdog interrupt will wake us up from sleep
    wdt_disable(); // Because next interrupt will otherwise lead to a reset, since wdt_enable() sets WDE / Watchdog System Reset Enable
    ADCSRA |= ADEN;
    /*
     * Since timer clock may be disabled adjust millis only if not slept in IDLE mode (SM2...0 bits are 000)
     */
    if (aAdjustMillis && (MCUCR & ((_BV(SM1) | _BV(SM0)))) != 0) {
        millis_timer_millis += computeSleepMillis(aWatchdogPrescaler);
    }
}

/*
 * This interrupt wakes up the cpu from sleep
 */
ISR(WDT_vect) {
    sNumberOfSleeps++;
}

Step 6: Modify the Fuses

22 mA of the the 27 mA are drawn by the BOD (BrownOutDetection/undervoltage detection). The BOD can only be disabled by reprogramming the fuses, which can only be done with an ISP programmer. Using this script you can reduce current down to 5.5 µA and also reduce startup time from sleep to 4 milliseconds.

5 of the remaining 5.5 µA are drawn by the active watchdog counter. If you can use external resets for wake up, current consumpion can go down to the 0.3 µA as stated in the datasheet.

If you are not able to reach this value, the reason can be, that the reverse current of the schottky diode between VCC and the pullup is too high. Keep in mind that a 12 MOhm resistor also draws 0.3 µA at 3.7 volt.

This results in an average current consumption of 9 µA (2.5 years with a 200 mAh button cell 2032) if you e.g. process data every 8 seconds for 3 milliseconds like here.

Step 7: Further Information

Battery Powered Contest

Participated in the
Battery Powered Contest

Be the First to Share

    Recommendations

    • Halloween Contest

      Halloween Contest
    • Unusual Uses Contest

      Unusual Uses Contest
    • Sewing Challenge

      Sewing Challenge

    Comments