Ардуинщики всех стран - объединяйтесь! В этом форуме, конечно.
Ответить

Как на ESP восстановить прерывание после light sleep?

Вс июл 31, 2022 12:29:43

Добрый день.
Подскажите пожалуйста как правильно сделать прерывание на ESP-07s: есть само прерывание обрабатывающее сигнал с приемника 433МГц
СпойлерIRAM_ATTR void ANT() { // прерывание по сигналу с антенны
volatile int num = (micros() - tmr7); // вычисляем время между сигналами
tmr7 = micros(); // сброс таймера
if (num > 4650 && num < 4800) dann = true;
if (dann == 1){
if (num > 600) err++; // проверяем нет ли символа разделителя
if (err > 1) { // перезаписываем если принято что то кроме символа разделителя
DataNumber = 0;
err = 1;
}
myDATA[DataNumber] = num; // записываем время сигнала в массив
DataNumber++;
if (num < 50) { // если в процессе принят мусор начинаем все заново
dann = false;
DataNumber = 0;
err = 0;
}
if (DataNumber > 17 && dann) { // если принят последний символ и нет ошибок отправляем на расшифровку
detachInterrupt(13);
DataReady = true;
}
}
}

чтобы уйти в сон по light sleep я отключаю прерывание detachInterrupt(13); иначе они не дают уйти в сон т.к. срабатывают слишком часто, сам сон:
Спойлерvoid light_sleep(){
digitalWrite(2, 1); // оставляем включенным пин А, так тратиться меньше энергии (примерно 0,4 мА)
digitalWrite(4, 0); // выключаем пин В
digitalWrite(12, 0); // выключаем пин С1
digitalWrite(14, 0); // выключаем пин С2
wifi_station_disconnect();
wifi_set_opmode_current(NULL_MODE);
wifi_fpm_set_sleep_type(LIGHT_SLEEP_T);
wifi_fpm_open(); // Enables force sleep
gpio_pin_wakeup_enable(GPIO_ID_PIN(5), GPIO_PIN_INTR_HILEVEL); // пин и состояние при котором проснемся
wifi_fpm_do_sleep(0xFFFFFFF); // Спим максимальное время
delay(5);
digitalWrite(4, 1); // выключаем канал В
modplus = 1;
}

А далее после просыпания если попробовать опять повесить прерывание на пин attachInterrupt(13, ANT, CHANGE); ESP зависает и перезапускается по ватчдогу:
Спойлерets Jan 8 2013,rst cause:4, boot mode:(3,6)

wdt reset
load 0x4010f000, len 3460, room 16
tail 4
chksum 0xcc
load 0x3fff20b8, len 40, room 4
tail 4
chksum 0xc9
csum 0xc9
v00042da0
~ld

Как правильно восстановить прерывание после light sleep?
весь код:
Спойлер#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>

volatile uint32_t tmr7; // таймер 1
volatile bool dann = false;
volatile int myDATA[19];
volatile byte DataNumber = 0;
volatile byte err = 0;
volatile bool DataReady = false;

bool modplus = 0; // переменная смена режима
byte buttn = 0; // кнопки пульта
uint32_t tmr1; // таймер 1
uint32_t tmr3; // таймер 3
uint32_t tmr5; // таймер 5
byte mod = 0;
byte modC = 9; // режим свечения канала C
bool AntEnable = 0; // включены ли сигналы с антенны
bool sig1 = 0;
bool sig2 = 1;

void setup() {
Serial.begin(115200);
pinMode(2, OUTPUT); // пин канала А
pinMode(4, OUTPUT); // пин канала В
pinMode(12, OUTPUT); // пин С1
pinMode(14, OUTPUT); // пин С2
pinMode(5, INPUT); // пин отслеживающий наличие питания через делитель напряжения 12в в 3в
digitalWrite(2, 1); // выключаем канал А
digitalWrite(4, 1); // выключаем канал В
digitalWrite(12, 0); // выключаем канал С1
digitalWrite(14, 0); // выключаем канал С2
attachInterrupt(13, ANT, CHANGE); // прерывание по сигналу антенны
analogWriteResolution(12); // 12 бит (0-4095)
analogWriteFreq(900); // Гц шим
Serial.println("Start");
}

IRAM_ATTR void ANT() { // прерывание по сигналу с антенны
volatile int num = (micros() - tmr7); // вычисляем время между сигналами
tmr7 = micros(); // сброс таймера
if (num > 4650 && num < 4800) dann = true;
if (dann == 1){
if (num > 600) err++; // проверяем нет ли символа разделителя
if (err > 1) { // перезаписываем если принято что то кроме символа разделителя
DataNumber = 0;
err = 1;
}
myDATA[DataNumber] = num; // записываем время сигнала в массив
DataNumber++;
if (num < 50) { // если в процессе принят мусор начинаем все заново
dann = false;
DataNumber = 0;
err = 0;
}
if (DataNumber > 17 && dann) { // если принят последний символ и нет ошибок отправляем на расшифровку
detachInterrupt(13);
DataReady = true;
}
}
}

void light_sleep(){
digitalWrite(2, 1); // оставляем включенным пин А, так тратиться меньше энергии (примерно 0,4 мА)
digitalWrite(4, 0); // выключаем пин В
digitalWrite(12, 0); // выключаем пин С1
digitalWrite(14, 0); // выключаем пин С2
wifi_station_disconnect();
wifi_set_opmode_current(NULL_MODE);
wifi_fpm_set_sleep_type(LIGHT_SLEEP_T);
wifi_fpm_open(); // Enables force sleep
gpio_pin_wakeup_enable(GPIO_ID_PIN(5), GPIO_PIN_INTR_HILEVEL); // пин и состояние при котором проснемся
wifi_fpm_do_sleep(0xFFFFFFF); // Спим максимальное время
delay(5);
digitalWrite(4, 1); // выключаем канал В
modplus = 1;
}

void DataOK(){ // расшифровка сигнала с антенны
DataReady = false;
int CodeButtonA[] = {4750, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0,}; // код кнопки A
int CodeButtonB[] = {4750, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0,}; // код кнопки B
int CodeButtonC[] = {4750, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0,}; // код кнопки C
int CodeButtonD[] = {4750, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0,}; // код кнопки D
int cod[19];
bool ButtonA = true;
bool ButtonB = true;
bool ButtonC = true;
bool ButtonD = true;
for (byte n = 1; n < 19; n++) {
if (myDATA[n] < 400) {
cod[n] = 0;
}
else cod[n] = 1;
if (cod[n] != CodeButtonA[n]) {
ButtonA = false;
}
if (cod[n] != CodeButtonB[n]) {
ButtonB = false;
}
if (cod[n] != CodeButtonC[n]) {
ButtonC = false;
}
if (cod[n] != CodeButtonD[n]) {
ButtonD = false;
}
}
if (ButtonA) buttn = 1;
if (ButtonB) buttn = 2;
if (ButtonC) buttn = 3;
if (ButtonD) buttn = 4;
attachInterrupt(13, ANT, CHANGE);
}

void loop() {
if (digitalRead(5) == 0) {
detachInterrupt(13); // отключаем прерывания на антенне
tmr5 = millis(); // сброс таймера
AntEnable = 1;
light_sleep();
}

if (DataReady) DataOK();

if (millis() - tmr5 >= 5000 && AntEnable == 1) { // включаем сигнал с антенны спустя задержку
tmr5 = millis(); // сброс таймера
AntEnable = 0;
attachInterrupt(13, ANT, CHANGE);
}

if (modplus == 1){ // переключение основных режимов при восстановлении питания
modplus = 0;
mod++;
if (mod > 1) mod = 0; // сбрасываем режим в ноль при переполнении
if (mod == 0){
modC = 3;

}
if (mod == 1){
modC = 9;
}
}

if (buttn == 3){
buttn = 0;
if (millis() - tmr3 >= 300) { // ищем разницу
tmr3 = millis(); // сброс таймера
modplus = 1;
}
}

if (modC == 3){
digitalWrite(12, 1); // включаем канал С1
digitalWrite(14, 0); // выключаем канал С2
}

if (modC == 9){
if (millis() - tmr1 >= 1000) { // ищем разницу
tmr1 = millis(); // сброс таймера
sig1 = !sig1;
sig2 = !sig1;
digitalWrite(12, 0);
digitalWrite(14, 0);
delayMicroseconds(20);
digitalWrite(12, sig1);
digitalWrite(14, sig2);
Serial.println("Work OK");
}
}
}

Re: Как на ESP восстановить прерывание после light sleep?

Вс июл 31, 2022 17:31:49

Я думаю, что следует отказаться от спящего режима. Esp8266 все равно на автономное питание не посадить. Разве только на powerbank.

Re: Как на ESP восстановить прерывание после light sleep?

Вс июл 31, 2022 18:47:16

Я думаю, что следует отказаться от спящего режима. Esp8266 все равно на автономное питание не посадить. Разве только на powerbank.

Мне нужна автономность только на пару секунд и её вполне успешно обеспечивает конденсатор, но вот без light sleep потребление тока возрастет в 200 раз и эт уже нужна батарея из ионисторов наверн. Неужели нет какого то способа попроще?

Re: Как на ESP восстановить прерывание после light sleep?

Вс июл 31, 2022 21:58:28

потребление тока возрастет в 200 раз

реальное потребление меряли?

можно попробовать поменять SDK через менеджер плат, возможно на каком-нибудь заработает корректно.

Re: Как на ESP восстановить прерывание после light sleep?

Пн авг 01, 2022 00:02:37

потребление тока возрастет в 200 раз

реальное потребление меряли?

можно попробовать поменять SDK через менеджер плат, возможно на каком-нибудь заработает корректно.

В режиме работы без вайфай около 70мА, в light slep 0,4мА. То есть в коде менять что то бесполезно — странно я думал я где то накосячил и чего то не учел(

Re: Как на ESP восстановить прерывание после light sleep?

Пн авг 01, 2022 06:08:23

Вы цифры из даташит на ЧИП приводите, который без флешки без обвязки и где измерения были сделаны в сферическом вакуме. Я же спрашивал цифры реального потребления вашего МОДУЛЯ.

Сделайте замеры.

Re: Как на ESP восстановить прерывание после light sleep?

Пн авг 01, 2022 09:19:33

Вы цифры из даташит на ЧИП приводите, который без флешки без обвязки и где измерения были сделаны в сферическом вакуме. Я же спрашивал цифры реального потребления вашего МОДУЛЯ.

Сделайте замеры.

Это реальные цифры для моей кастомной платы на esp07s: в легком сне 0,415мА, в работе с вайфай примерно 80-87мА, если попытаться выключить вайфай 70-75мА (хотя по инструкциям должно быть 15мА, но у меня чет больше, но даже 15 это в 30 раз больше). Емкости в ~1500мкф хватает на 5-10сек работы в зависимости от того на какой кусок кода попало отключение питания.
Ответить