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

Материал из Онлайн справочника
Перейти к навигации Перейти к поиску

Перевод: Максим Кузьмин (Cubewriter) Контакты:</br>* Skype: cubewriter</br>* E-mail: cubewriter@gmail.com</br>* Максим Кузьмин на freelance.ru
Проверка/Оформление/Редактирование: Мякишев Е.А.


Pixel Art Mini Meow Animated.gif Черновик


Измерение внутренней и наружной температуры с помощью 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 часа?

См.также

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