Attiny85 deep sleep whith a sketch whitin

Hi,

I am trying to write a sketch for an attiny85 which includes power down and wake from external interrupt functionality.

Now i found several sketches (like below) which describe how to achieve that but i cannot seem to figure out how to include a seperate sketch in there. So i want to power up the attiny by external interrupt and then run the second piece of code below. When i am ready using the project i want to power down the attiny via a button press (pin change interrupt?)

Both pieces of code are not mine

This is the sleep code i found

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

ISR(PCINT0_vect) {
  if (digitalRead(0) == LOW)
    digitalWrite(4, HIGH);
  else
    digitalWrite(4, LOW);
}

void setup() {  
  pinMode(4,OUTPUT); // LED
  pinMode(0,INPUT_PULLUP);
  pinMode(1,INPUT_PULLUP);
  pinMode(2,INPUT_PULLUP);
  ADCSRA = 0; // ADC disabled
  GIMSK = 0b00100000;  // General Interrupt Mask Register, / Bit 5 – PCIE: Pin Change Interrupt Enable / When the PCIE bit is set (one) and the I-bit in the Status Register (SREG) is set (one), pin change interrupt is enabled. Any change on any enabled PCINT[5:0] pin will cause an interrupt. The corresponding interrupt of Pin Change Interrupt Request is executed from the PCI Interrupt Vector. PCINT[5:0] pins are enabled individually by the PCMSK0 Register. / see https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2586-AVR-8-bit-Microcontroller-ATtiny25-ATtiny45-ATtiny85_Datasheet.pdf
  PCMSK = 0b00000111;  // Pin-change interrupt for PB0, PB1, PB2
} 

void loop() {
  sleep_enable();
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  
  sleep_cpu(); 
}

This is the code i want to run when the attiny is awake

// HAZI TECH
// Programmed by Hasitha Jayasundara
// Visit my YouTube Channel for more info - http://www.youtube.com/c/HAZITECH?sub_confirmation=1

//#include "Arduino.h"
//#include <EEPROM.h>

#define LED_PIN1 1 //LED 1
#define LED_PIN2 2 //LED 2
#define LED_PIN3 3 //LED 3
#define LED_PIN4 4 //LED 4
#define buttonPin 0 //Push Button Pin

int SPEED = 60;

int numb = 1;
int pres = 0;

void setup() 
{
//EEPROM.update(0,1); // *IMPORTANT* - Run this code line ONLY for the 1st time. Then comment it and re-upload the code
//numb = EEPROM.read(0);
pinMode(buttonPin, INPUT);
pinMode(LED_PIN1, OUTPUT);
pinMode(LED_PIN2, OUTPUT);
pinMode(LED_PIN3, OUTPUT);
pinMode(LED_PIN4, OUTPUT);
}

void loop() 
{
ButtonScan();

switch (numb) {
  case 1:
    HAZI_TECH_VIP_1();
    break;
  case 2:
    HAZI_TECH_VIP_2();
    break;
  case 3:
    HAZI_TECH_VIP_3();
    break;
  case 4:
    HAZI_TECH_VIP_4();
    break;
  case 5:
    HAZI_TECH_VIP_5();
    break;  
  case 6:
    HAZI_TECH_VIP_6();
    break; 
  case 7:
    HAZI_TECH_VIP_7();
    break; 
  case 8:
    HAZI_TECH_VIP_8();
    break; 
  default:
    HAZI_TECH_VIP_1();
    break;
}
}

void HAZI_TECH_VIP_1()
{
ButtonScan(); 
digitalWrite(LED_PIN1, LOW);
digitalWrite(LED_PIN2, LOW);
digitalWrite(LED_PIN3, LOW);
digitalWrite(LED_PIN4, LOW); 
}

void HAZI_TECH_VIP_2()
{
digitalWrite(LED_PIN1, HIGH);
digitalWrite(LED_PIN2, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN1, LOW);
digitalWrite(LED_PIN2, LOW);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN1, HIGH);
digitalWrite(LED_PIN2, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN1, LOW);
digitalWrite(LED_PIN2, LOW);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN1, HIGH);
digitalWrite(LED_PIN2, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN1, LOW);
digitalWrite(LED_PIN2, LOW);
delay (SPEED); ButtonScan();

digitalWrite(LED_PIN3, HIGH);
digitalWrite(LED_PIN4, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN3, LOW);
digitalWrite(LED_PIN4, LOW);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN3, HIGH);
digitalWrite(LED_PIN4, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN3, LOW);
digitalWrite(LED_PIN4, LOW);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN3, HIGH);
digitalWrite(LED_PIN4, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN3, LOW);
digitalWrite(LED_PIN4, LOW);
delay (SPEED); ButtonScan();
}

void HAZI_TECH_VIP_3()
{
digitalWrite(LED_PIN1, HIGH);
digitalWrite(LED_PIN3, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN1, LOW);
digitalWrite(LED_PIN3, LOW);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN1, HIGH);
digitalWrite(LED_PIN3, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN1, LOW);
digitalWrite(LED_PIN3, LOW);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN1, HIGH);
digitalWrite(LED_PIN3, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN1, LOW);
digitalWrite(LED_PIN3, LOW);
delay (SPEED); ButtonScan();

digitalWrite(LED_PIN2, HIGH);
digitalWrite(LED_PIN4, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN2, LOW);
digitalWrite(LED_PIN4, LOW);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN2, HIGH);
digitalWrite(LED_PIN4, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN2, LOW);
digitalWrite(LED_PIN4, LOW);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN2, HIGH);
digitalWrite(LED_PIN4, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN2, LOW);
digitalWrite(LED_PIN4, LOW);
delay (SPEED); ButtonScan();
}

void HAZI_TECH_VIP_4()
{
digitalWrite(LED_PIN1, HIGH);
digitalWrite(LED_PIN4, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN1, LOW);
digitalWrite(LED_PIN4, LOW);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN1, HIGH);
digitalWrite(LED_PIN4, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN1, LOW);
digitalWrite(LED_PIN4, LOW);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN1, HIGH);
digitalWrite(LED_PIN4, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN1, LOW);
digitalWrite(LED_PIN4, LOW);
delay (SPEED); ButtonScan();

digitalWrite(LED_PIN2, HIGH);
digitalWrite(LED_PIN3, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN2, LOW);
digitalWrite(LED_PIN3, LOW);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN2, HIGH);
digitalWrite(LED_PIN3, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN2, LOW);
digitalWrite(LED_PIN3, LOW);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN2, HIGH);
digitalWrite(LED_PIN3, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN2, LOW);
digitalWrite(LED_PIN3, LOW);
delay (SPEED); ButtonScan();
}

void HAZI_TECH_VIP_5()
{
digitalWrite(LED_PIN1, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN1, LOW);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN1, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN1, LOW);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN1, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN1, LOW);
delay (SPEED); ButtonScan();

digitalWrite(LED_PIN2, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN2, LOW);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN2, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN2, LOW);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN2, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN2, LOW);
delay (SPEED); ButtonScan();

digitalWrite(LED_PIN3, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN3, LOW);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN3, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN3, LOW);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN3, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN3, LOW);
delay (SPEED); ButtonScan();

digitalWrite(LED_PIN4, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN4, LOW);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN4, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN4, LOW);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN4, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN4, LOW);
delay (SPEED); ButtonScan();

digitalWrite(LED_PIN3, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN3, LOW);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN3, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN3, LOW);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN3, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN3, LOW);
delay (SPEED); ButtonScan();

digitalWrite(LED_PIN2, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN2, LOW);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN2, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN2, LOW);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN2, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN2, LOW);
delay (SPEED); ButtonScan();
}

void HAZI_TECH_VIP_6()
{
digitalWrite(LED_PIN1, HIGH);
digitalWrite(LED_PIN2, HIGH);
digitalWrite(LED_PIN3, HIGH);
digitalWrite(LED_PIN4, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN1, LOW);
digitalWrite(LED_PIN2, LOW);
digitalWrite(LED_PIN3, LOW);
digitalWrite(LED_PIN4, LOW);
delay (SPEED); ButtonScan();

digitalWrite(LED_PIN1, HIGH);
digitalWrite(LED_PIN2, HIGH);
digitalWrite(LED_PIN3, HIGH);
digitalWrite(LED_PIN4, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN1, LOW);
digitalWrite(LED_PIN2, LOW);
digitalWrite(LED_PIN3, LOW);
digitalWrite(LED_PIN4, LOW);
delay (SPEED); ButtonScan();

digitalWrite(LED_PIN1, HIGH);
digitalWrite(LED_PIN2, HIGH);
digitalWrite(LED_PIN3, HIGH);
digitalWrite(LED_PIN4, HIGH);
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN1, LOW);
digitalWrite(LED_PIN2, LOW);
digitalWrite(LED_PIN3, LOW);
digitalWrite(LED_PIN4, LOW);
delay (SPEED); ButtonScan();
delay (SPEED); ButtonScan();
delay (SPEED); ButtonScan();
}

void HAZI_TECH_VIP_7()
{
digitalWrite(LED_PIN1, HIGH);
digitalWrite(LED_PIN2, LOW);
delay (SPEED); ButtonScan();
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN2, HIGH);
digitalWrite(LED_PIN1, LOW);
delay (SPEED); ButtonScan();
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN3, HIGH);
digitalWrite(LED_PIN2, LOW);
delay (SPEED); ButtonScan();
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN4, HIGH);
digitalWrite(LED_PIN3, LOW);
delay (SPEED); ButtonScan();
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN3, HIGH);
digitalWrite(LED_PIN4, LOW);
delay (SPEED); ButtonScan();
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN2, HIGH);
digitalWrite(LED_PIN3, LOW);
delay (SPEED); ButtonScan();
delay (SPEED); ButtonScan();
}

void HAZI_TECH_VIP_8()
{
digitalWrite(LED_PIN1, HIGH);
digitalWrite(LED_PIN2, HIGH);
delay (SPEED); ButtonScan();
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN1, LOW);
digitalWrite(LED_PIN2, LOW);
delay (SPEED); ButtonScan();
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN3, HIGH);
digitalWrite(LED_PIN4, HIGH);
delay (SPEED); ButtonScan();
delay (SPEED); ButtonScan();
digitalWrite(LED_PIN3, LOW);
digitalWrite(LED_PIN4, LOW);
delay (SPEED); ButtonScan();
delay (SPEED); ButtonScan();
}


void ButtonScan()
{
if(digitalRead(buttonPin)==1)
   {
    if(pres==0)
   {
    numb++;
   // EEPROM.update(0,numb);
    pres=1;
    digitalWrite(LED_PIN1, HIGH);
    digitalWrite(LED_PIN2, HIGH);
    digitalWrite(LED_PIN3, HIGH);
    digitalWrite(LED_PIN4, HIGH);
    delay (750);
    digitalWrite(LED_PIN1, LOW);
    digitalWrite(LED_PIN2, LOW);
    digitalWrite(LED_PIN3, LOW);
    digitalWrite(LED_PIN4, LOW);
   }
    }
  else
  {
    pres=0;
   }  

 if(numb == 10)
 {
 numb = 1;
 }
}

I would suggest to try to integrate the "blink" example sketch first into the "sleep code".

That way you can confirm first that the sleep and wakeup works like you want and it it's only a few lines of extra code that needs integrating.

Thank you for the reply! If i take a blink sketch, where do i insert in in the power down code?

Here you can learn about the concept of "setup" and "loop".

An alternative is to get the main code working first then later get the sleep functioning. This because the sleep function is really only a power saving optimisation measure so you can apply it after you get your main code working.
Arduino gives you only 5 gpio pins on the ATtiny85 ( 6 pins are possible if you are prepared to use a high voltage programmer or a Digispark or similar).
The push button can have 3 functions to minimise pin usage. (1) for the normal activity in your sketch (short press), (2) to wake the device if sleeping (3) to put the device in sleep mode (long press).

1 Like

That is exactly what i want in this code. Basicly i have 4 led's for which i want to program 4 patterns. The idea is to have a long press to get the attiny out of sleep, then go through the 4 patterns via a single button press. Then again a long press to enable power down.

The base for the code is from Nick Gammon. This is what i've got until now. I am kinda stuck here.

I want to make a function to detect a long press and then attach it as interrupt.

// ATtiny85 sleep mode, wake on pin change interrupt demo
// Author: Nick Gammon
// Date: 12 October 2013

// ATMEL ATTINY 25/45/85 / ARDUINO
//
//                  +-\/-+
// Ain0 (D 5) PB5  1|    |8  Vcc
// Ain3 (D 3) PB3  2|    |7  PB2 (D 2) Ain1
// Ain2 (D 4) PB4  3|    |6  PB1 (D 1) pwm1
//            GND  4|    |5  PB0 (D 0) pwm0
//                  +----+

#include <avr/sleep.h>    // Sleep Modes
#include <avr/power.h>    // Power management

int SPEED = 60;

const byte LED_1 = 1;  // pin 2
const byte LED_2 = 2;  // pin 2
const byte LED_3 = 3;  // pin 2
const byte LED_4 = 4;  // pin 2
const byte SWITCH = 0; // pin 3 / PCINT0

ISR (PCINT0_vect) 
 {
 
 }
 
void setup ()
  {
  pinMode (LED_1, OUTPUT);
  pinMode (LED_2, OUTPUT);
  pinMode (LED_3, OUTPUT);
  pinMode (LED_4, OUTPUT);
  pinMode (SWITCH, INPUT);
  digitalWrite (SWITCH, HIGH);  // internal pull-up
  
  // pin change interrupt (example for D4)
  PCMSK  |= bit (PCINT0);  // want pin D4 / pin 3
  GIFR   |= bit (PCIF);    // clear any outstanding interrupts
  GIMSK  |= bit (PCIE);    // enable pin change interrupts 
  
  }  // end of setup

void loop ()
  {
pattern_1 ();
pattern_1 ();
pattern_1 ();
pattern_1 ();
pattern_1 ();

goToSleep ();
  }  // end of loop
  
  
void goToSleep ()
  {
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  ADCSRA = 0;            // turn off ADC
  power_all_disable ();  // power off ADC, Timer 0 and 1, serial interface
  sleep_enable();
  sleep_cpu();                             
  sleep_disable();   
  power_all_enable();    // power everything back on
  }  // end of goToSleep 

  void pattern_1 ()
  {
  // LED 1 ON
digitalWrite(LED_1, HIGH);
digitalWrite(LED_2, LOW);
digitalWrite(LED_3, LOW);
digitalWrite(LED_4, LOW);
delay (SPEED);

// LED 2 ON
digitalWrite(LED_1, LOW);
digitalWrite(LED_2, HIGH);
digitalWrite(LED_3, LOW);
digitalWrite(LED_4, LOW);
delay (SPEED);

// LED 3 ON
digitalWrite(LED_1, LOW);
digitalWrite(LED_2, LOW);
digitalWrite(LED_3, HIGH);
digitalWrite(LED_4, LOW);
delay (SPEED);

// LED 4 ON
digitalWrite(LED_1, LOW);
digitalWrite(LED_2, LOW);
digitalWrite(LED_3, LOW);
digitalWrite(LED_4, HIGH);
delay (SPEED);

// LED 3 ON
digitalWrite(LED_1, LOW);
digitalWrite(LED_2, LOW);
digitalWrite(LED_3, HIGH);
digitalWrite(LED_4, LOW);
delay (SPEED);

// LED 2 ON
digitalWrite(LED_1, LOW);
digitalWrite(LED_2, HIGH);
digitalWrite(LED_3, LOW);
digitalWrite(LED_4, LOW);
delay (SPEED);

// LED 1 ON
digitalWrite(LED_1, HIGH);
digitalWrite(LED_2, LOW);
digitalWrite(LED_3, LOW);
digitalWrite(LED_4, LOW);
delay (SPEED);

// All off
digitalWrite(LED_1, LOW);
digitalWrite(LED_2, LOW);
digitalWrite(LED_3, LOW);
digitalWrite(LED_4, LOW);
//delay (SPEED);

  }

You'll have to change it slightly because you can't really control the wakeup by a long press. Any press will wake it from sleep mode. So you have to decide if that press initiates also the first light sequence, or it waits after wakeup for another button press to initiate that first sequence.

To detect a long press, simply set a timer if the button changes state from not pressed to pressed. If it remains pressed for x milliseconds, you force it to sleep.

It will be something like but you can probably improve it:

if ( ! SWITCH ) {
  uint32_t buttonTimer = millis() ;
  while ( ! SWITCH ) {
    if ( millis() - buttonTimer > 1000UL ) {
       sleepFlag = true ;  // test and reset this flag at the end of the loop()
       break ;
    }
  }
}

You have an additional problem in that you use delay() statements in your code. That will make the button very unresponsive.
Replace the delay() statements with a millis() based timer so there is no blocking code.

Thank you! Yes i figured the delays are causing problems since the button is behaving strange. With that i mean it is not detecting buttonpresses as it should.

I will look into the millis options instead of delays

am i right if i say that i schould put my main code in the ISR (PCINT0_vect) and leave the rest of the code as is since that is taking care of the sleep functions?

#include <avr/sleep.h>    // Sleep Modes
#include <avr/power.h>    // Power management

const byte LED = 3;  // pin 2
const byte SWITCH = 0; // pin 5 / PCINT0

ISR (PCINT0_vect) 
 {
 **// PUT MAIN CODE HERE**
 }
 
void setup ()
  {
  pinMode (LED, OUTPUT);
  pinMode (SWITCH, INPUT);
  digitalWrite (SWITCH, HIGH);  // internal pull-up
  
  // pin change interrupt (example for D4)
  PCMSK  |= bit (PCINT4);  // want pin D4 / pin 3
  GIFR   |= bit (PCIF);    // clear any outstanding interrupts
  GIMSK  |= bit (PCIE);    // enable pin change interrupts 
  
  }  // end of setup

void loop () **// let the loop handle the sleep funtion, nothing more?**
  {
 goToSleep ();

  }  // end of loop
  
  
void goToSleep ()
  {
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  ADCSRA = 0;            // turn off ADC
  power_all_disable ();  // power off ADC, Timer 0 and 1, serial interface
  sleep_enable();
  sleep_cpu();                             
  sleep_disable();   
  power_all_enable();    // power everything back on
  }  // end of goToSleep 

No. Leave the ISR completely empty in this case. It has to be present to support the wakeup but that is all.
After an interrupt, your code re-starts immediately after the sleep_cpu(); statement.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.