#include #include #include #include #include #include "setenv.h" const uint8_t i2c_SDA = 0; const uint8_t i2c_SCL = 1; const uint8_t pinBMEminus = 3; // питание датчика - const uint8_t pinBMEplus = 19; // питание датчика + const uint8_t pinVcc = 4; // напряжение батареи TwoWire i2cBME280 = TwoWire(0); Adafruit_BME280 bme; WiFiClient espClient; PubSubClient client(espClient); //------------------------------------------------ const char *ssid = WiFi_SSID; const char *pass = WiFi_PASS; const char *mqtt_client = MQTT_CLIENT_N; const char *mqtt_client2 = MQTT_CLIENT_T; const char *mqtt_user = MQTT_USER; const char *mqtt_pass = MQTT_PASS; const char *mqtt_server = MQTT_SERVER; const char *mqtt_port = MQTT_PORT; const char *outTopicTemp = "/Temp"; // топик const char *outTopicPres = "/Pres"; // топик const char *outTopicHum = "/Hum"; // топик const char *outTopicVcc = "/Vcc"; // топик //------------------------------------------------ uint8_t countConnect = 20; // кол-во попыток соединения uint16_t countPause = 500; // пауза между попытками uint32_t timeSleep = 60000000; // время сна uint16_t TimeBeforeBedtime = 500; // время до засыпания uint8_t countMaxSleep = 10; // не передавать данные не более // countMaxSleep х timeSleep (10 мин) // Структура для хранения данных в RTC памяти: RTC_DATA_ATTR struct { float t; // температура float v; // напряжение uint16_t p; // давление uint8_t h; // влажность uint8_t countSleep; // счетчик предельного кол-ва циклов сна uint16_t bufRoom[3] = {0, 0, 0}; byte countRoom = 0; } data; // Разница при которой будут отправляться данные: float diffTemp = 0.25; // разница температур int diffPres = 5; // разница давлений int diffHum = 5; // разница влажностей float diffVcc = 0.1; // разница зарядки акб //----------------------------------- // inline bool mqtt_subscribe(PubSubClient &client, const String &topic) // { // Serial.print("Subscribing to: "); // Serial.println(topic); // return client.subscribe(topic.c_str()); // } //----------------------------------- inline bool mqtt_publish(PubSubClient &client, const String &topic, const String &value) { Serial.print(topic); Serial.print(" = "); Serial.println(value); return client.publish(topic.c_str(), value.c_str()); } //----------------------------------- // Отправка данных на MQTT сервер: void mqttDataOut(float temp, uint16_t pres, uint8_t hum, float vcc) { String topic = "/"; topic += mqtt_client2; topic += outTopicTemp; while (!mqtt_publish(client, topic, (String)temp)) { mqtt_publish(client, topic, (String)temp); } topic = "/"; topic += mqtt_client2; topic += outTopicPres; while (!mqtt_publish(client, topic, (String)pres)) { mqtt_publish(client, topic, (String)pres); } topic = "/"; topic += mqtt_client2; topic += outTopicHum; while (!mqtt_publish(client, topic, (String)hum)) { mqtt_publish(client, topic, (String)hum); } topic = "/"; topic += mqtt_client2; topic += outTopicVcc; while (!mqtt_publish(client, topic, (String)vcc)) { mqtt_publish(client, topic, (String)vcc); } } //----------------------------------- // Подключение к MQTT серверу: bool reconnect() { client.setServer(mqtt_server, String(mqtt_port).toInt()); Serial.println(mqtt_server); while (!(client.connect(mqtt_client, mqtt_user, mqtt_pass)) && countConnect--) { Serial.print(countConnect); Serial.print('>'); delay(countPause); } if (client.connected()) { return true; } else { return false; } } //----------------------------------- // Подключение к сети WiFi: bool setupWiFi(const char *wifi_ssid, const char *wifi_pass) { WiFi.begin(wifi_ssid, wifi_pass); Serial.println("\n================="); Serial.print("Setup WiFi: "); Serial.println(ssid); while ((WiFi.status() != WL_CONNECTED) && countConnect--) { Serial.print(countConnect); Serial.print('>'); delay(countPause); } if (WiFi.status() == WL_CONNECTED) { // индикация IP: Serial.println(); Serial.println(WiFi.localIP()); // индикация силы сигнала: int8_t dBm = WiFi.RSSI(); Serial.print("RSSI dBm = "); Serial.println(dBm); uint8_t quality_RSSI = 2 * (dBm + 100); if (quality_RSSI >= 100) quality_RSSI = 100; Serial.print("RSSI % = "); Serial.println(quality_RSSI); Serial.println("================="); return true; } else { return false; } } //----------------------------------- // медиана на 3 значения со своим буфером для усреднения ADC: uint16_t medianRoom(uint16_t newValRoom) { if (!(data.bufRoom[0] + data.bufRoom[1] + data.bufRoom[2])) data.bufRoom[0] = data.bufRoom[1] = data.bufRoom[2] = newValRoom; data.bufRoom[data.countRoom] = newValRoom; if (data.countRoom++ >= 2) data.countRoom = 0; uint16_t dataRoom = (max(data.bufRoom[0], data.bufRoom[1]) == max(data.bufRoom[1], data.bufRoom[2])) ? max(data.bufRoom[0], data.bufRoom[2]) : max(data.bufRoom[1], min(data.bufRoom[0], data.bufRoom[2])); return dataRoom; } //----------------------------------- // Читаем данные с датчика BME280: bool readData() { pinMode(pinBMEplus, OUTPUT); digitalWrite(pinBMEplus, HIGH); pinMode(pinBMEminus, OUTPUT); digitalWrite(pinBMEminus, LOW); delay(1); i2cBME280.begin(i2c_SDA, i2c_SCL, 100000); // Инициализация BME280 по адресу = 0х76 !!! if (!bme.begin(0x76, &i2cBME280)) { Serial.println("Could not find a valid BME280 sensor !"); pinMode(pinBMEplus, INPUT); digitalWrite(pinBMEplus, LOW); pinMode(pinBMEminus, INPUT); digitalWrite(pinBMEminus, LOW); delay(1); return false; } float temp = bme.readTemperature(); uint16_t pres = (bme.readPressure() * 0.7500637554192 / 100); uint8_t hum = bme.readHumidity(); pinMode(pinBMEplus, INPUT); digitalWrite(pinBMEplus, LOW); pinMode(pinBMEminus, INPUT); digitalWrite(pinBMEminus, LOW); delay(1); // Читаем ADC: uint16_t dataVcc = 0; for (uint8_t i = 0; i < 3; ++i) { dataVcc += analogRead(pinVcc); } // Пересчет ADC в напряжение АКБ: // 2.8 - максимальное напряжение на считываемой ножке // 4095 - количество отсчетов ADC // 3.6 - максимальное напряжение АКБ LiFePo4 float vcc = 0; vcc = 2.8 / 4095 * medianRoom(dataVcc / 3) * 3.6 / 2.8; // Если данные с датчика и напряжение питания изменились больше чем разница, // то заносим данные в память RTC и сбрасываем предельный счетчик циклов сна: if (abs(data.t - temp) >= diffTemp || abs(data.p - pres) >= diffPres || abs(data.h - hum) >= diffHum || abs(data.v - vcc) >= diffVcc || data.countSleep <= 1) { data.t = temp; data.p = pres; data.h = hum; data.v = vcc; data.countSleep = countMaxSleep - 1; return true; } else { if (--data.countSleep) { Serial.println("\nДанные изменились незначительно !\n"); return false; } else { return true; } } } //----------------------------------- void setup() { Serial.begin(115200); if (!readData()) { esp_deep_sleep(timeSleep); } if (!setupWiFi(ssid, pass)) { esp_deep_sleep(timeSleep); } if (!reconnect()) { esp_deep_sleep(timeSleep); } mqttDataOut(data.t, data.p, data.h, data.v); Serial.println("================="); Serial.flush(); delay(TimeBeforeBedtime); esp_deep_sleep(timeSleep); } void loop() {}