Пробуждение Attiny84 долгим нажатием кнопки

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

  1. Jazzy

    Jazzy Нерд

    Доброго времени суток! Сильно прошу не пинать, тема не новая...
    Основная задача - пробуждение "Тиньки" по прерыванию, но не мгновенно, а через 2е секунды удержания кнопки.

    Засада:
    - отправляем в сон и пробужнаем одной и той же кнопкой.
    следовательно, как только мк уснул, пин прерывания остается еще замкнут на землю.
    После повторного нажатия мк уже не просыпается. Подскажите, как пофиксить!) Как - то, видимо, через WDT..

    Скетч позволяет управлять светодиодом. Уходит в сон по таймеру либо при удержании кнопки.
    Во втором случае(удержание кнопки) мк не просыпается по прерыванию.


    Код (C++):



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

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



    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 loop(){
    //digitalWrite(ledPin, HIGH);

      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();   //            
            digitalWrite(ledPin, HIGH);
            if (lightMode == 0) {          // if its off
              digitalWrite(ledPin, LOW);
              lightMode = 1;               // turn lights on!
            }
            else {
              if (lightMode == 1) {
                digitalWrite(ledPin, HIGH);  
                lightMode = 0;        
              }
            }
          }
          buttonState = val;            
        }




      if ( millis() - lastButtonPushMillis > 2000) {    // 7200000L milliseconds is 2 hours
        turnOff();
        lightMode = 1;
      }

    }

    }


    void turnOff(){

       digitalWrite(ledPin, LOW);  //Temp code Need Sleep mode Code



        set_sleep_mode(SLEEP_MODE_PWR_DOWN);
        sleep_enable();
        MCUCR &= ~(_BV(ISC01) | _BV(ISC00));      //INT0 on low level
        GIMSK |= _BV(INT0);                       //enable INT0
        byte adcsra = ADCSRA;                     //save ADCSRA
        ADCSRA &= ~_BV(ADEN);                     //disable ADC
        cli();                                    //stop interrupts to ensure the BOD timed sequence executes as required
        byte mcucr1 = MCUCR | _BV(BODS) | _BV(BODSE);  //turn off the brown-out detector
        byte mcucr2 = mcucr1 & ~_BV(BODSE);
        MCUCR = mcucr1;
        MCUCR = mcucr2;
        sei();                                    //ensure interrupts enabled so we can wake up again
        sleep_cpu();                              //go to sleep
        sleep_disable();                          //wake up here
        ADCSRA = adcsra;

    }

    ISR(INT0_vect)
    {
        GIMSK = 0;                     //disable external interrupts (only need one to wake up)
    }
     
     
  2. Daniil

    Daniil Гуру

    Мне кажется, что в процедуре turnoff вы и усыпляете, и пробуждаете камушек?
    Как я понял, вы готовите мк ко сну, вкл прерывание и засыпаете (sleep_cpu), как только происходит прерывание выполнение кода продолжается.
    А что делает lightmode? Может вы с ифами что-то перепутали?
     
  3. Asper Daffy

    Asper Daffy Иксперд

    Что просыпался именно "по долгому" - это вопрос не скетча, а внешней обвязки. Чтобы скетч заработал, надо чтобы она уже проснулась! Пока не проснётся - скетч не работает.

    Поставь на кнопку RC цепочку с нужной постоянной времени (2 сек вроде надо, но по мне это слишком много) и в скетче ничего делать не надо. Нажал, подержал пока сработает - пошло прерывание.
     
  4. Jazzy

    Jazzy Нерд

    Скетч косячный, да. Это "конструктор")
    Там все было еще хуже..
    lightmode - статус для светодиода вроде)

    Если убрать sleep_disable(); - ситуация не меняется.
     
  5. Jazzy

    Jazzy Нерд

    Спасибо. Думал об этом и находил подобное предложение, но, хотелось бы без "лишних деталей" реализовать)
     
  6. parovoZZ

    parovoZZ Гуру

    а сон какой? Их там несколько с разной реакцией на внешние прерывания...
     
  7. Jazzy

    Jazzy Нерд

    Думается. Надо просыпаться по WDT и, если после пробуждения проходит менее 2с до "отжатия" кнопки, засыпать обратно. Если после 2с кнопка еще нажата - продолжать бодрствовать.
     
  8. parovoZZ

    parovoZZ Гуру

    sleep_disable не делает ничего. Он просто запрещает инструкцию sleep_cpu(). Это если она вызвана не в то время и не в том месте....
     
  9. Jazzy

    Jazzy Нерд

    Самый глубокий - SLEEP_MODE_PWR_DOWN
     
  10. parovoZZ

    parovoZZ Гуру

    просыпаться надо по прерыванию от пина, взводить WDT на около 2 секунды и засыпать. Если по пробуждению состояние пина не изменилось - цель достигнута.
     
  11. Jazzy

    Jazzy Нерд

    Я так и просыпаюсь - "INT0_vect - внешнее прерывание 0"
    Не понимаю пока, как взводить WDT правильно
     
    Последнее редактирование: 26 июл 2019
  12. parovoZZ

    parovoZZ Гуру

    Реально просыпаешься или пока только в коде? С этим вектором есть нюансы. Проще всего подписаться на PCINTx прерывание.
    чтобы с ним играться в адруине, нужен оптибут бутлодырь.
    Как работать с вачдогом я писал неоднократно в своих темах.
     
  13. Jazzy

    Jazzy Нерд


    Реально просыпаюсь/засыпаю. Ток падает на порядок.

    Добавил вот такое:

    WDTCSR = bit (WDCE) | bit (WDE);
    // set interrupt mode and an interval
    WDTCSR = bit (WDIE) | bit (WDP0) | bit (WDP3); // set WDIE, and 8 seconds delay
    wdt_reset(); // pat the dog

    Но работает пока не очень правильно
     
  14. Jazzy

    Jazzy Нерд

    На данном этапе решил проблему добавлением в схему мосфета для управления питанием.
    Сделал хитрый цикл "на таймере" - включение по нажатию, выключение по долгому нажатию кнопки.

    Теперь задумался, может тем же хитрым циклом усыплять/будить Тиньку...

    Подскажите, возможно ли в режиме сна сделать потребление в районе 3мкА?
    Если да, то как это сделать?
     
  15. parovoZZ

    parovoZZ Гуру

    С включенным вачдогом меньше 4 мкА на устаревшем атмеловском хламе не прыгнешь. Без вачдога порядка 200-500 нА. Если хочется и таймер во сне и малый ток, то есть несколько путей:
    1. Сменить МК.
    2. Поставить наноамперный таймер от TI.

    Ну и ознакомиться с моими темами по поводу многолетней жизни от дохлых батареек.
     
  16. Jazzy

    Jazzy Нерд

    На attiny84 без вачдога, возможно?

    Даже 4 мкА - норм
     
  17. Jazzy

    Jazzy Нерд

    Основной вопрос, какими строками отключать всё лишнее в режиме сна.
    С регистрами мало работал, а еще пол года разбираться - нет времени, проект горит.

    Если кто может "в лоб" подсказать, буду реально благодарен!
     
  18. parovoZZ

    parovoZZ Гуру

    В режиме deep_sleep оно само всё выключится - тактовый генератор остановлен. Исключение АЦП - если оно включается, то его обязательно надо выключить.
    Ну и не забывать все ноги перевести на выход (кроме кнопок). Кнопочные ноги либо на землю через кнопку повесить, либо включить подтяжку. Но не оставлять висящими - минимум 5 мкА набежит на ровном месте.
    У этой серии 24/44/84 вроде есть не PicoPower - их не брать. Лень дашик искать.
     
    Jazzy нравится это.
  19. DetSimen

    DetSimen Guest

    обычно на вход переводят, чтоб жрало меньше, не?
     
  20. parovoZZ

    parovoZZ Гуру

    Регистр входа всегда подключен к ноге.