Arduino

Как использовать Deep Sleep на ESP8266 (NodeMCU)?

• 17-11-2018 •

В прошлой записи, мы разбирали Подключение ESP8266 И DHT22 и отправка температуры на Majordomo. И на этом бы остановились , если бы не одна маленькая проблемка. Высокое энергопотребление.

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

К счастью, у esp8266 есть возможность сна.

Типы снов

Существует четыре типа режимов сна для ESP8266: No-sleep, Modem-sleep, Light-sleep и Deep-sleep.

Все они имеют разные функции.

Без сна

В режиме No-Sleep, будет работать все по максимуму. Очевидно, что это наиболее неэффективно.

Modem-sleep

Это режим по умолчанию для ESP8266. Тем не менее, он используется только когда вы подключены к точке доступа.

В режиме «Modem-sleep» контроллер отключает wi-fi между интервалами маяка DTIM . Этот интервал устанавливается вашим маршрутизатором.

Light-sleep

Выполняет ту же функцию, что и «Modem-sleep», но также отключает системные часы и приостанавливает работу CPU.

Deep-sleep

Все выключено, но часы реального времени (RTC), будут работать. Это то-же самое, как и компьютер сохраняет время, когда он выключен. Поскольку все выключено,  то это самый эффективный энергосберегающий вариант.

Глубокий сон, это то что нам надо, для того чтобы отправлять данные температуры по wi-fi.

И работать это будет следующим образом:

  1. Подключаемся к wi-fi
  2. Собираем данные с датчика
  3. Отправляем данные с датчика
  4. Засыпаем на 20 секунд
  5. Повторяем все с начало

Пример использования Deep sleep

Давайте рассмотрим простой пример:

Для начало нам нужно на самом контроллере соединить 2 контакта

Это обязательная процедура, чтобы заработал deep-sleep

Теперь сам код:


/**
 * Пример для считывания температуры и влажности
 * Используются DHT22 и ESP8266
 *
 * Copyright (c) 2018 smartideal. All rights reserved.
 * https://smartideal.net
 */
 
#include "DHT.h"
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>

#define DHTPIN 4     // Номер пина, который подключен к DHT22
#define DHTTYPE DHT22   // Указываем, какой тип датчика мы используем
byte mqtt_server[] = { 192, 168, 88, 254 };  // ip адресс mqtt сервера
char buffer[10];

DHT dht(DHTPIN, DHTTYPE);

// WiFi 
const char* WIFI_SSID = "your_SSID"; // Укажите ваш SSID
const char* WIFI_PASS = "your_PASSWORD"; // Укажите ваш wifi пароль

// Читаем MQTT сообщения
void callback(char* topic, byte* payload, unsigned int length) {
}

WiFiClient wifiClient;
PubSubClient client(mqtt_server, 1883, callback, wifiClient);

void connect() {

  WiFi.persistent(false);
  WiFi.mode(WIFI_OFF);
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASS);

  unsigned long wifiConnectStart = millis();

  while (WiFi.status() != WL_CONNECTED) {
    if (WiFi.status() == WL_CONNECT_FAILED) {
      Serial.println("Ошибка соединения WIFI. Проверьте данные: ");
      Serial.println();
      Serial.print("SSID: ");
      Serial.println(WIFI_SSID);
      Serial.print("Password: ");
      Serial.println(WIFI_PASS);
      Serial.println();
    }

    delay(500);
 
    if(millis() - wifiConnectStart > 5000) {
      Serial.println("Ошибка соединения WiFi");
      Serial.println("Попробуйте отправить обновленные параметры конфигурации.");
      return;
    }
  }

  Serial.println("WiFi соединение установлено");
  Serial.println("IP адрес: ");
  Serial.println(WiFi.localIP());
  Serial.println();
}

void setup() {
  Serial.begin(115200);
  Serial.setTimeout(2000);

  // Ждем, пока все загрузится.
  while(!Serial) { }

  Serial.println("Устройство запущено");
  Serial.println("-------------------------------------");
  Serial.println("Запускаем DHT!");
  Serial.println("-------------------------------------");
  connect();

}

// Собираем данные, складываем воедино и отправляем
void report(double humidity, double tempC) {
  StaticJsonBuffer<500> jsonBuffer;
  JsonObject& root = jsonBuffer.createObject();
  root["humidity"] = humidity;
  root["tempC"] = tempC;
  char payload[256];
  root.printTo(payload, sizeof(payload));
  char* s = payload;
  if (client.connect("ESP8266 Temperature and Humidity")) {
    if(client.publish("ESP/Temp", s) == true){
      Serial.println("Отправлено!");
      delay(2000);
      ESP.deepSleep(20e6); // 20e6 это и есть deep-sleep. Засыпаем на 20 секунд!
    }
  }
}

void loop() {

bool toReconnect = false;

  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("Нет соединения WiFi");
    toReconnect = true;
  }

  if (toReconnect) {
    connect();
  }

  
    float h = dht.readHumidity();
    float t = dht.readTemperature();

    if (isnan(h) || isnan(t)) {
      Serial.println("Данных нет! Останавливаем цикл и запускаем по новой");
      return;
    }

    report(h, t);
  
  
}

С данным кодом, ответ на majordomo мы видим следующим образом:

А на этом все, надеюсь статья вам была полезна! В следующих записях мы разберем как запускать MQTT и перехватывать сообщения в Majordomo!

4 thoughts on “Как использовать Deep Sleep на ESP8266 (NodeMCU)?

  1. Users/alex/Documents/Arduino/deep_sleep_DHT11/deep_sleep_DHT11.ino: In function ‘void connect()’:
    deep_sleep_DHT11:67:14: error: a function-definition is not allowed here before ‘{‘ token
    void setup() {
    ^
    deep_sleep_DHT11:125:1: error: expected ‘}’ at end of input
    }
    ^
    exit status 1
    a function-definition is not allowed here before ‘{‘ token

    1. Спасибо, исправил, проверил, сейчас код рабочий (Видимо случайно удалил фигурную скобку)

  2. В открытой печати надо бы было написать по русски — «….запускаем снова». Жаль, что коверкаете язык.

Добавить комментарий