WeMos D1 mini (esp8266), i tre tipi di modalità di sospensione per gestire il risparmio energetico – Parte 4

Spread the love

Quando si crea un nuovo progetto IoT, probabilmente è necessario collegare il microcontrollore a una fonte di energia elettrica come una batteria, ma se non si utilizzano le corrette opzioni di risparmio energetico, la batteria si esaurirà in pochissimo tempo.

Come molti microcontrollori IoT, WeMos D1 mini ha delle modalità di risparmio energetico.

Per creare un semplice power bank, leggi “Power bank di emergenza fatto in casa“.

Puoi trovare questo microcontrollore qui WeMos D1 mini - NodeMCU V2 V2.1 V3 - esp01 - esp01 programmer

I tipi di modalità di sospensione sono modem-sleep, light-sleep e deep-sleep. La tabella seguente mostra le differenze tra ciascuna modalità.

ItemModem-sleepLight-sleepDeep-sleep
Wi-FiOFFOFFOFF
System clockONOFFOFF
RTCONONON
CPUONPendingOFF
Substrate current15 mA0.4 mA~20 uA
Average current (DTIM = 1)16.2 mA1.8 mA
Average current (DTIM = 3)15.4 mA0.9 mA
Average current (DTIM = 10)15.2 mA0.55 mA

Modem sleep

Questo è lo stato predefinito del esp8266, ma lo si interrompe quando si collega il dispositivo tramite WIFI. Se non usi WIFI per un po ‘, la cosa migliore è mettere il dispositivo in modalità di sospensione del modem (modem-sleep).

Puoi mettere il tuo dispositivo in modalità modem-sleep con questo comando:

WiFi.disconnect();
WiFi.forceSleepBegin();
delay(1); //For some reason the modem won't go to sleep unless you do a delay

puoi ripristinare il WIFI con:

WiFi.forceSleepWake();
delay(1);
//Insert code to connect to WiFi, start your servers or clients or whatever

Ricorda che se vuoi usare un delay in modalità “normale” devi aggiungere questo comando (che rimuove le varie modalità di sleep):

      wifi_set_sleep_type(NONE_SLEEP_T);

Oppure devi disabilitare la modalità di sospensione automatica (meglio spiegata nel prossimo paragrafo) con questa funzione.

  wifi_fpm_auto_sleep_set_in_null_mode(NULL_MODE);

Qui lo sketch completo, fai attenzione per il debug uso la Serial1, fai riferimento alla parte 3 per capire in cosa consiste WeMos D1 mini (esp8266): debug sulla seriale secondaria

#include "Arduino.h"
#include <ESP8266WiFi.h>
// Required for LIGHT_SLEEP_T delay mode
extern "C" {
#include "user_interface.h"
}

const char* ssid = "<your-ssid>";
const char* password = "<your-passwd>";

//The setup function is called once at startup of the sketch
void setup() {
  Serial1.begin(115200);
  while(!Serial1) { }

  Serial1.println();
  Serial1.println("Start device in normal mode!");

  WiFi.mode(WIFI_STA);

  WiFi.begin(ssid, password);
  Serial1.println("");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial1.print(".");
  }
  Serial1.println("");
  Serial1.print("Connected to ");
  Serial1.println(ssid);
  Serial1.print("IP address: ");
  Serial1.println(WiFi.localIP());
}
void callback() {
  Serial1.println("Callback");
  Serial.flush();
}
void loop() {
	  Serial1.println("Enter modem sleep mode");


      uint32_t sleep_time_in_ms = 10000;
//      WiFi.disconnect();
      WiFi.forceSleepBegin();
      delay(sleep_time_in_ms + 1);

      WiFi.forceSleepWake();
      delay(1);
      Serial1.println("Exit modem sleep mode");

      WiFi.mode(WIFI_STA);
      WiFi.begin(ssid, password);
      Serial1.println("");

      // Wait for connection
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial1.print(".");
      }
      Serial1.println("");
      Serial1.print("Connected to ");
      Serial1.println(ssid);
      Serial1.print("IP address: ");
      Serial1.println(WiFi.localIP());

      wifi_set_sleep_type(NONE_SLEEP_T);
      delay(10000);  //  Put the esp to sleep for 15s
}

Questo tipo di modalità di sospensione, come puoi vedere nel video, consente di ottenere 20 mA di consumo energetico dal dispositivo.

Light sleep

Questo tipo di sospensione è abbastanza utile se è necessario mantenere attivo il dispositivo e la grande differenza rispetto al tipo precedente è che è possibile riattivare il dispositivo tramite interruzione su GPIO.

Per attivare la modalità di sospensione leggera è necessario utilizzare questo codice, non esiste un modo semplice per attivarlo come accade per la sospensione del modem.

Devi aggiungere questa configurazione allo sketch:

	  // Here all the code to put con light sleep
	  // the problem is that there is a bug on this
	  // process
	  //wifi_station_disconnect(); //not needed
	  uint32_t sleep_time_in_ms = 10000;
	  wifi_set_opmode(NULL_MODE);
	  wifi_fpm_set_sleep_type(LIGHT_SLEEP_T);
	  wifi_fpm_open();
	  wifi_fpm_set_wakeup_cb(callback);
	  wifi_fpm_do_sleep(sleep_time_in_ms *1000 );
	  delay(sleep_time_in_ms + 1);

Allo stesso modo possiamo usare questo codice per entrare in modalità MODEM_SLEEP:

	  // Here all the code to put con light sleep
	  // the problem is that there is a bug on this
	  // process
	  //wifi_station_disconnect(); //not needed
	  uint32_t sleep_time_in_ms = 10000;
	  wifi_set_opmode(NULL_MODE);
	  wifi_fpm_set_sleep_type(MODEM_SLEEP_T);
	  wifi_fpm_open();
	  wifi_fpm_set_wakeup_cb(callback);
	  wifi_fpm_do_sleep(sleep_time_in_ms *1000 );
	  delay(sleep_time_in_ms + 1);

Il dispositivo passa in modalità luce con un ridotto utilizzo della batteria e temperatura.

#include "Arduino.h"
#include <ESP8266WiFi.h>
// Required for LIGHT_SLEEP_T delay mode
extern "C" {
#include "user_interface.h"
}

const char* ssid = "<your-ssid>";
const char* password = "<your-passwd>";

//The setup function is called once at startup of the sketch
void setup() {
  Serial1.begin(115200);
  while(!Serial1) { }

  Serial1.println();
  Serial1.println("Start device in normal mode!");

  WiFi.mode(WIFI_STA);

  WiFi.begin(ssid, password);
  Serial1.println("");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial1.print(".");
  }
  Serial1.println("");
  Serial1.print("Connected to ");
  Serial1.println(ssid);
  Serial1.print("IP address: ");
  Serial1.println(WiFi.localIP());
}
void callback() {
  Serial1.println("Callback");
  Serial.flush();
}
void loop() {
	  Serial1.println("Enter light sleep mode");

      // Here all the code to put con light sleep
      // the problem is that there is a bug on this
      // process
      //wifi_station_disconnect(); //not needed
      uint32_t sleep_time_in_ms = 10000;
      wifi_set_opmode(NULL_MODE);
      wifi_fpm_set_sleep_type(LIGHT_SLEEP_T);
      wifi_fpm_open();
      wifi_fpm_set_wakeup_cb(callback);
      wifi_fpm_do_sleep(sleep_time_in_ms *1000 );
      delay(sleep_time_in_ms + 1);

      Serial1.println("Exit light sleep mode");

      WiFi.begin(ssid, password);
      Serial1.println("");
    
      // Wait for connection
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial1.print(".");
      }
      Serial1.println("");
      Serial1.print("Connected to ");
      Serial1.println(ssid);
      Serial1.print("IP address: ");
      Serial1.println(WiFi.localIP());
      
      wifi_set_sleep_type(NONE_SLEEP_T);
      delay(10000);  //  Put the esp to sleep for 15s
}

Questo tipo di modalità di sospensione, come puoi vedere nel video, consente di ottenere 20 mA di consumo energetico dal dispositivo, per ottenere un migliore risparmio energetico è necessario impostare la sveglia tramite GPIO.

Light sleep e sveglia tramite GPIO

WeMos D1 mini on light sleep and debug on Serial1 check ampere
WeMos D1 mini on light sleep and debug on Serial1 check ampere

Light sleep può essere riattivato dall’interruzione GPIO, il comando da impostare è

gpio_pin_wakeup_enable(GPIO_ID_PIN(LIGHT_WAKE_PIN), GPIO_PIN_INTR_LOLEVEL);

È necessario impostare il tempo di sospensione massimo e impostare un delay per attivare il tutto.

	  wifi_fpm_do_sleep(FPM_SLEEP_MAX_TIME);
	  delay(1000);

Il codice completo può essere così

#include "Arduino.h"
#include <ESP8266WiFi.h>

#define	FPM_SLEEP_MAX_TIME			 0xFFFFFFF

// Required for LIGHT_SLEEP_T delay mode
extern "C" {
#include "user_interface.h"
}

const char* ssid = "<your-ssid>";
const char* password = "<your-passwd>";

//The setup function is called once at startup of the sketch
void setup() {
  Serial1.begin(115200);
  while(!Serial1) { }

  Serial1.println();
  Serial1.println("Start device in normal mode!");

  WiFi.mode(WIFI_STA);

  WiFi.begin(ssid, password);
  Serial1.println("");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial1.print(".");
  }
  Serial1.println("");
  Serial1.print("Connected to ");
  Serial1.println(ssid);
  Serial1.print("IP address: ");
  Serial1.println(WiFi.localIP());
}
void callback() {
  Serial1.println("Callback");
  Serial.flush();
}

#define LIGHT_WAKE_PIN D5

void loop() {
	  Serial1.println("Enter light sleep mode");

	  //wifi_station_disconnect(); //not needed
	  gpio_pin_wakeup_enable(GPIO_ID_PIN(LIGHT_WAKE_PIN), GPIO_PIN_INTR_LOLEVEL);
	  wifi_set_opmode(NULL_MODE);
	  wifi_fpm_set_sleep_type(LIGHT_SLEEP_T);
	  wifi_fpm_open();
	  wifi_fpm_set_wakeup_cb(callback);
	  wifi_fpm_do_sleep(FPM_SLEEP_MAX_TIME);
	  delay(1000);

  	  Serial1.println("Exit light sleep mode");

      WiFi.begin(ssid, password);
      Serial1.println("");

      // Wait for connection
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial1.print(".");
      }
      Serial1.println("");
      Serial1.print("Connected to ");
      Serial1.println(ssid);
      Serial1.print("IP address: ");
      Serial1.println(WiFi.localIP());

      wifi_set_sleep_type(NONE_SLEEP_T);
  	  delay(10000);  //  Put the esp to sleep for 15s
}

Il risultato sarà

Come puoi vedere nel video, il risparmio energetico è migliore (6mA) e si può usare l’interrupt su GPIO per ripristinare il dispositivo.

Deep sleep

La modalità più comune e più utilizzata è il deep-sleep, un’applicazione pratica è quella di inviare dati a un server ogni periodo di tempo predefinito.

  • È necessario mettere il dispositivo in modalità deep-sleep
  • impostare un timer per svegliarsi
  • sveglia
  • invia i dati
  • rimetti il dispositivo in sospensione

Tutti esp8266 (tranne esp01) hanno un pin con etichetta wake, e tramite questo pin collegato al RESET sarà possibile risvegliare il microcontrollore.

WeMos D1 mini esp8266 piedinatura bassa risoluzione
WeMos D1 mini esp8266 piedinatura bassa risoluzione

Puoi selezionare varie opzioni di sleep, controlla la tua scelta migliore.

system_deep_sleep_set_option(0) Il parametro il Byte 108 di init decide se la calibrazione RF verrà eseguita dopo che il chip si è svegliato dal deep-sleep.
system_deep_sleep_set_option(1)Il chip eseguirà la calibrazione RF dopo essersi svegliato dal deep-sleep. Il consumo energetico è elevato.
system_deep_sleep_set_option(2) Il chip non eseguirà la calibrazione RF dopo essersi svegliato dal deep-sleep. Il consumo energetico è basso.
system_deep_sleep_set_option(3) Il chip non si accende in RF dopo essersi svegliato dal deep-sleep. Il consumo di energia è il più basso (lo stesso del Modem-sleep).

Sul WeMos D1 mini, come puoi vedere, è il pin di wake è il D0.

ESP.deepsleep(0) // suspends the module until it is woken up by a spike on the RST pin
ESP.deepsleep(5 * 1000000) // wake up the module every 5 seconds
ESP.deepsleep(5000000, RF_DISABLED) // wakes up the module every 5 seconds without re-activating the WiFi modem

Per riattivare un microcontrollore è necessario mettere il PIN di ripristino a LOW.

È possibile utilizzare un Wake pin (D0) collegato al Reset per riattivare il WeMos dopo qualche tempo, oppure è possibile utilizzare un pulsante esterno (o altro) in pull UP ed al click metterlo in LOW.

Perciò dopo aver impostato l’esp8266 in modalità di sospensione profonda, ci sono 2 modi per riattivarlo:

  • Impostando un timer
  • con un pulsante che mette il pin di reset a LOW.
WeMos D1 mini deep sleep and debug on Serial1 check Ampere
WeMos D1 mini deep sleep and debug on Serial1 check Ampere
#include "Arduino.h"

//The setup function is called once at startup of the sketch
void setup() {
  Serial1.begin(115200);
  while(!Serial1) { }
  Serial1.println();
  Serial1.println("Start device in normal mode!");

  delay(5000);
  // Wait for serial to initialize.
  while(!Serial1) { }

  // Deep sleep mode for 10 seconds, the ESP8266 wakes up by itself when GPIO 16 (D0 in NodeMCU board) is connected to the RESET pin
  Serial1.println("I'm awake, but I'm going into deep sleep mode for 10 seconds");
  ESP.deepSleep(10e6);
}

void loop() {
}

La potenza che utilizza il dispositivo è simile al light-sleep con sveglia tramite GPIO (6mA).

Modalità automatica

Per impostazione predefinita, il dispositivo esp ha la modalità di sospensione automatica abilitata.
Se aggiungi il codice per la sospensione light o per la sospensione modem al momento della configurazione e non disabiliti la modalità automatica sarà abilitata la sospensione in automatico dopo 10 secondi di delay in questo modo:

#include "Arduino.h"
#include <ESP8266WiFi.h>
// Required for LIGHT_SLEEP_T delay mode
extern "C" {
#include "user_interface.h"
}

const char* ssid = "<your-ssid>";
const char* password = "<your-passwd>";

//The setup function is called once at startup of the sketch
void setup() {
  Serial1.begin(115200);
  while(!Serial1) { }

  Serial1.println();
  Serial1.println("Start device in normal mode!");

  WiFi.mode(WIFI_STA);

  wifi_fpm_set_sleep_type(LIGHT_SLEEP_T);

  WiFi.begin(ssid, password);
  Serial1.println("");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial1.print(".");
  }
  Serial1.println("");
  Serial1.print("Connected to ");
  Serial1.println(ssid);
  Serial1.print("IP address: ");
  Serial1.println(WiFi.localIP());
}
unsigned long interval = 30000;
unsigned long previousMillis = millis() + interval;

void loop() {
	  unsigned long currentMillis = millis();

	  if (currentMillis - previousMillis >= interval) {
		  Serial1.println("Enter delay");

		  delay(20000);

		  Serial1.println("Exit delay");

		  WiFi.begin(ssid, password);
		  Serial1.println("");

		  // Wait for connection
		  while (WiFi.status() != WL_CONNECTED) {
			delay(500);
			Serial1.print(".");
		  }
		  Serial1.println("");
		  Serial1.print("Connected to ");
		  Serial1.println(ssid);
		  Serial1.print("IP address: ");
		  Serial1.println(WiFi.localIP());
		  previousMillis = currentMillis;

	  }
}

il risultato è questo:

Quando esegui il comando delay per i primi 10 secondi non accade nulla, dopo questo tempo viene attivata automaticamente la modalità di sospensione.

  1. WeMos D1 mini (esp8266): caratteristiche e configurazione dell’Arduino IDE
  2. WeMos D1 mini (esp8266): SPIFFS Filesystem integrato
  3. WeMos D1 mini (esp8266): debug sulla seriale secondaria
  4. WeMos D1 mini (esp8266), i tre tipi di modalità di sospensione per gestire il risparmio energetico
  5. WeMos D1 mini (esp8266): FileSystem integrato LittleFS
  6. esp12 esp07 (esp8266): flash, piedinatura, spec e config dell’IDE Arduino
  1. Firmware and OTA update
  1. esp32 e esp8266: file system FAT su memoria SPI flash esterna
  2. i2c esp8266: how to, rete 5V, 3.3V, velocità e pin personalizzati

Spread the love

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *