Attiny13-выход из сна

gzp13
Offline
Зарегистрирован: 06.04.2015

Здравствуйте. Кучу всего перечитал, но не разобрался.Как можно реализовать выход Attiny13 из сна? Суть такая, три положения на передатчике. Ставлю тумблер в положение 1-приемник принимает сигнал PWM(длительность 1500мс). Attiny13 принимает этот сигнал в обычном режиме. А можно сделать так, чтобы она спала, а как только пришел этот сигнал она просыпалась, выполняла какое то действие и снова засыпала. Аналогично и далее, тумблер в положение 2( длительность сигнала 2000мс)-опять проснулась и сделала что то и снова в спячку.

nik182
Offline
Зарегистрирован: 04.05.2015

Нет. Она может проснуться по сигналу, но спя не может определить, что это за сигнал. 

gzp13
Offline
Зарегистрирован: 06.04.2015

nik182 пишет:

Нет. Она может проснуться по сигналу, но спя не может определить, что это за сигнал. 

т.е это должно быть нажатие физическое кнопки?

nik182
Offline
Зарегистрирован: 04.05.2015

Необязательно. Запрограммировать можно почти любое прерывание - тот же фронт от сигнала PWM.   

gzp13
Offline
Зарегистрирован: 06.04.2015

nik182 пишет:

Необязательно. Запрограммировать можно почти любое прерывание - тот же фронт от сигнала PWM.   

Вот я написал код, но он не работает.

//Установить частоту платы 9.6МГц
#include <avr/io.h> // принято подключать
#include <avr/wdt.h> // здесь организована работа с ватчдогом
#include <avr/sleep.h> // здесь описаны режимы сна
#include <avr/interrupt.h> // работа с прерываниями
#define F_CPU 9600000UL // 9.6 MHz
#define PPM_pin 1
int PPM;
unsigned long time;
unsigned long previoustime=0;
int count=0;

ISR (WDT_vect) { // данна функция вызывается по прерыванию при срабатывании wdt
                 // если wdt не сбросить, то будет резет
  wdt_reset();         // сбрасываем wdt сторож
  WDTCR |= _BV(WDTIE); // разрешение прерываний от сторожевого таймера 
  count++; 
}
ISR(PCINT0_vect)
{
  watch();  
}

void setup()
{ 
  DDRB &= ~(1<<1);
  DDRB |= (1<<0);
  DDRB |= (1<<2);
  DDRB |= (1<<4);
  GIMSK |= (1<<PCIE); // Разрешаем внешние прерывания PCINT0.
  PCMSK |= (1<<1); // Разрешаем по маске прерывания на ногак кнопок (PCINT1)
  sei(); // Разрешаем прерывания глобально: SREG |= (1<<SREG_I)
  
  wdt_enable(WDTO_8S); // разрешаем ватчдог каждые 8сек.
  WDTCR |= _BV(WDTIE); // разрешаем прерывания по ватчдогу. Иначе будет резет.
  sei();               // разрешаем прерывания
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // если спать - то на полную
  wdt_reset(); // сбрасываем    
}

void loop()
 {
  PPM_read();
   watch();

    wdt_reset();    // перед сном сбрасываем, чтобы спать все отведенное время
      sleep_enable(); // разрешаем сон
      sleep_cpu();    // спать! 
}



//=============================================================================
//                           Считывание сигнала PPM
//=============================================================================
void PPM_read(){
  while (!(PINB & (1<<PINB1)));    //когда на пине РВ1 0
   time = micros();
  while (PINB & (1<<PINB1));      //когда на пине РВ1 1   
  time = micros()-time;
  if (time>980 && time<3000) PPM = time;
}
//========================================================
//если произощло прерывание на PB1////////////////////////////
//==================================================
void watch()          // должна проснуться если пришел сигнал на PB1
{
   if (PPM <1200 ) 
       {     
   PORTB &= ~(1<<0);
   PORTB &= ~(1<<2);
   PORTB &= ~(1<<4);
}

 if (PPM < 1550 && PPM> 1200) 
 {
    unsigned long time1=micros();
if ( time1-previoustime>25000)
{  
  previoustime=time1;
   PORTB ^= (1 << PB0);
PORTB ^= (1 << PB2);
PORTB ^= (1 << PB4);    
 }
 }
    if (PPM > 2020) {
     PORTB |= (1<<0); 
     PORTB |= (1<<2); 
     PORTB |= (1<<4); //digitalWrite (0, HIGH);
    
    }
if(count>=20)  спим 160 сек.
{
count=0;
}
}

 

nik182
Offline
Зарегистрирован: 04.05.2015

В режиме сна PWR_DOWN только intpc0 и вачдог работают. Читайте мануал стр 30 табд. 7-1. Почему это кто то должен делать за  Вас? 

gzp13
Offline
Зарегистрирован: 06.04.2015

nik182 пишет:

В режиме сна PWR_DOWN только intpc0 и вачдог работают. Читайте мануал стр 30 табд. 7-1. Почему это кто то должен делать за  Вас? 

Вот подправил, но все равно не так работает. Надо чтобы был режим POWER DOWN и контроллер выходил из этого режима по сигналу на PB0(PCINT0). А работает либо спящий режим если закомментировать строку        GIMSK |= (1<<PCIE); или PCCMSK |= (1<<0);    или если раскомментировать эти строки , то работает прерывание на PB0 но не работает режим POWER DOWN. Подсобите светом что не так, люди добрые)

//Установить частоту платы 9.6МГц
#include <avr/io.h> // принято подключать
#include <avr/wdt.h> // здесь организована работа с ватчдогом
#include <avr/sleep.h> // здесь описаны режимы сна
#include <avr/interrupt.h> // работа с прерываниями
#define F_CPU 9600000UL // 9.6 MHz
#define PPM_pin 1
int PPM;
unsigned long time;
unsigned long previoustime=0;
int count=0;

ISR (WDT_vect) { // данна функция вызывается по прерыванию при срабатывании wdt
                 // если wdt не сбросить, то будет резет
  wdt_reset();         // сбрасываем wdt сторож
  WDTCR |= _BV(WDTIE); // разрешение прерываний от сторожевого таймера 
   PORTB ^= (1 << 3); // это для проверки работы WATCHDOG
}

ISR(PCINT0_vect)
{
   watch();  
  }
void setup()
{ 
  DDRB &= ~(1<<0);
  DDRB |= (1<<1);
  DDRB |= (1<<2);
  DDRB |= (1<<4);
  DDRB |= (1<<3);
   
  MCUCR |= (0 << ISC01) | (0 << ISC00);
MCUCR |= (1<<SM1); // power-down mode
 MCUCR &= ~(1<<SM0); // power-down mode
 GIMSK |= (1<<PCIE); // Разрешаем внешние прерывания PCINT0.
  PORTB |= (1<<3);
  PCMSK |= (1<<0); // Разрешаем по маске прерывания на ногак кнопок (PCINT0)
  PRR = (1<<PRADC); // shut down ADC
  sei(); // Разрешаем прерывания глобально: SREG |= (1<<SREG_I)
  ADCSRA &= ~(1 << ADEN);
  wdt_reset(); // сбрасываем    
  wdt_enable(WDTO_4S); // разрешаем ватчдог каждые 8сек.
  WDTCR |= _BV(WDTIE); // разрешаем прерывания по ватчдогу. Иначе будет резет.
  
 sei();               // разрешаем прерывания
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // если спать - то на полную
 }
void loop()
 {
  PPM_read();
    wdt_reset();    // перед сном сбрасываем, чтобы спать все отведенное время
      sleep_enable(); // разрешаем сон
      sleep_cpu();    // спать! 
}



//=============================================================================
//                           Считывание сигнала PPM
//=============================================================================
void PPM_read(){
  
  while (!(PINB & (1<<0)));    //когда на пине РВ1 0
   time = micros();
  while (PINB & (1<<0));      //когда на пине РВ1 1   
  time = micros()-time;
  if (time>980 && time<3000) PPM = time;
}
//========================================================
//если произощло прерывание на PB1////////////////////////////
//==================================================
void watch()          // должна проснуться если пришел сигнал на PB0
{
   if (PPM <1200 ) 
       {     
   PORTB &= ~(1<<1);
   PORTB &= ~(1<<2);
   PORTB &= ~(1<<4);
}

 if (PPM < 1550 && PPM> 1200) 
 {
    unsigned long time1=micros();
if ( time1-previoustime>25000)
{  
  previoustime=time1;
   PORTB ^= (1 << 1);
PORTB ^= (1 << 2);
PORTB ^= (1 << 4);    
 }
 }
    if (PPM > 2000) {
     PORTB |= (1<<1); 
     PORTB |= (1<<2); 
     PORTB |= (1<<4); //digitalWrite (0, HIGH);
    }

}
gzp13
Offline
Зарегистрирован: 06.04.2015

 Хотя меряю тестером,ток без sleep enable 4.4мА, добавляю эти строки ток составляет 0.27мА, т.е как я понимаю спящий режим работает? Но вот в скетче BLINK ток в спящем режиме составляет 7мкА, сам измерял. Почему же в моем скетче ток потребления выше?

b707
Offline
Зарегистрирован: 26.05.2017

если импульс слишком короткий - просыпаться не будет. Для того чтоб МК просыпался по изменению уровня - измененый уровень должен сохранятся на все время выхода из спячки

Цитата:

Note that if a level triggered interrupt is used for wake-up from Power-down mode, the changed
level must be held for some time to wake up the MCU.

b707
Offline
Зарегистрирован: 26.05.2017

gzp13 пишет:

Хотя меряю тестером,ток без sleep enable 4.4мА

это - вообще без сна

 

Цитата:
добавляю эти строки ток составляет 0.27мА

много, это явно не POWER_DOWN - должны быть единицы мкА, а у вас сотни

Цитата:
Но вот в скетче BLINK ток в спящем режиме составляет 7мкА, сам измерял.

вот это похоже на правду

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

gzp13 пишет:

Почему же в моем скетче ток потребления выше?

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

gzp13
Offline
Зарегистрирован: 06.04.2015

andycat пишет:

gzp13 пишет:

Почему же в моем скетче ток потребления выше?

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

Я проверял, без переферии ток 7мкА. Что то я в скетче не так видимо сделал.

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

И? Мозг/логику включите, значит МК спит правильно, смотрите периферию и режим работы пинов в спящем режиме. Вариантов не много, или в ноль посадить в режиме выхода или в режим входа пины загнать при сне. После выхода из сна переводить в нужный рабочий режим.

gzp13
Offline
Зарегистрирован: 06.04.2015

andycat пишет:
И? Мозг/логику включите, значит МК спит правильно, смотрите периферию и режим работы пинов в спящем режиме. Вариантов не много, или в ноль посадить в режиме выхода или в режим входа пины загнать при сне. После выхода из сна переводить в нужный рабочий режим.

Мозг включил, сделал вывод что микроконтроллер спит правильно но не в моем скетче) Первый раз с режимом сна работаю, поэтому и обратился к спецам за помощью.) Вся периферия отключена. Пины как вы говорите загнать в режим входа в секции LOOP, а выводить в рабочий режим в секции ISR (WDT_vect) ?

Bruzzer
Offline
Зарегистрирован: 17.03.2020

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

gzp13
Offline
Зарегистрирован: 06.04.2015

Bruzzer пишет:

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

Проверил, сон работает как положено как только я отключаю прерывание на PB1(в регистр PCSMK записываю бит 0 в PCINT1). Как включаю сон не работает. Я так понимаю мне надо как то переконфигурировать порт PB1 чтобы он во сне работал как вход.Мне надо сделать прерывание из сна по изменению уровню сигнала.


//Установить частоту платы 9.6МГц
#include <avr/io.h> // принято подключать
#include <avr/wdt.h> // здесь организована работа с ватчдогом
#include <avr/sleep.h> // здесь описаны режимы сна
#include <avr/interrupt.h> // работа с прерываниями
#define F_CPU 9600000UL // 9.6 MHz
#define PPM_pin 1
int PPM;
unsigned long time;
unsigned long previoustime=0;
int count=0;

ISR (WDT_vect) { // данна функция вызывается по прерыванию при срабатывании wdt
                 // если wdt не сбросить, то будет резет
  wdt_reset();         // сбрасываем wdt сторож
  WDTCR |= _BV(WDTIE); // разрешение прерываний от сторожевого таймера
 PORTB ^= (1 << 3);   // для проверки сна
}

ISR(PCINT0_vect)
{
  watch();  
  }
void setup()
{ 
  DDRB &= ~(1<<1);
  DDRB |= (1<<0);
  DDRB |= (1<<2);
  DDRB |= (1<<4);
  DDRB |= (1<<3);
  PORTB |= (1<<3);
  
  MCUCR |= (0 << ISC01) | (0 << ISC00);
  MCUCR |= (1<<SM1); // power-down mode
  MCUCR &= ~(1<<SM0); // power-down mode
  GIMSK |= (1<<PCIE); // Разрешаем внешние прерывания PCINT0.
  MCUCR |= (1<<SE); 
  PCMSK |= (1<<1); // Разрешаем по маске прерывания на ногак кнопок (PCINT1)
  sei(); // Разрешаем прерывания глобально: SREG |= (1<<SREG_I)
  ADCSRA &= ~(1 << ADEN);
  wdt_reset(); // сбрасываем    
  wdt_enable(WDTO_4S); // разрешаем ватчдог каждые 8сек.
  WDTCR |= _BV(WDTIE); // разрешаем прерывания по ватчдогу. Иначе будет резет.
  
 sei();               // разрешаем прерывания
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // если спать - то на полную
 }
 
void loop()
 {
  PPM_read();
  PORTB &= ~(1<<3); //для проверки сна
    wdt_reset();    // перед сном сбрасываем, чтобы спать все отведенное время
    sleep_cpu();    // спать! 
    sleep_enable(); // разрешаем сон
     
}



//=============================================================================
//                           Считывание сигнала PPM
//=============================================================================

void PPM_read(){
  
  while (!(PINB & (1<<1)));    //когда на пине РВ1 0
   time = micros();
  while (PINB & (1<<1));      //когда на пине РВ1 1   
  time = micros()-time;
  if (time>980 && time<3000) PPM = time;
  
}
//========================================================
//если произощло прерывание на PB1////////////////////////////
//==================================================
void watch()          // должна проснуться если пришел сигнал на PB0
{
   if (PPM <1200 ) 
       {     
   PORTB &= ~(1<<0);
   PORTB &= ~(1<<2);
   PORTB &= ~(1<<4);
}

 if (PPM < 1550 && PPM> 1200) 
 {
    unsigned long time1=micros();
if ( time1-previoustime>25000)
{  
  previoustime=time1;
   PORTB ^= (1 << 0);
PORTB ^= (1 << 2);
PORTB ^= (1 << 4);    
 }
 }
    if (PPM > 2000) {
     PORTB |= (1<<0); 
     PORTB |= (1<<2); 
     PORTB |= (1<<4); //digitalWrite (0, HIGH);
    }

}

 

Bruzzer
Offline
Зарегистрирован: 17.03.2020

gzp13 пишет:

Bruzzer пишет:

Проверьте сначала сколько вы действительно спите ...

Проверил, сон работает как положено ...

Не знаю, как положено работать вашему сну, но если PB1 сигнал меняться не будет, то и сна не будет после первого срабатывания WDT, т.к. зависните в цикле PPM_read(). У вас вообще запутанный алгоритм. Непонятно зачем вам WDT, что вы делаете по прерыванию - обычно по прерыванию начинают измерения, а вы выводите результат. По моему, начните с простого сна и пробуждения и постепенно усложняйте.

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

как то странно....Вам WDT нужен или просыпание по сигналу с пина?

и конечно, пин по которому необходимо просыпаться должен быть сконфигурирован как вход.

вот в этой теме много всего, возьмите оттуда примеры

http://arduino.ru/forum/programmirovanie/attiny13a-101-primenenie?page=3...

 

gzp13
Offline
Зарегистрирован: 06.04.2015

andycat пишет:

как то странно....Вам WDT нужен или просыпание по сигналу с пина?

и конечно, пин по которому необходимо просыпаться должен быть сконфигурирован как вход.

вот в этой теме много всего, возьмите оттуда примеры

http://arduino.ru/forum/programmirovanie/attiny13a-101-primenenie?page=3...

 

Мне нужен WTT и просыпание по сигналу на PB1. Что то мне кажется что на пине PB1 у меня всегда лог.1, только разная длительность импульса, поэтому у меня и не работает прерывание. На PB1 поступает сигнал PWM с приемника радиоуправления самолетом.

gzp13
Offline
Зарегистрирован: 06.04.2015

 

Не знаю, как положено работать вашему сну, но если PB1 сигнал меняться не будет, то и сна не будет после первого срабатывания WDT, т.к. зависните в цикле PPM_read(). У вас вообще запутанный алгоритм. Непонятно зачем вам WDT, что вы делаете по прерыванию - обычно по прерыванию начинают измерения, а вы выводите результат. По моему, начните с простого сна и пробуждения и постепенно усложняйте.

[/quote]

Смысл такой, ATTINY13 подключена к поисковому радиомаяку. Чтобы она не жрала ток аккумулятора я хочу чтобы она спала. Если я включаю тумблер на аппаратуре радиоуправления, то тинька должна принять этот сигнал, и выполнить какое то действие, например включить пищалку.

b707
Offline
Зарегистрирован: 26.05.2017

теперь расскажите, что за сигнал PWM вы используете для пробуждения? - PWM - это периодический сигнал, он. говоря по простому, постоянно меняется то вверх то вниз :) - так вот, вы понимаете, что МК будет просыпаться по каждому фронту? то есть еслу у вас реально на пине PWM - тинька не будет спать вообще

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

gzp13
Offline
Зарегистрирован: 06.04.2015

b707 пишет:

теперь расскажите, что за сигнал PWM вы используете для пробуждения? - PWM - это периодический сигнал, он. говоря по простому, постоянно меняется то вверх то вниз :) - так вот, вы понимаете, что МК будет просыпаться по каждому фронту? то есть еслу у вас реально на пине PWM - тинька не будет спать вообще

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

Так и получается.Это я уже выяснил. Т.е рещения нет?

b707
Offline
Зарегистрирован: 26.05.2017

gzp13 пишет:

Так и получается.Это я уже выяснил. Т.е рещения нет?

что "получается" ? Что сигнал PWM не подходит для выхода из сна? - так вам это написали В САМОМ ПЕРВОМ ОТВЕТЕ.

Чего ради тогда мы три дня воду в ступе гоняем?

gzp13
Offline
Зарегистрирован: 06.04.2015

b707 пишет:

gzp13 пишет:

Так и получается.Это я уже выяснил. Т.е рещения нет?

что "получается" ? Что сигнал PWM не подходит для выхода из сна? - так вам это написали В САМОМ ПЕРВОМ ОТВЕТЕ.

Чего ради тогда мы три дня воду в ступе гоняем?

Ну извините если что не так)

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

gzp13 пишет:

Ну извините если что не так)

но тема зачем WDT не раскрыта :)

Update: выложите сюда картинку с осциллографа входного сигнала, будет проще понять что вы хотите.