ATtiny2313A и спящий режим

rygoravich
Offline
Зарегистрирован: 04.05.2016

Надеюсь, вопрос об 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В я пытаюсь вывести тиньку из спячки.

Не могу понять - где моя ошибка?

 
rygoravich
Offline
Зарегистрирован: 04.05.2016

Да, забыл помянуть - кварца нет, чип работает от внутреннего генератора частоты. На всякий случай пробовал скрипт при работе и на 1MHz и на 8MHz.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

лень даташит смотреть - а прерывание INT0 точно на 4 пине?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

и обычно строку 34 заносят внутрь функции прерывания первой строкой

еще включение прерывания я бы поставил перед самым сном sleep_mode

и sleep disable тоже бы воткнул внутрь функции прерывания

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

короче вот минимальный пример но для 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);
}

 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

rygoravich пишет:

Не могу понять - где моя ошибка?

 

Ошибка во внимательности к даташиту.

В PowerDownSleep моде нет системного клока, а значит нельзя определить фронт.

Внимательно читаем стр 49 и 50 ДШ и пробуждаем так:

1. подтягиваем INT0 не к 0,  а К ПИТАНИЮ!

2. прерывание не по CHANGE, а по LOW.

3. прерывание вызываем кратковременным замыканием ноги 6 (я так понял ДИП корпус?) на землю.

 

rygoravich
Offline
Зарегистрирован: 04.05.2016

Огромное спасибо, работает :) !