Не просыпается ESP-01s после длительного DeepSleep

S_Sergey_G

✩✩✩✩✩✩✩
23 Фев 2021
161
3
Вот получилось так, но считать просыпания не хочет. Срабатывает каждые 10 сек.
C++:
 #include <Servo.h>
 #include <EEPROM.h>
 Servo servo;
void writeIntIntoEEPROM(int address, int number)
{
  EEPROM.write(address, number >> 8);
  EEPROM.write(address + 1, number & 0xFF);
}

int readIntFromEEPROM(int address)
{
  return (EEPROM.read(address) << 8) + EEPROM.read(address + 1);
}
void setup(){
  Serial.begin(115200);
  servo.attach(0); //GPIO 0

  int i = readIntFromEEPROM(0);
 
  if(i % 12 == 0)
  {
  servo.write(180);
  delay(2000);
  servo.write(50);
  }
  writeIntIntoEEPROM(0, i + 1);
  ESP.deepSleep(10e6);  //выставляем время сна
}
void loop() {
}
 

Bruzzer

★★★✩✩✩✩
23 Май 2020
312
100
В Arduino IDE есть примеры работы с EEPROM для ESP. (Там же есть и приеры для LowPower и т.д. и т.п.).

Дополнено позже. Int в 8266 занимает 4 байта а не 2. Ошибка не из за этого, но иметь в виду надо. В вашем случае можно сохранять один младший байт, если сбрасывать i в 0 при кратности 12.
 
Изменено:

Старик Похабыч

★★★★★★★
14 Авг 2019
4,159
1,267
Москва
Посмотрел легкий сон, действительно, просыпается только он пинов, время роли не играет, но данные помнит. Получается в данном случае от нее смысла нет.
Значит остается дипслип . Данные о пробуждениях можно хранить в памяти RTC.
Но надо разобраться как следует.
Вот похожий пример со счетчиком:
 

S_Sergey_G

✩✩✩✩✩✩✩
23 Фев 2021
161
3
Не получается у меня этот проект ни как. Сделал сейчас на Ардуинке с внешним RTC. Работает, но один будильник почему то. Не знаю новую тему открыть или здесь можно продолжить?
Но хотелось на ESP, Может есть примеры пробуждение ESP от внешнего RTC?
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,159
1,267
Москва
а с приведенной выше библиотекой пробовали через глубокий сон ? Пример , на который я дал ссылку отлично считает кол-во нажатых ресетов. Т.е. сделав начальную схему и применив тот код (убрать просто счетчик секундный, который тоже не сбрасывается при ресете) можно сделать именно то. что надо (час спим, считаем ресеты, при 0 - работает срева)
На счет RTC не пробовал, сигнал там идет от часов, но как он сбрасывается не помню, хоть документацию и читал
 

poty

★★★★★★✩
19 Фев 2020
2,956
886
От RTC нужен периодический сигнал "будильника", он выводится на отдельный пин и может будить МК, что к нему подключен. DS3231 имеет два будильника, но выход "бужения" у него один - SQW. Но, думаю, для этой задачи достаточно одного будильника.
Другое дело если будет постоянно работать RTC, то потребление вырастет.
 
Изменено:
  • Лойс +1
Реакции: S_Sergey_G

S_Sergey_G

✩✩✩✩✩✩✩
23 Фев 2021
161
3
@Старик Похабыч,
Спасибо очень интересно, должно сработать.
Для проверки можно delya заменить на ESP.deepSleep ?
C++:
void loop() {
  // сделайте свою работу здесь - попробуйте перезагрузить чип снаружи или внутри, но не выключайте питание...
  Serial.println("Current state is " + (String)program_step);
  program_step = (program_step == 3) ? 1 : program_step + 1;
  Serial.println("New state is " + (String)program_step);
  state.saveToRTC();                    // параметров нет, потому что определение переменных требуется только один раз
  //delay(2000);
  ESP.deepSleep(10e6);
}
При такой замене в сериал принт пишет вот это;
13:33:50.300 -> r This is reset no. 1
13:33:50.396 -> Current state is 1
13:33:50.396 -> New state is 2
13:34:00.359 -> rl This is reset no. 2
13:34:00.453 -> Current state is 2
13:34:00.453 -> New state is 3
13:34:10.466 -> rl This is reset no. 3
13:34:10.513 -> Current state is 3
13:34:10.560 -> New state is 1
13:34:20.557 -> rl This is reset no. 4
13:34:20.605 -> Current state is 1
13:34:20.652 -> New state is 2
13:34:30.625 -> rl This is reset no. 5
13:34:30.721 -> Current state is 2
13:34:30.721 -> New state is 3
 
Изменено:

Старик Похабыч

★★★★★★★
14 Авг 2019
4,159
1,267
Москва
По сути loop вообще не нужен. Там достаточно только того, что в setup , исключительно тот кусок кода где считаются reset.
Получается запускается, в начале кол-во ресетов равно 0 - срабатывает кормушка.
Далее ресеты увеличиваются на 1. если это число будет равно 25, то считать его 0 и все это записываются в память RTC и ESP уходит в глубокий сон. Потом по ресету же просыпается и считывает значение из памяти и далее по кругу.
 

S_Sergey_G

✩✩✩✩✩✩✩
23 Фев 2021
161
3
@Старик Похабыч,
Вот получилось так ( временные интервалы для настройки и проверки): Работает. Но. После первого просыпания, после срабатывания серво, сервопривод чуть отрабатывает приоткрывая заслонку, последующие просыпания, все нормально, потом опять по кругу?
C++:
#include <RTCVars.h>
RTCVars state; // create the state object
#include <Servo.h>
Servo servo;
int reset_counter;                      // we want to keep these values after reset
int program_step;

void setup() {
  Serial.begin(115200);                 // allow debug output
  servo.attach(0); //D5
  state.registerVar( &reset_counter );  // we send a pointer to each of our variables
  state.registerVar( &program_step );

  if (state.loadFromRTC()) {            // we load the values from rtc memory back into the registered variables
    reset_counter++;
  
    // тут крутим мотор, если проснулись в нужный раз
    if(reset_counter % 3 == 0)
    {
         servo.write(180); ////ставим вал под 180
         delay(2000); //ждем 2 секунды
         servo.write(50); //ставим вал под 50
        
    }
    state.saveToRTC();                  // since we changed a state relevant variable, we store the new values
  } else {
    reset_counter = 0;                  // cold boot part
    Serial.println("This seems to be a cold boot. We don't have a valid state on RTC memory");
    program_step = 0;

    state.saveToRTC();
    }
}

void loop() {
  ESP.deepSleep(10e6);  //выставляем время сна
}
 
Изменено:

Старик Похабыч

★★★★★★★
14 Авг 2019
4,159
1,267
Москва
нет, это просто шаг программы , который крутится и не сбивается при ресете. Тут как бы 2 демонстрации в одном: продолжение шага программы и подсчет ресетов. Для реализации кормушки достаточно считать ресеты
 

S_Sergey_G

✩✩✩✩✩✩✩
23 Фев 2021
161
3
@Старик Похабыч,
Я удалил строки " program_step " правильно?
Но, что делать когда при первом запуске и последующих первых просыпаний, кратковременно срабатывает серво?
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,159
1,267
Москва
Отправку в глубокий сон можно делать сразу в setup , а loop оставить вообще пустым, так будет немного логичнее

Серва при аттаче стремиться к какому то дефолтному положению, для библиотеки это обычно 90 градусов, соотв туда она и дернется. Для того что бы этого не было надо сначала задать положение, а потом уже аттачить.
 

S_Sergey_G

✩✩✩✩✩✩✩
23 Фев 2021
161
3

Старик Похабыч

★★★★★★★
14 Авг 2019
4,159
1,267
Москва
Поясню. к примеру есть сервопривод который выполняет поворот из положения 1 (pos1) в положение 2 (pos2) и обратно и положение 1 отлично от 90 градусов. Тогда надо сначала руками задать положение 1, а потом прописать такой код:

C++:
void setup() {
  myservo.write(pos1);
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
}
и серва в начале не будет дергаться , т.к. она и находится в положении 1. И после цикла работы (в положение 2 и обратно) она опять будет в 1-ом положении и любое выключение не заставит серву дергаться. А ручное изменение заставит.
Если рукми не поставить положение 1, то серва все равно дернется 1 раз в начале, но последующие разы уже не будет.
 

S_Sergey_G

✩✩✩✩✩✩✩
23 Фев 2021
161
3
Посмотрите я всё правильно сделал?
C++:
#include <RTCVars.h>
RTCVars state; // create the state object
#include <Servo.h>
Servo servo;
int reset_counter;                      // we want to keep these values after reset
int pos1 = 50;

void setup() {
  Serial.begin(115200);                 // allow debug output
  servo.write(pos1);
  servo.attach(0);
  state.registerVar( &reset_counter );  // we send a pointer to each of our variables

  if (state.loadFromRTC()) {            // we load the values from rtc memory back into the registered variables
    reset_counter++;
  
    // тут крутим мотор, если проснулись в нужный раз
    if(reset_counter % 3 == 0) // задаём количество подсчётов просыпаний через которое сработает привод
    {
         servo.write(180); ////ставим вал под 180
         delay(2000); //ждем 2 секунды
         servo.write(50); //ставим вал под 50
        
  }
    state.saveToRTC();                  // since we changed a state relevant variable, we store the new values
  } else {
    reset_counter = 0;                  // часть холодного старта

    state.saveToRTC();
  }
    ESP.deepSleep(5e6); // спим на заданное время
  }

void loop() {
}
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,159
1,267
Москва
Думаю что не совсем.
Получается что при первом включении кормушка не сработает, а сработает только через 3 ресета.
Наверное стоит добавить срабатывание кормушки при первом включении там где
reset_counter = 0; // часть холодного старта
Т.е. я бы сделал так:

C++:
void setup() {
  Serial.begin(115200);                 // allow debug output
  servo.write(pos1);
  servo.attach(0);
  state.registerVar( &reset_counter );  // we send a pointer to each of our variables

  if (state.loadFromRTC())             // we load the values from rtc memory back into the registered variables
    reset_counter++;
  else
    reset_counter = 0;                  // часть холодного старта
    
 
  if (reset_counter % 3 == 0) // задаём количество подсчётов просыпаний через которое сработает привод
  {
    servo.write(180); ////ставим вал под 180
    delay(2000); //ждем 2 секунды
    servo.write(50); //ставим вал под 50
  }
  state.saveToRTC();                  // since we changed a state relevant variable, we store the new values

  ESP.deepSleep(5e6); // спим на заданное время
}
Так будет срабатывание сразу и число строк уменьшилось. Ну и еще из времени сна стоит вычесть 2 секунды с небольшим.

А такой вопрос, когда есп спит серву можно легко рукой пошевелить?
 

S_Sergey_G

✩✩✩✩✩✩✩
23 Фев 2021
161
3
@Старик Похабыч,
Спасибо Вам за помощь! Да и спасибо, что указали на 2 сек., даже не подумал об этом.
А такой вопрос, когда есп спит серву можно легко рукой пошевелить?
Сопротивление одинаково, что во сне, что без питания совсем.

Но у меня возникла другая проблема.
Устройство автономное. Уходит в сон это хорошо, но питание сервы сидит на батареи напрямую,
ток во сне 2,2 мА. Это очень много. Задействовал GPO02 pinMode(2, OUTPUT); , отпаял светодиод что бы не мешал,.
Через 1кОм подсоединил к базе транзистора КТ815 и транзистор должен управлять питанием сервы( я так делал на ардуино).
Но при таком подключении почему то ESP зависает ток потребления 40 мА напряжение падает до 2,8 вольт ( блок питания) и висит. В чем может быть проблема?
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,159
1,267
Москва
Это вопрос уже больше схемотехники, я не подскажу - тут по этому вопросу головастее есть. Но раз падает до 2.8, то может конденсатор поставить на питание ?
 

S_Sergey_G

✩✩✩✩✩✩✩
23 Фев 2021
161
3
@Старик Похабыч,
Ставил кондей не помогает.
Если светодиод подключаю к GPIO02 все нормально, вижу включение и отключение пина.
С транзистором такая просадка.
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,159
1,267
Москва
Да, может.
Кнопка Flash на NodeMCU подключает к земле GPIO0. Ее можно использовать как обычную кнопку. Если программно подтянуть вывод GPIO0 с помощью внутреннего подтягивающего резистора к высокому уровню, то появление низкого уровня на этом выводе будет означать, что кнопка нажата.
 

S_Sergey_G

✩✩✩✩✩✩✩
23 Фев 2021
161
3
@Старик Похабыч,
Это такой командой?
pinMode(0, OUT_PULLUP);
Сейчас просто загрузил пример моргание светодиода, назначил GPIO0 OUT, транзистор всегда открытый, т.е на GPIO0 всегда еденичка.
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,159
1,267
Москва
Кнопка flash переводит плату в режим программирования, т.е. вполне может быть что плата переходит в другой режим. Лучше использовать другой пин
 

S_Sergey_G

✩✩✩✩✩✩✩
23 Фев 2021
161
3
GPIO0 самый чистый, подтяжка внутри физическая. GPIO2 подключен светодиод ( я его выкинул) RX GPIO3 и TX GPIO1 тоже с причудами TX всегда на доли секунды включается сам для проверки RX вход.
Я уже все пины перепробовал.

код:
void setup() {
  Serial.begin(115200);                 // allow debug output
  pinMode(0, OUTPUT); // питание сервопривода
  servo.write(pos1);
  servo.attach(1);
  state.registerVar( &reset_counter );  // we send a pointer to each of our variables

  if (state.loadFromRTC())             // we load the values from rtc memory back into the registered variables
    reset_counter++;
  else
    reset_counter = 0;                  // часть холодного старта
    
 
  if (reset_counter % 3 == 0) // задаём количество подсчётов просыпаний через которое сработает привод
  {
    digitalWrite(0, HIGH);
    servo.write(180); ////ставим вал под 180
    delay(2000); //ждем 2 секунды
    servo.write(50); //ставим вал под 50
    digitalWrite(0, LOW);
    delay(100);
  }
  state.saveToRTC();                  // since we changed a state relevant variable, we store the new values

  ESP.deepSleep(5e6); // спим на заданное время
}
Может в коде напутал.