• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Общие вопросы по Arduino IDE для ESP8266

vvzvlad

New member
тогда я все же не пойму между какими двумя командами Вы измеряете время? между отправкой первого и второго символа?
Еще раз. У меня два устройства. Два разных физических устройства. Одно из них - плата с esp8266 и кнопкой. Я одновременно нажимаю кнопку на обоих устройствах, и они одновременно отправляют каждое свой пакет на сервер, на разные порты. Так вот, пакет, отправленный с esp8266 приходит в среднем на 100мс позже пакета, отправленного со второго устройства.
Заранее скажу - я измерял разницу между одновременным нажатием человеком двух кнопок, и она укладывается в 20мс. Т.е. я, одновременно нажимая кнопки, не создаю разницу больше 20мс. Куда-то деваются как минимум 80мс, на которые плата гарантированно медленнее второго устройства отправляет запрос.

Я измеряю именно время между нажатием кнопки и приходом пакета на сервер. Я не могу измерить абсолютное время, потому что для этого надо иметь синхронизированные часы на сервере и на устройстве, но я могу измерить относительное - насколько это получается быстрее или медленнее какого-нибудь эталона.
 

anakod

Moderator
Команда форума
Для повтора надо вызвать void gpio_pin_intr_state_set(uint32 i, GPIO_INT_TYPE intr_state) - иначе следующего прерывания не будет. Аппаратная фигня - сбрасывается и её надо заряжать заново.
Тут по-моему другой код, из Arduino IDE (не очень в курсе что там), но то что в Sming у меня реализовано я проверял, срабатывает несколько раз, сбрасывание бита обработанного прерывания осуществляется регистром, вроде все ОК.
 

tsrman

New member
@vvzvlad
давайте для чистоты экперемента поставим вместо 300 - delay(10) и проверим как-то повлияет это на задержку в 100мс?
еще можно в коде на самом esp выводить время в консоль, что-бы понять сколько на стороне esp занимает выполнение.
 

pvvx

Активный участник сообщества
Тут по-моему другой код, из Arduino IDE (не очень в курсе что там), но то что в Sming у меня реализовано я проверял, срабатывает несколько раз, сбрасывание бита обработанного прерывания осуществляется регистром, вроде все ОК.
GPIO_STATUS_W1TC подтверждается только у назначенных функций - если _gpioInterruptsList != NULL, а если равна? (Т.е. отключили функцию.)
А повторное срабатывание должен управлять пользователь - в функции прерывания вызовом gpio_pin_intr_state_set() или как он пожелает. Но описанное выше - не хорошо - attachInterrupt(x, NULL,xx).
 
Последнее редактирование:

Nikita

New member
Пожалуйста, подскажите, каким образом можно получить объем занятой оперативной памяти, видел, что где-то обсуждали, но повторно найти не могу? В моем sketch'е много строк, периодически встречаются произвольные перезагрузки esp8266.
ets Jan 8 2013,rst cause:4, boot mode:(3,0)

wdt reset
load 0x40100000, len 31264, room 16
tail 0
chksum 0x1f
load 0x3ffe8000, len 2596, room 8
tail 12
chksum 0x47
ho 0 tail 12 room 4
load 0x3ffe8a30, len 3088, room 12
tail 4
chksum 0xe5
csum 0xe5

Не совсем понимаю причину, возможно, в том, что нерационально расходую ОЗУ при работе со строками, хотелось бы найти утечку. Правильно ли я понимаю, что локальные переменные и массивы заведенные в loop() по окончании выполнения каждого цикла освобождают память "самостоятельно"? В частности вопрос про массивы char со строками. Либо же лучше не заморачиваться и пользоваться объектами String?
 

AmatorVic

New member
Пожалуйста, подскажите, каким образом можно получить объем занятой оперативной памяти, видел, что где-то обсуждали, но повторно найти не могу? В моем sketch'е много строк, периодически встречаются произвольные перезагрузки esp8266.
ets Jan 8 2013,rst cause:4, boot mode:(3,0)

wdt reset
load 0x40100000, len 31264, room 16
tail 0
chksum 0x1f
load 0x3ffe8000, len 2596, room 8
tail 12
chksum 0x47
ho 0 tail 12 room 4
load 0x3ffe8a30, len 3088, room 12
tail 4
chksum 0xe5
csum 0xe5

Не совсем понимаю причину, возможно, в том, что нерационально расходую ОЗУ при работе со строками, хотелось бы найти утечку. Правильно ли я понимаю, что локальные переменные и массивы заведенные в loop() по окончании выполнения каждого цикла освобождают память "самостоятельно"? В частности вопрос про массивы char со строками. Либо же лучше не заморачиваться и пользоваться объектами String?
Я пользуюсь String и тоже много текста, и ьтак же иногда вываливается по wdt reset, как у Вас.
Пытался использовать PROGMEM, но не получилось пока
 

bolwoi

New member
Пожалуйста, подскажите, каким образом можно получить объем занятой оперативной памяти, видел, что где-то обсуждали, но повторно найти не могу? В моем sketch'е много строк, периодически встречаются произвольные перезагрузки esp8266.
http://esp8266.ru/forum/threads/obschie-voprosy-po-arduino-ide-dlja-esp8266.224/page-6#post-4764
 

Telek

New member
Nikita, У меня тоже периодически ресетится, с таким же логом. Объем оперативы смотрел - все стабильно. Один из вариантов когда это происходит - не получение ответа от сервера. (GET запрос на сервер проходит, а ответка не получается... причем непонятно, не получается в следствии плохого приема(я через Ёту гоняю), или это какой-то сбой в sdk, который после вытекает в ресет). Причем периодичность разная. Может пол-дня отправлять данные раз в минуту, а может через десяток циклов ребутнутся.
И второй момент, если я сам рестартую модуль вызовом ((void (*)(void))0x40000080)();, то после ресета, модуль рестарует повторно... получается какой-то не правильный вызов ресета...
 

igrr

Moderator
Команда форума
@vvzvlad добавили небольшой фикс, теперь скорость нашего простенького веб-сервера, идущего в комплекте, увеличилась до 900kbps за счет уменьшения задержки отправки пакета (раньше было 100kbps). так что может быть в вашем тесте тоже станет немного лучше.
 

igrr

Moderator
Команда форума
@AmatorVic PROGMEM у нас только для совместимости — расход памяти будет ровно такой же как если вы сделаете просто const char*.
 

igrr

Moderator
Команда форума
В связи ещё с сильными различиями версий HTTP и типов запросов без специализированного сервера HTTP с минимальной, но необходимой функциональностью, работа Arduino как сервера HTTP не возможна. Т.е. её нельзя будет включать в глобальный инет - или помрет или будет лажать...
Согласен — более того, плохо себе представляю, чтобы кто-то включал модуль на esp в инет напрямую, с глобальным IP.
С моей точки зрения, http сервер нужен в основном чтобы задать название точки доступа, к которой модуль должен подключиться.
Если http сервер — важная часть проекта, то лучше добавить $5 к стоимости девайса, сделать его на базе какого-нибудь RT5350f и не заниматься ерундой :)
 

pvvx

Активный участник сообщества
Согласен — более того, плохо себе представляю, чтобы кто-то включал модуль на esp в инет напрямую, с глобальным IP.
С моей точки зрения, http сервер нужен в основном чтобы задать название точки доступа, к которой модуль должен подключиться.
Если http сервер — важная часть проекта, то лучше добавить $5 к стоимости девайса, сделать его на базе какого-нибудь RT5350f и не заниматься ерундой :)
Тоже самое и с запросами к модулю и от него по HTTP - без специальной реализации ничего хорошего не выйдет. Необходимы полные разборки заголовков HTTP и организации ответов.
Web уже работает у меня в проекте "свалки" и сидит напрямую в глобальной сети уже месяцы по фиксированному IP. Ничего его пока из сети не убивает и он не лажает, т.к. реализован специально для этого и никаких +$ не требует. Но написан кое как и требует пересмотра на более понятное описание в коде СИ или C++, т.к. я не программист - больше аппаратура и её связь с софт + обвязка и нахождение простого пути решения задач...
Перезагрузок и прочих зависаний нет, если всё описано правильно. Тем более WDT и прочее уже доступно в SDK в альтернативных исходниках и организуется любой уровень "защиты" от зависаний. В теущей SDK 1.0.1, при отрезании никчемных "obj" из либ Espressif, довольствуясь минимумом Lwip + WiFi (остальное своё) имеется беда только в LIGHT режиме sleep-а WiFi. И то она не приводит к зависаниям и перезагрузкам, а просто теряет TCP соединение. Ну не включать её и модуль будет здоров всегда и не зависнет и не перезагрузится. Остальные "бажки" SDK успешно обходятся, надо только их знать :)

Для главной темы модуля – малопотребляющего режима засыпания и просыпания с опросом датчиков ничего вообще в Arduino IDE не сделано. Данная задача решается специальным загрузчиком, которого в Arduino IDE нет. Уже проверено, что требуется другой загрузчик, состоящий из одного сегмента и тогда время от просыпания до опроса датчиков с включенным "кешированием" flash составляет 30 ms. По опросу программа должна определять – включать или нет далее модуль WiFi для передачи данных или засыпать далее. Ничего этого в Arduino IDE пока не сделано, а идет навязывание использования кривых методов реализации функционала модуля от Espressif. + Пока не проинициализирована SDK Espressif, после спец загрузчика, у нас в наличии 112 килобайт памяти RAM.
Другая задача модуля, как шлюза WiFi к стороннему устройству тоже не реализована.
 
Последнее редактирование:

igrr

Moderator
Команда форума
Для главной темы модуля – малопотребляющего режима засыпания и просыпания с опросом датчиков ничего вообще в Arduino IDE не сделано
Другая задача модуля, как шлюза WiFi к стороннему устройству тоже не реализована.
В моем понимании, Arduino — среда для того чтобы быстро сляпать прототип на коленке. Я не уверен, что кто-то всерьез будет писать код для продукта с использованием Arduino. Главное чтобы можно было за 10 минут подключить пару датчиков, поморгать светодиодом, и отправить/принять HTTP запрос. Если подобный "проект" перерастет стадию протоипа (а это происходит редко), и человек перерастет возможности Arduino, то он может начать ближе знакомиться с железом, начать писать эффективный код, экономить батарейку, выпиливать ненужное из памяти, и т.д.
Делать все это за пользователя, если ему нужно мигать светодиодом, я считаю преждевременной оптимизацией.
Поймите правильно — я не отказываюсь от работы над этими фичами, просто они довольно низко стоят в списке того, что я собираюсь сделать.
 

igrr

Moderator
Команда форума
arduino и nodemcu ориентированы примерно на одну и ту же публику, и у них есть свои достоинства и недостатки (например, ардуино нужно ставить, а в nodemcu память быстро заканчивается). впрочем про установку IDE — эта проблема в ближайшие пару недель решится, т.к. в 1.6.4 есть board manager, через который можно будет устанавливать и обновлять файлы для поддержки esp8266.
 

igrr

Moderator
Команда форума
Кстати, поддержка SD у нас теперь тоже есть :)
 

Telek

New member
igrr, я выше на пару страниц писал - есть проблема: использую wificlient, отправляю телеметрию на сервер. При неполучении ответа от сервера(на сервер данные приходят, а esp ответ не получает ответ на GET запрос... ) происходит или перезагрузка модуля, или утечка памяти(утечка небольшая 150-200байт).

Код:
extern "C" {
#include "user_interface.h"
}

#include <Wire.h>
#include <ESP8266WiFi.h>
#include <Ticker.h>
#include <Adafruit_BMP085.h>


#define WIFI_CONNECTION_LIMIT 90
#define SERVER_REQ_DELAY 500
#define SERVER_REQ_WAITING 120
#define MAIN_LOOP_DELAY 1000
#define MAIN_LOOP_DELAY_CNT 900
#define RAIN_COUNTER_PIN 12
#define LED_PIN 13
#define ADC_PARAM 11.0


extern "C" void wdt_feed (void);
extern "C" int readvdd33(void);


const char* ssid     = "";
const char* password = "";
const char* host = "184.106.153.149";
const char* writeKey = "";
const char* writeKey2 = "";

int isRebooted = 0;
int isWiFiDisconnected = 0;
int HostConnectionFailedCount = 0;
float Temperature=0;
long Pressure = 0;


volatile int RainCounter = 0;
volatile long LastMs;
float vcc=0;


volatile int wtdCounter = 0;
volatile int wtdFlag = 0;
int ccnt = 0;

Ticker flipper;

Adafruit_BMP085 dps = Adafruit_BMP085();

void setup() {
 
  // Настройка датчика дожня
  pinMode(RAIN_COUNTER_PIN, INPUT_PULLUP);
  delay(100);
  attachInterrupt(RAIN_COUNTER_PIN, rain_isr_down_up, CHANGE);

  // Светодиод
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);
  flipper.attach(0.3, flip);

  isRebooted = 1;

  Serial.begin(115200);

  Wire.pins(0, 2);
  Wire.begin();

  Serial.println("Starting...");

  delay(1000);
  dps.begin();

  //WiFi
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
 
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void loop() {
 
  WiFiClient client;

  ccnt++;

  int WiFiConnectionCount = 0;

  wtdFlag = 0;

  // Вычисление температуры и давления
  Pressure=dps.readPressure();
  Temperature=dps.readTemperature();

  Serial.print("Pressure(mm Hg):");
  Serial.print(Pressure / 133.3);    //Выводим давление в мм.рт ст
  Serial.print("Temp:");
  Serial.println(Temperature);
 
  //Передача данных
  if (WiFi.status() != WL_CONNECTED)
  {
    isWiFiDisconnected = 1;

    Serial.print("Connecting to ");
    Serial.println(ssid);

    WiFi.begin(ssid, password);

    while (WiFi.status() != WL_CONNECTED) {
      delay(1000);
      Serial.print(".");

      WiFiConnectionCount++;
      if (WiFiConnectionCount > WIFI_CONNECTION_LIMIT) {
        WiFiConnectionCount = 0;

        Serial.println();
        Serial.println("WiFi connection limit");
        WiFi.disconnect();
        return;
      }

    }

    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());

    delay(500);
  }


  // Устанавливаем соединение с хостом
  Serial.print("connecting to ");
  Serial.println(host);
  delay(2000);
  const int httpPort = 80;

  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    HostConnectionFailedCount++;
    return;
  }

  // Собираем GET запрос
  String url = "GET /update?key=";
  url += writeKey;
  url += "&field1=";
  url += Pressure / 133.3;
  url += "&field2=";
  url += Temperature;
  url += "&field3=";
  url += isRebooted;
  url += "&field4=";
  url += isWiFiDisconnected;
  url += "&field5=";
  url += HostConnectionFailedCount;
  url += "&field6=";
  url += system_get_free_heap_size();
  url += "&field7=";
  url += RainCounter;

  //RainCounter=0;

  Serial.print("Requesting URL: ");
  Serial.println(url);

  // This will send the request to the server
  client.print(url + "\r\n");

  Serial.println(ccnt);

  Serial.print("Wait");
  int wait_cnt = 0;

  while ((!client.available()) && (wait_cnt < SERVER_REQ_WAITING)) {
    Serial.print(".");
    wait_cnt++;
    delay(SERVER_REQ_DELAY);
    wtdFlag = 0;
  }
  Serial.println();
  if (wait_cnt >= SERVER_REQ_WAITING) {
    Serial.println("wait_cnt " + String(SERVER_REQ_WAITING));

  }

  while (client.available()) {
    Serial.print("-");
    String line = client.readStringUntil('\r');
    Serial.print(line);

  }

  client.stop();

  Serial.println();
  Serial.println("closing connection");

  isRebooted = 0;
  isWiFiDisconnected = 0;
  HostConnectionFailedCount = 0;

  Serial.print("RAIN_COUNTER: ");
  Serial.println(RainCounter);

  Serial.print("LastMs: ");
  Serial.println(LastMs);

  Serial.println(system_get_free_heap_size());
 
  vcc=analogRead(17);
  Serial.print("VCC: ");
  Serial.println(vcc);
  Serial.println(readvdd33());
 
  WiFi.disconnect();
 
  int delay_cnt=0;
  while (delay_cnt<MAIN_LOOP_DELAY_CNT){
    wtdFlag = 0;
    delay(MAIN_LOOP_DELAY);
    delay_cnt++;
    Serial.print(".");
  }
  //delay(2000);
}


void flip()
{
  int state = digitalRead(LED_PIN);
  digitalWrite(LED_PIN, !state);

  if (wtdFlag)
  {
    wtdCounter++;
  }
  else
  {
    wtdCounter = 0;
  };

  if (wtdCounter > 500)
  {
    ((void (*)(void))0x40000080)();
  };

  wtdFlag = 1;

}



void rain_isr_down_up(void)
{
  int dMs;
 
  ETS_GPIO_INTR_DISABLE();
 
  long ms = millis();

  dMs=ms - LastMs;
 
  if ((dMs > 10) && (dMs< 500))
  {
    RainCounter++;
  }
 
  LastMs = ms;
 
  ETS_GPIO_INTR_ENABLE();
}
 
Последнее редактирование:

igrr

Moderator
Команда форума
@Telek сорри, не нашел — можете код показать? Сейчас как раз разбираю пачку багов в сетевой части.

Edit: вижу, спасибо

Но я не против любых решений.
Чем бы дитя не тешился, лишь бы не плакал.
Отлично! Спасибо :)
 
Последнее редактирование:

Telek

New member
igrr, Код я приложил. Если делать WiFi.disconnect после каждой отправки, то при неполучении ответа будет утечка. Если не отключаться от точки - то перезагрузка.
PS. "неполучением ответа" я называю ситуацию, когда client.available() за определенное время (до 45 сек жду) не становится больше нуля(у меня в коде есть цикл ожидания).
 
Сверху Снизу