Приём данных с MQTT сервера внутри цикла

Мир Ардуинщиков
Offline
Зарегистрирован: 18.05.2020

Всем привет! Я занимаюсь ардуино и сделал много самых разных проектов. Недавно я начал делать "умный увлажнитель" на плате ESP8266, управляемый со смартфона по MQTT серверу. Я написал скетч который принимает данные MQTT сервера и когда плате ESP8266 приходит сообщение, то на 10 секунд включается светодиод. PS: я оставил только ту часть кода которая принимает сообщения с MQTT сервера. Если вам нужен полный код, то вот ссылка: https://drive.google.com/open?id=1iL7dp8FgjUuLZasjQ9RBiqLuJKXOTGrF

void callback(const MQTT::Publish& pub) {
 String payload = pub.payload_string();
    
 if (String(pub.topic()) == "wetting") {
   Serial.print("Название Топика: ");
   Serial.print(String(pub.topic()));
   Serial.print(" >>> ");
   Serial.println(payload.toInt());
   if (payload.toInt() == 1) {
     digitalWrite(D2, HIGH);
     int i = 0;
     while (i <= 10000 && payload.toInt() == 1) {
       i ++;
       callback(MQTT::Publish);
       payload = pub.payload_string();
       Serial.print("wetting: ");
       Serial.print(payload.toInt());
       Serial.print(" ");    
       Serial.println(i);
       delay(1);    
     } 
     digitalWrite(D2, LOW);
   }

   if (payload.toInt() == 0) {
     digitalWrite(D2, LOW);   
   }
 }
}

 У меня возникла одна проблема: когда я отправляю плате ESP8266 сообщение на MQTT сервер, то светодиод включается на 10 секунд. Но мне нужно сделать так, чтобы я мог прервать эту задержку отправив плате ESP8266 другое сообщение. Подскажите как вызвать функцию приёма сообщений внутри цикла while, с помощью которого осуществляется задержка. 

b707
Offline
Зарегистрирован: 26.05.2017

что-то вы несусветное наворотили в коде. Во-первых. у вас цико while будет работать не 10 секунд, а 10 тыс раз, что совсем не одно и тоже. Во-вторых, все эти разы вы будете выводить в терминал слово "wetting" и прочие сообщения - зачем это делать 10 тыс раз?

ну и главное, все это у вас код функции callback() - и вы внутри этой функции снова вызываете ее же (14 строка) ? - это верный способ завесить программу. тем более если это сделать 10 тыс раз

Отсчитывание временных интервалов делается на функции миллис. а не на многократном верчении циклов

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Мир Ардуинщиков пишет:
начал делать "умный увлажнитель"

Самый умный увлажнитель описан вот здесь. Увлажняет именно то, что надо за милую душу. Всё остальное - так, поделки.

Мир Ардуинщиков
Offline
Зарегистрирован: 18.05.2020

Спасибо, что подсказали! Я не заметил у себя в коде ошибку. Но вопрос остаётся, даже если осуществлять задержку с помощью "millis", то как тогда в это время проверять не пришли ли плате ESP8266 новые сообщения.

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Мир Ардуинщиков пишет:

даже если осуществлять задержку с помощью "millis", то как тогда в это время проверять не пришли ли плате ESP8266 новые сообщения.

Неверно. С помощью millis задержку осуществлять не нужно. Этим millis и отличается от delay.

AlloZawr
Offline
Зарегистрирован: 09.05.2020
unsigned long wetting_timer = 0 ;

void callback(const MQTT::Publish& pub) {
 String payload = pub.payload_string();
    
 if (String(pub.topic()) == "wetting") {
   Serial.print("Название Топика: ");
   Serial.print(String(pub.topic()));
   Serial.print(" >>> ");
   Serial.println(payload.toInt());
   if (payload.toInt() == 1) {
     digitalWrite(D2, HIGH);
     wetting_timer = millis() ;
     } else { 
     digitalWrite(D2, LOW);
     }
   }

 }
}

void wetting_timer_chk(){
   if (payload.toInt() == 1) 
     if ( (millis() - wettind_timer) > 10000){
     digitalWrite(D2, LOW);   
   }
}

 Типа такого можно попробовать и гденибудь в loop()  ...  wetting_timer_chk() 

AlloZawr
Offline
Зарегистрирован: 09.05.2020

От. копипасте до чего доводит ))  ошибочка

void wetting_timer_chk(){
  if (payload.toInt() == 1)

// заменить на 
void wetting_timer_chk(){
  if (Digitalread(D2) == 1)

 

 

Мир Ардуинщиков
Offline
Зарегистрирован: 18.05.2020

 

 

void callback(const MQTT::Publish& pub) {
 String payload = pub.payload_string();
    
 if (String(pub.topic()) == "wetting") {
   Serial.print("Название Топика: ");
   Serial.print(String(pub.topic()));
   Serial.print(" >>> ");
   Serial.println(payload.toInt());
   if (payload.toInt() == 1) {
     digitalWrite(D2, HIGH);
     wetting_timer = millis() ;
     } else { 
     digitalWrite(D2, LOW);
     }
   }

 }
}

void wetting_timer_chk(){
    if (digitalRead(D2) == 1) {
     if ( (millis() - wettind_timer) > 10000){
     digitalWrite(D2, LOW);   
   }
  }
}

 Типа такого можно попробовать и где нибудь в loop()  ...  wetting_timer_chk() 

Спасибо! Сейчас проверю.