ATtiny85 Sleep Mode. (Help please)

Hi All.

I need help I am in way over my head. I am trying to finish up on the code for an led light bar. The last step is to have it turn off (Go into Sleep mode) after 2hr and come back on when a button is pushed.

I know it has to do with a pin interrupt on the ATtiny, but I am clueless. I have looked all over this forum, Google and YouTube for a tutorial that I would be able to understand. Anything I did find look to be written for engineers.

Now I would normally not ask anyone to do the work for me. But if any one has any code that would work, I am begging you to please post.

And for the record, I did my best to figure it out.
Thanks you

Keith

/*
 *  Light Strip Ver 2.0
 */

int switchPin = 0;              // IC leg 5 (PB0) 
int ledPin = 4;                // IC leg 3(PB4)

int val;                        // variable for reading the pin status
int val2;                       // variable for reading the delayed status
int buttonState;                // variable to hold the button state

int fadeValueLow = 127;         // Light Output Low
int fadeValueHi =  255;           // Light Output Hight
int fadeOff = 0;
int lightMode = 0;              // What mode is the light in?
unsigned long lastButtonPushMillis ;


void setup() {
  pinMode(switchPin, INPUT);    // Set the switch pin as input
  digitalWrite(switchPin, HIGH);  // set internal pull-up resistor
  pinMode(ledPin, OUTPUT);


  buttonState = digitalRead(switchPin);   // read the initial state
}


void turnOff(){
  //analogWrite(ledPin, fadeOff);
  digitalWrite(ledPin, LOW);  //Temp code Need Sleep mode Code

}
void fadeLow(){
  analogWrite(ledPin, fadeValueLow); 
}

void fadeHi(){
  analogWrite(ledPin, fadeValueHi); 
}

void loop(){
  val = digitalRead(switchPin);      // read input value and store it in val
  delay(10);                         // 10 milliseconds is a good amount of time
  val2 = digitalRead(switchPin);     // read the input again to check for bounces
  if (val == val2) {                 // make sure we got 2 consistant readings!
    if (val != buttonState) {          // the button state has changed!
      if (val == LOW) {                // check if the button is pressed
        lastButtonPushMillis= millis();   //                  
        if (lightMode == 0) {          // if its off
          lightMode = 1;               // turn lights on!
        } 
        else {
          if (lightMode == 1) {        
            lightMode = 0;             
          } 


        }

      }
      buttonState = val;                 
    }

    // Now do whatever the lightMode indicates
    if (lightMode == 0) { // Low
      fadeLow();

    }

    if (lightMode == 1) { // Hi

      fadeHi();
    }

  }
  if ( millis() - lastButtonPushMillis > 5000 ) {    // 7200000L milliseconds is 2 hours
    turnOff();
  }

}

Try this:

// Untested code

void Int0ISR() {    // This function doesn't really have to DO anything.  It just has to exist.
}

void TurnOff() {
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
  sleep_enable();
  sleep_cpu ();
  sleep_disable();
}

void setup() {
...
  attachInterrupt(INT0, Int0ISR, LOW);  // Add this line
...
}

You will have to change your circuit so the push button activates LOW on pin B2, which is the INT0 pin on the Tiny85. But it looks like you already have that figured out with the internal pull-up and all. You just have to move it from PB0 to PB2.

Thank you so very much, I will give it a try.

I was nervous that is was going to be ragged on for asking something that was way over my head being a newbie and all.

Once more Thank you so very much

kculm:
I was nervous that is was going to be ragged on for asking something that was way over my head being a newbie and all.

You won't get ragged on for asking newbie questions.

You'll get ragged on for showing no effort in trying to solve issues yourself and not following directions.

Arrch:
You won't get ragged on for asking newbie questions.

You'll get ragged on for showing no effort in trying to solve issues yourself and not following directions.

I try to do my best. Thanks.

Tanhdron,

Thanks again for the code. I added your snippets to my code and it works, kind of. It shuts off, but when I push the button it does not wake up. I attached my code with your snippets in it in incase I missed something. I also moved the switch pin to PB2.

Keith

/*
 *  Light Strip Ver 2.0
 */


#include <avr/sleep.h>
#include <avr/interrupt.h>
int switchPin = 2;              // IC leg 5 (PB0) 
int ledPin = 4;                // IC leg 3(PB4)

int val;                        // variable for reading the pin status
int val2;                       // variable for reading the delayed status
int buttonState;                // variable to hold the button state

int fadeValueLow = 127;         // Light Output Low
int fadeValueHi =  255;           // Light Output Hight
int fadeOff = 0;
int lightMode = 0;              // What mode is the light in?
unsigned long lastButtonPushMillis ;


void setup() {
  pinMode(switchPin, INPUT);    // Set the switch pin as input
  digitalWrite(switchPin, HIGH);  // set internal pull-up resistor
  pinMode(ledPin, OUTPUT);
  attachInterrupt(INT0, Int0ISR, LOW);

  buttonState = digitalRead(switchPin);   // read the initial state
}
void Int0ISR() {    // This function doesn't really have to DO anything.  It just has to exist.
}

void turnOff(){
  //analogWrite(ledPin, fadeOff);
  // digitalWrite(ledPin, LOW);  //Temp code Need Sleep mode Code
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
  sleep_enable();
  sleep_cpu ();
  sleep_disable();
}
void fadeLow(){
  analogWrite(ledPin, fadeValueLow); 
}

void fadeHi(){
  analogWrite(ledPin, fadeValueHi); 
}

void loop(){
  val = digitalRead(switchPin);      // read input value and store it in val
  delay(10);                         // 10 milliseconds is a good amount of time
  val2 = digitalRead(switchPin);     // read the input again to check for bounces
  if (val == val2) {                 // make sure we got 2 consistant readings!
    if (val != buttonState) {          // the button state has changed!
      if (val == LOW) {                // check if the button is pressed
        lastButtonPushMillis= millis();   //                  
        if (lightMode == 0) {          // if its off
          lightMode = 1;               // turn lights on!
        } 
        else {
          if (lightMode == 1) {        
            lightMode = 0;             
          } 


        }

      }
      buttonState = val;                 
    }

    // Now do whatever the lightMode indicates
    if (lightMode == 0) { // Low
      fadeLow();

    }

    if (lightMode == 1) { // Hi

      fadeHi();
    }

  }
  if ( millis() - lastButtonPushMillis > 5000 ) {    // 7200000L milliseconds is 2 hours
    turnOff();
  }

}

It's a little bit confusing trying to understand exactly which pins and interrupts it's using. According to the spec sheet, INT0 is supposed to map to interrupt 1. Why is it that INT0 shows up as a 6?!? I'm confused as to what to pass to attachInterrupt(), exactly. Try this instead, and see if it works:

attachInterrupt(1, Int0ISR, LOW);

I know the concept works, because I have done it, but in a different way.

Ok Guys i am still having no luck.

this is where I am at now.

On power on led's come on at half power (that is Good)
After 5sec Attiny85 shuts down (that is Good)
I press the button leds should come back on (No Go)

Also if after power up I push the button the lights go to High ( that is good) press it again they go back to Low ( that is also good)
but after 5sec they go to High and luck up. ( Not Good)

As I was said before I am really green at all of this. i was thinking it may have to do with the way I have it setup. I have attached my layout.

Note I am using LED tape with built in resistors and that it why you don't see one on my bread board.

once more I can't thank you enough for your help

Keith

KculmLeda.png

I think the problem is that as long as the button is held down, the interrupt routine will be triggered, preventing anything else from being executed. So the debounce code will never register it as being down. What you need to do is enable the interrupt just before going to sleep, and disable it in the ISR. To do this, add the following line just before the call to sleep_enable():

  GIMSK = _BV(INT0);      // enable INT0

and add the following line within Int0ISR:

  GIMSK = 0;	// disable INT0

PS - using a voltage regulator without the recommended input capacitor is a bad idea, also you should have a decoupling capacitor between Vcc and Gnd of the ATtiny.

dc42:
PS - using a voltage regulator without the recommended input capacitor is a bad idea, also you should have a decoupling capacitor between Vcc and Gnd of the ATtiny.

I had planed on doing that with the finished design. i need to run to Radio shack in the AM.

Thanks.

dc42:

  GIMSK = _BV(INT0);      // enable INT0

and add the following line within Int0ISR:

  GIMSK = 0;	// disable INT0

First of all i would like to say thank you, I am learning alot. I plan on researching who all that code really works.

It almost there. ( I am sorry If I am staring to be a pane. but this little project has me fired up.)

This what I have now.

At power on LEDs Half Power .Good
Wait 5 sec AT85 turns off. Good.
Press Button AT85 wakes up . Great. but LED are in full mode. Not so Good. At85 stays on.
press Button once more LEDS go back to Half power. Wait 5 sec LEDs go to full power
Press Button once more LEDs blink but stay at Full power
Press button once more LEDs goto Half power, wait 5 sec at85 turns off.

You want the chip to remember which mode it was when it went to sleep?

Post your current code.

TanHadron:
You want the chip to remember which mode it was when it went to sleep?

Post your current code.

Thank you.

/*
 *  Light Strip Ver 2.0
 */


#include <avr/sleep.h>
#include <avr/interrupt.h>
int switchPin = 2;              // IC leg 5 (PB0) 
int ledPin = 4;                // IC leg 3(PB4)

int val;                        // variable for reading the pin status
int val2;                       // variable for reading the delayed status
int buttonState;                // variable to hold the button state

int fadeValueLow = 127;         // Light Output Low
int fadeValueHi =  255;           // Light Output Hight
int fadeOff = 0;
int lightMode = 0;              // What mode is the light in?
unsigned long lastButtonPushMillis ;


void setup() {
  pinMode(switchPin, INPUT);    // Set the switch pin as input
  digitalWrite(switchPin, HIGH);  // set internal pull-up resistor
  pinMode(ledPin, OUTPUT);
  attachInterrupt(1, Int0ISR, LOW);

  buttonState = digitalRead(switchPin);   // read the initial state
}
void Int0ISR() {  
 GIMSK = 0;	// disable INT0          
}

void turnOff(){
  //analogWrite(ledPin, fadeOff);
  // digitalWrite(ledPin, LOW);  //Temp code Need Sleep mode Code
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
  GIMSK = _BV(INT0);      // enable INT0  
  sleep_enable();
  sleep_cpu ();
  sleep_disable();
}
void fadeLow(){
  analogWrite(ledPin, fadeValueLow); 
}

void fadeHi(){
  analogWrite(ledPin, fadeValueHi); 
}

void loop(){
  val = digitalRead(switchPin);      // read input value and store it in val
  delay(10);                         // 10 milliseconds is a good amount of time
  val2 = digitalRead(switchPin);     // read the input again to check for bounces
  if (val == val2) {                 // make sure we got 2 consistant readings!
    if (val != buttonState) {          // the button state has changed!
      if (val == LOW) {                // check if the button is pressed
        lastButtonPushMillis= millis();   //                  
        if (lightMode == 0) {          // if its off
          lightMode = 1;               // turn lights on!
        } 
        else {
          if (lightMode == 1) {        
            lightMode = 0;             
          } 


        }

      }
      buttonState = val;                 
    }

    // Now do whatever the lightMode indicates
    if (lightMode == 0) { // Low
      fadeLow();

    }

    if (lightMode == 1) { // Hi

      fadeHi();
    }

  }
  if ( millis() - lastButtonPushMillis > 5000 ) {    // 7200000L milliseconds is 2 hours
    turnOff();
  }

}

try this:

  if ( millis() - lastButtonPushMillis > 5000 ) {    // 7200000L milliseconds is 2 hours
    turnOff();
    buttonState = LOW;  // Button must be pressed to wake up
  }

Also, I found out the correct parameter to attachInterrupt() is not 1.

  attachInterrupt(0, Int0ISR, LOW);

Perhaps a dumb observation but what's the purpose of a voltage regulator here? If you are sleeping the '85 it is done to save power... No?
What about the quiescent current that the regulator draws? in this case (data sheet attached) an AMS1117 draws a min current of 5 mA although there is no load current stated for that measurement after looking at the first graph it would appear that 5 mA is the minimum current, as that is the load current necessary for stable output.
The Atmel data sheet on figure 21-1 shows a 5 mA typical active current @ 8 MHz/5V internal oscillator, so regardless of your sleep code your regulator is going to eat more battery than the processor will.. I used it because it was the closest to parity with the regulator quiescent current. If you choose a lower power mode of operation the disparity becomes even larger.

Doc

ams1117.pdf (71.5 KB)

Docedison:
Perhaps a dumb observation but what's the purpose of a voltage regulator here?

Doc

Doc,

Not sure if I am doing right, but i am powering the LED strip with 9v.

With The LEDs off I am Pulling around 8mA with the AT85 off its down to 3mA. The end game to all of this is. I will be powering the light strip with a 9v batter and recharging it with solar panels.

If I am doing it wrong Please let me know. That is the only way i'll learn.

Thanks
Keith

kculm:
The end game to all of this is. I will be powering the light strip with a 9v batter and recharging it with solar panels.

In that case, I suggest you use a micropower regulator instead of a normal one, for example MCP1702-5002.

dc42:
In that case, I suggest you use a micropower regulator instead of a normal one, for example MCP1702-5002.

Thank you, I never used one before and I am going to look it up now. Is it somthing that someone with only basic skills will understand how to use.

kculm:

dc42:
In that case, I suggest you use a micropower regulator instead of a normal one, for example MCP1702-5002.

Thank you, I never used one before and I am going to look it up now. Is it somthing that someone with only basic skills will understand how to use.

It's just like any other 3-terminal linear voltage regulator, except that it consumes much less current.