Посмотр рубрик

Отличия ESP от Arduino

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
// 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

Полезные страницы #

Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
Прокрутить вверх