ESP8266:Примеры/Выполнение ежедневной задачи с помощью ESP8266

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

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


Выполнение ежедневной задачи с помощью ESP8266

В этом руководстве мы научимся делать на базе ESP8266 систему, раз в день публикующую в бесплатный сервис Thing Speak данные о температуре и влажности.

Необходимое оборудование

Подготовка IDE Arduino

Собрав цепь, откройте IDE Arduino и установите в нее две библиотеки.

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

Вбейте в поиске «dht», а затем нажмите на «Установка» (Install). Эту библиотеку также можно загрузить вручную отсюда.

Далее нам нужно будет установить библиотеку «ESPDailyTask». Для этого проделайте следующее:

  1. Кликните тут, чтобы скачать ZIP-архив библиотеки. Он должен загрузиться в папку «Загрузки»;
  2. Распакуйте его. У вас должна получиться папка «ESPDailyTask-master»;
  3. Переименуйте ее на «ESPDailyTask»;
  4. Переместите эту папку в папку «libraries» (туда устанавливаются библиотеки IDE Arduino), которая находится внутри папки, куда установлена IDE Arduino;
  5. Наконец, перезапустите IDE Arduino;

Thing Speak

В этом проекте мы воспользуемся сервисом ThingSpeak.com. Он позволяет публиковать данные от датчиков на их вебсайт и выводить на график, помечая датой/временем. Это позволяет получить доступ к своим данным из любой точки мира.

Стоит добавить, что это легко модифицируемый проект, и его можно настроить так, чтобы данные вместо Thing Speak публиковались в IoT-хабе или любой другой системе. Главное, что я хочу показать в этом проекте – это то, как постоянно переводить ESP8266 в режим глубокого сна, публикуя данные каждые 24 часа.

Создаем новый канал

Нет аккаунта в Thing Speak? Создайте его. Затем залогиньтесь и откройте вкладку Channels.

Далее нажмите на кнопку New Channel:

Задайте название и описание для своего канала, а также включите поле 2. Поле 1 будет получать данные о влажности (Humidity), а поле 2 – данные о температуре (Temperature). Заполнив поля, сохраните канал.

Настраиваем график

Чтобы настроить график нужным образом, перейдите на вкладку Private View и нажмите на кнопку редактирования (она изображена в виде карандаша):

Название графика задается в поле «Title». К примеру, первый график будет называться «Humidity %», а второй – «Temperature ˚C».

Вы также можете настроить фоновый цвет, оси X и Y и многое другое (см. скриншот ниже). Закончив, нажмите на кнопку Save.

API-ключ для записи (Write API Key)

Для публикации значений при помощи ESP8266 нам понадобится API-ключ для записи (Write API Key). Откройте вкладку API Keys и скопируйте в какое-нибудь безопасное место строчку из поля Key. Скоро она нам понадобится.

Подготавливаем код

В этом коде есть три переменные, значения которых нужно поменять. В двух строчках ниже нужно вставить SSID и пароль от своей WiFi-сети, чтобы ESP8266 могла подключиться к вашему роутеру.

// Вставьте здесь SSID и пароль для своей WiFi-сети:
const char* ssid     = "ВСТАВЬТЕ_СЮДА_СВОЙ_SSID";
const char* password = "ВСТАВЬТЕ_СЮДА_СВОЙ_ПАРОЛЬ";

В строчке ниже нужно вписать API-ключ для записи данных (Write API Key) в Thing Speak:

// Вставьте здесь API-ключ для записи (Write API Key) Thing Speak:
const char* apiKey = "ВАШ_API_КЛЮЧ_ThingSpeak";

Как работает этот код

Теперь давайте взглянем на этот код поближе. Блок setup() начинается с инициализации последовательной коммуникации.

void setup() {
  // Инициализируем последовательную коммуникацию (для отладки): 
  Serial.begin(115200);
  delay(10);

После этого вызываем метод sleep1Day(), чтобы определить, прошло ли 24 часа с того момента, когда данные были считаны в последний раз. Если не прошло, ESP8266 вернется в режим глубокого сна.

dailyTask.sleep1Day();

Но если эти 24 часа все же прошли, код продолжит работать дальше. В нем будет инициализирован датчик DHT, будет выполнено подключение к WiFi-роутеру и сделан HTTP-запрос GET к Thing Speak для публикации этих данных.

  // Ниже пишем код, который раз в день
  // будет выполняться при запуске ESP8266:
  dht.begin();
  initWifi();
  makeHTTPRequest();

Опубликовав данные, ESP8266 вернется в режим глубокого сна.

  // После этого переходим в режим глубокого сна: 
  dailyTask.backToSleep();
}

В блоке loop() ничего выполняться не будет, т.к. ESP8266 будет постоянно переходить в режим сна, просто не добираясь до loop().

void loop() {
  // ESP8266 «заснет» и не доберется до блока loop():
}

Дополнительное редактирование кода – смена датчика и переключение на Фаренгейты

Если вы используете не DHT11, а другой датчик, то выбрать его можно, раскомментировав правильную строчку и закомментировав все остальные во фрагменте ниже:

// Раскомментируйте строчку, соответствующую типу вашего датчика:
#define DHTTYPE DHT11   // DHT 11
//#define DHTTYPE DHT21   // DHT 21 (AM2301)
//#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321

Есть еще одна важная вещь, которую можно поменять в этом скетче. По умолчанию он публикует температуру в градусах Цельсия, но если закомментировать строчку, помеченную во фрагменте ниже красным цветом, и раскомментировать строчку, помеченную во фрагменте ниже зеленым цветом, скетч начнет публиковать данные в градусах Фаренгейта.

// Рассчитываем температуру в Цельсиях и Фаренгейтах и влажность: 
float hic = dht.computeHeatIndex(t, h, false); 
// Закомментируйте строчку ниже, если предпочитаете Фаренгейты: 
dtostrf(hic, 6, 2, temperatureTemp);
                 
float hif = dht.computeHeatIndex(f, h);
// Раскомментируйте строчку ниже, если предпочитаете Фаренгейты: 
//dtostrf(hif, 6, 2, temperatureTemp);

Внеся все необходимые изменения, можете загрузить код на ESP8266.

Проверяем проект

Наконец, открываем монитор порта IDE Arduino на скорости 115200 бод. При помощи небольшой хитрости мы можем сделать так, чтобы 24 часа для ESP8266 прошли за несколько секунд. Отключите провод между контактами RESET и D0 (GPIO16), а затем нажмите на кнопку RESET. Одно нажатие на нее имитирует один час.

Таким образом, чтобы сымитировать сутки, вам нужно нажать на эту кнопку 24 раза. Каждое нажатие на кнопку увеличивает значение в параметре «counter» («счетчик», см. ниже) на единицу. Если нажать на кнопку сброса 24 раза, это запустит публикацию данных в Thing Speak.

Как видите, данные о температуре и влажности были успешно опубликованы и в режиме реального времени показаны на графике.

Протестировав цепь, снова подключите провод между контактами RESET и D0. ESP8266 будет просыпаться каждый час, но новые данные опубликует только когда пройдет 24 часа. Надеюсь, этот проект был для вас полезен. Теперь вы должны понимать, как запрограммировать ESP8266 на выполнение ежедневной задачи.

Схема

Код

/*
 * Выполнение ежедневной задачи с помощью ESP8266
 * Автор – Руи Сантос 
 * Более подробно о проекте на: http://randomnerdtutorials.com
 */
 
#include <ESP8266WiFi.h>
#include <ESPDailyTask.h>
#include "DHT.h"

// Раскомментируйте строчку, соответствующую типу вашего датчика:
#define DHTTYPE DHT11   // DHT 11
//#define DHTTYPE DHT21   // DHT 21 (AM2301)
//#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321

// Вставьте здесь SSID и пароль для своей WiFi-сети:
const char* ssid     = "ВСТАВЬТЕ_СЮДА_СВОЙ_SSID";
const char* password = "ВСТАВЬТЕ_СЮДА_СВОЙ_ПАРОЛЬ";

// Вставьте здесь API-ключ для записи (Write API Key) Thing Speak:
const char* apiKey = "ВАШ_API_КЛЮЧ_ThingSpeak";

const char* resource = "/update?api_key=";

// Сервер API Thing Speak:
const char* server = "api.thingspeak.com";

// Задайте здесь, в какое время должен запускаться ваш код: 
ESPDailyTask dailyTask(11*60 + 15); // 11:15am

// Контакт, к которому подключен датчик DHT:
const int DHTPin = 5;
// Инициализируем датчик DHT:
DHT dht(DHTPin, DHTTYPE);

// Временные переменные:
static char temperatureTemp[7];
static char humidityTemp[7];

void setup() {
  // Инициализируем последовательную коммуникацию (для отладки): 
  Serial.begin(115200);
  delay(10);
  
  dailyTask.sleep1Day();
  
  // Ниже пишем код, который раз в день
  // будет выполняться при запуске ESP8266:
  dht.begin();
  initWifi();
  makeHTTPRequest();

  // После выполнения ежедневного кода
  // переходим в режим глубокого сна: 
  dailyTask.backToSleep();
}

void loop() {
  // ESP8266 «заснет» и не доберется до блока loop():
}

// Функция, устанавливающая WiFi-коммуникацию с роутером:
void initWifi() {
  Serial.print("Connecting to: ");  // "Подключаемся к: "
  Serial.print(ssid);
  WiFi.begin(ssid, password);  

  int timeout = 10 * 4; // 10 секунд
  while(WiFi.status() != WL_CONNECTED  && (timeout-- > 0)) {
    delay(250);
    Serial.print(".");
  }
  Serial.println("");

  if(WiFi.status() != WL_CONNECTED) {
     Serial.println("Failed to connect, going back to sleep");
                //  "Подключиться не удалось,
                //  возвращаемся в режим сна"
  }

  Serial.print("WiFi connected in: ");
           //  "Время подключения к WiFi: "
  Serial.print(millis());
  Serial.print(", IP address: ");  //  ", IP-адрес: "
  Serial.println(WiFi.localIP());
}

// Функция для выполнения HTTP-запроса к Thing Speak:
void makeHTTPRequest() {
  // Данные от датчика могут запаздывать на 2 секунды
  // (это очень медленный датчик):
  float h = dht.readHumidity();
  // Считываем температуру в градусах Цельсия (по умолчанию):
  float t = dht.readTemperature();
  // Считываем температуру в градусах Фаренгейта
  // (isFahrenheit = true):
  float f = dht.readTemperature(true);
  // Проверяем, удалось ли прочесть данные,
  // и если нет, то выходим (чтобы попробовать снова):
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println("Failed to read from DHT sensor!");
               //  "Не удалось прочесть данные с датчика DHT!"
    strcpy(temperatureTemp,"Failed");
    strcpy(humidityTemp, "Failed");
    return;    
  }
  else {
    // Рассчитываем температуру в Цельсиях и Фаренгейтах и влажность: 
    float hic = dht.computeHeatIndex(t, h, false); 
    // Закомментируйте строчку ниже, если предпочитаете Фаренгейты: 
    dtostrf(hic, 6, 2, temperatureTemp);
                 
    float hif = dht.computeHeatIndex(f, h);
    // Раскомментируйте строчку ниже, если предпочитаете Фаренгейты: 
    //dtostrf(hif, 6, 2, temperatureTemp);   
          
    dtostrf(h, 6, 2, humidityTemp);
    // Методы Serial.print() ниже можно удалить,
    // т.к. они нужно исключительно для отладки:
    Serial.print("Humidity: ");  //  "Влажность: "
    Serial.print(h);
    Serial.print(" %\t Temperature: ");  //  " Температура: "
    Serial.print(t);
    Serial.print(" *C ");
    Serial.print(f);
    Serial.print(" *F\t Heat index: ");  //  " Тепловой индекс: "
    Serial.print(hic);
    Serial.print(" *C ");
    Serial.print(hif);
    Serial.print(" *F");
    Serial.print("Humidity: ");  //  "Влажность: "
    Serial.print(h);
    Serial.print(" %\t Temperature: ");  //  " Температура: "
    Serial.print(t);
    Serial.print(" *C ");
    Serial.print(f);
    Serial.print(" *F\t Heat index: ");  //  " Тепловой индекс: "
    Serial.print(hic);
    Serial.print(" *C ");
    Serial.print(hif);
    Serial.println(" *F");
  }
  
  Serial.print("Connecting to ");  //  "Подключаемся к "
  Serial.print(server);
  
  WiFiClient client;
  int retries = 5;
  while(!!!client.connect(server, 80) && (retries-- > 0)) {
    Serial.print(".");
  }
  Serial.println();
  if(!!!client.connected()) {
     Serial.println("Failed to connect, going back to sleep");
                //  "Подключиться не удалось,
                //  Возвращаемся в режим сна"
  }
  
  Serial.print("Request resource: ");  //  "Ресурс запроса: "
  Serial.println(resource);
  client.print(String("GET ") + resource + apiKey + "&field1=" + humidityTemp + "&field2=" + temperatureTemp +
                  " HTTP/1.1\r\n" +
                  "Host: " + server + "\r\n" + 
                  "Connection: close\r\n\r\n");
                  
  int timeout = 5 * 10; // 5 секунд             
  while(!!!client.available() && (timeout-- > 0)){
    delay(100);
  }
  if(!!!client.available()) {
     Serial.println("No response, going back to sleep");
                //  "Нет ответа, возвращаемся в режим глубокого сна"
  }
  while(client.available()){
    Serial.write(client.read());
  }
  
  Serial.println("\nclosing connection");  
             //  " отключаем соединение"
  client.stop();
}

См.также

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