Débutant: ESP32 Task watchdog got triggered (Redémarrage en boucle)

Bonjour à tous,

Je voudrais mesurer la période de 2 signaux provenant de capteurs RPM.
Signal d'entrée 3.3v 50%dty, varie entre 0 et 1khz en fonction de la vitesse.

J'utilise pour les simulation un générateur de fréquence.

Je voudrais ensuite générer un signal similaire mais avec une période différente (+20%) de manière à diminuer la fréquence.

Voici ci-dessous une ébauche de code: (Code simplifié pour 1 seul capteur)


// Define pins
const int sensorPin1 = 4;   // GPIO pin for the first sensor
const int outputPin1  = 5;   // Output GPIO pin for the first modified signal


// Timing variables for sensor 1
volatile unsigned long lastRise1       = 0;
volatile unsigned long lastFall1       = 0;
volatile unsigned long lastPeriod1     = 0;
volatile unsigned long modifiedPeriod1 = 0;
volatile unsigned long lastSignalTime1 = 0;
volatile bool updateRequired1          = false;

// Timing variables for sensor 2
volatile unsigned long lastRise2       = 0;
volatile unsigned long lastFall2       = 0;
volatile unsigned long lastPeriod2     = 0;
volatile unsigned long modifiedPeriod2 = 0;
volatile unsigned long lastSignalTime2 = 0;
volatile bool updateRequired2          = false;



// nterrupt Service Routines
// These routines only update timing info and debug counters.

void IRAM_ATTR onChange1() {
    unsigned long currentTime = micros();
    if (digitalRead(sensorPin1) == HIGH) {

        if (lastFall1 != 0) {
            lastPeriod1 = 2 * (currentTime - lastFall1);
            lastSignalTime1 = millis();
            updateRequired1 = true;
        }
        lastRise1 = currentTime;
    } else {

        lastFall1 = currentTime;
    }
}

// Output Generation Function
void generateOutput(int pin, unsigned long period) {
    if (period > 0) {
        unsigned long halfPeriod = period / 2;
        digitalWrite(pin, HIGH);
        delayMicroseconds(halfPeriod);
        digitalWrite(pin, LOW);
        delayMicroseconds(halfPeriod);
    } else {
        digitalWrite(pin, LOW);
    }
}

// Task to generate output signals
void outputTask(void *parameter) {
    while (true) {
        if (updateRequired1) {
            modifiedPeriod1 = lastPeriod1 * 1.2;  // adjust period as needed
            updateRequired1 = false;
        }
        if (updateRequired2) {
            modifiedPeriod2 = lastPeriod2 * 1.2;
            updateRequired2 = false;
        }

        // If no signal has been detected recently, clear the modified period.
        if (millis() - lastSignalTime1 > 2 * lastPeriod1 / 1000) {
            modifiedPeriod1 = 0;
        }
        if (millis() - lastSignalTime2 > 2 * lastPeriod2 / 1000) {
            modifiedPeriod2 = 0;
        }

        generateOutput(outputPin1, modifiedPeriod1);

        
    }
}


//Setup
void setup() {
    // Initialize Serial for debug output
    Serial.begin(115200);
    // (Optional) Wait for Serial to connect (useful on some boards)
    while (!Serial) {
        ; // wait for serial port to connect.
    }

    pinMode(sensorPin1, INPUT);

    pinMode(outputPin1, OUTPUT);


    // Attach interrupts for both rising and falling edges.
    attachInterrupt(digitalPinToInterrupt(sensorPin1), onChange1, CHANGE);


    // Create tasks:
    // outputTask runs on core 0 to generate the output signal.
    xTaskCreatePinnedToCore(outputTask, "OutputTask", 1000, NULL, 1, NULL, 0);
    // debugTask runs on core 1 to print debug information.

}

//  Main loop 
void loop() {
    
}

Le problème est que:
Le code fonctionne, mais redémarre toutes les 5 secondes. (pendant un court instant, le signal passe à l'état bas et est faussé).

09:16:23.888 -> E (10109) task_wdt: Task watchdog got triggered. The following tasks/users did not reset the watchdog in time:
09:16:23.921 -> E (10109) task_wdt:  - IDLE0 (CPU 0)
09:16:23.921 -> E (10109) task_wdt: Tasks currently running:
09:16:23.921 -> E (10109) task_wdt: CPU 0: OutputTask
09:16:23.921 -> E (10109) task_wdt: CPU 1: loopTask
09:16:23.921 -> E (10109) task_wdt: Aborting.
09:16:23.921 -> E (10109) task_wdt: Print CPU 0 (current core) backtrace

Si j'ajoute la ligne ci-dessous dans la fonction "outputtask", le programme ne redémarre plus, mais mon signal est forcément faux. je n'ai plus un pwm de 50%
Donc dans mon cas, cette solution n'est pas bonne. J'ai besoin du temps réel.

vTaskDelay(1); // Delay of 1 tick (usually 1 ms)

Il s'agit de mon premier programme sur ESP32, avec FREETOS et utilisation de plusieurs coeurs.

D'avance, merci pour votre aide.

essayez en rajoutant juste une ligne qui dit

yield();

dans la fonction outputTask()

Je viens d'essayer, cela donne toujours le même résultat.

J'ai également testé avec

taskYIELD();

Faire le signal à la main avec generateOutput() est une solution un peu bourrin car cela monopolise beaucoup de ressource pour pas grand chose. Cela vaudrait peut-être le coup de regarder si LEDC ne pourrait pas être utilisé à la place.

+1

il est dommage de ne pas confier au hardware interne des ESP32 ce qui qu'il peut faire dans son coin comme la production de signaux périodiques de fréquence et rapport cyclique définis .
Pour LEDC il faut juste choisir une 'Résolution' compatible avec la plage de fréquences désirée.
Ensuite on change au vol quant on le souhaite fréquence et/ou Rapport cyclique

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