Здравствуйте. Пытаюсь наладить интервал отправки данных с датчика BME20 (на базе Node mcu) на mqtt сервер. Использую следующий код: Код (C++): #include "ESP8266WiFi.h" #include "PubSubClient.h" #include "Wire.h" #include "cactus_io_BME280_I2C.h" #include <SoftwareSerial.h> #include <OneWire.h> #include <DallasTemperature.h> #include <SPI.h> WiFiClient espClient; PubSubClient client(espClient); BME280_I2C bme(0x76); const char* SSID = "***************"; const char* PASSWORD = "***************"; const char* MQTT_BROKER = "192.168.1.1"; const int MQTT_PORT = 1883; const char* MQTT_TOPIC = "mqttHome/bedroom"; const char* MQTT_CLIENT_NAME = "alexmqtt"; const char* mqttPassword = "****************"; const int BME280_DELAY = 3000; //3000 const int RECHECK_INTERVAL = 700; //700 const int PUBLISH_INTERVAL = 2000; //2000 long lastReconnectAttempt = 0; long lastPublishAttempt = 0; const char* wl_status_to_string(wl_status_t status) { switch (status) { case WL_NO_SHIELD: return "WL_NO_SHIELD"; case WL_IDLE_STATUS: return "WL_IDLE_STATUS"; case WL_NO_SSID_AVAIL: return "WL_NO_SSID_AVAIL"; case WL_SCAN_COMPLETED: return "WL_SCAN_COMPLETED"; case WL_CONNECTED: return "WL_CONNECTED"; case WL_CONNECT_FAILED: return "WL_CONNECT_FAILED"; case WL_CONNECTION_LOST: return "WL_CONNECTION_LOST"; case WL_DISCONNECTED: return "WL_DISCONNECTED"; } } void setup() { setupWifi(); setupMQTT();; setupBME280(); } void loop() { long now = millis(); if(!client.connected()) { if(now - lastReconnectAttempt > RECHECK_INTERVAL) { lastReconnectAttempt = now; client.connect(MQTT_CLIENT_NAME); if(client.connected()) { // Resubscribe to any topics, if necessary // This is also a good place to publish an error to a separate topic! } } } else { if(now - lastPublishAttempt > PUBLISH_INTERVAL) { lastPublishAttempt = now; readAndPublishData(); //read data from BME and send to mqtt client.loop(); } } } void setupWifi() { Serial.println(""); Serial.print("Connecting to "); Serial.print(SSID); WiFi.begin(SSID, PASSWORD); while(WiFi.status() != WL_CONNECTED) { delay(RECHECK_INTERVAL); Serial.print("."); yield(); } Serial.println(""); Serial.println("WiFi connected"); Serial.print("IP address: "); Serial.println(WiFi.localIP()); } void setupBME280() { Serial.println(""); Serial.print("Setting up BME280"); while(!bme.begin()) { delay(RECHECK_INTERVAL); Serial.print("."); yield(); } Serial.println(""); Serial.println("BME280 found!"); delay(BME280_DELAY); } void setupMQTT() { client.setServer(MQTT_BROKER, MQTT_PORT); client.setCallback(callback); Serial.println(WiFi.localIP()); while (!client.connected()) { Serial.println("Connecting to MQTT..."); if (client.connect("ESP8266Client", MQTT_CLIENT_NAME, mqttPassword )) { Serial.println("connected"); } else { Serial.print("failed with state "); Serial.print(client.state()); delay(2000); } } client.publish("mqttHome/bedroom/status", wl_status_to_string(WiFi.status())); client.subscribe("mqttHome/bedroom/status"); } void readAndPublishData() { if(client.connected()) { bme.readSensor(); getPressure(); getTemperature(); getHumidity();; } void callback(char* topic, byte* payload, unsigned int length) { Serial.print("Message arrived in topic: "); Serial.println(topic); Serial.print("Message:"); for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); } Serial.println(); Serial.println("-----------------------"); } } Данный код отправляет данные на сервер раз в 2 сек. Мне нужно чтобы данные отправлялись раз в минуту. Когда я величиваю RECHECK_INTERVAL или PUBLISH_INTERVAL до 20 000 то данные отправляются раз в 20 секунд, а если ставлю 20 000, то отправляются через 30 сек после включения, а пото вовсе не отправляются. Подскажите пожалуйста, что не так.
Этот код и раз в 2 секунды не будет отправлять данные. Там нет отправки. Да и в конце со скобками Вы запутались.
Отправляет. Я подписался на топики с помощью mqtt.fx и получаю данные каждые 2 секунды. Со скобками может и напутал, так как удалялл не нужное, что не касается вопроса.
Если отправляет - значит используется не тот код, что в первом посте. В том, который в первом посте, только один publish есть: Код (C++): client.publish("mqttHome/bedroom/status", wl_status_to_string(WiFi.status())); И он только в setupMQTT(). Про скобки написал. Смысл его смотреть? Ну интервалы у Вас const int (максимальное значение должно быть не более 32767), а millis() возвращает unsigned long. Лучше константы через #define определить.
Вот весь код: Код (C++): #include "ESP8266WiFi.h" #include "PubSubClient.h" #include "Wire.h" #include "cactus_io_BME280_I2C.h" #include <SoftwareSerial.h> #include <OneWire.h> #include <DallasTemperature.h> #include <SPI.h> #define CO2_TX D6 // CO2 #define CO2_RX D7 // CO2 #define LOG_PERIOD 15000 //Период регистрации в миллисекундах, рекомендуемое значение 15000-60000. #define MAX_PERIOD 60000 //Максимальный период регистрации. WiFiClient espClient; PubSubClient client(espClient); BME280_I2C bme(0x76); SoftwareSerial SerialCO2(CO2_TX, CO2_RX); //CO2 byte cmd[9] = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79}; unsigned char response[9]; uint8_t responseHigh; uint8_t responseLow; unsigned long counts; //Gauge unsigned long cpm; unsigned int multiplier; unsigned long previousMillis; float uSv; // Переменная для перевода в микроЗиверты float ratio = 0.0057; // Коофициент для перевода импульсов в микроЗиверты float uP = 0; const byte interruptPin = D5; // Порт ESP к которому подключен счетчик void ICACHE_RAM_ATTR tube_impulse(){ //Функция подсчета имульсов counts++; } const char* SSID = "************"; const char* PASSWORD = "************"; const char* MQTT_BROKER = "192.168.1.1"; const int MQTT_PORT = 1883; const char* MQTT_TOPIC = "mqttHome/bedroom"; const char* MQTT_CLIENT_NAME = "alexmqtt"; const char* mqttPassword = "********"; const int BME280_DELAY = 3000; const int RECHECK_INTERVAL = 700; const int PUBLISH_INTERVAL = 2000; long lastReconnectAttempt = 0; long lastPublishAttempt = 0; const char* wl_status_to_string(wl_status_t status) { switch (status) { case WL_NO_SHIELD: return "WL_NO_SHIELD"; case WL_IDLE_STATUS: return "WL_IDLE_STATUS"; case WL_NO_SSID_AVAIL: return "WL_NO_SSID_AVAIL"; case WL_SCAN_COMPLETED: return "WL_SCAN_COMPLETED"; case WL_CONNECTED: return "WL_CONNECTED"; case WL_CONNECT_FAILED: return "WL_CONNECT_FAILED"; case WL_CONNECTION_LOST: return "WL_CONNECTION_LOST"; case WL_DISCONNECTED: return "WL_DISCONNECTED"; } } void setup() { setupWifi(); setupMQTT(); setupGauge(); setupBME280(); SerialCO2.begin (9600); } void loop() { long now = millis(); if(!client.connected()) { if(now - lastReconnectAttempt > RECHECK_INTERVAL) { lastReconnectAttempt = now; client.connect(MQTT_CLIENT_NAME); if(client.connected()) { // Resubscribe to any topics, if necessary // This is also a good place to publish an error to a separate topic! } } } else { if(now - lastPublishAttempt > PUBLISH_INTERVAL) { lastPublishAttempt = now; readAndPublishData(); client.loop(); } } } void setupGauge(){ counts = 0; cpm = 0; multiplier = MAX_PERIOD / LOG_PERIOD; Serial.begin(115200); interrupts(); pinMode(interruptPin, INPUT); attachInterrupt(digitalPinToInterrupt(interruptPin), tube_impulse, FALLING); //Определяем количество импульсов через внешнее прерывание на порту } void setupWifi() { Serial.println(""); Serial.print("Connecting to "); Serial.print(SSID); WiFi.begin(SSID, PASSWORD); while(WiFi.status() != WL_CONNECTED) { delay(RECHECK_INTERVAL); Serial.print("."); yield(); } Serial.println(""); Serial.println("WiFi connected"); Serial.print("IP address: "); Serial.println(WiFi.localIP()); } void setupBME280() { Serial.println(""); Serial.print("Setting up BME280"); while(!bme.begin()) { delay(RECHECK_INTERVAL); Serial.print("."); yield(); } Serial.println(""); Serial.println("BME280 found!"); delay(BME280_DELAY); } void setupMQTT() { client.setServer(MQTT_BROKER, MQTT_PORT); client.setCallback(callback); Serial.println(WiFi.localIP()); while (!client.connected()) { Serial.println("Connecting to MQTT..."); if (client.connect("ESP8266Client", MQTT_CLIENT_NAME, mqttPassword )) { Serial.println("connected"); } else { Serial.print("failed with state "); Serial.print(client.state()); delay(2000); } } client.publish("mqttHome/bedroom/status", wl_status_to_string(WiFi.status())); client.subscribe("mqttHome/bedroom/status"); } void readAndPublishData() { if(client.connected()) { bme.readSensor(); getPressure(); getTemperature(); getHumidity(); getCO2(); getGauge(); } } void callback(char* topic, byte* payload, unsigned int length) { Serial.print("Message arrived in topic: "); Serial.println(topic); Serial.print("Message:"); for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); } Serial.println(); Serial.println("-----------------------"); } void getPressure(){ float pressurePascals = bme.getPressure_MB(); String msgPr = String(pressurePascals); char msgAsCharAway[msgPr.length()]; msgPr.toCharArray(msgAsCharAway, msgPr.length()); Serial.print(bme.getPressure_MB()); Serial.print(" мм.рт.ст.\t"); client.publish("mqttHome/bedroom/pressure", msgAsCharAway); } void getTemperature(){ float temperature = bme.getTemperature_C(); String msgTempC = String (temperature); char msgAsCharAwayTempC[msgTempC.length()]; msgTempC.toCharArray(msgAsCharAwayTempC, msgTempC.length()); client.publish("mqttHome/bedroom/temperature", msgAsCharAwayTempC); Serial.print(bme.getTemperature_C()); Serial.print(" C\t "); } void getHumidity(){ float humidity = bme.getHumidity(); String msgHum = String (humidity); char msgAsCharAwayHum[msgHum.length()]; msgHum.toCharArray(msgAsCharAwayHum, msgHum.length()); client.publish("mqttHome/bedroom/humidity", msgAsCharAwayHum); Serial.print(bme.getHumidity()); Serial.print (" %\t\t"); } void getGauge(){ unsigned long currentMillis = millis(); if(currentMillis - previousMillis > LOG_PERIOD){ previousMillis = currentMillis; cpm = counts * multiplier; uSv = cpm * ratio; String msgGau = String (uSv); char msgAsCharAwayGau[msgGau.length()]; msgGau.toCharArray(msgAsCharAwayGau, msgGau.length()); client.publish("mqttHome/bedroom/uSv", msgAsCharAwayGau); Serial.println("uSv: "); Serial.print (uSv); Serial.println("cpm: "); Serial.print (cpm); counts = 0; } } void getCO2() //чтение показаний датчика MH-Z14A { SerialCO2.write(cmd, 9); //отправляем команду датчику memset(response, 0, 9); SerialCO2.readBytes(response, 9); //получаем ответ uint8_t crc = 0; for (int i = 1; i < 8; i++) crc+=response[i]; //считаем контрольную сумму crc = ~crc; crc++; if ( !(response[0] == 0xFF && response[1] == 0x86 && response[8] == crc) ) // сравниваем ответ с контрольной суммой { Serial.println("CRC error: " + String(crc) + " / "+ String(response[8])); //выводим ошибку } else { uint8_t responseHigh = (uint8_t) response[2]; uint8_t responseLow = (uint8_t) response[3]; float CO2 = (256*responseHigh) + responseLow; String msgCO2 = String (CO2); char msgAsCharAwayCO2[msgCO2.length()]; msgCO2.toCharArray(msgAsCharAwayCO2, msgCO2.length()); client.publish("mqttHome/bedroom/CO2", msgAsCharAwayCO2); Serial.println("CO2 "+String((256*responseHigh) + responseLow)+"ppm"); //выводим показания датчика } }
Ну в принципе правильно писали выше что вместо constint RECHECK_INTERVAL =700; constint PUBLISH_INTERVAL =2000; надо сделать const uint32_t RECHECK_INTERVAL =700UL; const uint32_t PUBLISH_INTERVAL =2000UL; и эти тоже long lastReconnectAttempt = 0; long lastPublishAttempt = 0; переделать на uint32_t lastReconnectAttempt = 0UL; uint32_t lastPublishAttempt = 0UL; и это тоже long now = millis(); на uint32_t now = millis();
Поставил const uint32_t RECHECK_INTERVAL = 700UL; //700 const uint32_t PUBLISH_INTERVAL = 10000UL; //2000 uint32_t lastReconnectAttempt = 0UL; uint32_t lastPublishAttempt = 0UL; uint32_t now = millis(); Когда PUBLISH_INTERVAL ставлю 10000UL, то данные отправляются раз в 10 сек, но когда ставлю 30000UL или 60000UL, то данные вообще не уходят. Может также нужно менять значения RECHECK_INTERVAL, lastReconnectAttempt, или lastPublishAttempt?