Redémarrage en boucle NodeMCU

Bonjour,

Je souhaite réaliser un projet permettant de faire tourner un moteur selon 3 modes : A heures fixe, par la pression d’un bouton, et par le déclenchement depuis l’application Blynk.

Il se produit 2 situations :

  1. Lorsque le lancement du moteur se fait en mode automatique ou avec l’appui sur le bouton, la nodeMcu reboot en affichant ceci de la moniteur série :
Exception (0):
19:48:54.687 -> epc1=0x4000dce5 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000
19:48:54.687 -> 
19:48:54.687 -> >>>stack>>>
19:48:54.687 -> 
19:48:54.687 -> ctx: cont
19:48:54.687 -> sp: 3ffffde0 end: 3fffffc0 offset: 01a0
19:48:54.687 -> 3fffff80:  3fffdad0 3ffeea98 3ffeea40 40201304  
19:48:54.721 -> 3fffff90:  3fffdad0 00000000 3ffeed38 402022f1  
19:48:54.721 -> 3fffffa0:  3fffdad0 00000000 3ffeed38 40205f28  
19:48:54.721 -> 3fffffb0:  feefeffe feefeffe 3ffe852c 40100fc5  
19:48:54.721 -> <<<stack<<<
19:48:54.721 -> 
19:48:54.721 ->  ets Jan  8 2013,rst cause:2, boot mode:(3,6)
19:48:54.721 -> 
19:48:54.721 -> load 0x4010f000, len 1392, room 16 
19:48:54.755 -> tail 0
19:48:54.755 -> chksum 0xd0
19:48:54.755 -> csum 0xd0
19:48:54.755 -> v3d128e5c
19:48:54.755 -> ~ld

Ensuite, la carte redémarre normalement.

  1. Lorsque le lancement se fait depuis l’application Blynk, le message d’erreur est le même. Cependant, cette fois ci la carte redémarre en boucle, et la seule solution est d’appuyer sur le bouton RST.

J’ai lu sur divers forum qu’il fallait faire le lien avec “rst cause” qui dans ce cas vaut 2. Cependant je ne suis pas parvenu à solutionner mon problème.

Ci dessous le code complet :

#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <Wire.h>
#include "Adafruit_MCP23017.h"
#include <LiquidCrystal_I2C.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <Stepper.h>

char auth[] = "***********************"; //Authentification Blynk
char ssid[] = "*********";
char pass[] = "************";    

const int led_rouge = 0;
const int led_orange = 4;
const int led_verte = 16;

const int stepsPerRevolution = 32*64;  
int motorSpeed ;
int val_potar;
int nb_distribution; 
unsigned long temps_distrib_manuel;
unsigned long temps_distrib_wifi;
unsigned long temps_distrib_auto;
unsigned long temps;
String heure ;

// Initialisation LCD
LiquidCrystal_I2C lcd(0x3F, 16, 2);
Adafruit_MCP23017 mcp;

//Initialisation stepper (step,1N1,1N4,1N3,1N1) ou (step,1N1,1N3,1N2,1N4)
Stepper myStepper(stepsPerRevolution, 14,13,12,15);

//Initialisation serveur NTP
WiFiClient espClient;
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "fr.pool.ntp.org", 3600, 60000);

void setup()
{

  Serial.begin(115200);
  Blynk.begin(auth, ssid, pass); //Connexion au réseau wifi
  mcp.begin();
  
  lcd.begin(16,2);
  lcd.init();
  timeClient.begin();
  
  pinMode(led_rouge, OUTPUT);
  pinMode(led_orange, OUTPUT);
  pinMode(led_verte, OUTPUT);
  pinMode(2, INPUT_PULLUP);
  mcp.pinMode(6, INPUT_PULLUP);
  mcp.pinMode(5, INPUT_PULLUP);
  mcp.pinMode(4, INPUT_PULLUP);

  mcp.digitalWrite(7, LOW);
  
}

void loop()
{
  Blynk.run();
  serveur_NTP ();
  stepper();
  val_potar=1;
  
  if (digitalRead(led_orange)==HIGH){               //Si LED allumée
    distribution_wifi ();
  }

  boolean etat_BP1=digitalRead(2);
  if (etat_BP1==LOW){                    //Si BP enclenché 
    Serial.println("Bouton ON");
    distribution_manuelle ();
  }

  distribution_automatique ();
  
  affichage_lcd ();
 
  if (nb_distribution<5){                 //Allumer LED si nb_disrtibution restante inférieur à 5 
    digitalWrite(led_rouge,HIGH);
   } 
   
 /* boolean etat_BP2=mcp.digitalRead(6);   
  while (etat_BP2=HIGH){                 //Affichage du nombre de distribution restante si appui sur BP2
    lcd.clear();
    lcd.home();
    lcd.print("Il reste");
    lcd.setCursor(0,1);
    lcd.write(nb_distribution);
    lcd.write("portion(s) à distribuer");
      }
      
  boolean etat_BP3=mcp.digitalRead(5);
  if (etat_BP2=HIGH){    
    lcd.clear();
    lcd.home();
    lcd.print("Voulez-vous remplir le réservoir ?");
    lcd.setCursor(0,1);
    lcd.write();
    lcd.write("");    
    
   } */
    
  }


void distribution_wifi ()
{
  temps_distrib_wifi = millis();
  while (millis()-temps_distrib_wifi<10000){
    Serial.println("Lancement moteur wifi");
    myStepper.setSpeed(motorSpeed);
    myStepper.step(2048);
    digitalWrite(led_rouge, LOW);
    digitalWrite(led_verte,LOW);
    digitalWrite(led_orange, LOW);
    
  }
  nb_distribution=nb_distribution-1;
}

void distribution_manuelle ()
{
  temps_distrib_manuel = millis();
  while (millis()-temps_distrib_manuel<10000){
    Serial.println("Lancement moteur manuel");
    myStepper.setSpeed(motorSpeed);
    myStepper.step(2048);
    digitalWrite(led_rouge, LOW);
    digitalWrite(led_verte,LOW);
    digitalWrite(led_orange,LOW);
  }
  nb_distribution=nb_distribution-1;
}

void distribution_automatique ()
{
  temps_distrib_auto = millis();
  if(heure=="12:00:00" or heure=="19:50:00" or heure=="20:00:00" or heure=="12:00:01" or heure=="16:00:01" or heure=="20:00:01") {
    while (millis()-temps_distrib_auto<10000){
      Serial.println("Lancement moteur automatique");
      myStepper.setSpeed(motorSpeed);
      myStepper.step(2048);
      lcd.clear();
      lcd.home();
      lcd.print("Distribution en cours...");
      digitalWrite(led_rouge, LOW);
      digitalWrite(led_verte,LOW);
      digitalWrite(led_orange,LOW);
    }
  }  
nb_distribution=nb_distribution-1;
}

void affichage_lcd ()
{
  
}

void serveur_NTP ()
{
  lcd.clear();
  timeClient.update();
  timeClient.getFormattedTime();
  heure=timeClient.getFormattedTime();
  if (millis()- temps>950){
    Serial.println(timeClient.getFormattedTime());
    lcd.print(heure); 
    temps=millis();
 } 
} 

void stepper (){
  int sensorReading = analogRead(A0);
  int motorSpeed = map(sensorReading, 0, 1023, 0, 10);  
  if (val_potar !=motorSpeed){                              //Si modification de la valeur du potentiomètgre
   // Serial.print(motorSpeed);
    lcd.clear();
    lcd.home();
    lcd.print("Vitesse moteur :");
    lcd.print(motorSpeed);
    val_potar=motorSpeed;
}

  
}

Merci à vous !

Bonsoir

le démarrage du moteur crée très probablement une baisse de tension d'alimentation pour l'ESP8266

RST cause 2 est typique d'une sous alimentation temporaire (uand il ne s'agit pas d'un appui volontaire sur le bouton de reset)

Il faut séparer l'alimentation du moteur et celle de la carte NodeMCU et faire en sorte que le pic de courant dans le moteur au démarrage ne produise pas de 'creux de tension' sur le 5V de la carte NodeMCU

Pour éviter d'avoir à 'tirer les vers du nez' des demandeurs d'aide il est demandé sur ce forum de décrire le montage , alimentation comprise

Bonjour,

Merci pour ce retour. Pour l’instant le moteur n’est pas branché, je réalise simplement les tests avec un bouton et le NodeMCU sur une breadboard.

Mais je vous place en PJ le schéma du montage que je compte réaliser.

al1fch:
Bonsoir

le démarrage du moteur crée très probablement une baisse de tension d'alimentation pour l'ESP8266

RST cause 2 est typique d'une sous alimentation temporaire (uand il ne s'agit pas d'un appui volontaire sur le bouton de reset)

Il faut séparer l'alimentation du moteur et celle de la carte NodeMCU et faire en sorte que le pic de courant dans le moteur au démarrage ne produise pas de 'creux de tension' sur le 5V de la carte NodeMCU

Pour éviter d'avoir à 'tirer les vers du nez' des demandeurs d'aide il est demandé sur ce forum de décrire le montage , alimentation comprise

Sur mon projet que je fais, j'ai ce type 2 quand une mise à jour OTA est fini et que ça reboot la carte, le type 2 c'est forcément dû à un problème d'alimentation ?

Non , 2 c'est un redémarrage par Reset, que ce soit un reset voulu ,ou un reset involontaire par baisse de tension sur l'alimentation .. et par conséquent sur l'entrée reset qui lui est reliée

(L'ESP8266 ne dispose pas de surveillance de la tension d'alimentation, de détecteur de 'creux de tension', une tension insuffisante se manifeste par un Reset)

Mais je vous place en PJ le schéma du montage que je compte réaliser.


je ne suis pas à l'aise avec ce genre de dessin ( sorte de plan de câblage à la mode semble-t-il ) fait avec Frtizing mais uniquement avec les schémas au sens où l'entend un électronicien c'est à dire un dessin ou les composants sont représentés par des symboles normalisés et non par leur aspect physique.
D'autres içi sauront peut être en tirer quelque chose.....pour ma part quand je vois ce genre de d'image sur le forum je passe mon chemin.. c'est pas pour moi....

al1fch:
Non , 2 c'est un redémarrage par Reset, que ce soit un reset voulu ,ou un reset involontaire par baisse de tension sur l'alimentation .. et par conséquent sur l'entrée reset qui lui est reliée

(L'ESP8266 ne dispose pas de surveillance de la tension d'alimentation, de détecteur de 'creux de tension', une tension insuffisante se manifeste par un Reset)

Ah je me disais bien que j'avais pas vu ceci dans les docs :slight_smile: Merci ! :wink:

J'aurai aimé vous proposer un schéma d'électronicien, mais malheureusement je n'en suis pas un... et comme les schémas Fritzing sont facilement compréhensibles par des non-initiés, j'imaginais, visiblement à tord, qu'ils le seraient tout autant pour des personnes plus aguerries !

Quoiqu'il en soit, le redémarrage a lieu sans même que je ne réalise aucun branchement, donc a priori, il ne devrait y avoir aucune chute de tension sur la carte. Le RST cause 2 pourrait-il venir d'ailleurs ?

Bonjour

while (millis()-temps_distrib_wifi<10000){

et en diminuant le 10000 à 1000 ou moins dans LES boucles while du même tonneau ?

Cordialement,
bidouilleelec

Les boucles while de 10s doivent bloquer le retour dans l'OS sous jacent qui gère la pile WiFi. Le reset est sans doute déclenché par le watchdog.
Il faudrait mettre une appel à yield() dans chacune des boucles while pour éviter ce problème.
A noter, une erreur sur while (etat_BP2=HIGH) qui gère l'affichage si tu la réactives il faudra écrire while (etat_BP2==HIGH) et cela va créer une nouvelle boucle "longue" il faudra aussi y mettre un yield().

gugutz_96:
J'aurai aimé vous proposer un schéma d'électronicien, mais malheureusement je n'en suis pas un...

Fritzing permet de générer un schéma électrique. Il faut néanmoins le retravailler un peu pour le rendre lisible.

fdufnews:
.....
A noter, une erreur sur while (etat_BP2=HIGH) qui gère l'affichage si tu la réactives il faudra écrire while (etat_BP2==HIGH) et cela va créer une nouvelle boucle "longue" il faudra aussi y mettre un yield().

De plus

  boolean etat_BP3=mcp.digitalRead(5);
  if (etat_BP2=HIGH){

C'est bien etat_BP2 ?

Cordialement,
bidouilleelec

Bonsoir,

Merci à vous pour vos conseils précieux ! J'en prend bonne note et j'ai corrigé l'erreur de variable dans la gestion de l'affichage.

Alors j'ai modifié la valeur 10000 dans la boucle while et ajouté des yield () dans mes boucles while. Je suis d'abord descendu à 3000 pour passer en dessous du délais du watchdog hardware (qui est aux alentours de 3,5s il me semble) et ça fonctionne nickel, plus aucun reboot. Par curiosité j'ai encore augmenté un peu la valeur pour voir jusqu'où je pouvais aller, et jusqu'à 8000, aucun reboot. Par contre au delà, le système reboot mais une seule fois. J'avoue ne pas bien comprendre ce qu'il se passe...

Un grand merci à vous pour votre aide !