Ошибка времени выполнения в arduino

Я пытаюсь подключить несколько клиентов к серверу, все они используют nodeMCU. Я получаю странную ошибку времени выполнения в Server Serial Monitor Arduino IDE, когда загружаю код.

Вот мой код сервера:

#include <ESP8266WiFi.h>
#define Max_Clients 5

WiFiServer server(80);                                        
WiFiClient *clients[Max_Clients] = {NULL};                    
String inputs [Max_Clients] = {""};                           //Инициализация для хранения строки, полученной от клиентов

void setup() {
  pinMode(D1,OUTPUT);                                         //Инициализация выводов для отображения выхода и входа
  pinMode(D2,OUTPUT);
  pinMode(D3,OUTPUT);
  pinMode(A0,INPUT);

  Serial.begin(9600);                                         //Начать связь между ESP8266-12E и окном монитора

  WiFi.mode(WIFI_AP);                                         //Этот ESP8266-12E — точка доступа
  WiFi.softAP("NodeMCU_js", "12345678");                      //Укажите (SSID, пароль)

  IPAddress myIP = WiFi.softAPIP();                           //Получаем IP сервера
  Serial.println("Server IP is: ");                           //Выводим IP-адрес в окно монитора
  Serial.println(myIP);
  server.begin();                                             //Запускаем HTTP-сервер
}

void loop() { 
  WiFiClient client = server.available();                     //Проверяем, подключился ли новый клиент к серверу

if (client) {  
Serial.println("A new Client has connected :)");

for (int i=0 ; i<Max_Clients ; ++i){              //Подтверждает и настраивает новых клиентов
  if (NULL == clients[i]){
    clients[i] = new WiFiClient(client);          //ничего в client[i] не означает, что это новый клиент
    break;
    }
  }
}

for(int i=0 ; i<Max_Clients ; ++i){                           //Для доступных клиентов
  if (NULL != clients[i] && clients[i]->available()){    
    String request = clients[i]->readStringUntil('\r');
    Serial.println("The string of client "+String(i+1));    //Печать сообщения клиента
    inputs[i] = request;
    Serial.println(inputs[i]);

    int duty[4];
    duty[i] = inputs[i].toInt();

    if (i == 0){
      analogWrite(D1, duty[i]);
      clients[i]->println("To client 1.\r");
    }
    if (i == 1){
      analogWrite(D2, duty[i]);
      clients[i]->println("To client 2.\r");
    }
    if (i == 2){
      analogWrite(D3, duty[i]);
      clients[i]->println("To client 3.\r");
    }

    clients[i]->flush();                                    //Ожидание завершения передачи
    clients[i]->stop();
   }   
  } 
 }                                                                 //закрытие цикла void

Вот мой клиентский код (который будет одинаковым для всех клиентов):

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>

char ssid[] = "NodeMCU_js";
char password[] = "12345678";

WiFiClient client;                // Создает клиента, который может подключаться к указанному IP-адресу и порту в Интернете, как определено в client.connect()

IPAddress server(192,168,4,1);

void setup() {
  pinMode(A0,INPUT);
  pinMode(D6,OUTPUT);

  WiFi.persistent(false);
  WiFi.mode(WIFI_STA);

  Serial.begin(9600);                 //Последовательное соединение
  WiFi.begin(ssid,password);          //WiFi-подключение

  while (WiFi.status() != WL_CONNECTED) {         //Ждем завершения подключения WiFI
    delay(500);
    Serial.println("Connecting...");
  }
  Serial.println("Connected.");
  client.connect(server, 80);   // Подключение к серверу
  }

void loop() {

  if(WiFi.status() == WL_CONNECTED){   //Проверка статуса подключения WiFi

    int sense = 200;
    client.println(sense+"\r");  //Сообщение клиента серверу
    String answer = client.readStringUntil('\r');         //Чтение ответа с сервера
    Serial.println("from server: " + answer);             //Печать ответа
    client.flush();

    delay(3600000);
    }
  else{
    Serial.println("Error in WiFi connection");   
    }
  }

При загрузке этого кода последовательный монитор на сервере показывает:

Подключился новый Клиент :) Строка клиента 1 nt8_t* BufferedStreamDataSource::get_buffer(size_t) [с TStream = >ProgmemStream; uint8_t = беззнаковый символ; size_t = беззнаковое целое] Строка клиента 1

В то время как последовательный монитор на клиенте показывает:

Подключение... Подключение... Подключение... Подключение... Подключение... Подключение... Подключение... Подключено. с сервера: Клиенту 1.

Я понятия не имею об источнике этой ошибки. Любая помощь приветствуется.

Заранее спасибо.

, 👍0

Обсуждение

не используйте порт 80, если это не HTTP. используйте порт 23 или 2323, который указывает на связь по простому сокету (telnet). и вы можете протестировать сервер с помощью клиента telnet., @Juraj

Вам не следует использовать 23, так как это подразумевает интерактивное соединение. Вам следует использовать *любой* порт, кроме 80 - в идеале не использовать порт, связанный с каким-либо известным протоколом. Но на самом деле не имеет значения, какой порт вы используете во встроенной системе... Кстати, telnet может подключаться к любому порту - даже к 80., @Majenko

Ну, я уже успешно использовал этот порт для установления соединения. Какие еще порты доступны?, @Dingodudesir

порты до 1023 зарезервированы https://en.wikipedia.org/wiki/Список_номеров_портов_TCP_и_UDP, @Juraj


2 ответа


Лучший ответ:

1

Я подозреваю, что проблема на стороне клиента. Эта строка:

client.println(sense+"\r");  //Сообщение клиента серверу

не делает то, что вы думаете.

sense — это число (200). "\r" — это строковая константа, расположенная по адресу в памяти. Когда вы складываете их вместе, вы не объединяете две строки, а добавляете 200 к адресу строковой константы, а затем отправляете все, что она находит в этом месте.

"\r" на самом деле излишен в любом случае, так как вы используете println, который добавляет \r\n в конец печати. Однако, если вы хотите сделать это вручную, вам просто нужно разделить его на два отпечатка:

client.print(sense);
clienr.print("\r");
,

Могу ли я просто сделать строку 'смысловой'? Она должна передаваться как String и вносить изменения на клиенте., @Dingodudesir

Можно, но зачем? Это пустая трата ресурсов и никакой пользы., @Majenko


-1
  1. Исследуйте WL_CONNECTED, я думаю, вы обнаружите, что это состояние подключения к вашей точке доступа, а не состояние, если устройство подключилось, также существуют проблемы с этой переменной. Состояние не меняется при разрыве соединения.

  2. Чтобы установить соединение, вам нужно сделать запрос GET или POST на страницу на вашем сервере, например...

    если (клиент.подключение(сервер, httpPort)) { // подключен к ресурсу // отправить данные client.print("GET /myfile"); клиент.println(" HTTP/1.1"); client.println("Хост: IP-АДРЕС"); client.println("Соединение: закрыто"); клиент.println(); } еще { // Нет соединения с сервером // возможно, следует продолжать повторять попытки, иначе ждем следующего вызова } // конец, если соединение установлено

  3. Ваш серверный код должен обслуживать страницу и постоянно проверять наличие соединения с

    webServer.on("/", doRoot);

  4. Затем есть функция, которая записывает HTML обратно клиенту, например...

    void doRoot() { // написать HTML Строка html; html = ""; html += "

    Моя страница

    "; // и отправить его webServer.send(200, "текст/html", html); }

,

Извините, я не могу разобраться с форматированием для этого сайта. Я использую Enter Code, и там написано Enter Code here, но когда вставляю, получается мусор., @Brian Moreau

Да, блоки кода и нумерованные списки плохо работают вместе., @Majenko

WiFiClient — это TCP-сокет. Его можно использовать как есть. Нет необходимости использовать протокол HTTP между двумя устройствами. Но не очень удобно использовать порт 80, который по стандарту зарезервирован для HTTP., @Juraj

Это может хорошо работать для связи на основе веб-сервера. Однако в моем случае один из nodeMCU является сервером., @Dingodudesir