Не могу разбудить Attiniy44 из режима сна_mode_pwr_down

В настоящее время я играю со спящими режимами. Когда я нажимаю кнопку, начинается мелодия, снова нажимаю, чтобы перейти в глубокий сон и экономить батарею 3 В, снова нажимаю, чтобы проснуться, и мелодия начинается снова. Но похоже, что он не полностью засыпает и не может проснуться.

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

#define cs6 1109
#define fs5 740
#define d6 1175
#define c6 1047
#define f5 698
#define b5 988
#define e5 659
#define bf5 932
#define ef5 622
#define b4 494
#define g5 784
#define led1 8
#define led2 7

const uint16_t halloween[] PROGMEM = { cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
                                       cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
                                       cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
                                       cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
                                       cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
                                       cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
                                       c6,  f5,  f5,  c6,  f5,  f5,  c6,  f5, cs6,  f5,
                                       c6,  f5,  f5,  c6,  f5,  f5,  c6,  f5, cs6,  f5,
                                       cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
                                       cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
                                       c6,  f5,  f5,  c6,  f5,  f5,  c6,  f5, cs6,  f5,
                                       c6,  f5,  f5,  c6,  f5,  f5,  c6,  f5, cs6,  f5,
                                       b5,  e5,  e5,  b5,  e5,  e5,  b5,  e5,  c6,  e5,
                                       b5,  e5,  e5,  b5,  e5,  e5,  b5,  e5,  c6,  e5,
                                       bf5, ef5, ef5, bf5, ef5, ef5, bf5, ef5,  b5, ef5,
                                       bf5, ef5, ef5, bf5, ef5, ef5, bf5, ef5,  b5, ef5,
                                       b5,  e5,  e5,  b5,  e5,  e5,  b5,  e5,  c6,  e5,
                                       b5,  e5,  e5,  b5,  e5,  e5,  b5,  e5,  c6,  e5,
                                       bf5, ef5, ef5, bf5, ef5, ef5, bf5, ef5,  b5, ef5,
                                       bf5, ef5, ef5, bf5, ef5, ef5, bf5, ef5,  b5, ef5,
                                       fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
                                       fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
                                       fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
                                       fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
                                       fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
                                       fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
                                       fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
                                       fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
                                       fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4
                                     };
                                     

typedef enum {
  ACTION_OFF,
  ACTION_ON
}
MyActions;

const int buzzer = PA1;
unsigned long previousMillis = 0;
unsigned long pauseBetweenNotes = 218;
int noteDurations = 6;
int thisNote=0;
int ledState = LOW;

OneButton button(10, true, true);

MyActions nextAction = ACTION_OFF; // никаких действий при запуске

void setup() {
  pinMode(buzzer, OUTPUT);
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(10), wakeUpFromSleep, FALLING);
  button.attachClick(myClickFunction);

}

void melody () {

  unsigned long currentMillis = millis();

  if (thisNote <= 290 && currentMillis - previousMillis >= pauseBetweenNotes)
  {
    previousMillis = currentMillis;

    if (ledState == LOW) {

      ledState = HIGH;

      tone(buzzer, pgm_read_word(&halloween[thisNote]), 168);
      pauseBetweenNotes = 167 * 0.65;
      thisNote++;
    }

    else {

      ledState = LOW;
    }
    digitalWrite(led1, ledState);
    digitalWrite(led2, ledState);

  }
}

void wakeUpFromSleep() {
  // Активация прерывания при пульсации
  detachInterrupt(digitalPinToInterrupt(10));
  sleep_disable();
  power_all_enable();
 }

void myClickFunction() {
  
  if (nextAction == ACTION_OFF)
  {
    nextAction = ACTION_ON;
    thisNote = 0;
    pauseBetweenNotes = 0;
    previousMillis = 0;
  }
  
  else
  {
    nextAction = ACTION_OFF;
    digitalWrite(led1, LOW);  // Спегни я вел
    digitalWrite(led2, LOW);
    noTone(buzzer);
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    sleep_enable();
    sleep_cpu();
  }
}

void loop() {
  
  button.tick();
  
  if (nextAction == ACTION_OFF) {
    wakeUpFromSleep();
  }

  else if (nextAction == ACTION_ON) {
    melody();
    }
}

, 👍0

Обсуждение

Когда вы нажимаете кнопку , высока вероятность того, что прерывание деактивировано. Вы прикрепляете прерывание в процедуре установки, но затем отсоединяете его с помощью первого бег по «петле». Без активного прерывания и после первого нажатия кнопки MCU спит и повторное нажатие кнопки ничего не делает., @Peter Paul Kiefer

Итак, вы думаете, что я должен прикрепить прерывание где-то еще?, @tommy

attachInterrupt(digitalPinToInterrupt(10)), невозможно полностью понять, не зная, какую конфигурацию ядра какой платы вы используете., @timemage

Я использую микроконтроллер attiny44a, а контакт кнопки подключен к контакту PB0., @tommy

Это не совсем то, что я спросил, но это важная информация для правильного ответа, который вы должны отредактировать в своем вопросе., @timemage

Я написал Attiny44 в заголовке моей темы, я должен также вставить вопрос в текст?, @tommy

«attiny44» — это не «какую конфигурацию ядра платы вы используете». Вы можете по крайней мере включить «PB0» в свой вопрос, чтобы кто-то (не я) мог объяснить вам, почему attachInterrupt просто не будет работать с этим выводом. И почему он не просыпается с этим контактом., @timemage

Согласно техническому описанию, внешнее прерывание запускается любым контактом PCINT[11:0], поэтому я думаю, что PB0 подходит для attachInterrupt., @tommy

Я понимаю ваше замешательство. Но это не тот случай. attachInterrupt работает с INT#, а не PCINT#. Это разные вещи. Важно отметить, что ни один из PCINT не разбудит ваш чип после отключения питания., @timemage

хорошо, так что новый код никогда не будет работать, мне нужно полностью переделать....., @tommy

И для вывода кнопки я должен использовать PB2, который, согласно таблице данных, имеет INT0., @tommy

Итак, я нашел еще одну таблицу данных, и в ней PCINT отмечен как источник пробуждения в таблице, а не только в утверждении в другом месте таблицы. Чтобы подтвердить, что это не просто ошибка, я установил T44A с включенным предохранителем CKOUT, убедившись, что он перестает выводить часы в спящем режиме отключения питания. Настроил PCINT и запустил его с помощью кнопки, и он действительно разбудил и возобновил производство CKOUT. Так по крайней мере с Т44А проверено будить с PCINT. Часть, касающаяся PCINT и attachInterrupt, остается в силе; поэтому вам нужно будет интегрировать библиотеку NicoHood для этой части., @timemage

Да, я использовал его библиотеку, и с PB0, похоже, работает отключение питания., @tommy


1 ответ


2

Обновлено Я написал следующую программу. Он должен предоставлять запрашиваемые функции.

Но пока у меня нет доступа к ATtiny44a, поэтому я использовал Arduino UNO. Я прочитал оба даташита и не нашел ничего, что мешало бы программе работать на ATtiny44. Поэтому, пожалуйста, попробуйте его, и если он заработает, вы можете прочитать комментарии в программе, чтобы понять, что я сделал, чтобы заставить ее работать.

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

Ах, и я немного ускорил мелодию ;-). Мне нравится Heavy Metal больше, чем стиль Walzing Matilda ;-). И я меняю программу так, чтобы она запускала мелодию снова и снова, пока ты снова не нажмешь кнопку. Ваша Программа однажды перестала часто воспроизводить мелодию.

// Этот код предназначен для работы на обычном Arduino Uno
// Первоначальный запрос состоял в том, чтобы реализовать это для ATtiny44a.
// Я задокументирую, если есть разница
// во внимание. Большая часть кода должна выполняться на
// также attiny44.

// Цель этой программы — позволить микроконтроллеру воспроизвести мелодию
// запускается и останавливается нажатием кнопки. MCU должен войти
// энергосберегающий спящий режим при остановке мелодии.
// В спящем режиме нажатие кнопки должно разбудить MCU
// который затем должен продолжить воспроизведение мелодии.

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

// Контакт кнопки должен быть вторым для Arduino Uno
// для крошечного можно использовать любой вывод, так что вывод 2 подойдет.
const int buttonPin = 2;
const int buzzerPin = 10;
const int led1 = 8;
const int led2 = 7;

// Внимание!!!!: Я использую подтяжку и кнопку
// подключен к GND.
// С этой настройкой нажатие на кнопку приведет контакт к GND.
// Поэтому мы читаем LOW, пока кнопка нажата.
// Если кнопка ВЫСОКАЯ активна - это означает, что кнопка
// подключен к VCC - LOW следующей константы должен
// изменить на HIGH, а RISING нужно изменить на FALLEN.
#define BUTTON_PRESSED LOW
#define INTERRUPT_TRIGGER_METHOD RISING

// Я решил использовать очень большую задержку для устранения дребезга, потому что
// показал очень "веселый" кнопка. Не стесняйтесь экспериментировать
// с этой задержкой.
const long debounceDelay = 150L;


// установка мелодии

// определяем значения высоты тона ноты
#define cs6 1109
#define fs5 740
#define d6 1175
#define c6 1047
#define f5 698
#define b5 988
#define e5 659
#define bf5 932
#define ef5 622
#define b4 494
#define g5 784

// предоставить мелодию в виде массива.
const uint16_t halloween[] PROGMEM = { 
  cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
  cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
  cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
  cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
  cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
  cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
  c6,  f5,  f5,  c6,  f5,  f5,  c6,  f5,  cs6,  f5,
  c6,  f5,  f5,  c6,  f5,  f5,  c6,  f5,  cs6,  f5,
  cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
  cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
  c6,  f5,  f5,  c6,  f5,  f5,  c6,  f5,  cs6,  f5,
  c6,  f5,  f5,  c6,  f5,  f5,  c6,  f5,  cs6,  f5,
  b5,  e5,  e5,  b5,  e5,  e5,  b5,  e5,  c6,  e5,
  b5,  e5,  e5,  b5,  e5,  e5,  b5,  e5,  c6,  e5,
  bf5, ef5, ef5, bf5, ef5, ef5, bf5, ef5,  b5, ef5,
  bf5, ef5, ef5, bf5, ef5, ef5, bf5, ef5,  b5, ef5,
  b5,  e5,  e5,  b5,  e5,  e5,  b5,  e5,  c6,  e5,
  b5,  e5,  e5,  b5,  e5,  e5,  b5,  e5,  c6,  e5,
  bf5, ef5, ef5, bf5, ef5, ef5, bf5, ef5,  b5, ef5,
  bf5, ef5, ef5, bf5, ef5, ef5, bf5, ef5,  b5, ef5,
  fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
  fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
  fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
  fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
  fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
  fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
  fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
  fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
  fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4
};

// определяем переменные обработки для функции воспроизведения
unsigned long previousMillis = 0;
unsigned long pauseBetweenNotes = 300;
unsigned long lengthOfActiveNote = 300;
int noteCounter = 0;
boolean toneOn = false;

// обработка режима воспроизведения
// после вставки батарейки мелодия не играет.
// После того, как пользователь нажал и отпустил
// кнопка, мы начнем с мелодии.
volatile boolean playMelody = false;
volatile bool playModeChangeRequested = false;

// чтение и устранение дребезга кнопки
volatile unsigned long lastDebouncingMillis = 0;


void stopTheMelody()
{
  noTone(buzzerPin);
  toneOn = false;
  digitalWrite(led1, toneOn);
  digitalWrite(led2, toneOn);  
}

void startTheMelody()
{
  previousMillis = 0;
  pauseBetweenNotes = 0;
  noteCounter = 0;
  toneOn = false;
  digitalWrite(led1, toneOn);
  digitalWrite(led2, toneOn);  
}

void melody () 
{
  unsigned long currentMillis = millis();
  if (! toneOn && 
      (currentMillis - previousMillis) > pauseBetweenNotes)
  {
    pauseBetweenNotes = 167 * 0.2;
    tone(buzzerPin, pgm_read_word(&halloween[noteCounter]));
    noteCounter++;    
    if (noteCounter > 290)
    {
      // старая программа проигрывает мелодию только один раз
      // со сбросом счетчика банкнот в 0
      // мелодия запускается снова и снова.
      noteCounter = 0;
    }
    toneOn = true;
    digitalWrite(led1, toneOn);
    digitalWrite(led2, toneOn);  
    previousMillis = currentMillis;
  }
  else if(toneOn && 
          (currentMillis - previousMillis) > lengthOfActiveNote)
  {
    lengthOfActiveNote = 58;
    noTone(buzzerPin);
    toneOn = false;
    digitalWrite(led1, toneOn);
    digitalWrite(led2, toneOn);  
    previousMillis = currentMillis;
  } 
}

// Это процедура обслуживания прерывания.
// Он вызывается каждый раз, когда кнопка будет отпущена.
void ISR_buttonReleased()
{ 
  // Здесь мы знаем, что этот ISR вызывается, потому что,
  // кнопка была отпущена.
  lastDebouncingMillis = 0L;
  playModeChangeRequested = true;

  if (!playMelody)
  {
    // если прерывание сработало во время сна MCU
    // нам нужно выключить спящий режим, чтобы возобновить работу
    // нормальная активность. В противном случае метод устранения дребезга не работает.
    // работать, как это делает код вне ISR.
    sleep_disable();
    power_all_enable();
  }
}

void setup()
{
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(buzzerPin, OUTPUT);

  // настройка паранойи
  playMelody = false;
  playModeChangeRequested = false;
  lastDebouncingMillis = 0;
  
  // прерывание срабатывает по переднему фронту, т.е.
  // когда кнопка будет отпущена
  attachInterrupt(
       digitalPinToInterrupt(buttonPin), 
       ISR_buttonReleased, 
       INTERRUPT_TRIGGER_METHOD);

  // остановить мелодию и спать
  stopTheMelody();
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sleep_cpu();
}

void loop()
{
  // lastDebouncingMillis будет установлено в 0 1st) в
  // подпрограмма установки и 2-я) в ISR.
  if (lastDebouncingMillis==0 || 
      digitalRead(buttonPin)==BUTTON_PRESSED)
  {
    // Вот волшебство!
    // Синхронизируем ISR, спящий режим, длинная кнопка
    // нажмите без отпускания и
    // кнопка подпрыгивает с этим единственным оператором if.
    lastDebouncingMillis = millis();
  }  
  
  if (playModeChangeRequested) 
  {
    unsigned long tempMillis = millis();
    if((tempMillis - lastDebouncingMillis) > debounceDelay)
    {      
      playModeChangeRequested = false;
      playMelody = !playMelody;
      if (!playMelody)
      {
        // остановить мелодию и спать
        stopTheMelody();
        set_sleep_mode(SLEEP_MODE_PWR_DOWN);
        sleep_enable();
        sleep_cpu();
      }
      else
      {
        startTheMelody();
      }
    }
  }
  
  if(playMelody)
  {
      melody();
  }      
}

Старый ответ удален

Старый ответ был недостаточно ясен для этой сложной темы.

,

**Комментарии были [перемещены в чат](https://chat.stackexchange.com/rooms/144738/discussion-on-answer-by-peter-paul-kiefer-cant-wake-up-my-attiniy44-from -спать); пожалуйста, не продолжайте обсуждение здесь. ** Перед публикацией комментария под этим, пожалуйста, ознакомьтесь с [целями комментариев](/help/привилегии/комментарий). Комментарии, которые не требуют пояснений или предложений по улучшению, обычно относятся к [ответу](/help/how-to-answer), [мета] или [чату]. Комментарии, продолжающие обсуждение, могут быть удалены., @Juraj