SpenceKonde / megaTinyCore

Arduino core for the tinyAVR 0/1/2-series - Ones's digit 2,4,5,7 (pincount, 8,14,20,24), tens digit 0, 1, or 2 (featureset), preceded by flash in kb. Library maintainers: porting help available!
Other
561 stars 146 forks source link

SLEEP_MODE_PWR_DOWN have too much consumption #1142

Open PM04290 opened 1 month ago

PM04290 commented 1 month ago

Hello, I use new ATtinys since few weeks (ATtiny84 before, without problem) and i need to have a minimum consumption in sleep mode. After documention reading, i wrotte the little code below for ATTiny3216 and i have 520µA in sleep mode, too far from AVR datasheet (5µA) I'am on 5Vdc, 1MHz internal, no BOR, no millis()

I found a few rare posts that talk about the problem but none solve my problem; any idea?

// Led ON during 100ms, and power off during 10s
#include "avr/sleep.h"
#define PIN_DEBUG_LED  PIN_PC2
volatile uint16_t sleepCounter = 0;

ISR(RTC_PIT_vect)
{
  RTC.PITINTFLAGS = RTC_PI_bm; // Clear interrupt flag by writing '1' (required)
  sleepCounter++;
}

void timerInit()
{
  while (RTC.STATUS > 0) {}                /* Wait for all register to be synchronized                    */
  RTC.CLKSEL      = RTC_CLKSEL_INT32K_gc;  /* 32.768kHz Internal Ultra-Low-Power Oscillator (OSCULP32K)   */
  RTC.PITINTCTRL  = RTC_PI_bm;             /* PIT Interrupt: enabled                                      */
  RTC.PITCTRLA    = RTC_PERIOD_CYC32768_gc /* RTC Clock Cycles 32768, resulting in 32.768kHz/32768 = 1Hz  */
                    | RTC_PITEN_bm;        /* Enable PIT counter: enabled                                 */
}

void setup() {
  for (uint8_t i = 0; i < 8; i++)
  {
    *((uint8_t *)&PORTA + 0x10 + i) |= 1 << PORT_PULLUPEN_bp;
    *((uint8_t *)&PORTB + 0x10 + i) |= 1 << PORT_PULLUPEN_bp;
  }
  pinMode(PIN_DEBUG_LED, OUTPUT);
  timerInit();
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
}

void loop() {
  digitalWrite(PIN_DEBUG_LED, HIGH);
  delay(100);
  digitalWrite(PIN_DEBUG_LED, LOW);
  powerOff();
}

void powerOff()
{
  ADC0.CTRLA &= ~ADC_ENABLE_bm; // Disable ADC
  sleepCounter = 0;
  do {
    sleep_cpu();
  } while (sleepCounter < 10);

  ADC0.CTRLA |= ADC_ENABLE_bm;  // Enable ADC
}
freemovers commented 1 month ago

A lot of information about the sleep modes can be found here: https://github.com/SpenceKonde/megaTinyCore/blob/master/megaavr/extras/PowerSave.md Since you are using an ATtiny3216 you have to make sure that you disable input buffer and enable the internal pull-ups for pins on PORTC as well. If you want to reduce the power consumption even more, then you should replace the delay(100) with another timer (RTC) and have it sleep for that time period.

PM04290 commented 1 month ago

@SpenceKonde i read somewhere that you plan to investigate for Sleep power saving. some remarks to help you in this way : If hardware have floating input, put them in INPUT_PULLUP have no (signifiant) effect, the only way to stop consumption is to desactivate input PORTA.PIN0CTRL = PORT_ISC_INPUT_DISABLE_gc; Exemple on ATtiny1616 with all pins floating, in power off sleep mode i have 0.1µA BUT, it's imposible to go back with friendly function, like pinMode, when wakeup. if you write a dedicated library for power saving, you may create function to manage pins easly