Помогите со спящим режимом

imv14
Offline
Зарегистрирован: 02.04.2014

Добрый день знатоки. Помогите со спящим режимом. Хочу чтобы ардуина просыпалась через каждую минуту, посылала данные через nrf, дождавшись ответа снова засыпала. 

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <stdint.h>
#include <avr/sleep.h>
#include <avr/power.h>


#define CE_PIN 9          
#define CSN_PIN 10 //для UNO

const uint64_t writingPipe = 0xE8E8F0F0AALL;
uint32_t message;  // Эта переменная для сбора обратного сообщения от приемника;
int T; 
int Pos[3];
int sleepStatus = 0;             // Переменная для хранения статуса (спим, проснулись) - не используется в коде
int count = 0;                   // Счетчик

RF24 radio(CE_PIN, CSN_PIN);

void setup() {
  Serial.begin(9600);
  delay(2000);   
  pinMode(2, OUTPUT);   
  radio.begin();                      
  radio.setChannel(0);       // канал для передачи           
  radio.setRetries(15,15);   //           
  radio.setDataRate(RF24_250KBPS);   // скорость передачи 
  radio.setPALevel(RF24_PA_MAX);     // мощность передатчмка
  radio.setAutoAck(1);                
  radio.openWritingPipe(writingPipe);  

  radio.enableAckPayload(); // разрешаем посылку message   
}

void loop(){ 
  
  digitalWrite(8, HIGH);//подаем питание на D8
  delay(500);
  T = analogRead(7);  //читаем напряжение на А7
  digitalWrite(2, LOW);//отключаем питание на D8
  Pos[0] = 0; 
  Pos[1] = T;
  Pos[2] = 1;
  radio.write( &Pos, sizeof(Pos) );
    if ( radio.isAckPayloadAvailable() ) {  // Ждем получения...
      radio.read(&message,sizeof(message));  // 
}
    if (message = 111) { // если пришел ответ то спать

      ********** ЗАСТАВИТЬ АРДУИНО СПАТЬ *****************

    }
}

 

imv14
Offline
Зарегистрирован: 02.04.2014

Читал здесь на форуме темы про спящий режим, но ничего конкретного не нашел.   

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013
imv14
Offline
Зарегистрирован: 02.04.2014

Спасибо, видел эти статьи. Не пойму можно ли во время сна пользоваться обычным таймеро или он не будет работать. Правильно ли будет использовать  MsTimer2::set(10000, wakeUpNow); или надо как-то использовать сторожевой таймер(не особо понимаю что это).

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <stdint.h>
#include <avr/sleep.h>
#include <avr/power.h>
#include <MsTimer2.h>

#define CE_PIN 9          
#define CSN_PIN 10 //для UNO

const uint64_t writingPipe = 0xE8E8F0F0AALL;
uint32_t message;  // Эта переменная для сбора обратного сообщения от приемника;
int T; 
int Pos[3];
int sleepStatus = 0;             // Переменная для хранения статуса (спим, проснулись) - не используется в коде
int count = 0;                   // Счетчик

RF24 radio(CE_PIN, CSN_PIN);

void wakeUpNow() 
{
  sleep_disable();  // после просыпания - выключить спящий режим
}

void setup() {
  
  MsTimer2::set(10000, wakeUpNow); // 10000 ms  = 10 s
  MsTimer2::start();
  
  Serial.begin(9600);
  delay(2000);   
  pinMode(2, OUTPUT);   
  radio.begin();                      
  radio.setChannel(0);                  
  radio.setRetries(15,15);              
  radio.setDataRate(RF24_250KBPS);    
  radio.setPALevel(RF24_PA_MAX);      
  radio.setAutoAck(1);                
  radio.openWritingPipe(writingPipe);  

  radio.enableAckPayload();   
}

void sleepNow()         // Функция увода ардуины в спячку.
{
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);   // Здесь устанавливается режим сна
  sleep_enable();                        // Включаем sleep-бит в регистре mcucr. Теперь возможен слип
  sleep_mode();                          // Здесь устройство перейдет в режим сна!!!
}

void loop(){ 
  
  digitalWrite(8, HIGH);//подаем питание на D8
  delay(500);
  T = analogRead(7);  //читаем напряжение на А7
  digitalWrite(2, LOW);//отключаем питание на D8
  Pos[0] = 0; 
  Pos[1] = T;
  Pos[2] = 1;
  radio.write( &Pos, sizeof(Pos) );
    if ( radio.isAckPayloadAvailable() ) {  // Ждем получения...
      radio.read(&message,sizeof(message));  //... и имеем переменную message с числом 111 от приемника.
}
    if (message = 111) {    // если пришел ответ то спать
      Serial.println(111);
        sleepNow();         // засыпаем      
    }
}

 

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

imv14 пишет:

Не пойму можно ли во время сна пользоваться обычным таймеро или он не будет работать.

Смотря какую глубину сна выберете. Там их несколько, и для каждой стадии - описано: что будет работать, а что - нет...

imv14 пишет:

Правильно ли будет использовать  MsTimer2::set(10000, wakeUpNow); или надо как-то использовать сторожевой таймер(не особо понимаю что это).

Сторожевой таймер, по истечению установленного промежутка времени (8 секунд максимум), вызовет ресет платы кроме случая:

Цитата:

используется свойство "WDTCSR Bit 6 - WDIE: Watchdog Interrupt Enable", т.е. при установке этого бита в "единицу" первое срабатывание WatchDog будет просто вызывать прерывание а не ресетить процессор: разница в точке, с которой продолжается работа скетча.

imv14
Offline
Зарегистрирован: 02.04.2014

Хотелось бы чтобы плата с датчиком работала от батарейки как можно дольше, как лучше быть. Я так понял, что MsTimer2::set(10000, wakeUpNow); будет работать только в режиме SLEEP_MODE_PWR_SAVE: 1.62 mA.

Посоветуйте пожалуйста как мне решить проблему, просыпаться нужно хотя бы раз в минуту.

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

imv14 пишет:

Посоветуйте пожалуйста как мне решить проблему, просыпаться нужно хотя бы раз в минуту.

Тут либо спать кусочками по 8 секунд, либо отключать WatchDog и "будить" МК с помощью внешнего раздражителя-таймера, который, в свою очередь, тоже будет кушать электричество. У DS3107 есть внутренние будильники, которые можно было бы использовать для этого.

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

Цитата:

 У DS3107 есть внутренние будильники, которые можно было бы использовать для этого.

О! А я блин и не знал. Спасибо!

imv14
Offline
Зарегистрирован: 02.04.2014

А на счет MsTimer2::set(10000, wakeUpNow); будет работать только в режиме SLEEP_MODE_PWR_SAVE, это я правильно понимаю. Гляньте пожалуйста мой код, корректно ли будет сделать так если я заменю SLEEP_MODE_PWR_DOWN на SLEEP_MODE_PWR_SAVE.