Run when powered up, but not on wake from sleep?

I have recently added "sleep" to a sketch that I'm working on. It has reduced power consumption to almost nothing, which is great.

What I'm wondering is: Is it possible to have a piece of code run ONLY when the device is powered on, and NOT run every time that the device wakes from sleep?

I realize that I may be asking for something impossible. It may be that the CPU views a wake and a power-on as basically the same thing. However, I figure that it can't hurt to ask. Maybe having the answer here will save someone else time in the future.

Some more specifics about my application:

  • There is one momentary switch that controls the device. Press it once to toggle the state of a variable.

  • The sleep function interrupt is the same momentary switch. So, it enters sleep mode until the switch is pressed again.

  • Before adding the sleep/wake function, I had code that would allow the user to toggle the initial/power-on state of the variable by holding the switch while powering on.

  • After adding the sleep/wake function, every time that it wakes up because the switch is depressed, it toggles the variable.

  • Setup runs every time that it wakes from sleep.

  • The device doesn't know the difference between being powered on and waking from sleep.

Is there a programming answer to how I can differentiate the "power on setup" from the "wake setup"?

Is there a programming answer to how I can differentiate the "power on setup" from the "wake setup"?

The real question is "Is there some code we can look at"?

What I'm wondering is: Is it possible to have a piece of code run ONLY when the device is powered on, and NOT run every time that the device wakes from sleep?

Yes, put it in setup

void setup(){
// code that runs once
}

void loop (){
// code here potentially runs forever
}

Yes, put it in setup

The OP seems to have thought of that because he says

Setup runs every time that it wakes from sleep.

We need to see a circuit diagram as well as the code. If sertup() is being run when you "wake" then you are doing a reset/power on reset and not a normal sleep/wake

Mark

My code is below. I’m using an attiny45 to control a relay. It is a bistable relay, so when the momentary switch is depressed, the relay should switch. Otherwise, the attiny should sleep.

There is code in setup() that checks to see if the switch is pressed when the circuit is initially energized. If so, it switches the power-up state of the relay and LED, and saves it in the EPROM. The LED flashes three times to acknowledge that the power-up state has been changed.

After I added the sleep/wake code, setup() runs every time that it wakes. I believe that this is true because the LED flashes three times every single time the switch is pressed, not just on initial power-up.

holmes4:
If sertup() is being run when you “wake” then you are doing a reset/power on reset and not a normal sleep/wake

That may be the case. Can that be done with the sleep library? This is my first time using the sleep function, so I’m sure the issue is with my implementation of it. I just can’t figure out where…

#include <EEPROM.h>
#include <Bounce.h>
#include <avr/sleep.h>

// for attiny25/45/85
#define SW            0          // ATtiny Pin 5 
#define MUTE          1          // ATtiny Pin 6
#define RELAY1        4          // pins for relay coil
#define RELAY2        3
#define LED           2          // ATtiny Pin 7

#define ON            1
#define OFF           0
#define DEBOUNCETIME  60   
#define RELAYDELAY    15         // bi-stable relay, time for the coil to be energized
#define CLICKMUTE     15         // length of time for mute before and after switching relay  

Bounce sw = Bounce(SW, DEBOUNCETIME); // initialize debouncer

int state     = 0;         // effect on or off?
int address   = 0;         // EEPROM address of state value
unsigned long lastMillis=0;
unsigned long doubleMillis=0;

int ledState = LOW;                     // ledState used to set the LED
boolean flag = false;

void setup() {
  ADCSRA = 0;                            // turn ADC (Analog to Digital Converter) off
  pinMode(SW, INPUT);                    // make switch pin an input
  digitalWrite(SW, HIGH);                // internal pullup 
  digitalWrite(LED, HIGH);               // led off
  pinMode(LED, OUTPUT);                  // make led pin an output
  pinMode(MUTE,OUTPUT);                  // make MUTE pin an output
  digitalWrite(RELAY2, LOW);
  pinMode(RELAY2,OUTPUT); digitalWrite(RELAY2, LOW);
  digitalWrite(RELAY1, LOW);
  pinMode(RELAY1, OUTPUT); digitalWrite(RELAY1, LOW);
  
  attachInterrupt(0,wakeupnow,HIGH);  
    
  state = EEPROM.read(address);          // get state from EEPROM
  sw.update();
  if(digitalRead(SW) == 0) {             // button pushed at startup -> save 'on' state for next
    state &= 1;                          // to be sure it's written only 1 or 0
    state ^= 1;                          // flip stored state
    EEPROM.write(address, state);        // write flipped state to EEPROM
      
    digitalWrite(LED, HIGH); delay(100); // blink three times as confirmation
    digitalWrite(LED, LOW);  delay(100);
    digitalWrite(LED, HIGH); delay(100);
    digitalWrite(LED, LOW);  delay(100);
    digitalWrite(LED, HIGH); delay(100);
    digitalWrite(LED, LOW);  delay(100);
    digitalWrite(LED, HIGH); delay(100);
    digitalWrite(LED, LOW);
  } 
           
  if(state == 1) {               // state == 1 -> turn effect on, led on
    effectOn();
  } else {                       // state == 0 -> turn effect off, led off
    effectOff();
  }
}

void effectOn() {
  digitalWrite(MUTE, HIGH);  // turn Mute on
  delay(CLICKMUTE);            // wait for mute to engage
  digitalWrite(LED, LOW);      // turn LED on
  digitalWrite(RELAY1, HIGH);  // switch relay to on position
  delay(RELAYDELAY);           // wait a little bit
  digitalWrite(RELAY1, LOW);   // turn current through coil off
  delay(CLICKMUTE);            // wait a little bit
  digitalWrite(MUTE, LOW);   // turn Mute off
  state = 1;                  // remember on state
}

void effectOff() {
  digitalWrite(MUTE, HIGH);  // turn Mute on
  delay(CLICKMUTE);            // wait for mute to engage
  digitalWrite(LED, HIGH);     // turn LED off
  digitalWrite(RELAY2, HIGH);  // switch relay to off position
  delay(RELAYDELAY);           // wait a little bit
  digitalWrite(RELAY2, LOW);   // turn current through coil off
  delay(CLICKMUTE);            // wait a little bit
  digitalWrite(MUTE, LOW);   // turn Mute off
  state = 0;                 // remember off state
}

void wakeupnow(){
	flag = true;
}


void sleep() {

    GIMSK |= _BV(PCIE);                     // Enable Pin Change Interrupts
    PCMSK |= _BV(PCINT0);                   // Use PB0 (Pin5) as interrupt pin
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);    

    sleep_enable();                         // Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
    sei();                                  // Enable interrupts
    sleep_mode();
    
    cli();                                  // Disable interrupts
    PCMSK &= ~_BV(PCINT0);                  // Turn off PB0 (Pin5) as interrupt pin
    sleep_disable();                        // Clear SE bit

    }                                       

void loop() {
    
      if(sw.fallingEdge() == 1) { // switch is pressed 
        if(state == 1) {  // effect was on, turn off
          effectOff();    // turn effect off, led off
        } else {          // effect was off, turn on
          effectOn();
          }
      }
      if(sw.fallingEdge() == 0) {          // switch is released (pulled up - invert test)    
        delay(50);
        sleep();
      }
    }
  attachInterrupt(0,wakeupnow,HIGH);

There is no HIGH mode for attachInterrupt.

http://www.gammon.com.au/interrupts

  sleep_enable();                         // Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
  sei();                                  // Enable interrupts
  sleep_mode();

  cli();                                  // Disable interrupts

Why are you disabling interrupts here? Subsequent delay() calls won't work properly.

Nick, thanks for your time and help.

I have changed the attachInterrupt. I missed that HIGH mode is only for the Due.

attachInterrupt(0,wakeupnow,CHANGE)

I also got rid of the cli() that was disabling interrupts.

The problem still remains where every wake re-runs the setup().

  PCMSK |= _BV(PCINT0);                   // Use PB0 (Pin5) as interrupt pin

You have enabled pin change interrupts but don't have an interrupt handler for them. That makes the code jump back to the reset vector.

http://www.gammon.com.au/interrupts

eg.

ISR (PCINT0_vect) 
 {
  // handle interrupt
 }

[quote author=Nick Gammon link=msg=2315336 date=1436846653] You have enabled pin change interrupts but don't have an interrupt handler for them. That makes the code jump back to the reset vector. [/quote]

BOOM! That's it!

Thank you so much for your help. This was starting to drive me crazy!

The information on your website is fantastic. It's very technical while being presented in a logical way that makes it easy to follow. I've bookmarked it. Maybe it will save me some future aggravation.

Thanks again Nick.