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()
не очищает команду? Я озадачен тем, почему цикл на сервере выполняется только дважды, прежде чем мне придется сбросить клиент, и почему после сброса клиент мгновенно распознается, но требуется так много времени, чтобы увидеть его снова. Есть ли у кого-нибудь совет?
@Kyle Chesney, 👍0
1 ответ
Лучший ответ:
Вы 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.");
}
}
- Обнаружение ESP8266 в сети
- ESP8266 не подключается к Wi-Fi
- Каково использование зарезервированных контактов и контактов SDD2, SDD3 NodeMCU?
- NodeMCU продолжает отключаться
- Соединение сетей Wi-Fi на nodemcu: как настроить esp8266 в качестве расширителя Wi-Fi, простейший случай
- Безопасный HTTPS-запрос не выполняется в 90 % случаев.
- Ошибка запуска FirebaseDemo в NodeMCU
- Как связать MPU9250 и NodeMcu?
Спасибо, это решило проблему с двумя петлями! Теперь у меня появились новые проблемы на стороне клиента: после однократной отправки переключателя я не могу отправить его снова без сброса клиента, особенно; Есть ли способ сохранить соединение открытым?, @Kyle Chesney
вы останавливаете клиента на стороне сервера?, @Juraj
для постоянного соединения на стороне сервера см. пример WiFiTelnetToSerial. на стороне клиента вы можете использовать один глобальный клиентский объект. но проверьте, подключено ли оно, а если нет, остановите вызов и затем подключитесь снова, @Juraj
Да, я останавливаюсь на стороне сервера. На стороне клиента я выполнил рефакторинг на
loop() {if (client.connect(...)) { while (client.connected()) { if(toggled) client.flush() } client.stop() }
, что решило все проблемы, за исключением того, что каждые несколько секунд выдается ошибка сброса программного WDT. Я посмотрел пример, спасибо!, @Kyle Chesneyудалить flash() и while (connected()). Используете ли вы последнюю версию основного пакета Arduino esp8266? (2.4.2), @Juraj
Удаление части while(connected()) возвращает проблему одноразового использования. Что касается библиотеки, то _после_ обновления в менеджере библиотек показывает ее версию 1.0.0, @Kyle Chesney
Директор библиотеки? это пакет досок, @Juraj
сделайте
WiFiClient client
глобальным и используйтеloop()
в качестве цикла, @JurajАх, у меня 2.4.1, только что обновился, ошибку на стороне клиента это не решило. «Клиент WiFiClient» является глобальным, и, насколько я могу судить, для цикла я использую «loop()»., @Kyle Chesney
В 2.4.1 были ошибки., @Juraj
Я добавил цикл клиента для ответа, @Juraj
Фантастика, больше никаких ошибок, я, должно быть, перегружаю память, каждый раз пытаясь установить соединение. Большое спасибо за помощь!, @Kyle Chesney
2.4.1 имела утечку памяти при повторном использовании объекта WiFiClient., @Juraj