Здравствуйте. Делаю для себя устройство для умного дома (защита от протечки водоснабжения) на базе esp32.
Используется wifi и mqtt.
Проблема заключается в том, что если пропадет wifi соединение или подключение к mqtt брокеру, то скетч прервется и будет пытаться реконектиться. То есть не будут опрашиваться датчики и управляться сервоприводы на кранах.
Прошу помощи в переделки скетча таким образом, чтобы и датчики опрашивались и подключение и к wifi и к mqtt продолжало выполняться.
Много лет назад уже делал себе такое устройство и проблема была та же, но я, постеснявшись спросить решение у людей в интернете, просто использовал в связке arduino nano и esp8266. За опрос датчиков и управление кранами отвечала ардуино, а данные в mqtt отправляла esp8266.
Сейчас в новое место жительства нужно еще одно устройство, и хотел реализовать уже на одной esp32.
Хочется именно квалифицированной помощи, чтобы максимально исключить программные баги в таком ответственном устройстве.
#include <WiFi.h>
#include <PubSubClient.h>
#include <ESPmDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
const char* ssid = "mywifirouter";
const char* password = "12345678";
const char* mqttServer = "192.168.100.4";
const int mqttPort = 1883;
const char* mqttUser = "user";
const char* mqttPassword = "password";
WiFiClient espClient;
PubSubClient client(espClient);
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.println("Connecting to WiFi..");
}
Serial.println("Connected to the WiFi network");
client.setServer(mqttServer, mqttPort);
while (!client.connected()) {
Serial.println("Connecting to MQTT...");
if (client.connect("ESP32Client", mqttUser, mqttPassword)) {
Serial.println("connected");
} else {
Serial.print("failed with state ");
Serial.print(client.state());
delay(2000);
}
}
ArduinoOTA.setHostname("esp32_MQTT_Test");
ArduinoOTA
.onStart([]() {
String type;
if (ArduinoOTA.getCommand() == U_FLASH)
type = "sketch";
else // U_SPIFFS
type = "filesystem";
// NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
Serial.println("Start updating " + type);
})
.onEnd([]() {
Serial.println("\nEnd");
})
.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
})
.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
else if (error == OTA_END_ERROR) Serial.println("End Failed");
});
ArduinoOTA.begin();
Serial.println("Ready");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
client.publish("esp32/esp32test", "Hello from Alex");
}
void loop() {
ArduinoOTA.handle();
client.loop();
//далее мой код (опрос датчиков и т.п.)
}
#include <Что-то там>
MyGlobal myLovelyGlobalVariable;
void setup() {
// всякая служебная фигня про сеть
//...
xTaskCreate(
myTask,
"The name for my task",
4096, //размер стека для моей задачи
NULL, //тебе не надо
1, // приоритет, тебе не нужно
NULL //снова забей, тебе не нужно
);
}
void myTask(void * p) {
//вот тут пишешь всю свою работу с датчиками, регуляторами
//и внутрижопными жужжателями
//***то что выполнится ОДИН раз - как setup
//int i,j,k; // твои переменные всякие
// например
const int myLED = LED_BUILTIN;
pinMode(myLED, OUTPUT);
for(;;) {
//а вот тут всё, что хотел написать в loop() ;)
digitalWrite(myLED, !digitalRead(myLED));
delay(1000);
//О да! Тут можно использовать делеи сколько угодно.
//другой поток (Task) никак от них не зависит.
//Этих самых потоков можешь писать сколько угодно,
// у меня обычно не один десяток. Просто помни, что каждый "тик" по умолчанию 1 мс.
// если не знаешь, что такое системный "тик" не напрягайся, значит тебе это еще не нужно
}
}
void loop() {
// вот тут твоего кода НЕ НУЖНО, только системные и сетевые вещи
}
Я правильно понимаю, это какое-то подобие многозадачности?
То есть я могу разбить скетч на несколько задач: одна будет постоянно следить за сетевым соединением и переподключаться, а другая задача будет опрашивать датчики и в случаи тревоги закрыть краны?
Почему переменные и pinModы назначаются внутри таски, а не перед void setup() и не в самом void setup()?
В выключателях света на ESP8266, в loop(), я оставлял только всю работу с Wi-Fi и mqtt.
Всю обработку событий, включение и выключение реле перенесены в Ticker.
Так же и со счетчиками воды.
В таком виде, пропадание Wi-Fi, в принципе никак не ощущается.
“Подобие”??? FreeRTOS совершенно нормальная многозадачная ОС. Если привык к pthread, то эта библиотека тоже есть под FreeRTOS. Можешь ей пользоваться. Можно таксами системными - как нравится, так и делай, как привык.
Да!!! Так и положено писать подобные вещи. Для этого и нужна ОС. Делать разные задачи в РАЗНЫХ потоках управления, не мешая друг другу. “Не мона, а нуна!” (с).
Да как хочешь. Это же пример. “Иллюстрация” - знаешь такое слово? ;))
==
ЗЫ: Пипец! Создание Ардуино понизило порог вхождения в эмбеддинг-программирование просто ниже плинтуса! Популяризация - хорошо, но откуда берутся люди, которые НЕ ЗНАЮТ ВООБЩЕ НИЧЕГО? Зачем им нужна Ардуинка, чОрт побери?!
Извиняюсь за свою неграмотность в программировании, я инженер строитель, и вообще далеко не программист, поэтому и задаю вопросы на профильном форуме.
Просто я думал форум для того и нужен чтобы незнающие люди задавали вопросы, а знающие, по возможности, на них отвечали.
Я установил библиотеку. Пытаюсь скомпилировать хоть какой-нибудь скетч из примеров библиотеки и полный экран ошибок. Ошибки появляются, если выбирать плату esp32 или esp8266. На платах ардуины ошибки не вылазят.
In file included from C:\Users\Alexandr\AppData\Local\Temp.arduinoIDE-unsaved202316-11148-1rfsq7n.7zc6\AnalogRead_DigitalRead\AnalogRead_DigitalRead.ino:1:
c:\Users\Alexandr\Documents\Arduino\libraries\FreeRTOS\src/Arduino_FreeRTOS.h:133:10: error: #error INCLUDE_vTaskDelayUntil and INCLUDE_xTaskDelayUntil are both defined. INCLUDE_vTaskDelayUntil is no longer required and should be removed #error INCLUDE_vTaskDelayUntil and INCLUDE_xTaskDelayUntil are both defined. INCLUDE_vTaskDelayUntil is no longer required and should be removed
^~~~~
In file included from c:\Users\Alexandr\Documents\Arduino\libraries\FreeRTOS\src/Arduino_FreeRTOS.h:1365,
from C:\Users\Alexandr\AppData\Local\Temp.arduinoIDE-unsaved202316-11148-1rfsq7n.7zc6\AnalogRead_DigitalRead\AnalogRead_DigitalRead.ino:1:
c:\Users\Alexandr\Documents\Arduino\libraries\FreeRTOS\src/FreeRTOSVariant.h:33:10: fatal error: avr/io.h: No such file or directory #include <avr/io.h>
^~~~~~~~~~
compilation terminated.
Я Вам, ещё в самом первом в этой теме ответе, предложил перенести тему в раздел, где люди берутся делать работу за деньги. Вы проигнорировали. Напрасно. Поскольку Вы
это для Вас реальный вариант сделать Вашу хотелку.
Ну, или есть ещё вариант стать “далеко программистом”, но это потребует пары лет. Если Вы готовы - приступайте.
И зачем? Когда хобби - гончарный круг, все понимают, что ДО задания вопросов нужно учиться. Если хобби - программирования, то нужно прийти на форум и спрашивать полную херню!
Нормально, чё? 3.14здец какой-то!!!
sadman41, заменил #include <Arduino_FreeRTOS.h>, на #include <esp_log.h> и все заработало. Спасибо большое, буду изучать дальше.
Так, как, переносить тему в платный раздел?
Если бы я хотел отдавать деньги за то, что мне самому интересно сделать, я бы просто купил готовое заводское устройство.
WladDrakula, вы такой смешной =)
Таких лютых ЧСВшников последний раз встречал году в 2008.
Написал аж 2 сообщения подряд оффтопом, да еще и с оскорблениями.
Хорошо, что на форуме есть люди лучше вас.
p.s. Несколько лет изучал homeassistant, и привык к англоязычной аудитории, которой важно поддержать, а не унизить.
Что делать то будете, если ваш любимый изученный асистанс в один прекрасный момент рубанут на Россию наши западные “друзья”? Надо уже со своими облаками начинать работать плотнее. Не?