Timers, interruptions et fonctions ESP32

Bonjour à tous.

J'ai un programme sur un esp32 qui doit gérer du temps.
Je m'explique :
J'ai une caméra branchée sur un Raspberry que je pilote à distance.
Quand j'envoie "Allume la camera", il alimente le Raspberry et sa camera.
Maintenant quand je veux éteindre la camera (et le raspberry donc), j'envoie un ordre d'extinction au raspberry, j'attends 1 minute que celui-ci ait le temps de s'éteindre, et je coupe l'alimentation.

J'ai également une alimentation d'un moteur que je veux laisser active 6 secondes (moteurTremie dans mon programme).

Pour se faire j'ai ce code :

#define DELAY_TREMIE_FILLING_US 6000000L
#define DELAY_RASPBERRY_OFF_US 60000000L

hw_timer_t *timerRaspberry = NULL; // Permet de créer une interruption sur timer.
hw_timer_t *timerTremie = NULL; // Permet de créer une interruption sur timer.

void IRAM_ATTR TimerRaspberryOff() // Code qui s'exécute après 1 minute
{
	digitalWrite(PIN_ALIM_RASPBERRY, LOW); // Coupe l'alimentation du raspberry pi.

	etatCameraMessage.set(0); // Actualise l'etat de la porte
	send(etatCameraMessage); // Envoie l'état actualisé
    
    timerAlarmDisable(timerRaspberry); // Désactive l'alarme du timer (interruption toute les minutes)
	Serial.println("Execution interruption arret raspberry.");
}

void IRAM_ATTR TimerTremieOff() // Code qui s'exécute après 1 minute
{
	digitalWrite(PIN_RELAY_TREMIE, LOW);

	etatMoteurTremieMessage.set(0);
	debugMessage.set("Tremie eteinte.");
	
	send(debugMessage);
	send(etatMoteurTremieMessage); // Etat moteur.

	Serial.println("Execution interruption arret tremie");

        timerAlarmDisable(timerTremie); // Désactive l'alarme du timer
}

void TimersInit()
{
  	timerRaspberry = timerBegin(0, 80, true); // Timer 0, diviseur de fréquence 80 (donc une incrémentation toutes les µs), compteur croissant
  	timerAttachInterrupt(timerRaspberry, TimerRaspberryOff, true); // Attache l'interruption à la fonction onTimer
	timerAlarmWrite(timerRaspberry, DELAY_RASPBERRY_OFF_US, false); // Déclenche l'interruption après 60 000 000 µs soit 60 s

	timerTremie = timerBegin(1, 80, true); // Timer 1, diviseur de fréquence 80 (donc une incrémentation toutes les µs), compteur croissant
	timerAttachInterrupt(timerTremie, TimerTremieOff, true); // Attache l'interruption à la fonction onTimer
	timerAlarmWrite(timerTremie, DELAY_TREMIE_FILLING_US, false); // Déclenche l'interruption après 6 000 000 µs soit 6 s
}

void setup()
{
    TimersInit(); // Initialisation des timers (interruptions pour arret de la caméra ou de la trémie).
}

// Si la commande camera off est envoyée j'exécute ça : 

void Camera_Off(hw_timer_t *timerRaspberry, String *pDebugString)
{
	timerAlarmEnable(timerRaspberry); // Active l'alarme du timer (donc le déclenchement de l'interruption) 
	digitalWrite(PIN_CAMERA_OFF, LOW); // Commande d'arret au raspberry pi + camera.
	*pDebugString = "Camera éteinte dans 1 min.";
	Serial.println("Camera éteinte dans 1 min....");
}

// Et si c'est l'alumage de la trémie : 

void Tremie_On(hw_timer_t *timerTremie, bool *pEtatMoteurTremie)
{
	timerAlarmEnable(timerTremie); // Active l'alarme du timer (donc le déclenchement de l'interruption)
    digitalWrite(PIN_RELAY_TREMIE, HIGH); // Active l'alimentation du moteur trémie

    *pEtatMoteurTremie = 1;

	Serial.println("Allumage moteur tremie...");
}

Lorsque je compile ça fonctionne mais quand j'envoie l'ordre d'éteindre la caméra, le moniteur série m'affiche ça :

Camera éteinte dans 1 min....
ERROR A stack overflow in task loopTask has been detected.
Backtrace:0x400837fd:0x3ffbef3c |<-CORRUPTED
ELF file SHA256: 0000000000000000
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:2
load:0x3fff0030,len:1184
load:0x40078000,len:12776
load:0x40080400,len:3032
entry 0x400805e4
ets Jun 8 2016 00:22:57
rst:0x5 (DEEPSLEEP_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:2
load:0x3fff0030,len:1184
load:0x40078000,len:12776
load:0x40080400,len:3032
entry 0x400805e4

Et mon esp redémarre.

Quand j'envoie l'ordre d'allumer la trémie j'ai un message similaire avant qu'il reboot :

Allumage moteur tremie...
Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1).
Core 1 register dump:
PC : 0x40095d86 PS : 0x00060a35 A0 : 0x80094d46 A1 : 0x3ffbef2c
A2 : 0x3ffbc8b0 A3 : 0x3ffcb0c0 A4 : 0x00000004 A5 : 0x00060a23
A6 : 0x00060a23 A7 : 0x00000001 A8 : 0x3ffcb0c0 A9 : 0x00000018
A10 : 0x3ffcb0c0 A11 : 0x00000018 A12 : 0x00000004 A13 : 0x00060a23
A14 : 0x007bf188 A15 : 0x003fffff SAR : 0x0000000a EXCCAUSE: 0x00000006
EXCVADDR: 0x00000000 LBEG : 0x40084aed LEND : 0x40084af5 LCOUNT : 0x00000027
Core 1 was running in ISR context:
EPC1 : 0x400e29f7 EPC2 : 0x00000000 EPC3 : 0x00000000 EPC4 : 0x00000000
Backtrace:0x40095d83:0x3ffbef2c |<-CORRUPTED
Core 0 register dump:
PC : 0x40095f0b PS : 0x00060035 A0 : 0x80094973 A1 : 0x3ffbeadc
A2 : 0x3ffbf188 A3 : 0xb33fffff A4 : 0x0000abab A5 : 0x00060023
A6 : 0x00060021 A7 : 0x0000cdcd A8 : 0x0000abab A9 : 0xffffffff
A10 : 0x00000000 A11 : 0x00000000 A12 : 0x3ffc3870 A13 : 0x00000007
A14 : 0x007bf188 A15 : 0x003fffff SAR : 0x0000001a EXCCAUSE: 0x00000006
EXCVADDR: 0x00000000 LBEG : 0x00000000 LEND : 0x00000000 LCOUNT : 0x00000000
Backtrace:0x40095f08:0x3ffbeadc |<-CORRUPTED
ELF file SHA256: 0000000000000000
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:2
load:0x3fff0030,len:1184
load:0x40078000,len:12776
load:0x40080400,len:3032
entry 0x400805e4

Je précise également que ces messages s'affichent de suite après la commande et pas 6 secondes après (pour la trémie) ou 1 min après (pour le raspberry)
Du coup je suppose que mon code est incorrect et j'aimerais savoir où et pourquoi. Par avance merci à vous qui aurez pris le temps de me lire :slight_smile:

Le watchdog devient fou...

Tes fonctions 'interrupt handler' (TimerRaspberryOff, TimerTremieOff) doivent durer trop longtemps et mettre le chien de garde en panique.
Ces fonctions doivent faire le minimum de chose, par exemple mettre un flag à 1 (mais pas de communication série - trop long) pour que le programme principal gère ce qu'il faut faire en cas de besoin.

1 Like

En effet. J'aurais cru que ce serait actif au moment de l'appel de la fonction et pas immédiatement après avoir donné un ordre !

Après, comme j'avais pas une initialisation du timer à 0, il est possible que ce soit pour ça et que le temps soit déjà écoulé quand j'envoyais un ordre.

En tous cas merci pour l'aide apportée :slight_smile:

Tu sauras faire à partir de là ?

Oui c'est bon le problème est réglé merci beaucoup :slight_smile:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.