ESP8266:Примеры/Измерение внутренней и наружной температуры с помощью WeatherStation

Материал из ВикиСправочника
Перейти к: навигация, поиск

Перевод: Максим Кузьмин (Cubewriter)
Перевел 1819 статей для сайта.

Контакты:

Проверка/Оформление/Редактирование: Мякишев Е.А.


Ambox content.png Черновик


Измерение внутренней и наружной температуры с помощью WeatherStation[1][2]

Предназначение программы, идущей вместе с WeatherStation – просто отображение информации. Это как бы исходная точка для новичков, которую можно дополнять и изменять под собственные нужды. К примеру, к программе можно пристроить специальный модуль, считывающий из интернета правильное время или информацию о текущей и будущей погоде. Но что если вам нужно измерить и показать информацию из разных мест дома или квартиры? Эта статья рассказывает, как считывать данные с датчика температуры/влажности DHT22 – и когда он подключен к WeatherStation напрямую, и когда он находится в другой комнате, а данные передает через WiFi.

Эта статья написана с прицелом на то, что вы уже работали с WorkingStation и датчиком DHT22.

Необходимые компоненты

  • Одна погодная станция WeatherStation на базе ESP8266
  • Один датчик температуры/влажности DHT22
  • Одна адаптерная плата NodeMCU V1.0

Прямое подключение DHT22 к погодной станции WeatherStation

Если вы измеряете температуру и влажность в той же комнате, где находится WeatherStation, датчик DHT22 можно подключить следующим образом:

Погодная станция WeatherStation, к которой напрямую подключен датчик DHT22, измеряющий температуру и влажность

Теперь нужно импортировать библиотеку «DHT», и проще всего сделать это при помощи менеджера библиотек. Чтобы открыть его, кликните в IDE Arduino по Скетч > Подключить библиотеку > Управлять библиотеками... (Sketch > Include Library > Manage Libraries...).

Теперь давайте найдем библиотеку «DHT»:

DHT22LibraryManager.png

Теперь, когда библиотека установлена в IDE Arduino, можно приступить к модификации скетча. Но перед тем, как продолжить, у вас должна быть полностью настроена WeatherStation. Отредактировав скетч, сохраните его под новым названием. Вот так скетч выглядит в отредактированном виде:

  1. /** Лицензия MIT (MIT)
  2. Копирайт (c) 2016, Дэниэл Эйкорн (Daniel Eichhorn)
  3.  
  4. Данная лицензия разрешает лицам, получившим копию данного программного
  5. обеспечения и сопутствующей документации (в дальнейшем именуемыми
  6. «Программное Обеспечение»), безвозмездно использовать Программное
  7. Обеспечение без ограничений, включая неограниченное право на
  8. использование, копирование, изменение, слияние, публикацию,
  9. распространение, сублицензирование и/или продажу копий Программного
  10. Обеспечения, а также лицам, которым предоставляется данное Программное
  11. Обеспечение, при соблюдении следующих условий:
  12.  
  13. Указанное выше уведомление об авторском праве и данные условия должны
  14. быть включены во все копии или значимые части данного Программного
  15. Обеспечения.
  16.  
  17. ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ», БЕЗ
  18. КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНО ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ
  19. ГАРАНТИИ ТОВАРНОЙ ПРИГОДНОСТИ, СООТВЕТСТВИЯ ПО ЕГО КОНКРЕТНОМУ
  20. НАЗНАЧЕНИЮ И ОТСУТСТВИЯ НАРУШЕНИЙ, НО НЕ ОГРАНИЧИВАЯСЬ ИМИ. НИ В КАКОМ
  21. СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ НЕ НЕСУТ ОТВЕТСТВЕННОСТИ ПО
  22. КАКИМ-ЛИБО ИСКАМ, ЗА УЩЕРБ ИЛИ ПО ИНЫМ ТРЕБОВАНИЯМ, В ТОМ ЧИСЛЕ,
  23. ПРИ ДЕЙСТВИИ КОНТРАКТА, ДЕЛИКТЕ ИЛИ ИНОЙ СИТУАЦИИ, ВОЗНИКШИМ ИЗ-ЗА
  24. ИСПОЛЬЗОВАНИЯ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ ИЛИ ИНЫХ ДЕЙСТВИЙ С ПРОГРАММНЫМ
  25. ОБЕСПЕЧЕНИЕМ.
  26.  
  27. Более подробно читайте на http://blog.squix.ch
  28. */
  29.  
  30. #include <ESP8266WiFi.h>
  31. #include <Ticker.h>
  32. #include <JsonListener.h>
  33. #include "SSD1306Wire.h"
  34. #include "OLEDDisplayUi.h"
  35. #include "Wire.h"
  36. #include "WundergroundClient.h"
  37. #include "WeatherStationFonts.h"
  38. #include "WeatherStationImages.h"
  39. #include "TimeClient.h"
  40. #include "ThingspeakClient.h"
  41. #include "DHT.h"
  42.  
  43. /***************************
  44.  * Начальные настройки
  45.  **************************/
  46. // о начальных настройках для WeatherStation читайте тут:
  47. // http://blog.squix.org/weatherstation-getting-code-adapting-it
  48.  
  49. // константы для WiFi:
  50. const char* WIFI_SSID = "X";
  51. const char* WIFI_PWD = "X";
  52.  
  53. // интервал обновления – 10 минут (ограничение Wunderground):
  54. const int UPDATE_INTERVAL_SECS = 10 * 60;
  55.  
  56. // константы для дисплея:
  57. const int I2C_DISPLAY_ADDRESS = 0x3c;
  58. const int SDA_PIN = D3;
  59. const int SDC_PIN = D4;
  60.  
  61. // константа для библиотеки TimeClient:
  62. const float UTC_OFFSET = 1;
  63.  
  64. // константы для библиотеки WundergroundClient:
  65. const boolean IS_METRIC = true;
  66. const String WUNDERGRROUND_API_KEY = "X";
  67. const String WUNDERGRROUND_LANGUAGE = "DL";
  68. const String WUNDERGROUND_COUNTRY = "CH";
  69. const String WUNDERGROUND_CITY = "Zurich";
  70.  
  71. // константы для библиотеки ThingspeakClient:
  72. const String THINGSPEAK_CHANNEL_ID = "X";
  73. const String THINGSPEAK_API_READ_KEY = "X";
  74.  
  75. // инициализируем OLED-дисплей для адреса 0x3c
  76. // (контакт SDA – это 14, а SDC – это 12):
  77.  
  78. SSD1306Wire     display(I2C_DISPLAY_ADDRESS, SDA_PIN, SDC_PIN);
  79. OLEDDisplayUi   ui( &display );
  80.  
  81. // настройки для библиотеки «DHT»:
  82. #define DHTPIN D6  //  это цифровой контакт, к которому
  83.                    //  мы подключены; если используете не NodeMCU,
  84.                    //  а что-то другое, поменяйте D6
  85.                    //  на другой контакт
  86.  
  87. // уберите знаки комментария у типа датчика, который используете:
  88. //#define DHTTYPE DHT11   // DHT 11
  89. #define DHTTYPE DHT22     // DHT 22  (AM2302), AM2321
  90. //#define DHTTYPE DHT21   // DHT 21 (AM2301)
  91.  
  92. /***************************
  93.  * Финальные настройки
  94.  **************************/
  95.  
  96. TimeClient timeClient(UTC_OFFSET);
  97.  
  98. // если предпочитаете имперскую/дюймовую систему и Фаренгейты:
  99. WundergroundClient wunderground(IS_METRIC);
  100.  
  101. ThingspeakClient thingspeak;
  102.  
  103. // инициализируем датчик температуры/влажности:
  104. DHT dht(DHTPIN, DHTTYPE);
  105.  
  106. // флаг, который меняется в «маятниковой» функции каждые 10 минут:
  107. bool readyForWeatherUpdate = false;
  108.  
  109. String lastUpdate = "--";
  110.  
  111. float humidity = 0.;
  112. float temperature = 0.;
  113.  
  114. Ticker ticker;
  115.  
  116. // объявляем прототипы:
  117. void drawProgress(OLEDDisplay *display, int percentage, String label);
  118. void updateData(OLEDDisplay *display);
  119. void drawDateTime(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);
  120. void drawCurrentWeather(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);
  121. void drawForecast(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);
  122. void drawThingspeak(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);
  123. void drawForecastDetails(OLEDDisplay *display, int x, int y, int dayIndex);
  124. void drawHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state);
  125. void setReadyForWeatherUpdate();
  126. void drawIndoor(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);
  127.  
  128. // добавляем фреймы;
  129. // этот массив хранит указатели функции на все фреймы;
  130. // фрейм – это блок данных, перемещающийся справа налево:
  131. FrameCallback frames[] = { drawDateTime, drawCurrentWeather, drawForecast, drawThingspeak, drawIndoor };
  132. int numberOfFrames = 5;
  133.  
  134. OverlayCallback overlays[] = { drawHeaderOverlay };
  135. int numberOfOverlays = 1;
  136.  
  137. void setup() {
  138.   Serial.begin(115200);
  139.   Serial.println();
  140.   Serial.println();
  141.  
  142.   // инициализируем дисплей:
  143.   display.init();
  144.   display.clear();
  145.   display.display();
  146.  
  147.   //display.flipScreenVertically();
  148.   display.setFont(ArialMT_Plain_10);
  149.   display.setTextAlignment(TEXT_ALIGN_CENTER);
  150.   display.setContrast(255);
  151.  
  152.   WiFi.begin(WIFI_SSID, WIFI_PWD);
  153.  
  154.   int counter = 0;
  155.   while (WiFi.status() != WL_CONNECTED) {
  156.     delay(500);
  157.     Serial.print(".");
  158.     display.clear();
  159.     display.drawString(64, 10, "Connecting to WiFi");
  160.                            //  "Подключение к WiFi"
  161.     display.drawXbm(46, 30, 8, 8, counter % 3 == 0 ? activeSymbole : inactiveSymbole);
  162.     display.drawXbm(60, 30, 8, 8, counter % 3 == 1 ? activeSymbole : inactiveSymbole);
  163.     display.drawXbm(74, 30, 8, 8, counter % 3 == 2 ? activeSymbole : inactiveSymbole);
  164.     display.display();
  165.  
  166.     counter++;
  167.   }
  168.  
  169.   ui.setTargetFPS(30);
  170.  
  171.   ui.setActiveSymbol(activeSymbole);
  172.   ui.setInactiveSymbol(inactiveSymbole);
  173.  
  174.   // в этом аргументе можно выставить TOP, LEFT, BOTTOM и RIGHT:
  175.   ui.setIndicatorPosition(BOTTOM);
  176.  
  177.   // здесь задаем, где будет находиться первый фрейм:
  178.   ui.setIndicatorDirection(LEFT_RIGHT);
  179.  
  180.   // здесь задаем тип перехода (можно использовать варианты
  181.   // SLIDE_LEFT, SLIDE_RIGHT, SLIDE_TOP, SLIDE_DOWN):
  182.   ui.setFrameAnimation(SLIDE_LEFT);
  183.  
  184.   ui.setFrames(frames, numberOfFrames);
  185.  
  186.   ui.setOverlays(overlays, numberOfOverlays);
  187.  
  188.   // функция ui.init() тоже принимает участие в инициализации дисплея:
  189.   ui.init();
  190.  
  191.   Serial.println("");
  192.  
  193.   updateData(&display);
  194.  
  195.   ticker.attach(UPDATE_INTERVAL_SECS, setReadyForWeatherUpdate);
  196.  
  197. }
  198.  
  199. void loop() {
  200.  
  201.   if (readyForWeatherUpdate && ui.getUiState()->frameState == FIXED) {
  202.     updateData(&display);
  203.   }
  204.  
  205.   int remainingTimeBudget = ui.update();
  206.  
  207.   if (remainingTimeBudget > 0) {
  208.     // если у вас еще осталось время, здесь можно
  209.     // добавить еще кода для других задач:
  210.     delay(remainingTimeBudget);
  211.   }
  212.  
  213.  
  214. }
  215.  
  216. void drawProgress(OLEDDisplay *display, int percentage, String label) {
  217.   display->clear();
  218.   display->setTextAlignment(TEXT_ALIGN_CENTER);
  219.   display->setFont(ArialMT_Plain_10);
  220.   display->drawString(64, 10, label);
  221.   display->drawProgressBar(2, 28, 124, 10, percentage);
  222.   display->display();
  223. }
  224.  
  225. void updateData(OLEDDisplay *display) {
  226.   drawProgress(display, 10, "Updating time...");
  227.                         //  "Обновляем время..."
  228.   timeClient.updateTime();
  229.   drawProgress(display, 30, "Updating conditions...");
  230.                         //  "Обновляем условия..."
  231.   wunderground.updateConditions(WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGROUND_COUNTRY, WUNDERGROUND_CITY);
  232.   drawProgress(display, 50, "Updating forecasts...");
  233.                         //  "Обновляем прогнозы..."
  234.   wunderground.updateForecast(WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGROUND_COUNTRY, WUNDERGROUND_CITY);
  235.   drawProgress(display, 80, "Updating thingspeak...");
  236.                         //  "Обновляем ThingSpeak..."
  237.   thingspeak.getLastChannelItem(THINGSPEAK_CHANNEL_ID, THINGSPEAK_API_READ_KEY);
  238.   lastUpdate = timeClient.getFormattedTime();
  239.  
  240.   drawProgress(display, 90, "Updating local temperature and humidity");
  241.                        //  "Обновляем местную температуру и влажность"
  242.   humidity = dht.readHumidity();
  243.   // считываем температуру в Фаренгейтах (isFahrenheit = true):
  244.   temperature = dht.readTemperature(!IS_METRIC);
  245.  
  246.   readyForWeatherUpdate = false;
  247.   drawProgress(display, 100, "Done...");
  248.                          //  "Готово..."
  249.  
  250.   delay(1000);
  251. }
  252.  
  253. void drawDateTime(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
  254.   display->setTextAlignment(TEXT_ALIGN_CENTER);
  255.   display->setFont(ArialMT_Plain_10);
  256.   String date = wunderground.getDate();
  257.   int textWidth = display->getStringWidth(date);
  258.   display->drawString(64 + x, 5 + y, date);
  259.   display->setFont(ArialMT_Plain_24);
  260.   String time = timeClient.getFormattedTime();
  261.   textWidth = display->getStringWidth(time);
  262.   display->drawString(64 + x, 15 + y, time);
  263.   display->setTextAlignment(TEXT_ALIGN_LEFT);
  264. }
  265.  
  266. void drawCurrentWeather(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
  267.   display->setFont(ArialMT_Plain_10);
  268.   display->setTextAlignment(TEXT_ALIGN_LEFT);
  269.   display->drawString(60 + x, 5 + y, wunderground.getWeatherText());
  270.  
  271.   display->setFont(ArialMT_Plain_24);
  272.   String temp = wunderground.getCurrentTemp() + "°C";
  273.   display->drawString(60 + x, 15 + y, temp);
  274.   int tempWidth = display->getStringWidth(temp);
  275.  
  276.   display->setFont(Meteocons_Plain_42);
  277.   String weatherIcon = wunderground.getTodayIcon();
  278.   int weatherIconWidth = display->getStringWidth(weatherIcon);
  279.   display->drawString(32 + x - weatherIconWidth / 2, 05 + y, weatherIcon);
  280. }
  281.  
  282. void drawIndoor(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
  283.   display->setTextAlignment(TEXT_ALIGN_CENTER);
  284.   display->setFont(ArialMT_Plain_10);
  285.   display->drawString(64 + x, 0 + y, "Indoor");
  286.                                  //  "Внутри"
  287.  
  288.   display->setFont(ArialMT_Plain_16);
  289.   display->drawString(64 + x, 10 + y, String(temperature, 1) + "°C");
  290.   display->drawString(64 + x, 30 + y, String(humidity, 1) + "%");
  291. }
  292.  
  293. void drawForecast(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
  294.   drawForecastDetails(display, x, y, 0);
  295.   drawForecastDetails(display, x + 44, y, 2);
  296.   drawForecastDetails(display, x + 88, y, 4);
  297. }
  298.  
  299. void drawThingspeak(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
  300.   display->setTextAlignment(TEXT_ALIGN_CENTER);
  301.   display->setFont(ArialMT_Plain_10);
  302.   display->drawString(64 + x, 0 + y, "Outdoor");
  303.                                  //  "Снаружи”
  304.  
  305.   display->setFont(ArialMT_Plain_16);
  306.   display-> rawstring(64 + x, 10 + y, thingspeak.getFieldValue(0) + “°C”);
  307.   display-> rawstring(64 + x, 30 + y, thingspeak.getFieldValue(1) +%);
  308. }
  309.  
  310. void drawForecastDetails(OLEDDisplay *display, int x, int y, int dayIndex) {
  311.   display->setTextAlignment(TEXT_ALIGN_CENTER);
  312.   display->setFont(ArialMT_Plain_10);
  313.   String day = wunderground.getForecastTitle(dayIndex).substring(0, 3);
  314.   day.toUpperCase();
  315.   display-> rawstring(x + 20, y, day);
  316.  
  317.   display->setFont(Meteocons_Plain_21);
  318.   display-> rawstring(x + 20, y + 12, wunderground.getForecastIcon(dayIndex));
  319.  
  320.   display->setFont(ArialMT_Plain_10);
  321.   display-> rawstring(x + 20, y + 34, wunderground.getForecastLowTemp(dayIndex) +|+ wunderground.getForecastHighTemp(dayIndex));
  322.   display->setTextAlignment(TEXT_ALIGN_LEFT);
  323. }
  324.  
  325. void drawHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state) {
  326.   display->setColor(WHITE);
  327.   display->setFont(ArialMT_Plain_10);
  328.   String time = timeClient.getFormattedTime().substring(0, 5);
  329.   display->setTextAlignment(TEXT_ALIGN_LEFT);
  330.   display-> rawstring(0, 54, time);
  331.   display->setTextAlignment(TEXT_ALIGN_RIGHT);
  332.   String temp = wunderground.getCurrentTemp() + “°C”;
  333.   display-> rawstring(128, 54, temp);
  334.   display->drawHorizontalLine(0, 52, 128);
  335. }
  336.  
  337. void setReadyForWeatherUpdate() {
  338.   Serial.println(“Setting readyForUpdate to true);
  339.              //  “Установление readyForUpdate на «true»”
  340.   readyForWeatherUpdate = true;
  341. }

Теперь подробнее об изменениях:

  • Строчка 37: Я добавил библиотеку «DHT»
  • Строчки 77-83: Настройки для библиотеки «DHT». Если используете DHT11 или DHT21, эти настройки можно поменять. Также можно поменять используемый контакт. Если не использовать контакт D6 на NodeMCU, при компиляции будет ошибка
  • Строчки 104/105: Две новых переменных для влажности и температуры. Если используете новый модуль WeatherStation, эти переменные можно поместить в новые классы, а не в глобальное пространство...
  • Строчки 110-119: Эти прототипы помогают компилятору/линкеру использовать функции, которые будут использоваться только потом
  • Строчки 119/124: Я добавил новую функцию drawIndoor() и увеличил количество фреймов до 6. Благодаря этому фреймворк знает, какой метод вызвать, чтобы показать информацию о внутреннем помещении
  • Строчки 231-233: В данном руководстве данные о температуре и влажности обновляются только один раз в 10 минут. Обновление данных обойдется нам лишь в 250 мс, но для цикла loop() это по-прежнему может быть слишком много. Но это можно делать и в while()
  • Строчки 271-277: Этот фрагмент рисует фрейм с информацией о внутреннем помещении. Как видите, он очень похож на функцию drawThingspeak(). И это не случайно, т.к. они отображают похожие данные.

Вот и все! Теперь, когда код отредактирован, скомпилируйте его и загрузите на ESP8266.

WeatherStationDHT22.jpg

Теперь давайте приступим ко второй части – созданию сенсорного «узла», который будет сначала постить данные в бесплатном облачном сервисе, а лишь затем выгружать их на WeatherStation, которая находится в другой комнате и будет показывать их на дисплее.

Необходимые компоненты

Для сенсорного «узла» вам потребуются:

  • Одна адаптерная плата NodeMCU ESP8266 (или любой другой модуль с чипом ESP8266)
  • Один датчик DHT22
  • Три провода типа «мама-мама»
  • Один источник питания с USB-разъемом

И я пишу это руководство с учетом того, что вы уже настроили рабочую WeatherStation.

Подключение компонентов

В подключении сенсорного «узла» нет ничего сложного. У платы датчика DHT есть только три контакта: GND («земля»), VCC (3,3-вольтовое напряжение) и DAT (это линия для передачи данных, подключаемая к контакту D6 на NodeMCU):

Датчик DHT, подключенный к WeatherStation напрямую

ThingSpeak

ThingSpeak – это бесплатный облачный сервис, позволяющий без особого труда постить данные, считанные с датчиков, а также визуализировать их и считывать при помощи простых HTTP-методов. Здесь стоит отметить, что для хранения погодных данных можно также использовать Wunderground, и способ этот, вероятно, будет даже проще, чем ThingSpeak. Но я все же считаю, что при использовании в образовательных целей ThingSpeak дает гораздо больше свободы. Ему можно отсылать данные, к примеру, от датчика движения и других подобных датчиков. Кроме того, в ThingSpeak встроена очень полезная функция, называемая «webhook» – она позволяет отправлять push-уведомления на смартфон, планшет и т.д.

Итак, вначале нужно зарегистрировать аккаунт в ThingSpeak (это бесплатно). Сделать это можно по этой ссылке. Зарегистрировавшись, залогиньтесь в новом аккаунте и перейдите к пункту «My Channels».

Thingspeak1.png

Затем кликните по кнопке «New Channel». Откроется новое меню. Заполните форму, которая находится в этом меню.

Thingspeak2.png

Поле «Name» (т.е. «название») поможет вам распознать свой канал среди множества других, которые вы, возможно, создали ранее. Другие важные элементы – названия в полях «Field1» и «Field2». Эти названия позднее будут отображены в графике, и с их помощью я сообщаю ThingSpeak, что значение, которое я отсылаю вместе с атрибутом «field1», должно быть показано как «Temperature» (т.е. температура).

Теперь перейдите к вкладке «API Keys» и запомните (а лучше – запишите) где-нибудь два ключа, сгенерированных в этом меню:

Thingspeak4.png

Первый ключ позволит вам записывать данные на этот ThingSpeak-канал, а второй – считывать данные с этого канала. Это секретные ключи, так что берегите их как зеницу ока. Зная эти ключи, злоумышленники могут заспамить ваш канал или даже «украсть» данные. К слову, сделав скриншот, я сгенерировал новые ключи :D

Итак, запишите ключи, скоро они нам понадобятся. Также запомните ID канала – он изображен в самом верху экрана.

Программирование сенсорного «узла»

Итак, теперь у нас есть все необходимые ингредиенты для постинга данных на ThingSpeak. Осталось лишь нужным образом запрограммировать ESP8266. Перейдите по этой ссылке и загрузите ZIP-файл с программой или воспользуйтесь командой git checkout (знающие поймут).

Теперь адаптируйте настройки под собственные нужды. Особенно это касается настроек WiFi и ключа «Write API», который мы сгенерировали и записали в разделе выше.

Интереса ради можно поиграться с интервалом обновления (в секундах). Имейте в виду, что минимальный интервал обновления в ThingSpeak составляет 15 секунд. Если задать интервал меньше, обновления будут просто игнорироваться. Теперь осталось записать программу на NodeMCU, и сенсорный «узел» должен начать работать. Чтобы посмотреть на результаты, можно вернуться к ThingSpeak и взглянуть на графики:

Thingspeak5.png

Показ данных на погодной станции

Теперь самое простое. Словно повар из кулинарной ТВ-передачи, я уже давно все приготовил за вас :) В библиотеке WeatherStation есть скетч WeatherStationDemo, который уже содержит все необходимое для отображения данных нашего сенсорного «узла».

Измените в нем строчки, в которые нужно вписать ключ «Read API» и ID канала, о которых шла речь в разделе «ThingSpeak» выше. Если вы не удалили фрагмент с сенсорным «узлом» из программы для WeatherStation, вам нужно просто загрузить на WeatherStation скетч с обновленным API-ключом и ID канала, и вуаля! Вы только что успешно отправили данные о температуре и влажности из соседней комнаты во внешний мир, а затем на маленький OLED-дисплей! Кстати, знаю пару людей (включая мою жену), которых этот трюк не впечатлит вовсе :D

Этот последний шаг может быть слегка непонятным, т.к. повар приготовил жаркое за несколько часов до начала ТВ-шоу, поэтому вот то же самое, но в замедленной съемке: библиотека WeatherStation теперь оснащена классом ThingSpeak, который берет на себя всю черновую работу. Вы «скармливаете» ему ID канала и API-ключ, а он загружает JSON-объект и выбирает только последний блок данных, т.к. именно он нам, в сущности, и нужен.

Чтобы было понятнее, можете взглянуть сюда. Возможно, вы даже захотите изменить/расширить этот код под собственные нужды.

Почему бы, к примеру, не замутить график, показывающий данные за последние 24 часа?

См.также

Внешние ссылки

  1. blog.squix.org - ESP8266 Weather Station: Measuring Inside and Outside Temperature – Part 1
  2. blog.squix.org - ESP8266 Weather Station: Measuring Inside and Outside Temperature – Part 2