ESP32 reboot tout le temps

Bonjour je cherche à créer des signaux avec l esp32 (code ci dessous). Le problème est que l esp32 reboote tout le temps. J’ai mis les mssages que j’obtiens. Qui peut m’orienter sur la bonne piste? Je souhaite envoyer des signaux sans discontinuité. J’ai urilisé le timer0 de l’esp32 pour diminuer la fréquence. Merci pour votre aide.

/* Copyright (c) 2017 pcbreflux. All Rights Reserved.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
 * 
 */
hw_timer_t * timer0 = NULL;
//hw_timer_t * timer1 = NULL;
portMUX_TYPE timerMux0 = portMUX_INITIALIZER_UNLOCKED;
//portMUX_TYPE timerMux1 = portMUX_INITIALIZER_UNLOCKED;

volatile uint8_t led1stat = 0; 
volatile uint8_t led2stat = 0;


volatile int interruptCounter;
int totalInterruptCounter;
int ValueBit = 1; // valeur pour tester, remettre a 1 pour 58ms et 116ms


byte AdresseLoco, Commande, Controle;

byte Loco = 10;// locomotive 3
byte Direction=0; // en avant pour le test
int Vitesse = 10;




void IRAM_ATTR onTimer0(){
  // Critical Code here
  portENTER_CRITICAL_ISR(&timerMux0);
  
PREAMBULE();
OctetUN();
OctetDeux();
OctetTrois();

portEXIT_CRITICAL_ISR(&timerMux0);
}

//void IRAM_ATTR onTimer1(){
  // Critical Code here
  //portENTER_CRITICAL_ISR(&timerMux1);
  //led2stat=1-led2stat;
 // digitalWrite(20, led2stat);   // turn the LED on or off
 // portEXIT_CRITICAL_ISR(&timerMux1);
//}

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

  pinMode(19, OUTPUT);
  pinMode(21, OUTPUT);
  
  digitalWrite(19, LOW);    // turn the LED off by making the voltage LOW
  digitalWrite(21, LOW);    // turn the LED off by making the voltage LOW


 // Serial.println("start timer 1");
 // timer1 = timerBegin(1, 80, true);  // timer 1, MWDT clock period = 12.5 ns * TIMGn_Tx_WDT_CLK_PRESCALE -> 12.5 ns * 2320 -> 29000 ns = 29 us, countUp
 // timerAttachInterrupt(timer1, &onTimer1, true); // edge (not level) triggered 
  //timerAlarmWrite(timer1, ValueBit, true); // 1 * 29 us = 29 us, autoreload true

  Serial.println("start timer 0");
  timer0 = timerBegin(0, 580, true);  // timer 0, MWDT clock period = 12.5 ns * TIMGn_Tx_WDT_CLK_PRESCALE -> 12.5 ns * 80 -> 1000 ns = 1 us, countUp
  timerAttachInterrupt(timer0, &onTimer0, true); // edge (not level) triggered 
  timerAlarmWrite(timer0, 1, true); // 2000000 * 1 us = 2 s, autoreload true

  // at least enable the timer alarms
  timerAlarmEnable(timer0); // enable
 // timerAlarmEnable(timer1); // enable
}

void loop() {
  // nope nothing here
  vTaskDelay(portMAX_DELAY); // wait as much as posible ...
    

}


void BitZero() {
digitalWrite(19,LOW);
digitalWrite(21,HIGH);
delayMicroseconds(ValueBit * 116);
digitalWrite(19,HIGH);
digitalWrite(21,LOW);
delayMicroseconds(ValueBit*116);
}
void BitUn() {
digitalWrite(19,LOW);
digitalWrite(21,HIGH);
delayMicroseconds(ValueBit*58);
digitalWrite(19,HIGH);
digitalWrite(21,LOW);
delayMicroseconds(ValueBit*58);
}

void PREAMBULE()
{
BitUn(),BitUn(),BitUn(),BitUn(),BitUn(),BitUn(),BitUn(),BitUn(),BitUn(),BitUn(),BitUn(),BitUn(),BitUn(),BitUn(),BitUn(),BitUn(),BitUn(),BitUn(),BitUn(),BitUn(),BitZero(); //20 BITS UN
}

void OctetUN() { // octect d'adressage
//byte AdresseLoco;
AdresseLoco=bitWrite(Loco,7,0);

for (int ii = 0; ii < 8; ii++) {
if (AdresseLoco & (B10000000 >> ii)) {
//BitUn(); 
Serial.print(1);
}
else {
//BitZero(); 
Serial.print(0);

}
}
Serial.print("\t");
//BitZero(); 
Serial.print(0);

}

void OctetDeux(){ //octet de direction et de vitesse
//byte Commande;
int CommandeVitesse;
if (Direction = 1) {
Commande = B01100000;
}
else {
Commande = B01000000;
}
CommandeVitesse=Vitesse+3;
static boolean VitesseOctetC=bitRead(CommandeVitesse,0);
Commande=bitWrite(Commande,5,VitesseOctetC);
static boolean VitesseOctetZERO=bitRead(CommandeVitesse,1);
Commande=bitWrite(Commande,0,VitesseOctetZERO);
static boolean VitesseOctetUN=bitRead(CommandeVitesse,2);
Commande=bitWrite(Commande,1,VitesseOctetUN);
static boolean VitesseOctetDEUX=bitRead(CommandeVitesse,3);
Commande=bitWrite(Commande,2,VitesseOctetDEUX);
static boolean VitesseOctetTROIS=bitRead(CommandeVitesse,4);
Commande=bitWrite(Commande,3,VitesseOctetTROIS);
static boolean VitesseOctetQUATRE=bitRead(CommandeVitesse,5);
Commande=bitWrite(Commande,4,VitesseOctetTROIS);
//Serial.print("\t");
for (int ii = 0; ii < 8; ii++) {
if (Commande & (B10000000 >> ii)) {
//BitUn(); 
Serial.print(1);
}
else {
//BitZero(); 
Serial.print(0);

}
}
Serial.print("\t");
//BitZero();
Serial.print(0);
}

void OctetTrois(){
byte Controle;
Controle = AdresseLoco ^ Commande;
//Serial.print("\t");
for (int ii = 0; ii < 8; ii++) {
if (Controle & (B10000000 >> ii)) {
//BitUn();
Serial.print(1);
}
else {
//BitZero();
Serial.print(0);

}
}
Serial.print("\t");
//BitZero();
Serial.println(0);
}

void vide() {
  PREAMBULE(),BitUn(),BitUn(),BitUn(),BitUn(),BitUn(),BitUn(),BitUn(),BitUn(),BitZero(),BitZero(),BitZero(),BitZero(),BitZero(),BitZero(),BitZero(),BitZero(),BitZero(),BitZero(),BitUn(),BitUn(),BitUn(),BitUn(),BitUn(),BitUn(),BitUn(),BitUn(), BitUn();
}

J’obtiens ce type de message:
Rebooting…
ets Jun 8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:9720
ho 0 tail 12 room 4
load:0x40080400,len:6352
entry 0x400806b8
start timer 0
00001010 001100110 001101100 0
0 001100110 001101100 0
000
00001010 001100110 001101100 0
Guru Meditation Error: Core 1 panic’ed (Interrupt wdt timeout on CPU1)
Core 1 register dump:
PC : 0x4008166a PS : 0x00060c34 A0 : 0x80082166 A1 : 0x3ffbe6d0
A2 : 0x01af7972 A3 : 0x00000000 A4 : 0x40081240 A5 : 0x3ffbe7d0
A6 : 0x000000ff A7 : 0x3ffbe890 A8 : 0x00000000 A9 : 0x00000000
A10 : 0x00000000 A11 : 0x00000001 A12 : 0x00000050 A13 : 0x4008a520
A14 : 0x00000000 A15 : 0x00000000 SAR : 0x0000000b EXCCAUSE: 0x00000006
EXCVADDR: 0x00000000 LBEG : 0x400014fd LEND : 0x4000150d LCOUNT : 0xffffffff
Core 1 was running in ISR context:
EPC1 : 0x40081517 EPC2 : 0x00000000 EPC3 : 0x00000000 EPC4 : 0x4008166a

Backtrace: 0x4008166a:0x3ffbe6d0 0x40082163:0x3ffbe6f0 0x40081143:0x3ffbe710 0x40081183:0x3ffbe730 0x400d0d0a:0x3ffbe750 0x400d0d47:0x3ffbe770 0x40080e80:0x3ffbe790 0x40081235:0x3ffbe7b0 0x40084699:0x3ffbe7d0 0x4008123d:0x3ffb1f80 0x400d1abb:0x3ffb1fb0 0x400882c1:0x3ffb1fd0

Core 0 register dump:
PC : 0x400e988a PS : 0x00060134 A0 : 0x800d4486 A1 : 0x3ffbbff0
A2 : 0x00000000 A3 : 0x00000001 A4 : 0x00000000 A5 : 0x00000001
A6 : 0x00060120 A7 : 0x00000000 A8 : 0x800d404e A9 : 0x3ffbbfc0
A10 : 0x00000000 A11 : 0x40084e24 A12 : 0x00060120 A13 : 0x00000020
A14 : 0x00000020 A15 : 0x00000000 SAR : 0x00000000 EXCCAUSE: 0x00000006
EXCVADDR: 0x00000000 LBEG : 0x00000000 LEND : 0x00000000 LCOUNT : 0x00000000

Backtrace: 0x400e988a:0x3ffbbff0 0x400d4483:0x3ffbc010 0x400897b2:0x3ffbc030 0x400882c1:0x3ffbc050

Bonjour

Guru Meditation Error: Core  1 panic'ed (Interrupt wdt timeout on CPU1)

panique sur le coeur n°1, le chien de garde se réveille car il n'a pas été servi à temps
de mémoire le coeur n°1 est celui qui, par défaut, exécute le code établi avec l'IDE Arduino , l'autre coeur s'occupant par exemple de la pile WiFi s'il y a lieu.

Il est possible d'obtenir des informations détaillées sur l'état des fonctions au moment de l'incident.
Installer pour cela le décodeur d'exception et lui fournir le contenu de 'backtrace'.

Il se pourrait que le problème se situe dans le timing de la routine d'interruption et ses fonctions

PREAMBULE();
OctetUN();
OctetDeux();
OctetTrois();

Recette : l'insertion d'un yield() suffit parfois à règler (ou repousser) le problème en facilitant le travail du RTOS

Bonjour,
+1 avec al1fch
il faut faire au + court avec les interruptions, or tes fonctions appelées contiennent une tripotée de delay (delayMicroseconds(ValueBit * 116)

il faut repenser la structure de la génération de tes signaux
typiquement, il faut ne faut laisser dans la routine d'interruption que le + urgent (digitalWrite(19,HIGH); digitalWrite(21,LOW)
et renvoyer le reste vers la boucle principale

de plus il faut sans doute que toutes les fonctions exécutées dans le cadre de l'interruption soit en IRAM_ATTR

 PREAMBULE();
OctetUN();
OctetDeux();
OctetTrois();

Mon grain de sel de neuneu un peu éclairé sur l'ESP32 :
L'ESP32 avec fonction Wifi ou BT n'est pas un microcontroleur comme ceux que l'on a l'habitude de voir : il y a dedans un système d'exploitation (FreeRTOS), ce qui permet au micro de simultanément gérer la Wifi/BT et la programmation classique.

D'où l'énorme quantité de mémoire nécessaire et ces impositions qui, il faut le reconnaître, ne sont pas vraiment mise en avant dans la documentation. Heureusement qu'il y a des spécialistes sur ce forum.

Merci à tous. Je ne suis qu'un humble débutant. je pensais qu'en "diminuant" la cadence de calcul cela permettait de ménager le coeur. Concrètement, comment je peux procéder? je souhaite envoyer une série de HIGH pendant 58ms et de LOW pendant 58ms ou bien de HIGH pendant 116ms et de LOW pendant 116ms. Quelle est la technique du yield()? ou bien y a t il un autre moyen pour éviter les delay() pour fabriquer mes BitZero ou BitUn? merci beaucoup.

comme le rappelle 68tjs, le'ESP32 n'est pas un simple microcontrolleur, c'est un SOC ('System on Chip) qui tourne avec le système d'exploitation temps réel FreeRTOS .L'IDE Arduino pour notre confort, masque tout cela.

Que dit le décodeur d'exceptions, quelle fonction produit le réveil du chien de garde ?
Quelle fonction déclenche le chien de garde (wdt) ?

sur un ESP8266 yield() rend la main au 'système d'exploitation'

sur un ESP8266 delay() contient commence par un yield() et n'a pas l'effet bloquant auquel on est habitué avec les microprocesseurs habituels des cartes Arduino

Je n'ai pas plongé dans le code de ces fonctions sur ESP32 pour vérifier si l'effet y est le même.

@el_gringo : Et si tu commençais par bien décrire avec précision(chronogrames) les divers trains d'impulsions que tu veux produire ? Ensuite il serait possible de faire le tour solutions hardware(PWM, RMT...) et/ou software disponibles sur un ESP32.

+En haut de ton code on peut lire :

Copyright (c) 2017 pcbreflux. All Rights Reserved.

de quel code du dépot github de pcbreflux es-tu parti ?

Je suis parti de là.

Je souhaite générer des séries d'octets composés de 2 signaux.

Un signal appelé BitZero qui est constitué d'un signal HIGH pendant 116ms et d'un autre LOW pendant 116ms (BitZero=0)
Le 2ème signal, BitUn, est la même chose mais sur 58ms (BitUn=1)

Ces signaux sont transmis via un pont L298n à des rails et au décodeur d'une locomotive ou autre accessoire.

Par exemple, pour passer une instruction, je vais générer 16 BitZero et ensuite une série de 3 octets composés de 8 bits pour commander ce que je veux. Ce signal ne doit jamais s'arrêter.

J'espère que cela est plus clair.

C’est super lent... vous pouvez sans doute gérer ça dans la loop juste avec un if et millis...

Par ailleurs dans le code qui a servi de modèle on peut remarquer que dans les routines d'interruption on se contente de modifier une variable puis on fait un digitalWrite. ..c'est très court et rapide, on n'y reste pas 100 ou 200ms...(ordre de grandeur des périodes a produire)

Voila un petit exemple, qui utilise millis. Je pense que c’est compliqué plus que nécessaire (même pas sûr que ça marche), l’idée était de ne jamais bloquer le processeur dans une attente.

#define PIN 10
unsigned long chrono = 0;

bool pinSet (int pinNumber, unsigned long duration, bool level) {
  if (millis() - chrono < duration) return false;
  digitalWrite (pinNumber, level);
  chrono = millis();
  return true;
}

void BitZero (int pinNumber) {
  volatile bool ok = false;
  if (!ok && pinSet (pinNumber, 116, HIGH)) {
    ok = true;
    return;
  }
  if (!ok) return;
  if (ok && pinSet (pinNumber, 116, LOW)) {
    ok = false;
    return;
  }
}

void BitUn (int pinNumber) {
  volatile bool ok = false;
  if (!ok && pinSet (pinNumber, 58, HIGH)) {
    ok = true;
    return;
  }
  if (!ok) return;
  if (ok && pinSet (pinNumber, 58, LOW)) {
    ok = false;
    return;
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(PIN, OUTPUT);
  for (int i = 0, i < 16; i++) BitZero(PIN);
  // envoi d'un octet
  byte monOctet = b01001101;
  for (int i = 0, i < 8; i++) bitRead(monOctet, i) ? BitUn(PIN) : BitZero(PIN);
}

void loop() {

}

Ca envoie le bitZero puis un octet choisi au hasard.

C est super sympa. Merci bcp.

J'ai corrigé une typo : bitRead au lieu de butRead !

Encore une petite question. Si je souhaite réduire la fréquence parce que les 80Mhz sont trop rapides, comment est ce que je peux faire avec le esp32? par exemple utiliser 80 comme prescaler : timer0 = timerBegin(0, 80, true) mais pour le coup sans interruption?
Merci

Encore une petite question. Si je souhaite réduire la fréquence parce que les 80Mhz sont trop rapides, comment est ce que je peux faire avec le esp32? par exemple utiliser 80 comme prescaler : timer0 = timerBegin(0, 80, true) mais pour le coup sans interruption?
Merci

Bonsoir

Les timers de l'ESP32 présentent-ils un intérêt sans leur faire déclencher des interruptions ?
cet article semble bien présenter l'utilisation des timers d'un ESP32 :