Добрый день. Подскажите пожалуйста как правильно сделать прерывание на 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"); } } }
|