Blocage au réveil ESP8266 NodeMCU

Bonjour,
J'ai un NodeMCU V3 ESP8266 avec lequel je souhaite utiliser le mode de sommeil profond. Mais la carte à un comportement étrange. J'en ai essayé une autre ... comportement identique. J'ai donc écrit un programme très simple pour reproduire le problème.

void setup() {
  Serial.begin(74880);
  Serial.setTimeout(2000);
  while(!Serial) { }

  Serial.println("Started");
  ESP.deepSleep( 15 * 1000000 );
}

void loop() {
}

Comme vous le voyez, le code est très simple : il doit simplement afficher "Started" au réveil puis se rendormir 15 secondes. (la pin D0 est reliée à la pin RST)
La vitesse de 74880 est choisie pour éviter d'afficher des hiéroglyphes au début de l'init et permet d'afficher en clair ce qu'envoie le module avant le setup.

Résultat affiché dans la console =>

12:38:12.716 -> 
12:38:12.716 ->  ets Jan  8 2013,rst cause:2, boot mode:(3,6)
12:38:12.716 -> 
12:38:12.716 -> load 0x4010f000, len 3460, room 16 
12:38:12.716 -> tail 4
12:38:12.716 -> chksum 0xcc
12:38:12.716 -> load 0x3fff20b8, len 40, room 4 
12:38:12.716 -> tail 4
12:38:12.716 -> chksum 0xc9
12:38:12.716 -> csum 0xc9
12:38:12.716 -> v00041c20
12:38:12.716 -> ~ld
12:38:12.810 -> Started

puis 15 secondes plus tard =>

12:38:27.499 -> 
12:38:27.499 ->  ets Jan  8 2013,rst cause:2, boot mode:(3,6)
12:38:27.499 -> 

Puis ensuite plus rien.

Le reset manuel provoque exactement le même phénomène. Au premier reset manuel on a l'affichage correct, puis au second reset on a juste la ligne ets....boot mode:(3,6). Et si on refait ensuite un reset on a de nouveau l'affichage correct et ainsi de suite.

Si j'enlève la ligne ESP.deepSleep, l'affichage se fait correctement à chaque reset manuel.

Pour info, voici la configuration de programmation dans l'IDE Arduino =>
*Type de carte: "NodeMCU 1.0 (ESP-12E Module)" *
Builtin Led: "2"
Upload Speed: "115200"
CPU Frequency: "80 MHz"
Flash Size: "4M B (FS:2MB OTA:-1019KB)''
Debug port: "Disabled"
Debug Level: "WIFI"
IwIP Variant: "v2 Lover Memory"
VTables: "Flash"
*C++ Exceptions: "Disabled (new aborts on oom)" *
Stack Protection: "Disabled"
Erase Flash: "Only Sketch"
*SSL Support: "All SSL ciphers (most compatible)" *
MMU: "32KB cache + 32KB IRAM (balanced)"
Non-32-Bit Access: "Use pgm_read macros for IRAM/PROGMEM"

Avez-vous une idée de la façon de résoudre ce problème ?

:warning:
Post mis dans la mauvaise section, on parle anglais dans les forums généraux. déplacé vers le forum francophone.

Merci de prendre en compte les recommandations listées dans Les bonnes pratiques du Forum Francophone

rajoutez juste pour voir un petit delay

void setup() {
  Serial.begin(74880);
  while(!Serial) yield();
  Serial.setTimeout(2000);
  delay(250); // à tester 
  Serial.println("Started");
  ESP.deepSleep( 15 * 1000000ul );
}

void loop() {}

Bonjour JML,
Cette modif ne change rien ...

Chose également étrange ... peut-être en rapport avec le problème : Je dois toujours m'y prendre à deux fois pour réussir à charger le code. La première fois j'ai ceci qui s'affiche :

esptool.py v3.0
Serial port COM9
Connecting....
Chip is ESP8266EX
Features: WiFi
Crystal is 26MHz
MAC: bc:dd:c2:9d:2d:3e
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Traceback (most recent call last):
  File "C:\Users\jnles\Documents\ArduinoData\packages\esp8266\hardware\esp8266\3.0.2/tools/upload.py", line 66, in <module>
    esptool.main(cmdline)
  File "C:/Users/jnles/Documents/ArduinoData/packages/esp8266/hardware/esp8266/3.0.2/tools/esptool\esptool.py", line 3599, in main
    detect_flash_size(esp, args)
  File "C:/Users/jnles/Documents/ArduinoData/packages/esp8266/hardware/esp8266/3.0.2/tools/esptool\esptool.py", line 2848, in detect_flash_size
    flash_id = esp.flash_id()
  File "C:/Users/jnles/Documents/ArduinoData/packages/esp8266/hardware/esp8266/3.0.2/tools/esptool\esptool.py", line 688, in flash_id
    return self.run_spiflash_command(SPIFLASH_RDID, b"", 24)
  File "C:/Users/jnles/Documents/ArduinoData/packages/esp8266/hardware/esp8266/3.0.2/tools/esptool\esptool.py", line 948, in run_spiflash_command
    old_spi_usr = self.read_reg(SPI_USR_REG)
  File "C:/Users/jnles/Documents/ArduinoData/packages/esp8266/hardware/esp8266/3.0.2/tools/esptool\esptool.py", line 562, in read_reg
    val, data = self.command(self.ESP_READ_REG, struct.pack('<I', addr))
  File "C:/Users/jnles/Documents/ArduinoData/packages/esp8266/hardware/esp8266/3.0.2/tools/esptool\esptool.py", line 386, in command
    p = self.read()
  File "C:/Users/jnles/Documents/ArduinoData/packages/esp8266/hardware/esp8266/3.0.2/tools/esptool\esptool.py", line 331, in read
    return next(self._slip_reader)
  File "C:/Users/jnles/Documents/ArduinoData/packages/esp8266/hardware/esp8266/3.0.2/tools/esptool\esptool.py", line 2636, in slip_reader
    raise FatalError("Timed out waiting for packet %s" % waiting_for)
esptool.FatalError: Timed out waiting for packet header
esptool.FatalError: Timed out waiting for packet header

et la seconde fois :

esptool.py v3.0
Serial port COM9
Connecting....
Chip is ESP8266EX
Features: WiFi
Crystal is 26MHz
MAC: bc:dd:c2:9d:2d:3e
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Auto-detected Flash size: 4MB
Compressed 269360 bytes to 197740...
Writing at 0x00000000... (7 %)
Writing at 0x00004000... (15 %)
Writing at 0x00008000... (23 %)
Writing at 0x0000c000... (30 %)
Writing at 0x00010000... (38 %)
Writing at 0x00014000... (46 %)
Writing at 0x00018000... (53 %)
Writing at 0x0001c000... (61 %)
Writing at 0x00020000... (69 %)
Writing at 0x00024000... (76 %)
Writing at 0x00028000... (84 %)
Writing at 0x0002c000... (92 %)
Writing at 0x00030000... (100 %)
Wrote 269360 bytes (197740 compressed) at 0x00000000 in 17.4 seconds (effective 124.0 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...

peut être la première tentative plante à cause du sleep

essayez avec un delay de 2s juste pour voir

Même chose, ça ne change rien.
J'ai même ajouté un delay(2000) en tout début de setup ... pour voir.

Mais je dois m'absenter ... je continuerai les recherches plus tard.
Mais n'hésitez pas à soumettre vos idées ! :wink:

essayez avec un terminal série autre que celui de l'IDE (PuTTY, CoolTerm, ...)

L'ESP8266 ne partirait pas en deepsleep avant d'avoir eu le temps de sortir le contenu du print
Voir l'exemple officiel TimerWakeUp

bon point. un flush serait pas mal en effet

Merci pour vos suggestions.
Hélas ... ça ne change rien.
J'ai essayé le code suivant :

void setup() {  
  delay(1000);
  Serial.flush();
  Serial.begin(74880);
  Serial.setTimeout(2000);
  while(!Serial){};
  delay(1000);
  Serial.println("Started");
  delay(1000);
  ESP.deepSleep( 0 );
}

void loop() {
}

J'ai mis un deepSleep(0) et utilise le bouton reset manuellement.
J'ai aussi essayé de déplacer le flush avant le deepSleep, mais ça ne change rien.
J'ai aussi utilisé Putty à la place de la console de l'IDE Arduino : le comportement est identique.

Ce qui est étrange c'est que ça fonctionne un coup sur deux. Idem pour le téléchargement. J'ai même pu observer ceci :
Si l'exécution se passe mal alors le téléchargement passe du premier coup.
Si l'exécution va jusqu'au bout, alors le téléchargement plante.

Autre observation :
Après un téléchargement OK, la console affiche uniquement "started".
Si j'appuis sur le bouton RST, alors la console affiche uniquement la ligne " ets Jan 8 2013,rst cause:2, boot mode:(3,6)"
Si j'appuis de nouveau sur le bouton RST, alors la console affiche

 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 3584, room 16 
tail 0
chksum 0xb0
csum 0xb0
v2843a5ac
~ld
Started

(Le "Started s'affiche bien une seconde après le reste).

Vraiment étrange, n'est-ce pas ?

Tu peux essayer ça si tu veux.

unsigned long previousMillis = 0;
const long interval = 5000;
void setup() {
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.println();
  Serial.println("bonjour");
  Serial.println(millis());
}
void loop() {
  unsigned long currentMillis = millis();
   if (currentMillis - previousMillis >= interval) { //éveil>=5 sec?
    previousMillis = currentMillis;
    Serial.println("bonne nuit");
    ESP.deepSleep(3e6);         //deepSleep 3 sec  
  }
  digitalWrite(LED_BUILTIN, HIGH);
  delay(100);
  digitalWrite(LED_BUILTIN, LOW);
  delay(100);
}

Merci ZX80 pour la suggestion. Hélas ... même phénomène :
voici ce qui s'affiche à la console :

xxxxxxx (des hiéroglyphes) xxxxx
bonjour
62
bonne nuit
xxxxxxx (des hiéroglyphes) xxxxx

Les hiéroglyphes sont normaux puisqu'on est à 115200 baud et non à 74880. C'est ce qui est envoyé par la carte avant le Serial.begin().
La première exécution est bonne : La console affiche bonjour et 62, la led clignote 5 secondes, puis la console affiche "bonne nuit". 3 secondes plus tard la console affiche la ligne de hiéroglyphes (plus courte que la première) puis plus rien et les leds ne clignotent plus.

Je pense que c'est le ESP.deepSleep() qui met la carte dans un état tel que le réveil se passe mal.

Je viens de tomber sur cette page :
https://github.com/esp8266/Arduino/issues/6007

C'est exactement le problème que j'ai et la solution semble ... hardware !
Il est vrai que mes cartes NodeMCU V3 ont maintenant quelques années.
Dans cette discussion il est suggéré de placer des pullup ou pulldown sur certaines broches : j'essaierai plus tard.

À explorer…

Bonjour,
La piste était la bonne : J'ai résolu mon problème qui était bien hardware !
Une résistance de pullup (donc entre le 3v et la pin) de 47k ou 10k (les deux fonctionnent) sur la pin S0 (MISO) corrige le problème, aussi bien au moment du chargement du script qu'au réveil, qu'il soit manuel ou automatique. J'ai fait le test sur mes 2 cartes.
En tous les cas merci à vous pour vos suggestions : on se sent moins seul à creuser :sweat_smile:
Bonne journée !

1 Like

Bravo !

Bonjour Lesjno, j'ai le même problème de non réveil après deepsleep de mon ESP8266 nodecmu, je voudrais savoir comment mettre en œuvre votre solution, doit on après avoir placé une resistance entre le 3v3 et la pin SD0, mettre aussi un pont entre le RST et la pin D0 ? merci pour votre réponse, cordialement Philippe

Bonjour Philippe,
Oui, bien sur ! Si vous ne reliez pas D0 à RST jamais il ne se réveillera :wink:
La résistance c'est seulement pour palier un défaut hardware de la carte.
Attention : la résistance est à mettre sur la pin S0 (sur les schémas elle figure aussi en tant que "MISO" ou "SDD0"). Ne la mettez pas sur D0 ! :grinning:
Cordialement

Merci beaucoup pour votre réponse Lesjno je vais tester çà , bon dimanche, cordialement Philippe