From c988d82e25a8b45b0a23dc75846efabde021f50d Mon Sep 17 00:00:00 2001 From: vlapa Date: Sat, 13 Jun 2026 20:55:58 +0300 Subject: First --- platformio.ini | 27 +++++ src/main.cpp | 305 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/setenv_source.h | 12 +++ 3 files changed, 344 insertions(+) create mode 100644 platformio.ini create mode 100644 src/main.cpp create mode 100644 src/setenv_source.h diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..9138555 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,27 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +; [env:esp32-c3-devkitm-1] +; platform = espressif32 +; board = esp32-c3-devkitm-1 + +[env:esp32-c3-devkitc-02] +platform = espressif32 +board = esp32-c3-devkitc-02 + +framework = arduino + +monitor_speed = 115200 +upload_speed = 921600 + +lib_deps = + adafruit/Adafruit BME280 Library + knolleary/PubSubClient + \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..05206c3 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,305 @@ +#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() {} \ No newline at end of file diff --git a/src/setenv_source.h b/src/setenv_source.h new file mode 100644 index 0000000..032beb5 --- /dev/null +++ b/src/setenv_source.h @@ -0,0 +1,12 @@ +/* Установка переменных: + +const char *WiFi_SSID = ""; +const char *WiFi_PASS = ""; +const char *MQTT_CLIENT_N = "1234567890"; +const char *MQTT_CLIENT_T = ""; +const char *MQTT_USER = ""; +const char *MQTT_PASS = ""; +const char *MQTT_SERVER = "000.000.000.000"; +const char *MQTT_PORT = "1883"; + +*/ \ No newline at end of file -- cgit v1.2.3