• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Выполнение программы без подключенных клиентов

dimaxa7

New member
Код для основного цикла очень простой:

ArduinoOTA.handle();
server.handleClient();

receiveData();

Однако без подключенных клиентов он не переходит к receiveData(); (эта функция ответственна за данные, получаемые с модуля nRF24l01). Если же добавить Serial.println(), то цикл начинает крутиться и все работает как задумано (принимаем данные с nRF, а если подключаются клиенты, то показываем всю инфу). Serial.println() не является полноценным решением, должно же быть что-то лучше, мб он без клиентов уходит с сон, или просто дальше функции server.handleClient() не идет почему-то?

http://weathertmpbme.ddns.net/ с пустыми логином/паролем - сайт с измеряемыми данными, работает-тестируется когда ничего не делаю. Пока вся система в самом начальном состоянии, будет допиливаться и дополняться как будет свободное время.
 
Последнее редактирование:

dimaxa7

New member
Покажите ваш код.
Что именно? В сетапе подключается к роутеру, поднимается сервер, пара страниц. Все это делалось по примерам из интернета и ничего нового нет. А цикл loop полностью описан и показана проблема, что без клиентов функция, получаются данные, не работает, цикл просто ее пропускает, что ли.

Код:
loop () {
   ArduinoOTA.handle();
   server.handleClient();

   receiveData();
}
 

CodeNameHawk

Moderator
Команда форума
Ошибка в строке N , ах да я не вижу кода, вы что думаете, что в сетапе не сумеете сделать ошибку или тем более в receiveData();
 

dimaxa7

New member
Ошибка в строке N , ах да я не вижу кода, вы что думаете, что в сетапе не сумеете сделать ошибку или тем более в receiveData();
Ошибок в коде нет, Вы, видимо, суть не поняли. Вот так будет вывод в консоль
Код:
void loop(void) {
  ArduinoOTA.handle();
  server.handleClient();

  Serial.println();
  receiveData();
}

void receiveData() {
  char buffRx[30];
  byte pipeNo;

  while (radio.available()) {
    radio.read(&buffRx, sizeof(buffRx));
    Serial.println(buffRx);
  }
}
А вот так - нет.
Код:
void loop(void) {
  ArduinoOTA.handle();
  server.handleClient();

  // Serial.println();
  receiveData();
}

void receiveData() {
  char buffRx[30];
  byte pipeNo;

  while (radio.available()) {
    radio.read(&buffRx, sizeof(buffRx));
    Serial.println(buffRx);
  }
}
Компилируется и выводится все отлично, просто нужна возможность собирать данные все время, а не ждать активного соединения.

Код для сетапа, хотя хз зачем он нужен
Код:
void setup(void) {
  Serial.begin(115200);

  init_nRF24l01();
  init_SPI();

  init_server();

  init_OTA();
  initTMPBMEsheet();

  configTime(timezone * 3600, 0, "pool.ntp.org", "time.nist.gov");
    if (debug) Serial.print("\nWaiting for time");
    while (!time(nullptr)) { if (debug) Serial.print("."); delay(200);} if (debug) Serial.println("");


  //Serial.println(ESP.getFlashChipRealSize());
}

void init_nRF24l01() {
  radio.begin();                                     
  radio.setChannel(0x65);                            
  radio.setDataRate     (RF24_250KBPS);                
  radio.setPALevel      (RF24_PA_HIGH); 
  radio.openReadingPipe (1, 0x1234567890LL);         
  radio.startListening  ();

  radio.printDetails();
}

const char* www_username = "";
const char* www_password = "";
const char* ssid = "ххх";
const char* password = "ххх";

void init_server() {
  WiFi.mode(WIFI_STA); //режим клиент
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println(WiFi.localIP());

  server.on("/", handleApi);
  server.on("/xml", handleXML);
  server.on("/reset", []() {                    // Перезагрузка
    if (!server.authenticate(www_username, www_password))
      return server.requestAuthentication();
    server.send(200, "text/plain", "ok");
    ESP.restart();
  });
  server.onNotFound(handleNotFound);          //  Cтраница ошибки

  server.on ("/stock0", handlePageStock0);
  server.on ("/stock1", handlePageStock1);
  server.on ("/stock2", handlePageStock2);
  server.on ("/stock3", handlePageStock3);

  server.on ("/data0.json", processCSV_temp36);
  server.on ("/data1.json", processCSV_tempBME);
  server.on ("/data2.json", processCSV_humBME);
  server.on ("/data3.json", processCSV_presBME);

  server.begin();
}

void init_SPI() {
  SPI.setHwCs(true);
  SPI.begin();
  SPI.setDataMode(SPI_MODE0);
  SPI.setBitOrder(MSBFIRST);
}

void init_OTA() {
  ArduinoOTA.setHostname("ESP8266-00001");
  ArduinoOTA.begin();
}

void initTMPBMEsheet() {
  TMPBME[0]._name = "Temperature TMP36";
  TMPBME[0]._unit = "&degC";

  TMPBME[1]._name = "Temperature BME280";
  TMPBME[1]._unit = "&degC";

  TMPBME[2]._name = "Humidity BME280";
  TMPBME[2]._unit = "%";

  TMPBME[3]._name = "Pressure BME280";
  TMPBME[3]._unit = "mBar";
}
и подключение библиотек
Код:
#include <time.h>

#include <ArduinoOTA.h>
#include <WiFiUdp.h>

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <SPI.h>

#include <nRF24L01.h>
#include <RF24.h>

#define debug true
 

Юрий Ботов

Moderator
Команда форума
Ошибок в коде нет,
Когда все работает - значит ошибок нет, а вот если что то не так - значит они есть!

Например,
  • char buffRx[30];
  • byte pipeNo;
  • while (radio.available()) {
  • radio.read(&buffRx, sizeof(buffRx));
  • Serial.println(buffRx);
Вот тут вы объявляете буфер длиной 30, потенциально весь его заполняете и не ставите в конце нуль-символ После чего у println срывает крышу и он печатает в порт всю память пока не нарвется на какой нибудь нолик или просто виснет. Надо как то так:
Код:
char buffRx[31];
byte pipeNo; // видимо это тоже ошибка? нафига он там нужен?

while(radio.available()) {
  int cnt = radio.read(&buffRx, sizeof(buffRx)-1); // посмотрите в описании библиотеки как именно возвращается количество прочтенных байт, я с nRF не работал и пишу "как это обычно бывает"
  buffRx[cnt+1] = 0;
  Serial.println(buffRx);
 

dimaxa7

New member
Когда все работает - значит ошибок нет, а вот если что то не так - значит они есть!

Например,

Вот тут вы объявляете буфер длиной 30, потенциально весь его заполняете и не ставите в конце нуль-символ После чего у println срывает крышу и он печатает в порт всю память пока не нарвется на какой нибудь нолик или просто виснет. Надо как то так:
Код:
char buffRx[31];
byte pipeNo; // видимо это тоже ошибка? нафига он там нужен?

while(radio.available()) {
  int cnt = radio.read(&buffRx, sizeof(buffRx)-1); // посмотрите в описании библиотеки как именно возвращается количество прочтенных байт, я с nRF не работал и пишу "как это обычно бывает"
  buffRx[cnt+1] = 0;
  Serial.println(buffRx);
Если бы он вообще что-то печатал - было бы дело, но, если подробнее и еще раз, то дело обстоит так: открываю порт, тишина. Открываю в браузере сайт - вижу данные в порту и на сайте все работает. Закрываю вкладку - опять данные в порт не идут. Потом дописываю в loop вывод ничего(Serial.println()), и о чудо! всегда данные в порт сыплются с датчика. Насчет окончания - все продумано. Пакет может быть только 30 символов и последний изначально нуль-символ (так уже отправляет датчик-модуль, иначе не отправляет вообще). Это не единственные данные, которые надо принимать. Пакеты предполагаются разных типов: данные с датчика, которые обрабатываются одним путем, служебные данные (об ошибках, состоянии батареи и тд), поэтому их надо ждать всё время, но, увы, до него, почему-то, не доходит, пока не подключиться к серверу. Рассчитывал на ответ из разряда: "да это же так библиотека ESP8266WebServer так работает, пока нет клиентов - усыпляет ESP, допиши вот это вот тут и будет хорошо", но, видимо, не распространенная проблема.

pipeNo используется для определения номера трубы, с которой читаем пришедший пакет, библиотека nRF, но пока такой функционал не нужен. Не мешает и пусть будет.
 

CodeNameHawk

Moderator
Команда форума
Рассчитывал на ответ из разряда: "да это же так библиотека ESP8266WebServer так работает, пока нет клиентов - усыпляет ESP, допиши вот это вот тут и будет хорошо", но, видимо, не распространенная проблема.
Вместо того, чтобы рассказывать сказки
Ошибок в коде нет,
займитесь отладкой.
Раз самая простая (Serial.print ) отпадает, кто мешает поморгать светодиодом? Так вы сможете узнать чем занимается ваша программа, пока вы за ней не наблюдаете..
 

CodeNameHawk

Moderator
Команда форума
Потом дописываю в loop вывод ничего(Serial.println()), и о чудо! всегда данные в порт сыплются с датчика.
Чего тут удивляться,
Код:
  while (radio.available()) {
    radio.read(&buffRx, sizeof(buffRx));
вы сразу, после появления данных, без проверки их количества, читаете весь буфер, а он возможно еще не успел наполниться.
Вот простая задержка (Serial.print) и помогает. Это теория а так только отладкой поймаете ошибку.(Возможно она окажется простой логической ошибкой, а не ошибкой в коде)
 
Сверху Снизу