Вечный сон

Нет ответов
std
Offline
Зарегистрирован: 05.01.2012

Задача: с одной кнопки (на D2 или D3) и включать, и выключать. Ну то есть типа как кнопка "положить трубу" на сотике, только не держать долго. Для ясности будем называть состояние системы сразу после включающего прерывания - утром, состояние перед   set_sleep_mode() - вечером.

Делаю правильно (с утра снимаем прерывание по detachInterrupt(), вечером ставим заново, а днём работаем, не имея прерывания и нажимание кнопки Power ловим по digitalRead(D2)==LOW) - ингода судя по симптомам уходит в спячку со снятым прерыванием, то есть невозможно разбудить. Делаю неправильно (поднять прерывание в сетюпе и не трогать вообще, на состояние "утром", "вечером" - забить) - пашет на ура.

Что делаю не так?

Как правильно:

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

#define BTN_PWR (2)
#define BTN_RND (5)

volatile boolean ISRflag=false,         // the interrupt routine is set
                 ONflag=true;           // power state
int seconds=0;

unsigned long last_on=millis();

void doWake(void){                                     // wake
  if(ISRflag){
    ONflag=true;
    ISRflag=false;
    detachInterrupt(0);
  }
}

void doSleep(void){                                    // sleep
  ONflag=false;
  if(!ISRflag){
    attachInterrupt(0,doWake,LOW);
    ISRflag=true;
  }
  delay(100);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sleep_mode();
  sleep_disable(); 
  power_all_enable();
}

void setup(){
  pinMode(A0,INPUT);
  pinMode(BTN_PWR,INPUT_PULLUP);
  pinMode(BTN_RND,INPUT_PULLUP);
  randomSeed(analogRead(A0));
  doRandom();                                          // first action
}

void loop(){                                           // main
  if(ONflag){
    if(millis()-last_on>=1000){                        // shutdown enable tick
      seconds++;
      last_on=millis();
    }
    if(digitalRead(BTN_PWR)==LOW && seconds>=2){       // shutdown cmd
                                                       // if(seconds>=15) - auto shutdown
      seconds=0;
      doBlank();
      delay(2000);
      doSleep();
      doRandom();
    }  
    if(digitalRead(BTN_RND)==LOW){                     // action cmd
      delay(250);
      doRandom();
    }
  }
}

void doRandom(void){
// switch random LEDs on
}

void doBlank(void){
// switch all LEDs off
}

Как неправильно, но работает:

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

#define BTN_PWR (2)
#define BTN_RND (5)

volatile boolean ONflag=true;           // power state
int seconds=0;

unsigned long last_on=millis();

void doWake(void){                                     // wake
  ONflag=true;
}

void doSleep(void){                                    // sleep
  ONflag=false;
  delay(100);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sleep_mode();
  sleep_disable(); 
  power_all_enable();
}

void setup(){
  pinMode(A0,INPUT);
  pinMode(BTN_PWR,INPUT_PULLUP);
  pinMode(BTN_RND,INPUT_PULLUP);
  randomSeed(analogRead(A0));
  doRandom();                                          // first action
  attachInterrupt(0,doWake,LOW);
}

void loop(){                                           // main
  if(ONflag){
    if(millis()-last_on>=1000){                        // shutdown enable tick
      seconds++;
      last_on=millis();
    }
    if(digitalRead(BTN_PWR)==LOW && seconds>=2){       // shutdown cmd
                                                       // if(seconds>=15) - auto shutdown
      seconds=0;
      doBlank();
      delay(2000);
      doSleep();
      doRandom();
    }  
    if(digitalRead(BTN_RND)==LOW){                     // action cmd
      delay(250);
      doRandom();
    }
  }
}

void doRandom(void){
// switch random LEDs on
}

void doBlank(void){
// switch all LEDs off
}