Корпус для метеодатчика на ESP8266

📁 Корпус для метеодатчика на ESP8266
📐 STL
🪵 PETG, печатать белым цветом!
❤️ Ставь лайк, если понравилось!

Башня погодной станции для размещения сенсоров температуры\влажности\давления. Корпус рассчитан на размещение модуля ESP-7 (ESP8266 с гнездом под внешнюю антенну). В нижней крышке имеется отверстие для крепления антенны (если в ней возникает необходимость).

Проект автономного датчика с питанием от солнечной батарейки. 

Данные обновляются каждые 5 минут+-10сек. Для начала передачи на narodmon.ru нужно зарегистрироваться в проекте. Питание от LiPo c подзарядкой от солнечной батарейки до 4.2В. Заряд идет даже в ноябрьский пасмурный наглухо день, от маленькой 1 ваттной 5в солнечной батарейки размером 107x61мм (на али стоит в районе 150р).

Изображение

Заряда за один световой, пасмурный день хватает на 2-3 дня вообще без света. На графике видно скорость расхода ночью и скорость заряда днем. 

Изображение

Умеет работать с датчиком BME280, BMP280, c одним или несколькими DS18B20, шлет уровень VCC, % сигнала wifi, время соединения и передачи данных millis(). Автоматически определяет наличие датчиков и шлет по ним инфу на сервер. При первом запуске (или отсутствии сети) создает точку доступа на 10 секунд (нужно успеть подключится, сделано с целью экономии батареек при пропадании wifi). В веб интерфейсе можно просканировать сети и подключится к имеющийся либо вписать название сети вручную. после чего на сайт начинают отправляться данные а в SERIAL печатается уникальный ID станции( В случае если в коде поставить #define debug true иначе только ошибки выдает в Serial), который потом привяжется к сайту. Все показания, статистику на графиках можно смотреть в приложениях для разных платформ в том числе Android, IOS.
Лучше собирать на голой ESP. но под руками был только NOD MCU.

  1. #include <ESP8266WiFi.h>
  2. //Настройки скетча:
  3. #define debug false // Вывод отладочных сообщений. Замедляет работу. false по умолчанию
  4. #define SendData true // Отправлять данные на сервер (для отладки). true по умолчанию
  5. #define postingInterval 300e6 // интервал между отправками данных в секундах (330 сек=5,5 минут)
  6. #define MinVccSleep 4e9 // Время спячки при севших батарейках. 0 - до передергивания питания.
  7. #define VccDiode 840//Падение напряжения (мВ) на диоде в питании ESP от литиевого АКБ для коректировки показаний напряжения питания 3,95/3,49
  8. #define maxVCC 4150// Максимальное напряжение питания. При превышении ЕСП не отключается а садит батарею.
  9. #define minVCC 2500+VccDiode // Минимальное напряжение питания.
  10. #define swRx 3 // Не меняем, это пины UART
  11. #define swTx 1 // Не меняем
  12. #define swSCL 3 // Пины подключения датчика BMx280 IO3
  13. #define swSDA 0 // Пины подключения датчика BMx280
  14. #define measurePin 2 // сюда фоторезистор и на + а также конденсатор 2,2 мкФ и на минус.
  15. #define ssid "dich"
  16. #define password "0612748587"
  17. IPAddress local_IP(192, 168, 0, 61);
  18. IPAddress gateway(192, 168, 0, 1);
  19. IPAddress subnet(255, 255, 255, 0);
  20. IPAddress primaryDNS(192, 168, 0, 1);
  21. IPAddress secondaryDNS(8, 8, 4, 4);
  22.  
  23. #include "SoftwareSerial.h"
  24. SoftwareSerial swSerial;
  25. #include <Wire.h>
  26. #include <BMx280I2C.h>
  27. byte bmx_not_found = false;
  28. BMx280I2C bmx280(0x76);
  29. void ICACHE_RAM_ATTR InterruptMeasurePin();//ставим функцию прерываний InterruptMeasurePin() в RAM память для стабильной работы
  30. uint32_t RCtime1;// тут хранится начальное время RC цепи
  31. volatile uint32_t RCtime2;// тут хранится конечное время RC цепи
  32. boolean LightSensor_not_found = false;
  33. unsigned long TimeWIFI;// Переменная времени подключения к WIFI
  34. ADC_MODE(ADC_VCC);// Будем измерять напряжение на VCC внутри МК
  35. int VCC; //Напряжение батареи
  36. uint32_t calculateCRC32(const uint8_t *data, size_t length);
  37. struct { //Структура, хранящаяся в RTC памяти
  38. uint32_t crc32;
  39. uint32_t data[3];// Если нужно еще что-то хранить во сне то увеличиваем индекс 1 на нужное кол-во переменных и работаем как с переменной rtcData.data[1].... rtcData.data[125].
  40. } rtcData;
  41.  
  42. uint32_t calculateCRC32(const uint8_t *data, size_t length) {// Расчет CRC RTC памяти чтоб понять битые там данные или нет
  43. uint32_t crc = 0xffffffff;
  44. while (length--) {
  45. uint8_t c = *data++;
  46. for (uint32_t i = 0x80; i > 0; i >>= 1) {
  47. bool bit = crc & 0x80000000;
  48. if (c & i) {
  49. bit = !bit;
  50. }
  51. crc <<= 1;
  52. if (bit) {
  53. crc ^= 0x04c11db7;
  54. }
  55. }
  56. }
  57. return crc;
  58. }
  59.  
  60. //Читаем данные из RTC памяти
  61. void RTCread() {
  62. static boolean firstRUN = true;
  63. if (ESP.rtcUserMemoryRead(0, (uint32_t*) &rtcData, sizeof(rtcData))) {
  64. uint32_t crcOfData = calculateCRC32((uint8_t*) &rtcData.data[0], sizeof(rtcData.data));
  65. if (crcOfData != rtcData.crc32) {// При первом включении и при битых данных в RTC памяти
  66. rtcData.data[0] = 1; // Назначаем данные по умолчанию при первом включении
  67. rtcData.data[1] = 0;
  68. rtcData.data[2] = 0;
  69. }
  70. }
  71. }
  72.  
  73. //Обновляем данные в RTC памяти
  74. void RTCupdate() {
  75. rtcData.data[0]++;// Увеличиваем количество срабатываний
  76. rtcData.data[1] = millis();// Запоминаем время передачи
  77. rtcData.data[2] = TimeWIFI;//// Запоминаем время соединения WIFI
  78. rtcData.crc32 = calculateCRC32((uint8_t*) &rtcData.data[0], sizeof(rtcData.data));
  79. ESP.rtcUserMemoryWrite(0, (uint32_t*) &rtcData, sizeof(rtcData));// Write struct to RTC memory
  80. }
  81.  
  82. // процедура подключения к Wifi. Также запускаем измерения с датчиков
  83. void wificonect() {
  84. WiFi.mode(WIFI_STA);
  85. WiFi.setAutoConnect(true);
  86. WiFi.setAutoReconnect(false);
  87. WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS);
  88. WiFi.begin(ssid, password);
  89. int i = 0;
  90. while (WiFi.status() != WL_CONNECTED) {
  91. static boolean firstRUN = true;
  92. if (firstRUN) { // один раз запускаем при каждой перезагрузке
  93. RTCread();// Пока конектится wifi читаем переменніе из RTC памяти что сохранили перед прошлым сном
  94. Measure();// Запускаем измерения датчиков
  95. }
  96. firstRUN = false;
  97. if (debug) if (!(i % 100))swSerial.print (".");
  98. delay(1);
  99. i++; if (i > 5000) ESP.deepSleep(60e6, RF_NO_CAL);//СПИМ 1 МИНУТу если не было соединения в течении 5 секунд. Если у вас плохой конект с wifi то следует увеличить число до 10000
  100. }
  101. TimeWIFI = millis();// Запоминаем время подключения к WIFI
  102. if (debug) {
  103. swSerial.println();
  104. if (!SendData) swSerial.println F("Отладочный режим. Данные на сервер не передаются.");
  105. swSerial.print (millis());// тут можно посмотреть время подключения к wifi
  106. swSerial.println F(" Подключено к wifi");
  107. }
  108. }
  109.  
  110. void setup() {
  111. if (debug) {
  112. swSerial.begin(115200, SWSERIAL_8N1, swRx, swTx, false, 256);//
  113. swSerial.enableIntTx(false);
  114. }
  115. VCC = ESP.getVcc() + VccDiode; //Корректировка напряжения АКБ
  116. if (VCC < minVCC) ESP.deepSleep(MinVccSleep); // спим при низком питании
  117. wificonect();// подключаемся к сети
  118. }
  119.  
  120. void loop() {
  121. SendToNarodmon();
  122. //digitalWrite(BMX280_VCC, LOW);// отключаем питание датчиков
  123. RTCupdate();
  124. if (debug) swSerial.print (millis());
  125. if (VCC > maxVCC) {
  126. digitalWrite(LED_BUILTIN, LOW);
  127. delay(postingInterval / 1000); //разряжаем батарею
  128. ESP.deepSleep(1e6, RF_NO_CAL); //перезагружаемся
  129. } else {
  130. ESP.deepSleep(postingInterval, RF_NO_CAL);
  131. }
  132. }
  133.  
  134. void Measure() { // Запуск измерения датчиков
  135. //Запуск измерения освещенности посредством времени RC цепи.
  136. pinMode(measurePin, OUTPUT);//разряжаем конденсатор
  137. delay(1);
  138. attachInterrupt (digitalPinToInterrupt (measurePin), InterruptMeasurePin, CHANGE);// включаем прерывание которое сработает при заряде конденсатора до логической единицы
  139. pinMode(measurePin, INPUT);// начало заряда
  140. RCtime1 = micros();// запоминаем время начала заряда конденсатора
  141. if (digitalRead(measurePin)){
  142. LightSensor_not_found = true;
  143. detachInterrupt (digitalPinToInterrupt(measurePin));
  144. }
  145. //----------------------------------------------------
  146.  
  147. //BMX280
  148. Wire.pins(swSDA, swSCL);//Настройка програмного I2C интерфейса
  149. Wire.begin(swSDA, swSCL);
  150. if (!bmx280.begin()) {
  151. if (debug) swSerial.println F("Датчик BMx не обнаружен. Проверьте датчик.");
  152. bmx_not_found = true;
  153. }
  154. if (debug && !bmx_not_found) {
  155. swSerial.print F("Тип датчика ");
  156. if (bmx280.isBME280())swSerial.println F("BME280");
  157. else swSerial.println F("BMP280");
  158. }
  159. if (!bmx_not_found) { // Если датчик найден
  160. bmx280.resetToDefaults(); //reset sensor to default parameters.
  161. bmx280.writeOversamplingPressure(BMx280MI::OSRS_P_x16);
  162. bmx280.writeOversamplingTemperature(BMx280MI::OSRS_T_x16);
  163. if (bmx280.isBME280()) bmx280.writeOversamplingHumidity(BMx280MI::OSRS_H_x16);//Для BME
  164. for (int i= 0; i<2; i++){
  165. while (!bmx280.measure()) {}
  166. while (!bmx280.hasValue()) {}
  167. }
  168. }
  169. }
  170.  
  171. void InterruptMeasurePin() {// по прерыванию в момент заряда конденсатора запоминаем время
  172. RCtime2 = micros();
  173. }
  174.  
  175. bool SendToNarodmon() { // Собственно формирование пакета и отправка.
  176. if (!bmx_not_found)
  177. bmx280.measure();
  178.  
  179. if (debug) {
  180. swSerial.print F("ip адресс: ");swSerial.println(WiFi.localIP()); swSerial.print F("Narodmon ID: ");
  181. }
  182. WiFiClient client;
  183. String buf = "#ESP" + WiFi.macAddress() + "\n"; //mac адрес для авторизации датчика
  184. buf.replace(":", "");// удаляем двоеточия из мак адреса
  185.  
  186. if (!bmx_not_found) { // если bmx подключен то выводим с него данные
  187. while (!bmx280.hasValue()) {}
  188. buf = buf + "#TEMPC#" + String(bmx280.getTemperature()) + "#Датчик температуры BMx280\n"; //показания температуры
  189. if (bmx280.isBME280()) buf = buf + "#HUMID#" + String(bmx280.getHumidity()) + "#Датчик влажности BME280\n"; //показания влажности
  190. buf = buf + "#PRESS#" + String(bmx280.getPressure64()) + "#Датчик давления BMx280\n"; //показания давления
  191. }
  192. if (!LightSensor_not_found){ // Если датчик освещенности с конденсатором подключены
  193. if (!RCtime2){//Если конденсатор не успел зарядится
  194. RCtime2=micros();
  195. }
  196. uint32_t Lux = constrain((RCtime2-RCtime1),1,200000);
  197. Lux = cbrt(Lux)*10;
  198. Lux = map(Lux, 1, 585, 585, 1);//попугаи света.
  199. buf = buf + "#LIGHT#" + String(Lux) + "#Освещенность\n";
  200. }
  201. if (SendData) client.connect("narodmon.ru", 8283); // подключение
  202. //Данные от ESP ( Напряжение питания,уровень wifi
  203. buf = buf + "#VCC#" + String(VCC) + "#Напряжение батареи\n"; //показания температуры
  204. buf = buf + "#WIFI#" + String(WiFi.RSSI()) + "#Уровень WI-FI " + String(WiFi.SSID()) + "\n"; // уровень WIFI сигнала
  205. String worcktime = String(rtcData.data[2]); // Время соединения с wifi при предыдущей отправке
  206. float WTime = worcktime.toInt(); WTime /= 1000;
  207. buf = buf + "#UPTIME#" + String(WTime) + "#Время соединения с WIFI\n";
  208. worcktime = String(rtcData.data[1]); // Время работы при предыдущей отправке
  209. WTime = worcktime.toInt(); WTime /= 1000;
  210. buf = buf + "#WORKTIME#" + String(WTime) + "#Время передачи данных\n";
  211. buf = buf + "#WM#" + String(rtcData.data[0]) + "#№ показаний\n";
  212. buf = buf + "##\n"; //окончание передачи
  213. if (SendData) client.print(buf); // и отправляем данные
  214. if (debug) {
  215. swSerial.print(buf);
  216. }
  217. delay(10);// сделать 100 если нужен ответ или 10 если не нужен . Время активности увеличивается в 2 раза
  218. if (SendData) {
  219. while (client.available()) {
  220. String line = client.readStringUntil('\r'); // если что-то в ответ будет - все в Serial
  221. if (debug) {
  222. swSerial.println(line);
  223. }
  224. }
  225. }
  226. return true; //ушло
  227. }
  228.  
  229.  

Изображение

21:46
58
Нет комментариев. Ваш будет первым!

Ссылка появится после регистрации

Похожие модели

Портативный настольный источник питания
📁 Портативный настольный источникПодробнее
YAESU FT-817 Рельсы
📁 Рельсы с подвесом для тангенты иПодробнее
Защитный каркас Yaesu FT 817
📁 Защитные рельсы для Yaesu FT 817 и 818Подробнее
Контейнер для батарей ft-817
📁 Контейнер для аккумулятора FT-817 сПодробнее
Корпус для адаптера питания
📁 Корпус для преобразователя питания сПодробнее
Корпус для DC регулируемого источника
📁 Корпус для DC регулируемого источникаПодробнее
Крепление "народного" налобного фонаря
📁 Крепление «народного» налобного фонаряПодробнее
Ручка настройки Yaesu FT-817
📁 Ручка VFO для FT-817/818. ИспользуйтеПодробнее
Модель кнопки для Imax B6
Вам понадобится капля клея, чтобыПодробнее
Мештастик корпус для точки с солнечной батареей
📁 Meshtastic Мештастик кейс с солнечнойПодробнее
Антенный изолятор "орешек"
Это стандартный изолятор дляПодробнее
Адаптер питания Yaesu FT-817
📁 Вертикальный адаптер под коннекторыПодробнее
Посещая этот сайт, вы соглашаетесь с тем, что мы используем файлы cookie.