Closed brightproject closed 1 year ago
Работающее решение на прерываниях для ESP8266
#define ENC_A 12
#define ENC_B 14
#define ENC_KEY 13
#include "GyverEncoder.h"
Encoder enc1(ENC_A, ENC_B, ENC_KEY);
void setup() {
Serial.begin(9600);
enc1.setType(TYPE2); // тип энкодера TYPE1 одношаговый, TYPE2 двухшаговый. Если ваш энкодер работает странно, смените тип\=
attachInterrupt(0, isr_ENC_A, CHANGE); // прерывание на 2 пине! CLK у энка
attachInterrupt(1, isr_ENC_B, CHANGE); // прерывание на 3 пине! DT у энка
}
//void ICACHE_RAM_ATTR my_int();
ICACHE_RAM_ATTR void isr_ENC_A() {
enc1.tick(); // отработка в прерывании
}
ICACHE_RAM_ATTR void isr_ENC_B() {
enc1.tick(); // отработка в прерывании
}
void loop() {
enc1.tick();
if (enc1.isRight()) Serial.println("Right"); // если был поворот
if (enc1.isLeft()) Serial.println("Left");
if (enc1.isRightH()) Serial.println("Right holded"); // если было удержание + поворот
if (enc1.isLeftH()) Serial.println("Left holded");
}
Исходник как "доработать" функцию, смотрел здесь.
Везде в интернете находил примеры с неверной последовательностью
void ICACHE_RAM_ATTR MyInterruptHandler()
{
// do your interrupt handling stuff in here....
}
Но это неверно, либо не работает для esp8266!!!
Также находил код с примером, где ICACHE_RAM_ATTR подставлять в дефайн в начале кода.
Помимо этого находил разные строки для добавления, например встречал вместо ICACHE_RAM_ATTR пишут IRAM_ATTR Ответ почему так нашел здесь.
_Примечание. Начиная с версии 3.0.0 esp8266/Arduino , ICACHE_RAM_ATTR был изменен на IRAMATTR. Для будущих читателей я обновил ссылки на документацию по ESP8266 Arduino Core , но остальную часть вопроса оставил без изменений.
Вообще не понимаю, это своего рода "костыль" от самого espressif?
ICACHE_RAM_ATTR и ICACHE_FLASH_ATTR являются атрибутами компоновщика. После того, как вы скомпилируете свой скетч, вы можете сказать, должна ли функция храниться в ОЗУ или во флэш-памяти (обычно вы ничего не устанавливаете: нет кеша).
ESP8266 является многозадачным, а ESP32 имеет 2 ядра. Таким образом, вы можете выполнять свой код как многопоточный, поскольку он использует RTOS.
А теперь проблема: Вся флешка используется под программу и хранилище. Чтение и запись во флэш-память могут выполняться только через 1 поток. Если вы попытаетесь получить доступ к флэш-памяти одновременно через 2 разных потока, ваш ESP, вероятно, выйдет из строя.
Это потому, что вы можете поместить свою функцию в ОЗУ вместо флэш-памяти. Так что даже если вы что-то записываете в EEPROM или flash, эту функцию можно вызвать без обращения к flash.
С ICACHE_RAM_ATTRвами поставить функцию на ОЗУ.
С ICACHE_FLASH_ATTRвами поставить функцию на FLASH (для экономии оперативной памяти).
Функции прерывания должны использовать ICACHE_RAM_ATTR. Функция, которая вызывается часто, не должна использовать какой-либо атрибут кеша.
Важно: НИКОГДА не обращайтесь к флэш-памяти внутри прерывания! Прерывание может произойти во время доступа к флешке, поэтому если вы попытаетесь получить доступ к флешке в это же время, вы получите сбой (иногда это происходит через 1-2 часа после использования вашего устройства).
Поскольку у вас есть только 32 КБ IRAM (ОЗУ инструкций), вы должны попытаться поместить в ОЗУ только функции прерывания, а не все свои функции, даже если это возможно сделать.
читайте доки на свою версию SDK esp8266, там в разных версиях прерывания нужно декларировать по разному
Данный код перезагружает модуль ЕСП12 и выдает циклически ошибку
Автор библиотеки пишет, что нужно в имя функции подставлять IRAM_ATTR void имя(){} https://alexgyver.ru/lessons/interrupts/ Но в таком случае функция isrCLK не декларирована вообще. В статье всего две строки по поводу wemos mini(esp8266)
Приведите хотя бы один пример использования прерываний для этих "железок"!