ATtiny2313A и спящий режим
- Войдите на сайт для отправки комментариев
Надеюсь, вопрос об ATtiny не будет оффтопом на ардуиновском форуме :) . В свое оправдание скажу, что прошивал ее через Arduino ISP.
Итак, имеется ATtiny2313A. Согласно даташиту она поддерживает сон в режимах idle, stand-by и power-down. В реальности вроде как первый не срабатывает, во вторые два отправить удается, но при этом по прерыванию не просыпается.
Собственно, тестовый скетч (не обращайте внимания, что два раза digitalWrite(pwLed, HIGH) - хуже от этого не будет, просто на всякий случай, пока не разобрался до конца, как это работает):
#include <avr/sleep.h>
#include <avr/power.h>
// Кнопка пробуждения
const int btnUp=4;
const int btnInterrupt=0;
// Светодиод активного режима
const int pwLed=13;
// Ожидание до засыпания, мс
const int waitSleep = 5000;
void setup() {
pinMode(pwLed, OUTPUT);
digitalWrite(pwLed, HIGH);
pinMode(btnUp, INPUT);
}
void loop() {
delay(waitSleep);
sleepNow();
}
void sleepNow() { // Спим
attachInterrupt(btnInterrupt, wakeUpNow, CHANGE);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
//set_sleep_mode(SLEEP_MODE_STANDBY);
//set_sleep_mode(SLEEP_MODE_IDLE);
digitalWrite(pwLed, LOW);
sleep_enable();
sleep_mode();
sleep_disable();
detachInterrupt(btnInterrupt);
digitalWrite(pwLed, HIGH);
}
void wakeUpNow() { // Просыпаемся - включаем диодик
digitalWrite(pwLed, HIGH);
}
Собственно, если в скрипте устанавливаем set_sleep_mode(SLEEP_MODE_IDLE), то контрольный диод не гаснет вообще, если SLEEP_MODE_PWR_DOWN или SLEEP_MODE_STANDBY - то он гаснет секунд через 5 после включения, но потом не загорается, даже если подать +5В на 6 контакт.
О схеме: на 16 выводе МК (13 пин в терминологии arduino ide) через резистор 1k подключен диод-индикатор, 1 вывод (reset) через 10k резистор выведен на +5В, 6 вывод (4пин arduino, к которому, согласно даташиту привязано прерывание 0) тоже через 10k - на ноль. Также на 6 выводе имеется проводок (вместо кнопки), замыкая который на +5В я пытаюсь вывести тиньку из спячки.
Не могу понять - где моя ошибка?
Да, забыл помянуть - кварца нет, чип работает от внутреннего генератора частоты. На всякий случай пробовал скрипт при работе и на 1MHz и на 8MHz.
лень даташит смотреть - а прерывание INT0 точно на 4 пине?
и обычно строку 34 заносят внутрь функции прерывания первой строкой
еще включение прерывания я бы поставил перед самым сном sleep_mode
и sleep disable тоже бы воткнул внутрь функции прерывания
короче вот минимальный пример но для UNO
#include <avr/sleep.h> #include <avr/interrupt.h> #define KEYPIN 2 // wakeup pin to GND INT0 void wakeUp() { sleep_disable(); detachInterrupt(0); } void setup() { // put your setup code here, to run once: pinMode(KEYPIN, INPUT); // wakeup pin to GND digitalWrite(KEYPIN, HIGH); // up resistor to on // OFF unused pins for (byte i = 0; i <= 19; i++) { if (i == KEYPIN) { continue; } pinMode (i, OUTPUT); // changed as per below digitalWrite (i, LOW); // ditto } // Flash quick sequence so we know setup has started for (int k = 0; k < 10; k = k + 1) { if (k % 2 == 0) { digitalWrite(LED_BUILTIN, HIGH); } else { digitalWrite(LED_BUILTIN, LOW); } delay(250); } // for } void sleep() { // disable ADC ADCSRA = 0; // sleep set_sleep_mode (SLEEP_MODE_PWR_DOWN); sleep_enable(); // turn off brown-out enable in software MCUCR = bit (BODS) | bit (BODSE); MCUCR = bit (BODS); // interrupt attachInterrupt(0, wakeUp, LOW); sleep_mode(); //Спим (Прерывания продолжают работать.) Программа останавливается. } // sleep void loop() { // put your main code here, to run repeatedly: sleep(); digitalWrite(LED_BUILTIN, HIGH); delay(2000); digitalWrite(LED_BUILTIN, LOW); }Не могу понять - где моя ошибка?
Ошибка во внимательности к даташиту.
В PowerDownSleep моде нет системного клока, а значит нельзя определить фронт.
Внимательно читаем стр 49 и 50 ДШ и пробуждаем так:
1. подтягиваем INT0 не к 0, а К ПИТАНИЮ!
2. прерывание не по CHANGE, а по LOW.
3. прерывание вызываем кратковременным замыканием ноги 6 (я так понял ДИП корпус?) на землю.
Огромное спасибо, работает :) !