鳕鱼天空

This is Mr Wang's Tech Blog.

Ardino节电模式、自动休眠、按钮打开和关闭

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

#include <MsTimer2.h>

int pin = 13;

volatile int f_sleepButton = 0;
volatile int f_sleepTimer = 0;

void setup() {
  //Serial.begin(9600);
  //Serial.print("Welcome to use!\n");
  pinMode(pin, OUTPUT);
  pinMode(2, INPUT);

  MsTimer2::set(2000, sleepTimer);        // 中断设置函数,每 2000ms 进入一次中断
  MsTimer2::start();

  sleepNow();
}

void loop() {
  if (digitalRead(2)) {
    //sleepNow();
    f_sleepButton++;
    clearsleepTimer();
    delay(50);
  }
  if (f_sleepButton == 24) {  // 长按1.2秒关机
    sleepNow();
  }
  if (f_sleepTimer == 10) { // 延时没有操作关机
    sleepNow();
  }
}

void sleepTimer() {
  f_sleepTimer++;
}

void sleepNow()         // here we put the arduino to sleep
{
  //detachInterrupt(0);
  digitalWrite(pin, HIGH);

  //delay(1000);
  //return;
  //Serial.print("sleep_enable\n");


  /* Now is the time to set the sleep mode. In the Atmega8 datasheet
     http://www.atmel.com/dyn/resources/prod_documents/doc2486.pdf on page 35
     there is a list of sleep modes which explains which clocks and
     wake up sources are available in which sleep modus.

     In the avr/sleep.h file, the call names of these sleep modus are to be found:

     The 5 different modes are:
         SLEEP_MODE_IDLE         -the least power savings
         SLEEP_MODE_ADC
         SLEEP_MODE_PWR_SAVE
         SLEEP_MODE_STANDBY
         SLEEP_MODE_PWR_DOWN     -the most power savings

     For now, we want as much power savings as possible,
     so we choose the according sleep modus: SLEEP_MODE_PWR_DOWN

  */
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);   // sleep mode is set here

  sleep_enable();              // enables the sleep bit in the mcucr register
  // so sleep is possible. just a safety pin

  /* Now is time to enable a interrupt. we do it here so an
     accidentally pushed interrupt button doesn't interrupt
     our running program. if you want to be able to run
     interrupt code besides the sleep function, place it in
     setup() for example.

     In the function call attachInterrupt(A, B, C)
     A   can be either 0 or 1 for interrupts on pin 2 or 3.

     B   Name of a function you want to execute at interrupt for A.

     C   Trigger mode of the interrupt pin. can be:
                 LOW        a low level triggers
                 CHANGE     a change in level triggers
                 RISING     a rising edge of a level triggers
                 FALLING    a falling edge of a level triggers

     In all but the IDLE sleep modes only LOW can be used.
  */

  attachInterrupt(0, wakeUpNow, RISING ); // use interrupt 0 (pin 2) and run function
  // wakeUpNow when pin 2 gets LOW

  sleep_mode();                // here the device is actually put to sleep!!
  //

  sleep_disable();             // first thing after waking from sleep:
  // disable sleep...


  detachInterrupt(0);          // disables interrupt 0 on pin 2 so the
  // wakeUpNow code will not be executed
  // during normal running time.
  power_all_enable();/* Re-enable the peripherals. */

  delay(100);                 // wat 2 sec. so humans can notice the
  // interrupt.
  // LED to show the interrupt is handled
  digitalWrite (pin, LOW);      // turn off the interrupt LED

}

void wakeUpNow()
{ //Serial.print("wakeUpNow\n");
  f_sleepButton = 0;
  //digitalWrite(pin, LOW);
  //attachInterrupt(0,sleepNow, FALLING ); // 睡眠模式
}

void clearsleepTimer() {
  f_sleepTimer = 0;
}