ESP8266 Одноранговая сеть с AP и STA — кэширование клиентов AP, очистка их запросов?

Я довольно неопытен в работе с Arduino и совершенно новичок в сетевых технологиях, так что потерпите.

Я запрограммировал пару устройств NodeMCU, чтобы они сообщали об использовании инструмента посредством активации светодиода. У меня один настроен как точка доступа, а другой как клиент. Я примерно следовал второму ответу на этот вопрос, чтобы настроить свой. Со временем я перенесу этот конкретный проект на mqtt, но мне хотелось бы понять, как заставить прямой одноранговый обмен работать и в других проектах.

Хотя он работает частично, у меня возникла пара проблем, которые, как я предполагаю, связаны с сетью.
1. После подключения клиента ESP8266 сервер распознает его только в течение двух циклов (каждый занимает ~5 секунд), затем мне приходится перезапускать клиент, который мгновенно обнаруживается сервером.
2. После подключения клиента, если я нажимаю кнопку на клиенте (во время распознавания) только один раз, команда «переключить» отправляется повторно, в результате чего светодиод мигает несколько циклов, пока не остановится, и клиент должен быть отключен. перезапустил снова.
2.1. Если я закомментирую кнопку устранения дребезга на клиенте, это произойдет более надежно. Если при включенном устранении дребезга я нажму кнопку сразу после первого «клиента найден!» сообщение, светодиод обычно включает второй (последний) цикл. Последующие нажатия ничего не меняют.

Эскиз сервера:

// Сервер использования счетчика частиц
// Размещаем снаружи со светодиодом

// загружаем библиотеки
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>

// Устанавливаем переменные
#define use_LED   D2

const char* ssid = "esp_server";
const char* password = "password";

WiFiServer server(80); // устанавливаем порт 80

int toggle = 0;
String request = "";

void setup() {
  Serial.begin(9600);
  pinMode(use_LED, OUTPUT);

  WiFi.mode(WIFI_AP);
  WiFi.softAP(ssid, password);
  digitalWrite(use_LED, HIGH);
  delay(1000);
  Serial.println(WiFi.softAPIP());

  digitalWrite(use_LED, LOW);

  server.begin();
}

void loop() {
  // Проверяем наличие клиента
  WiFiClient client = server.available();
  if (client) {
  // Подождем, пока клиент подключится
// while(!client.available()) { задержка(1); }/
  Serial.println("client found!");

  // Разбор команд
  String request = client.readString();
  Serial.println(request);

  // После однократного нажатия переключателя клиента он переключается между включением и выключением при каждом цикле
  if (request == "toggle") {
    toggle = 1 - toggle; // переключаемся на противоположное при получении запроса
    digitalWrite(use_LED, toggle);
    delay(2000);
  }

  client.flush();
  }

}

Эскиз клиента

// Клиент использования счетчика частиц
// Помещаем в комнату анализа с помощью кнопки


#include <ESP8266WiFi.h>
#include <WiFiClient.h>

#define toggle_button D1 // обязательно используйте понижающий резистор


int toggled = 0;


// Настраиваем соединение с сервером ESP
const char* ssid = "esp_server";    // ssid сервера
const char* password = "password";  // пароль сервера
const int port = 80;                // порт сервера

byte ip[] = {192,168,4,1};

WiFiClient client;

void setup() {
  Serial.begin(9600);
  pinMode(toggle_button, INPUT);
  Serial.println("active");

  WiFi.mode(WIFI_STA); // Настройка как клиент
  WiFi.begin(ssid, password); // Подключаемся к серверу ESP
}

void loop() {
  toggled = digitalRead(toggle_button);

  if (client.connect(ip, port)) { Serial.println("CONNECTED"); }


  if (toggled == HIGH) {
    // отправляем команду для переключения светодиода при нажатии кнопки
    Serial.println("triggered");
    client.print("toggle");
  }

  client.flush();
}

Как ни странно, медленное распознавание происходит только на стороне сервера, клиент рассылает последовательный вывод «CONNECTED» до тех пор, пока не остановится (я предполагаю, что когда второй цикл завершится на стороне сервера, я смогу отслеживать только последовательный порт одного из них). время). Но однажды обнаружил следующие строки, указывающие на ошибку Wi-Fi или памяти в выводе, расположенные среди всех строк "CONNECTED" :

Exception (29):
epc1=0x40202a8f epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000

ctx: cont 
sp: 3ffefa30 end: 3ffefc40 offset: 01a0

>>>stack>>>
3ffefbd0:  3ffe8b70 3ffee9b0 3ffeebe4 40202a8d  
3ffefbe0:  0104a8c0 00000000 3ffeebe4 4020328c  
3ffefbf0:  00000000 3ffee9b4 3ffeebe4 3ffeec10  
3ffefc00:  3fffdad0 3ffee9b0 3ffee998 40202107  
3ffefc10:  401070a0 0104a8c0 00000001 40203519  
3ffefc20:  3fffdad0 00000000 3ffeec08 40203544  
3ffefc30:  feefeffe feefeffe 3ffeec20 40100710  
<<<stack<<<

У меня есть подтягивающие резисторы как на клиентском коммутаторе, так и на светодиоде сервера. Я предполагаю, что client.flush() не очищает команду? Я озадачен тем, почему цикл на сервере выполняется только дважды, прежде чем мне придется сбросить клиент, и почему после сброса клиент мгновенно распознается, но требуется так много времени, чтобы увидеть его снова. Есть ли у кого-нибудь совет?

, 👍0


1 ответ


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

0

Вы connect() и не stop() клиента. Вы выходите из лимита в 5 подключений.

Используйте клиент в if (client.connect(...)), распечатайте и затем выполните client.stop().

А также stop() клиентский объект сервера.

readString имеет тайм-аут в одну секунду. вам следует отправить разделитель и использовать readStringUntil

Изменить: для постоянного подключения нескольких клиентов на стороне сервера см. пример WiFiTelnetToSerial. На стороне клиента вы можете использовать один глобальный клиентский объект. Но проверьте, подключено ли оно, а если нет, остановите вызов и подключитесь снова.

void loop() {

    if (!client.connected()) {
      client.stop();
      if (!client.connect(ip, port)) {
        delay(1000);
        return;
      }
    }

    int toggled = digitalRead(toggle_button);

    if (toggled == HIGH) {
      // отправляем команду для переключения светодиода при нажатии кнопки
      Serial.println("triggered");
      client.print("toggle.");
    }
}
,