attiny45 on sleep mode.. any ideas??

Hey guys!
I've been trying to learn how to use sleep mode on a attiny45 lately. I've managed to find a sketch that works and therefore I can upload it to my tiny45 without any error! Problem is I thought this was supposed to make the chip wake up and turn the LED on.. why is that it doesn't work? I think I need explainations on how all of this works, I've done my research and still cant figure out what is the purpose/nature of an interrupt.. If someone knows the meaning of that code, explain it to me please!
Thanks for your help!

#include <avr/wdt.h> //watch dog timer
#include <avr/sleep.h>
#include <avr/interrupt.h>

#define _BV(BIT)  (1<<BIT)
#define LEDPIN 0

void setup() {
  if(MCUSR & _BV(WDRF)){                 // If a reset was caused by the Watchdog Timer...
      MCUSR &= ~_BV(WDRF);               // Clear the WDT reset flag
      WDTCR |= (_BV(WDCE) | _BV(WDE));   // Enable the WD Change Bit
      WDTCR = 0x00;                      // Disable the WDT
  }

  cli();                                 // Disable the Interrupts

                                         // Set up Watch Dog Timer for Inactivity
  WDTCR |= (_BV(WDCE) | _BV(WDE));       // Enable the WD Change Bit
  WDTCR =   _BV(WDIE) |                  // Enable WDT Interrupt
            _BV(WDP2) | _BV(WDP1);       // Set Timeout to ~1 seconds

  sei();                                  // Enable the Interrupts

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);    // Set Sleep Mode: Power Down
  sleep_enable();                         // Enable Sleep Mode
}



void loop() {
  for(;;) {
    if (MCUCR & _BV(SE)){            // If Sleep is    Enabled...
      cli();                         // Disable Interrupts
      sleep_bod_disable();           // Disable BOD
      sei();                         // Enable Interrupts
      sleep_cpu();                   // Go to Sleep
    }
  }  
}

ISR(WDTCR_vect) {
  sleep_disable();               // Disable Sleep on Wakeup
  digitalWrite(LEDPIN, HIGH);    // turn on the led to verify the watchdog timer is working
  do {} while(2 == 2);           //keep the LED on forever so there's no mistaking WDT is working
  sleep_enable();                // Enable Sleep Mode
}

This code is very special and it depends on the used ATtiny core you use in your IDE if it works as expected. Some cores already disable the WDT and reset the registers before they call the setup routine so the intended effect will not take place.

What reason should that code have other than to play with registers in a way that is not expected to work in a standard Arduino environment?

It is the only code I've found that works with the attiny45.. Actually i'm not even sure it works, but it's the only one that can compile! I dont know what it does, cause most of the terms are too complicated for me.. I cant find the resources online to learn all the concepts in this code efficiently.. Is there a way to do it? or an easier way to put attinies on sleep mode? would it help to try different attiny cores?

Thanks!

2 questions:

  1. how can the code go further than this line
  do {} while(2 == 2);           //keep the LED on forever so there's no mistaking WDT is working
  1. whch pin is pin0? never used,,

You are right, so the code stays stuck on an infinite do loop.. then could I take it off? if I try to, the compiler bugs and show

avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x03
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x03

etc. until it fails.. Also, there's that for loop with nothing in it: for(;;).. is it useful? should it be taken off too?

Ho, and also, pin 0 is the physical pin # 5 on the attiny.. you can easily google it if it doesnt ring bells. Thanks!

  1. how can the code go further than this line

If the watchdog resets the CPU.

It is the only code I've found that works with the attiny45.

As the ATtiny45 is from the same family as the ATtiny85 you can use many examples from there, just keep an eye on the size of the compiled code.

Is there a way to do it? or an easier way to put attinies on sleep mode? would it help to try different attiny cores?

What do you want to achieve? Just putting the Tiny to sleep is as easy as this:

set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_mode();

It's often trickier to prepare the setup so that the CPU got woken up at some time again.

pylon:
What do you want to achieve? Just putting the Tiny to sleep is as easy as this:

set_sleep_mode(SLEEP_MODE_PWR_DOWN);

sleep_mode();

Wow thanks! But yeah, then I need to find a way to wake it up by itself, so I can use it to take measures and go back to sleep, and loop.

Do you have any idea of what would be the easiest way to wake the chip? most codes I find are pretty long with a lot of functions I find pretty difficult to learn.. Really, for now, I just want to achieve the simplest go to sleep + wake up code I can make (and understand it, if possible).

By the way how did you learn all that stuff? Is there a place on internet that could help me learn? I keep googling, looking on blogs and things like that but I think it's not very efficient..

Do you have any idea of what would be the easiest way to wake the chip? most codes I find are pretty long with a lot of functions I find pretty difficult to learn.. Really, for now, I just want to achieve the simplest go to sleep + wake up code I can make (and understand it, if possible).

What event should wake it up? Is it time-based, an external signal, an incoming communication?

There are several sleep modes with different current consumptions. Depending on the wake-up event not all modes are available.

By the way how did you learn all that stuff? Is there a place on internet that could help me learn? I keep googling, looking on blogs and things like that but I think it's not very efficient..

I started with easy Arduino projects, included more features, learnt how to use the Arduino environment and then studied the datasheet of the microcontroller. And I read many, many threads in this forum :). The sleep codes are easier to learn on an Arduino than on that Tiny, most of the code is identical, so if you want to learn how the sleep modes are working, I would use an UNO, debugging on the ATtiny is quite complex.

Setup doesn't run early enough to stop the WDT.
If using a bootloader the bootloader MUST halt the WDT.
With no bootloader your program should halt the WDT as early as possible, like this.

#include <avr/wdt.h>

//prototype
void catch_wdt(void)     \
  __attribute__((naked)) \
  __attribute__((section(".init3")));

void catch_wdt(void)
{
  MCUSR = 0;
  wdt_disable();
}

void setup
{
}

void loop
{
}

Both the avrlibc docs and the datasheet for the mcu will have more information.

Using the Arduino UNO Learning Kit, we may proceed to study/analyse the following program that deals with sleep/wake-up mechanism of the ATmega328P. In this program, the MCU instructs the ADC (analog-to-digital converter) module to go for conversion in 'Noise Reduction Mode', and then the MCU instructs itself to go for sleep. At the end of analog signal conversion, the ADC interrupts the MCU; the MCU wakes up from sleep, goes to ISR, reads analog signal, and sends it to Serial Monitor. The process repeats at 1-sec interval.

The program blinks L (the built-in LED of UNO) in the ISR to indicate that the MCU has really waked up from sleep and then it has executed the ISR. The 1-sec blinking interval has been created by programming the TC1 as the delay() function can not be easily used in ISR.

use a jumper wire and connect the 3.3V point with A3-pin o the UNO

#include<avr/sleep.h>     //this header file must be included for the sleep_mode to work

void setup() 
{
    Serial.begin(9600);
    pinMode(13, OUTPUT);

    TCCR1A = 0x00;
    TCCR1B = 0x00;
    TCNT1 = 0xC2F7;      //pre-set value for 1-sec delay
    TCCR1B = 0x05;        //TC1 is started at clkTC1 = clkYSY/1024

     analogReference(DEFAULT);  //Vref = AVCC = 5V
     bitSet(ADCSRA, 3);              //ADC interrupt is enabled
     interrupts();                        //Global interrupt enable bit
     // SMCR = 0x03;
     set_sleep_mode(SLEEP_MODE_ADC);  //ADC noise reduction and MCU sleep mode
     sleep_mode();                                   //MCU sleeps; it is not dead; it is not executing any instruction

}

void loop() 
{
  
}

ISR(ADC_vect)
{
 
    unsigned int x = analogRead(A3);   //reading Ch-3
    Serial.println(x, DEC);                    //Serial Monitor shows: 675 - 685
    
    while(bitRead(TIFR1, 0) !=HIGH)    //wait until 1-sec is elapsed
        ;
    bitSet(TIFR1, 0);                           //TOV1 (TC1 overflow) bit is cleared
    TCNT1 = 0xC2F7;                          //reload pre-set value
  
    digitalWrite(13, !digitalRead(13));    //blinks built-in L of UNO
}