Вход в спящий режим долгим нажатием кнопки, помогите допилить!

Тема в разделе "Микроконтроллеры AVR", создана пользователем Jazzy, 7 сен 2017.

  1. Jazzy

    Jazzy Нерд

    Доброго времени и пространства неравнодушным!)

    Бъюсь над задачей входа/выхода микроконтроллера в режим сна при долгом нажатии кнопки(3секунды например). Пока делаю на arduino.

    - Нашел скетч для засыпания, работает.
    - Сделал скетч для долгого нажатия с использованием millis.
    Помогите правильно объединить!!!


    КНОПОШНЫЙ КОД вот:
    Код (C++):

    const int ledPin =  13;
    int buttonPin = 3;               //choose the input pin for a pushbutton
    int buttonVal = 1;
    int ledState = HIGH;             // этой переменной устанавливаем состояние светодиода
    unsigned long previousMillis = 0;        // храним время последнего переключения светодиода
    unsigned long interval = 3000;  

    void setup() {

      pinMode(ledPin, OUTPUT);
      pinMode(buttonPin, INPUT);
      Serial.begin(9600);
    }

    void loop(){

    unsigned long currentMillis = millis();

      buttonVal = digitalRead(buttonPin);


       if(currentMillis - previousMillis < 10) {
       ledState = HIGH;
    }
       
       if(buttonVal == HIGH && ledState == HIGH  && currentMillis - previousMillis >= interval) {
       digitalWrite(ledPin, HIGH);
       ledState = LOW;
    }

       if(buttonVal == LOW && ledState == LOW && currentMillis - previousMillis >= interval) {
       digitalWrite(ledPin, LOW);
       previousMillis = currentMillis;
       ledState = HIGH;
    }

       if(buttonVal == LOW && ledState == HIGH && currentMillis - previousMillis < interval) {
       digitalWrite(ledPin, LOW);
       ledState = LOW;
    }

       if(buttonVal == HIGH && ledState == LOW  && currentMillis - previousMillis < interval) {
       digitalWrite(ledPin, LOW);
       previousMillis = currentMillis;
       ledState = HIGH;

      }
    }

     

    примерный СОННЫЙ КОД вот:
    Код (C++):
     #include <avr/sleep.h>

    unsigned long eventTime = 0;
    int buttonstate = 0;

    int wakePin = 2;                 // pin used for waking up
    int sleepStatus = 0;             // variable to store a request for sleep
    int count = 0;                   // counter

    const int buttonPin = 0;

    void wakeUpNow()        // here the interrupt is handled after wakeup
    {

    }

    void setup()
    {
      pinMode(buttonPin, INPUT);
      pinMode(wakePin, INPUT);
      Serial.begin(9600);
      attachInterrupt(0, wakeUpNow, LOW); // use interrupt 0 (pin 2) and run function
                                          // wakeUpNow when pin 2 gets LOW
    }

    void sleepNow()         // here we put the arduino to sleep
    {
        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

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

        sleep_mode();            // here the device is actually put to sleep!!
                                 // THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP

        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.

    }

    void loop()
    {

       int reading = analogRead(buttonPin); // проверял, работает ли ацп
       Serial.println(reading);

      if (Serial.available()) {
        int val = Serial.read();
        if (val == 'S') {
          Serial.println("Serial: Entering Sleep mode");
          delay(100);     // this delay is needed, the sleep
                          //function will provoke a Serial error otherwise!!

          sleepNow();     // sleep function called here
        }

      }
    }
     
    Последнее редактирование: 7 сен 2017
  2. b707

    b707 Гуру

    трудновато будет, ибо в скетче c millis накручена какая-то непонятная хрень, явно более сложная. чем просто удержание кнопки... поищите другой пример

    и, кстати. неясно почему вы поместили это в раздел микроконтроллеры... надо было в самый первый. для чайников, так как вопрос соответсвующий. из разряда "я нуб и не хочу учиться. напишите за меня"
     
  3. ostrov

    ostrov Гуру

    Не знаете как отличить короткое нажатие от длинного?

    Кстати, про спящий режим. Он имеет смысл только при отключении периферии, даже у Уно разница в потреблении почти не заметна. Делать будете на голом МК?
     
    Jazzy нравится это.
  4. b707

    b707 Гуру

    это мне или ТС?
    Странная логика. "Даже у Уно". У модельных плат разница именно потому и невелика, что основными потребителями там является "обвязка" - светодиоды, USB-модуль и схема питания, которые не зависят от режима сна. А на голом МК можно получить очень интересные результаты.
    И не так уж "не заметна" разница даже на ардуинах. Заметна и весьма. На Нано без отключения периферии, даже без удаления светодиодов и регулятора напряжения спящий режим в несколько раз экномичнее дефолтного. Понятно, что ни о какой длительной работе речь не идет, но говорить, что 50ма и 8 - это не разница?
     
  5. Jazzy

    Jazzy Нерд

    Вот так "в целом" работает, но цикл loop не повторяется. Можно включить светодиод прерыванием и усыпить через millis, удерживая 3с. Есть супермозги, кто поможет докрутить? ; -)

    Микроконтроллер Attiny84 + nrf24 и все работает. Вот только цифровой кнопки вкл/выкл нехватает ну очень!!

    И да, наворотил там условий.. Изначально не прогер, буду рад решению поизящнее!)

    Код (C++):
     #include <avr/sleep.h>
    #include <SoftwareSerial.h>

    int buttonVal = 1;
    int ledState = HIGH;             // этой переменной устанавливаем состояние светодиода
    unsigned long previousMillis = 0;        // храним время последнего переключения светодиода
    unsigned long interval = 3000;

    int ledPin = 10;
    int wakePin = 2;                 // pin used for waking up
    int sleepStatus = 0;             // variable to store a request for sleep
    int count = 0;                   // counter
    int APin = 9;
    int analog = 1;

    void wakeUpNow()        // here the interrupt is handled after wakeup
    {

    }

    SoftwareSerial mySerial (0, 1);  // Rx, Tx

    void setup()
    {
      pinMode(wakePin, INPUT);
      pinMode(ledPin, OUTPUT);
      pinMode(APin, INPUT);

      mySerial.begin(9600);



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

    void sleepNow()         // here we put the arduino to sleep
    {
        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



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

        sleep_mode();            // here the device is actually put to sleep!!
                                 // THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP

        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.

    }

    void loop(){

      //analog = digitalRead(APin);
      buttonVal = digitalRead(wakePin);
      unsigned long currentMillis = millis();



       if(buttonVal == LOW && ledState == HIGH && currentMillis - previousMillis < interval) {
       digitalWrite(ledPin, HIGH);
       delay(900);
       ledState = HIGH;

       }  
       if(buttonVal == HIGH && ledState == HIGH  && currentMillis - previousMillis < interval) {
       ledState = HIGH;
       sleepNow();
       previousMillis = currentMillis;
       }
     
       if(buttonVal == LOW && ledState == HIGH  && currentMillis - previousMillis >= interval) {
       digitalWrite(ledPin, LOW);
       ledState = LOW;
       delay(1000);

    }
       if(buttonVal == LOW && ledState == LOW && currentMillis - previousMillis >= interval) {
       previousMillis = currentMillis;
       ledState = HIGH;
    }


       if(buttonVal == LOW && ledState == LOW  && currentMillis - previousMillis < interval) {
       previousMillis = currentMillis;
       ledState = HIGH;
      }

    }