Не могу разбудить 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();
}
}
@tommy, 👍0
Обсуждение1 ответ
Обновлено Я написал следующую программу. Он должен предоставлять запрашиваемые функции.
Но пока у меня нет доступа к 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
- Как сгенерировать аппаратное прерывание в mpu6050 для пробуждения Arduino из режима SLEEP_MODE_PWR_DOWN?
- Как перевести ATtiny/ATmega в режим глубокого сна (чтобы годами работать от батарей), но при этом обнаруживать нажатие кнопки?
- ESP8266 глубокий сон и MQTT
- ESP.deepSleep() — снова и снова?
- Пользовательская функция сна для Nextion
- Вывод ESP8266 из deepSleep с помощью кнопки
- PIR движение выводит ESP8266 из глубокого сна
- Память ESP8266 RTC (для загрузки)
Когда вы нажимаете кнопку , высока вероятность того, что прерывание деактивировано. Вы прикрепляете прерывание в процедуре установки, но затем отсоединяете его с помощью первого бег по «петле». Без активного прерывания и после первого нажатия кнопки 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