ESP8266 виснет

kab

New member
Подскажите в чем может быть проблема постоянного зависания при работе с сетью. Например при прослушивании udp через некоторое время зависает esp. А при подключении и прослушивании сокета постоянные перезагрузки, через 3-5-10 минут.(все работает, слушает\передает но постоянный reset). Может где то что то стек переполняется? или еще что то? Arduino ide 1.6.5.
В ардуино иде есть функция ( не помню, как называется - поищите сами) - выдает количество свободной памяти. Сделайте вывод и в мониторе порта последите - не уменьшается ли доступная память критически в процессе работы.
 

Roboter

New member
У меня модуль, NodeMCU ESP8266, виснет от установки пина 7 в input

void setup() {
pinMode(7, INPUT);
}
в консоли пишет

ets Jan 8 2013,rst cause:4, boot mode:(3,6)

wdt reset
load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v4ceabea9
~ld

если поставить пин 0 - работает (подключена кнопка)
пин 3 - работает (весит в воздухе)
6,7,8 - виснет
 

nikolz

Well-known member
У меня модуль, NodeMCU ESP8266, виснет от установки пина 7 в input

void setup() {
pinMode(7, INPUT);
}
в консоли пишет

ets Jan 8 2013,rst cause:4, boot mode:(3,6)

wdt reset
load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v4ceabea9
~ld

если поставить пин 0 - работает (подключена кнопка)
пин 3 - работает (весит в воздухе)
6,7,8 - виснет
Есть два обозначения пинов :
это либо D0...D10 - для nodemcu, либо GPIO0...GPIO16.
Что такое pin 6,7,8 ?
 

enjoynering

Active member
сам погорел недавно на обозначении пинов - https://esp8266.ru/forum/threads/max31855-ne-rabotaet.3133/#post-47964

убил два часа на поиск и нашел проблему. оказывается в arduino core for esp8266 по другому задаются пины!!! если в Arduino для AVRтипа UNO написать digitalWrite(4, LOW) то это значит что цифровой пин D4 в ноль. В Arduino для ESP8266 все оказалось не так, если написать digitalWrite(4, LOW) то это значит GPIO4 в ноль, а не D4. век живи век учись.
вызвав pinMode(7, INPUT) вы вызываете GPIO7 который работает как выход, для чтения вашего гениального кода из флешки. Пытаясь сделать его входом, роняете систему, срабатывает WDT. Круг замкнулся.

правильно вот так pinMode(D7, INPUT) что равнозначно GPIO13

описание пинов для NODEMCU в макросах тут - Arduino/pins_arduino.h at master · esp8266/Arduino · GitHub
 

Вложения

Последнее редактирование:

Maddoc

New member
Возникла проблема модуль - nodemcu 1.0. Пишу программу для считывания показаний с цифрового штангенциркуля, работает на прерываниях, и хотел показания вывести на web через websockets, но почему то модуль перезагружается при срабатывании прерывания и при попытке подключится к модулю по WIFi. Если отдельно прерывания все нормально в COM PORT шлет, и так же если отдельно с WEB работать без прерываний тоже все нормально подключается и работает. Работаю с библиотеками:
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

Код:
// Вызов прерывания при начале передачи данных
attachInterrupt(digitalPinToInterrupt(clock_Master), read_bitM, FALLING);

void read_bitM() // Обработчик прерывания Мастер индикатора
{
flag_M = 1; // Разрешается чтение
}
Да я понимаю что Ардуино - Дурино но может кто подскажет как решить проблему, не хотелось бы писать код вечно ждуший сигнала. Пробовал на 2 модулях с разными бутлодерами результат один ресет во время подключения клиента.
 

Maddoc

New member
Ух ну не знаю... 900 строк ...прикрепил.
Но к стати, есть надежда, потому что в самом слабом варианте работает, показания снимает четко и на страницу выводит, если обновлять вручную:
Код:
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
//SSID and Password to your ESP Access Point
const char* ssid = "ESP_WIFI";
const char* password = "";
ESP8266WebServer server(80); //Server on port 80
//*************************************************************************
volatile long word_bitM, word_bitS = 0; // переменная полученного значения
volatile int count_M, count_S = 0;    // переменная счетчика импульсов
volatile float result_M, last_result_M,
      result_S, last_result_S = 0;
volatile int sign_M, sign_S = 1;
volatile int flag = 1;
volatile unsigned int Time_countM, Time_countS = 0;
int Resiv_count_S;
int stop_int;

void handleRoot() {
  //server.send(200, "text/plain", "hello from esp8266!");
  server.send(200, "text/plain", String(result_M));
}

// Объявление выводов МК
#define data_Master D1
#define clock_Master D2
#define data_Slave D3
#define clock_Slave D5

#define detectpin_M D6
#define detectpin_S D7

void read_bitM() // Обработчик прерывания Мастер индикатора
{
  delayMicroseconds(20); // задержка для проверки значения, по середине синхроимпулса
  if (count_M < 16)
  {
    bitWrite(word_bitM, count_M, !digitalRead(data_Master)); //  чтение бита
  }
  if (count_M == 20) // Проверка знака 20й бит
  {
    if (digitalRead(data_Master))
      sign_M = 1;
    else
      sign_M = -1;
  }
  digitalWrite(detectpin_M, HIGH);
  count_M++;
  digitalWrite(detectpin_M, LOW);
  //noInterrupts();
}

void read_bitS() // Обработчик прерывания Подчиненного индикатора
{
  delayMicroseconds(20); // задержка для проверки значения, по середине синхроимпулса
  if (count_S < 16)
  {
    bitWrite(word_bitS, count_S, !digitalRead(data_Slave)); //  чтение бита
  }
  if (count_S == 20) // Проверка знака 20й бит
  {
    if (digitalRead(data_Slave))
      sign_S = 1;
    else
      sign_S = -1;
  }
  digitalWrite(detectpin_S, HIGH);
  count_S++;
  digitalWrite(detectpin_S, LOW);
  //noInterrupts();
}

void setup()
{
  //ets_update_cpu_frequency(8);
  pinMode(clock_Master, INPUT); // Вход для синхроимпульса
  pinMode(data_Master, INPUT);  // Вход для приема данных
  pinMode(clock_Slave, INPUT);  // Вход для синхроимпульса
  pinMode(data_Slave, INPUT);   // Вход для приема данных
  pinMode(detectpin_M, OUTPUT);
  pinMode(detectpin_S, OUTPUT); 
  delay(50);
  attachInterrupt(digitalPinToInterrupt(clock_Master), read_bitM, FALLING); // Вызов прерывания при начале передачи данных 
  noInterrupts();
  Serial.begin(115200);
  Serial.println("");
  WiFi.mode(WIFI_AP);           //Only Access point
  WiFi.softAP(ssid, password);  //Start HOTspot removing password will disable security
  IPAddress myIP = WiFi.softAPIP(); //Get IP address
  Serial.print("HotSpt IP:");
  Serial.println(myIP);
  server.on("/", handleRoot);      //Which routine to handle at root location
  server.begin();                  //Start server
  Serial.println("HTTP server started");
 
}

// Функция определения начала передачи данных
void Get_start(uint8_t clockpin, uint8_t datapin, volatile long word_bit, volatile int count)
{

  if (flag)
  { // Если оба пина находятся в одинаковом состоянии дольше 1 мс разрешаются прерывания
    // Поиск начального участка без сигнала, что бы не начать считать импульсы посередине пакета данных
    if ((digitalRead(clockpin) == digitalRead(datapin)) && ((micros() - stop_int) > 1000))
    {
      flag = 0;
      interrupts(); // Разрешаем прерывания когда свободный участок найден
    }
    else
    {
      stop_int = micros(); // Сбрасываем значение таймера
      flag = 1;
      word_bit = 0;
      count = 0;
    }
  }
}

void loop()
{
  Get_start(clock_Master, data_Master, word_bitM, count_M);
  // Проверка формирования Значения для Master
  if (count_M == 24) // Неполный пакет игнорируется
  {

    digitalWrite(detectpin_M, HIGH); // debug
    delay(2);
    result_M = (word_bitM * sign_M) / 100.00;
    digitalWrite(detectpin_M, LOW); // debug
    // Serial.print("count_M: ");
    // Serial.println(count_M);
    // Serial.print("word_bit_M: ");
    // Serial.println(word_bitM, BIN);
    // Serial.print("word_bit_M DEC: ");
    // Serial.println(word_bitM, DEC);
    if (last_result_M != result_M)//Вывод результата если он отличается от предыдущего
    {
      Serial.print("RESULT_M: ");
      Serial.println(result_M, 2);
      last_result_M = result_M;
    }
    stop_int = micros();
    flag = 1;
    count_M = 0;
    word_bitM = 0;
    delay(1);
  }
  if (count_M > 24) // если количество бит больше заданного прекращаем прерывания, и сбрасываем данные
  {
    noInterrupts();
    flag = 1;
    count_M = 0;
    word_bitM = 0;
  }

  Get_start(clock_Slave, data_Slave, word_bitS, count_S);
  // Проверка формирования Значения для Slave
  if (count_S == 24) // Неполный пакет игнорируется
  {
    digitalWrite(detectpin_S, HIGH); // debug
    delay(2);
    result_S = (word_bitS * sign_S) / 100.00;
    digitalWrite(detectpin_S, LOW); // debug
   
    // Тестовый блок проверки количества пакетов в СЕК.
    Resiv_count_S++;
    if (Time_countS == 0)
    Time_countS = micros();
    if ((micros() - Time_countS) > 1000000){
    Serial.print("Resived paket_S: ");
    Serial.println(Resiv_count_S);
    Time_countS = 0;
    Resiv_count_S = 0; 
    }

   
    // Serial.print("word_bit_S: ");
    // Serial.println(word_bitM, BIN);
    // Serial.print("word_bit_S DEC: ");
    // Serial.println(word_bitM, DEC);
    if (last_result_S != result_S) //Вывод результата если он отличается от предыдущего
    {
      Serial.print("RESULT_S: ");
      Serial.println(result_S, 2);
      last_result_S = result_S;
    }
    stop_int = micros();
    flag = 1;
    count_S = 0;
    word_bitS = 0;
    delay(1);
  }
  if (count_S > 24) // если количество бит больше заданного прекращаем прерывания, и сбрасываем данные
  {
    noInterrupts();
    flag = 1;
    count_S = 0;
    word_bitS = 0;
  }
  server.handleClient();          //Handle client requests
}
 

Вложения

Maddoc

New member
посмотрите count_M
Вы сравниваете его с 16 и 20 и инкрементируете,
а где сбрасываете в ноль ? или работаете по переполнению?
Да обработчик прерываний без веб работает хорошо, и даже если питание отключить посреди пакета. count_M сбрасывается в ноль если больше 24. Там если что для понимания 2 штангенциркуля подключено. Ну соответственно они шлют пакеты по 24 бита по прерыванию на шине clock считываю показания на data все просто, если длинна полученного пакета отличается от 24 значит пакет битый и не учитывается. Но вот походу какой то библиотеке это не особо нравится. Основная часть это разработка от Третьякова Сергея.
 

nikolz

Well-known member
Да обработчик прерываний без веб работает хорошо, и даже если питание отключить посреди пакета. count_M сбрасывается в ноль если больше 24. Там если что для понимания 2 штангенциркуля подключено. Ну соответственно они шлют пакеты по 24 бита по прерыванию на шине clock считываю показания на data все просто, если длинна полученного пакета отличается от 24 значит пакет битый и не учитывается. Но вот походу какой то библиотеке это не особо нравится. Основная часть это разработка от Третьякова Сергея.
Как вы определяете начало передачи из штангея?
Есть сигнал готовности данных от него?
 

nikolz

Well-known member
что-то у вас не продумано
два раза этот блок повторяется
if (count_S > 24) // если количество бит больше заданного прекращаем прерывания, и сбрасываем данные
{
//noInterrupts();
flag = 1;
count_S = 0;
word_bitS = 0;
}
 

nikolz

Well-known member
посмотрите этот кусок
flag = 1;
count_M = 0;
word_bitM = 0;
delay(1);
}
if (count_M > 24) // если количество бит больше заданного прекращаем прерывания, и сбрасываем данные
{
//noInterrupts();
flag = 1;
count_M = 0;
word_bitM = 0;
}
---------------------------
может быть так записать:
}
if (count_M >=24) // если количество бит больше заданного прекращаем прерывания, и сбрасываем данные
{
//noInterrupts();
flag = 1;
count_M = 0;
word_bitM = 0;
}
 

Maddoc

New member
что-то у вас не продумано
два раза этот блок повторяется
if (count_S > 24) // если количество бит больше заданного прекращаем прерывания, и сбрасываем данные
{
//noInterrupts();
flag = 1;
count_S = 0;
word_bitS = 0;
}
Это 2й штангель, там count_S и count_M.
 

nikolz

Well-known member
По заднему фронту clock. Мне бы узнать, какие есть ограничения нюансы при работе с прерываниями и вайфай.
прерывание долго нельзя
а wifi может быть долго.
---------------------
Все зависит от того, что вы будете делать с введенными данными.
Может быть их сначала обработать а потом передавать
и какая у вас скорость считывания(дискретизации)
допускается пропуск данных или нет
 
Сверху Снизу