ESP, IoT Особенности esp8266

AlexGyver

★★★★★★✩
Команда форума
30 Июл 2018
359
567
Всем привет! Готовлю урок по esp8266 из по Arduino IDE, решил собрать информацию от участников форума, тут много кто с ней работает. Какие есть особенности, ограничения и другие отличия от обычных Arduino? Что могу добавить от себя:
  • Ограничения на пины - тут всё понятно, подробно расписано в официальном референсе
  • Отличия при работе с eeprom - тоже всё описано в референсе
  • int 32 битный
  • Компилятор пакует структуры кратно 4 байтам, добавляя лишние байты. Для побайтной передачи на avr байтовые переменные лучше класть друг за другом в конце структуры
  • Для работы wifi нужно избегать замкнутых циклов, либо раскидывать yield() или delay(0) по всей программе
  • ШИМ 10 бит
  • enum нельзя использовать как целочисленные
 
Изменено:

bort707

★★★★★★✩
21 Сен 2020
2,899
862
Компилятор пакует структуры, помещая байты в конец выделенной области памяти независимо от их заданного положения в структуре
откуда эта информация?
Насколько я знаю, компилятор НИКОГДА не меняет порядок полей в структуре(с какой стати? - а вдруг этот порядок важен). Но он может выровнять отдельные поля как ему удобнее, вставив между ними пустые байты
 

AlexGyver

★★★★★★✩
Команда форума
30 Июл 2018
359
567
откуда эта информация?
Насколько я знаю, компилятор НИКОГДА не меняет порядок полей в структуре(с какой стати? - а вдруг этот порядок важен). Но он может выровнять отдельные поля как ему удобнее, вставив между ними пустые байты
из личных тестов. Даже если и не компилятор - то кто то другой их меняет
 

bort707

★★★★★★✩
21 Сен 2020
2,899
862
а как тестировали?

Добавка чуть позже:
Алекс, думаю что это ошибка Порядок полей в структуре не меняется.
Вот дискуссия на эту тему:
https://www.cyberforum.ru/c/thread2037903.html

Цитаты оттуда:

C11, 6.7.2.1
15 Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared.

и

C11 6.5.8
5 ... If the objects pointed to are members of the same aggregate object, pointers to structure members declared later compare greater than pointers to members declared earlier in the structure

номера в начале цитат - пункты стандарта языка С11
 
Изменено:

AlexGyver

★★★★★★✩
Команда форума
30 Июл 2018
359
567
@bort707, я передавал структуру побайтно с esp на avr. Сейчас откопал свои заметки - да, я тут неправильно написал. Компилятор добавляет пустые поля, чтобы добить до 4 байт, поэтому я себе записал жирно БАЙТЫ КЛАСТЬ В КОНЕЦ, иначе без костылей принять не получится.
struct.png
C++:
/*struct Data {
  byte valB1;
  byte valB2;
  float valF;
  int valI;
};*/
struct Data { 
  float valF;
  int valI;
  byte valB1;
  byte valB2;
};

void setup() {
  Serial.begin(9600);
  Data data;
  data.valB1 = 231;
  data.valB2 = 123;
  data.valF = 12.34;
  data.valI = 66;

  for (byte i = 0; i < sizeof(data); i++) {
    Serial.println(*((byte*)&data + i));
  }
}
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,192
1,281
Москва
я очень не люблю эти int , byte , word.. думаю если бы использовались uin8_t , int32_t и прочее проблем было бы меньше. с float не уверен
 

AlexGyver

★★★★★★✩
Команда форума
30 Июл 2018
359
567
я очень не люблю эти int , byte , word.. думаю если бы использовались uin8_t , int32_t и прочее проблем было бы меньше. с float не уверен
абсолютно неважно, они редефайнены (тайпдефены) в файлах ядра. Для компилятора это те же int/uint 8/16/32
Но в случае с esp - да, int16 будет 2 байта, в том числе в структуре, что добавляет неоднозначности новичкам
 

Сотнег

★★★★★★★
15 Янв 2020
4,125
1,439
функция abs()
если брать чужой код от других плат, неожиданно приведёт результат к целочисленному.
на многих других платах результат float
 

kostyamat

★★★★★★✩
29 Окт 2019
1,097
630
От себя добавлю:
Неоднозначное поведение на разных версиях фреймворка ардуино, приводящие к проблеме "неявного приведения к типу".
Поэтому лучше сразу явно описывать типы данных при пересчете. Иначе что накомпилирует компилятор - неизвестно.
Например:
uint8_t a = 254
uint16_t b = 1000;
uint16_t c = a +b;
не факт, что c будет равно 1254 в итоге. Лучше записать так
uint16_t c = (uint16_t)a + b;
Особенно это относится к работе с float.
Пример:
uint8_t a = 15;
float b = a / 2; // получим 7, а не 7.5.
float b = (float)a / 2; // вот теперь точно получим 7.5.
А для гарантии
float b = (float)a / 2.0f; // потому как были прецеденты в прошлом.
*** Это возможно уже устаревшая информация, но единожды обжогшись дуют и на холодную воду.

Ещё одно различие: Если в AVR фреймворке инициализировать переменную типа unsigned int (любой размерности), можно ожидать, что компилятор автоматически присвоит ей значение 0, в фреймворк ардуино для esp8266 переменная получит значение "мусора" который оказался в ОЗУ по адресу созданой переменной.
*** Опять же, возможно исправили. Но начальное значение лучше таки указать при инициализации.
И на последок - "родным" типом вещественных значений для esp8266 является double, а не float. С double контроллер работает быстрее.
 
Изменено:

kDn

★★★★★✩✩
18 Ноя 2019
1,103
437
@kostyamat, все вышеописанное к фреймворку/контроллеру не имеет вообще никакого отношения, за это отвечает компилятор. Более того - никаких чудес тут нет и быть не может, все строго в соответствии с приоритетами и стандартом. Если есть возражения покажите кейс, где есть расхождение со стандартом, поскольку в ваших примерах я такого не вижу.

Что же касается комментария под *** - а именно разницы в работе с вещественным типом - есть подтверждение в виде проверки? Поскольку как я помню FPU нет в ESP8266, а как следствие - чем меньше тип данных и чем менее требуется точность, тем быстрее будут вычисления, что расходится с вашим утверждением.

-----------------------
На всякий случай - я не докапываюсь :), но поскольку вы последовательно и уже не в первый раз утверждаете весьма странные вещи, то сложно удержаться от просьбы предоставить подтверждение слов. К примеру любая переменная созданная на стеке и не инициализированная на любом устройстве будет содержать мусор, даже если этот мусор случайно окажется равным 0, это не говорит о каком-то особом поведении на какой-то платформе - просто так сложились звезды. Если одно целочисленное значение делится на другое - то результат будет всегда целочисленным, не смотря на то, что он далее присваивается вещественной переменной, поскольку приоритеты операций.

------------------------
По теме:

Главное про что следует знать - это постоянное трахание с F("строка"), при этом еще одна F("строка") это уже другая строка, поскольку дедупликации нема. Все эти PSTR(...), FPSTR(...) обертки, отдельные функции для работы типа printf и printf_P. В общем местами крайне неудобно и не по-человечески сделано. Если же забить на использование флеш-строк, то очень даже быстро 40кб (половину от 80 съест SDK) исчезают вникуда.

Ну а так-то - вполне нормальный контроллер, работать можно. :)
 

kostyamat

★★★★★★✩
29 Окт 2019
1,097
630

@kDn,
Так я же не утверждаю, что есть расхождения со стандартами. Я говорю, что по мере эволюции фреймворка и компилятора для esp наблюдалось разное поведение одного и того же кода. Поэтому пришлось учить себя четко определять типы при пересчете, дабы уберечься от поломки кода после очередного обновления ядра.

На счет double vs float. Я когда трахался с tixy.lend описывал странную ситуацию, что если использовать функции и переменные float, вместо double производительность вместо расти падала. Меня это тоже удивило тогда. Принял как факт. В ядре имеются как double мат.функции, так и мат.функции, принимающие и возвращающие float. Первые объективно работают быстрее. Почему так - особо не углублялся.
 

MustDIEmaniak

✩✩✩✩✩✩✩
24 Янв 2021
4
3
Если еще не поздно :)

Не получается "сдружить" nrf24l01 с ESP8266 в вариациях D1mini, D1 mini pro, "NodeMCU" (пишу так, чтобы лучше понимать форм-фактор).
В интернете 2 варианта "дружбы":
1. Простейшее использование пинов 2(D4) и 15(D8) в качестве CE и CSN(SS);
2. Через опции библиотеки RF24, а именно SOFTSPI + библиотека DigitalIO.

Оба варианта у меня не работают, где 1 просто не работает, а 2 не компилируется для вышеуказанных ESP плат.
Я запилю скоро отдельный пост с примером скетча, который спокойно работает на Nano. Причем, на макетке воткнуты Nano и любая из ESP, распределяю провода на ESP - 0 эффекта, а переношу провода на Nano - работает.