Post

esp8266-mode-DeepSleep

esp8266-mode-DeepSleep

esp8266-mode-DeepSleep

Le mode DeepSleep

http://destroyedlolo.info/ESP/

Le DeepSleep place l’ESP8266 dans un mode de très basse consommation énergétique dont il ne sortira que par un reset …
Ce dernier peut être déclenché automatiquement lorsque la durée programmée dans le “RTC” sera échue en reliant les broches XPD_DCDC (aussi nommée IO16) et RST.

Pour placer l’ESP dans ce mode, il faut appeler la fonction

1
ESP.deepSleep()

dont l’argument est le nombre de micro-secondes à attendre (10e-6 secondes).

Le croquis TestPower.ino démontre l’utilisation des différents modes d’éconnomie de l’ESP.

1
2
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/* Test de consomation
 *  
 *  Envoie toutes les DELAI secondes la tension d'alimentation par MQTT.
 *  Le but est de tester les différentes méthodes d'économies d'energie.
 *  
 *  Ecoutez le résultat par 
 *  	mosquitto_sub -v -h bpi.chez.moi -t 'TestESP/#'
 *  
 *  Par "Destroyedlolo", mis dans le Domaine Publique.
 *  
 *  It's in french as linked with tutorials on my website
 *  http://destroyedlolo.info/ESP/
 */

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

extern "C" {
  #include "user_interface.h"
}

	/****
	 * Parametrages
	 ****/

		/* Quel mode allons-nous tester ? */
#define MODE_AUCUN	0				// Fonctionnement sans optimisations
#define MODE_LIGHT_SLEEP 1	// Light Sleep
#define MODE_DEEP_SLEEP	 2	// Deep sleep (les broches RST et D0 doivent être connectées)

#define MODE MODE_DEEP_SLEEP

#define SAVEWIFI	// essaie d'utiliser la sauvegarde faite dans la Flash de l'ESP.
#define LED				// Allume la LED lors de la recherche du réseau et du MQTT
#define AUTORECONNECT	// N'appelle pas explicitement WiFi.begin() : utilise l'auto-reconnection

#define MQTT_CLIENT "TestESP"
String MQTT_Topic("TestESP/");	// Racine des messages envoyés
#define DELAI 60	// Delai en secondes entre chaque boucle

	/****
	 * Paramêtres maison
	 ****/
#include "Maison.h"			// Paramètres de mon réseau (WIFI_*, MQTT_*, ...)
#define LED_BUILTIN 2		// La LED est sur le GPIO2 sur mon NodeMCU v0.1

	/* IP static pour éviter d'attendre le DHCP */
IPAddress adr_ip(192, 168, 0, 17);
IPAddress adr_gateway(192, 168, 0, 10);
IPAddress adr_dns(192, 168, 0, 3);

	/****
	 * Réseau
	 ****/

WiFiClient clientWiFi;
PubSubClient clientMQTT(clientWiFi);

unsigned long dwifi;	// Combien de temps à duré l'initialisation du Wifi

unsigned long connexion_WiFi(){
	unsigned long debut, fin;

#	ifdef LED
		digitalWrite(LED_BUILTIN, LOW);
#	endif

	Serial.println("Connexion WiFi");
	debut = millis();

#ifdef SAVEWIFI
		/* Les infos de la connexion sont écrites à chaque fois dans la Flash :
		 * on essaie dans un premier temps de les réutiliser avant d'en imposer des nouvelles. 
		 */
#	ifndef AUTORECONNECT
	WiFi.begin();
#	endif

	for( int i=0; i< 120; i++ ){	// On essaie de se connecter pendant 1 minute
		if(WiFi.status() == WL_CONNECTED)
			break;
		delay(500);
		Serial.print("-");
	}

	if(WiFi.status() != WL_CONNECTED){	// La connexion a échoué, on force les settings
		WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
		while(WiFi.status() != WL_CONNECTED){
			delay(500);
			Serial.print(".");
		}
	}
#else
	WiFi.persistent( false );	// Supprime la sauvegarde des info WiFi en Flash

	WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
	while(WiFi.status() != WL_CONNECTED){
		delay(500);
		Serial.print(".");
	}
#endif

	fin = millis();

	Serial.println("ok");
	WiFi.printDiag( Serial );
	Serial.print("AutoConnect : ");
	Serial.println(WiFi.getAutoConnect() ? "Oui" : "Non");

#	ifdef LED
		digitalWrite(LED_BUILTIN, HIGH);
#	endif
	return fin - debut;
}

void Connexion_MQTT(){
#	ifdef LED
		digitalWrite(LED_BUILTIN, LOW);
#	endif

	Serial.println("Connexion MQTT");
	while(!clientMQTT.connected()){
		if(clientMQTT.connect(MQTT_CLIENT)){
			Serial.println("connecté");
			break;
		} else {
			Serial.print("Echec, rc:");
			Serial.println(clientMQTT.state());
			delay(1000);	// Test dans 1 seconde
		}
	}

#	ifdef LED
		digitalWrite(LED_BUILTIN, HIGH);
#	endif
}


	/***
	 * C'est parti
	 ***/

ADC_MODE(ADC_VCC);	// Nécessaire pour avoir la tension d'alimentation

void setup(){
#	ifdef LED
		pinMode(LED_BUILTIN, OUTPUT);
#	endif

		/* Console */
	Serial.begin(115200);
	delay(10);	// Le temps que ça se stabilise

		/* Configuration réseau */
	WiFi.config(adr_ip, adr_gateway, adr_dns);
#	if MODE == MODE_LIGHT_SLEEP
		wifi_set_sleep_type(LIGHT_SLEEP_T);
#	else
		wifi_set_sleep_type(MODEM_SLEEP_T);
#	endif
//	WiFi.mode(WIFI_STA);
	dwifi = connexion_WiFi();
	clientMQTT.setServer(BROKER_HOST, BROKER_PORT);
}

void loop() {
	int debut, fin;
	if(!clientMQTT.connected()){
		debut = millis();
		Connexion_MQTT();
		fin = millis();

		Serial.print("La reconnexion a durée ");
		Serial.print( fin - debut );
		Serial.println(" milli-secondes");
		if(dwifi){
			clientMQTT.publish( (MQTT_Topic + "Wifi").c_str(), String( dwifi ).c_str() );
			dwifi = 0;
		}
		clientMQTT.publish( (MQTT_Topic + "reconnect").c_str(), String( fin - debut ).c_str() );
	}

	Serial.print("Alimentation : ");
	Serial.println(ESP.getVcc());
	debut = millis();
	clientMQTT.publish( (MQTT_Topic + "Alim").c_str(), String( ESP.getVcc() ).c_str() );
	fin = millis();
	Serial.print("Durée de l'envoi : ");
	Serial.print( fin - debut );
	Serial.println(" ms");
	clientMQTT.publish( (MQTT_Topic + "Alim/duree").c_str(), String( fin - debut ).c_str() );

		/* En dessous d'une 20e de secondes, cette ligne permet
		 *  de conserver la connexion avec le broker.
		 *  Au delà, delà, la connexion est systématiquement réinitialisée
		 * Permet aussi de prendre en charge les messages entrant.
		 */
	clientMQTT.loop();

#if MODE == MODE_DEEP_SLEEP
	ESP.deepSleep(DELAI * 1e6);	// Attention, l'unité est la µs
#else	// Autres modes basés uniquement sur delay()
	delay( DELAI * 1e3 );
#endif
}

Qui dit Reset, dit que toutes les variables seront perdues au réveil.
Heureusement, une petite mémoire de 512 octets est conservée avec le RTC : elle est accessibles par les fonctions

1
bool rtcUserMemoryWrite(uint32_t offset, uint32_t *data, size_t size);

et

1
bool rtcUserMemoryRead(uint32_t offset, uint32_t *data, size_t size);

Un exemple avec la classe Context de la domotique.

Il en va de même pour les configurations hardware, le programme redémarrera par la fonction

1
setup()

comme lors de la mise sous tension.

Cet article est sous licence CC BY 4.0 par l'auteur.