ESP8266 и ESP32 поддерживают Arduino-фреймворк, но с некоторыми отличиями и добавлениями. Рассмотрим некоторые из них.
Математика #
Деление на 0 #
В отличие от AVR, деление на 0 приводит к критической ошибке и перезагрузке МК - стараемся этого избегать.
Типы данных #
int,size_t- 32 битdouble- 64 бит- Указатель/ссылка - 32 бит
- Выравнивание памяти - 4 байта
При передаче данных между ESP и условно AVR, где int 16 битный, лучше использовать явные типы данных - short/long, а лучше int16_t/int32_t и так далее
Arduino-функции #
map() #
В функции map(val, min, max, to_min, to_max) нет защиты от деления на 0, поэтому если min равен max - МК перезагрузится. Если min и max задаются какими-то внешними условиями - проверяйте их равенство вручную и исключайте вызов map() с такими аргументами.
min() и max() #
Функции min() и max() реализованы как функции, а не как макросы, поэтому должны использоваться с данными одного типа. Использование переменных разного типа приведёт к ошибке компиляции:
unsigned long v;
v = max(v, 123); // ошибка
v = max(v, 123ul); // ОК
analogWrite #
У ESP32 (тестировалось на версии SDK 2.x) после вызова analogWrite пин перестаёт работать как обычный GPIO - не реагирует на digitalWrite, что не соответствует Ардуино-фреймворку, где digitalWrite отключает ШИМ. Для отключения генерации ШИМ нужно вручную вызвать ledcDetachPin(пин).
printf #
В отличие от классических Arduino, в ESP к классу Print добавлен метод printf - форматированный вывод (см. урок про него). Это означает, что можно печатать с форматированием в разные интерфейсы, например выводить в монитор порта как
Serial.printf("Hello %d world", 12); // Hello 12 world
Прерывания #
- В обработчике нельзя использовать динамическое выделение и перераспределение памяти (
new,malloc,realloc), соответственно работать соStringтоже нельзя - В прерывании нельзя использовать задержки
- Функция-обработчик должна быть объявлена со специальным атрибутом, он размещает код функции в оперативной памяти:
- ESP8266 -
IRAM_ATTR - ESP32 -
ARDUINO_ISR_ATTR
- ESP8266 -
// IRAM_ATTR void isr() {} // ESP8266
// void ARDUINO_ISR_ATTR isr() {} // ESP32
void setup() {
attachInterrupt(1, isr, RISING);
}
Есть ещё атрибут DRAM_ATTR - у объявленной с ним функции находящиеся внутри static const переменные также будут размещены в оперативной памяти. При использовании IRAM_ATTR такие переменные компилятор может разместить во Flash памяти.
EEPROM #
EEPROM является эмуляцией из Flash памяти, поэтому мы можем выбрать нужный размер:
- Перед началом работы нужно вызвать
EEPROM.begin(4.. 4096)с указанием размера области памяти в байтах - Для применения изменений в памяти нужно вызвать
EEPROM.commit() - В некоторых версиях SDK отсутствует
EEPROM.update()иEEPROM.length() - У Flash памяти небольшой ресурс - всего около 10'000 перезаписей. У фирменной памяти Winbond (можно найти на некоторых моделях ESP-12 и прочих) - около 50'000 перезаписей
Важно: EEPROM реализован следующим образом: после запуска EEPROM.begin(4.. 4096) содержимое EEPROM указанного размера дублируется в оперативной памяти. После любого изменения и вызова EEPROM.commit() стирается весь блок Flash памяти (4 кБ) и записывается заново. Таким образом ресурс "EEPROM" памяти у ESP вырабатывается довольно быстро и весь сразу, а не по ячейкам.
Вместо EEPROM используйте библиотеку FileData для удобного хранения любых данных в файловой системе
PROGMEM #
- ESP8266: PROGMEM работает как на AVR, без него данные могут располагаться в оперативной памяти
- ESP32: начиная с 2.x версии,
const-данные автоматически располагаются во Flash памяти и читаются оттуда. PROGMEM API полностью поддерживается для совместимости со скетчами под AVR/ESP8266
Полезные страницы #
- Набор GyverKIT – наш большой стартовый набор Arduino, продаётся в России
- Каталог ссылок на дешёвые Ардуины, датчики, модули и прочие железки с AliExpress
- Обратная связь – сообщить об ошибке в уроке или предложить дополнение по тексту ([email protected])
- Поддержать автора за работу над уроками