ATtiny 85 not waking up

The below code uses a hall sensor to calculate flow using interrupt on INT0.
While the flow is not present I want the Attiny to go to sleep. I am using the power down mode . While the attiny is awake the current usage is 24 mA with LED on , where as when Attiny goes to sleep the current drops to 3.5mA. But after attiny goes to sleep and the flow comes back, its not waking up and the led does not come on. Any idea why attiny is not waking up?

Thanks

#define GREEN PB0
#define RED PB1
#define hallsensor PB2
#define pin1 PB5
#define pin2 PB3
#define pin3 PB4

uint8_t mcucr1, mcucr2;

#ifndef cbi
#define cbi(sfr,bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr,bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

//#define BODS 7                   //BOD Sleep bit in MCUCR
//#define BODSE 2                  //BOD Sleep enable bit in MCUCR

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


#define BODS 7                   //BOD Sleep bit in MCUCR
#define BODSE 2                  //BOD Sleep enable bit in MCUCR


volatile int NbTopsFan; //measuring the rising edges of the signal
float Calc;

int count = 0;
float t = 0;
float greenVal = 0;
//float blueVal = 255;


void rpm ()     //This is the function that the interupt calls
{
  NbTopsFan++;  //This function measures the rising and falling edge of the hall effect sensors signal

}


void sleepNow()
{
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
 
     ACSR |= _BV(ACD);                         //disable the analog comparator
    ADCSRA &= ~_BV(ADEN);                     //disable ADC
   
    power_timer0_disable();
    power_timer1_disable();
    mcucr1 = MCUCR | _BV(BODS) | _BV(BODSE);  //turn off the brown-out detector
    mcucr2 = mcucr1 & ~_BV(BODSE);
    MCUCR = mcucr1;
    MCUCR = mcucr2;
     sei();
    sleep_enable();
    power_timer0_enable();
    power_timer1_enable();
                          //ensure interrupts enabled so we can wake up again
  
                  
    GIMSK |= _BV(INT0);          
    sleep_disable();  
    power_all_enable();
 
 
 

 
}
// The setup() method runs once, when the sketch starts
void setup() //
{
 
  pinMode(GREEN, OUTPUT);
  pinMode(RED, OUTPUT);
 
  pinMode(pin1, OUTPUT);
  pinMode(pin2, OUTPUT);
  pinMode(pin3, OUTPUT);
  //pinMode(BLUE, OUTPUT);
 
  digitalWrite(GREEN, HIGH);
  digitalWrite(RED, HIGH);
 
  digitalWrite(pin1, LOW);
  digitalWrite(pin2, LOW);
  digitalWrite(pin3, LOW);
 
  pinMode(hallsensor, INPUT); //initializes digital pin 2 as an input
  attachInterrupt(0, rpm, RISING); //and the interrupt is attached
 
  analogWrite(GREEN, (int)greenVal);
 
  disable_adc();
  disable_ac();
  disable_brown_out_detector();
  disable_watchdog();
 
 
}
// the loop() method runs over and over again,
// as long as the Arduino has power

void disable_brown_out_detector() {
  mcucr1 = MCUCR | _BV(BODS) | _BV(BODSE);
  mcucr2 = mcucr1 & ~_BV(BODSE);
  MCUCR = mcucr1;
  MCUCR = mcucr2; 
}

void disable_adc() {
  cbi(ADCSRA,ADEN);
}   

void disable_ac() {
  sbi(ACSR,ACD); 
}
void disable_watchdog() {
  cbi(WDTCR,WDIE);
}


void loop () 
{
  NbTopsFan = 0;   
  sei();          
  delay (1000);   

  Calc = (NbTopsFan * 60 / 7.5); 
  if((Calc >0) )
  {
   
     analogWrite (GREEN, 255);
     delay(500);
     analogWrite(GREEN, 0);

  }
 
  
   if (Calc==0)
  {
  count++;
 // Serial.print(count, DEC);
 // Serial.print("\n");}
 
  if (Calc>0)
  count = 0;

  if (count > 10) {
    delay(100);

  digitalWrite(GREEN,HIGH);
 
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  
  disable_adc();
  disable_ac();
  disable_brown_out_detector();
  disable_watchdog();
  sei();
  sleepNow();

 }
 
}
 
}

Why do this?

      sei();

You never disable interrupts.


  attachInterrupt(0, rpm, RISING); //and the interrupt is attached

The only external interrupt that will wake it from sleep mode power down is LOW.

In addition to LOW external interrupt you can also use pin change interrupt to wake the processor.

Thanks for all the replies
But changing it to LOW did not help.

In the data sheet it mentions.

Only an External Reset, a Watchdog Reset, a Brown-out Reset, USI start condition interupt, an external level interrupt on INT0 or a pin change interrupt can wake up the MCU.

Where can I get more information on waking the attiny85 with attachInterupt on LOW.

Also I have changed my sleepnow() and interrupt routine as below but it still does not wake up.

Thanks

void rpm ()     //This is the function that the interupt calls
{
  NbTopsFan++;  //This function measures the rising and falling edge of the hall effect sensors signal
  sleep_disable();
  digitalWrite(helperLED, HIGH);
}


void sleepNow()
{ //sei();
  sleep_cpu();
}

http://www.insidegadgets.com/2011/02/05/reduce-attiny-power-consumption-by-sleeping-with-the-watchdog-timer/

Thanks again for the replies.

I checked the link and realized that I do not want to use a watchdog timer. Although because I do not want it to keep waking up to check if flow is present.

Is there a way using the Power down sleep mode to wake up the ATTiny85 when an interrupt occurs.

Thanks

cimon:
Thanks for all the replies
But changing it to LOW did not help.

Are you bringing the line low when you want it to wake up? And have it high the rest of the time?

Yes , the hall sensor output is digital so it goes high and low.

I found out that if I retain everything in my original code but replace
sleep_cpu() in sleep function with sleep_enable() then it is able to wake up when flow returns. But the problem is that when it goes to sleep the current draw is 8.7 and 3.5 mA which is very high.

I dont know why sleep_cpu will not allow ATtiny to wake up and sleep_enable will?

Any idead.

Thanks

I've got stuff about power saving here:

You should be able to get much lower than a milliamp.

You may want to check this out:

I just accomplished something similar from the help in this video. While I don't know the exact cause of the issues you are experiencing, methinks it has something to do with all the delay( ) functions you're calling. As you know, when you call a delay( ) function, it delays anything else from happening until the delay is over, including external interrupts. I think you should rewrite all your delay( ) functions as millis( ) delays and check out the video above for vectoring your interrupt the way you want it.

I just used exactly what he did on my project and it worked like a charm. My ATTiny85 is now drawing 7mA when in active mode, then goes into sleep mode after 30 seconds and is drawing ~0mA on my multimeter. Soon as it wakes up, it goes back up to 7mA. Perfect for what I'm doing.

Hope that helps! Good luck!

MaximusAurelius:
...it delays anything else from happening until the delay is over, including external interrupts.

No, using delay does not interfere with interrupts.

But not using the delay function (if not justified) is a good idea anyway. :wink: