ESP32, problème avec le multi-tâche

Bonsoir à toutes et à tous,

Dans mes essais de multi-tâche, je tombe sur un problème dont je ne trouve pas la source.

J'ai une fonction, si je la place dans la loop() ne pose aucun problème.

Maintenant, si je la place dans une tâche, ça ne veut plus fonctionner. La fonction est la suivante :

  getLocalTime(&timeinfo);
  strftime( message1, 24, "%d/%m/%Y %H:%M:%S,", &timeinfo);
  sprintf(message2, "%.1f,%.1f,%.1f\n", pActif, vRMS, iRMS);

  t0 = millis();
  if (appendFile2(SD, "/Valeurs.txt", message1, message2) == 1)
    Serial.println("Problème");

avec :

uint8_t appendFile2(fs::FS &fs, const char * path, const char * message1, const char * message2){
  File file = fs.open(path, FILE_APPEND);
  if(!file){
    return 1;
  } else {
    file.print(message1);
    file.print(message2);
    file.close();
    return 0;
  }
}

La même fonction dans sa tâche :

  xTaskCreatePinnedToCore(&Traitement, "Traitement", 2048, NULL, 1, NULL, 1);
void Traitement(void *params)
{
  while (true)
  {
    printf("Traitement\n");
    getLocalTime(&timeinfo);
    strftime( message1, 24, "%d/%m/%Y %H:%M:%S,", &timeinfo);
    sprintf(message2, "%.1f,%.1f,%.1f\n", pActif, vRMS, iRMS);
    if (appendFile2(SD, "/Valeurs.txt", message1, message2) == 1)
      printf("Problème\n");
    vTaskDelay(3000 / portTICK_PERIOD_MS); 
  }
}

Voici l'erreur obtenue :

18:36:10.530 -> Carte SD détectée // cà, c'est dans le setup()
18:36:10.530 -> Traitement // je rentre dans la fonction
18:36:10.530 -> 26/12/2024 18:36:10, // pistage de message1 avec des print
18:36:10.530 -> 0.0,0.0,0.0 // pistage de message2 
18:36:10.530 -> Guru Meditation Error: Core  1 panic'ed (Unhandled debug exception). Si j'utilse le core 0, le problème est le même
18:36:10.530 -> Debug exception reason: Stack canary watchpoint triggered (Traitement) 
18:36:10.530 -> Core  1 register dump:
18:36:10.530 -> PC      : 0x40090976  PS      : 0x00060836  A0      : 0x80090184  A1      : 0x3ffd3ad0  
18:36:10.563 -> A2      : 0x3ffbddb4  A3      : 0xffffffff  A4      : 0x00060823  A5      : 0x3f407a80  
18:36:10.563 -> A6      : 0x00000000  A7      : 0x00000004  A8      : 0x00000000  A9      : 0x00000001  
18:36:10.563 -> A10     : 0x007b7b2c  A11     : 0x3ffb7b2c  A12     : 0x3ffcd1cc  A13     : 0x00003fa2  
18:36:10.563 -> A14     : 0x00000000  A15     : 0x00000200  SAR     : 0x0000001b  EXCCAUSE: 0x00000001  
18:36:10.596 -> EXCVADDR: 0x00000000  LBEG    : 0x4008a0ac  LEND    : 0x4008a0b7  LCOUNT  : 0xffffffff  
18:36:10.596 -> 
18:36:10.596 -> 
18:36:10.596 -> Backtrace: 0x40090973:0x3ffd3ad0 0x40090181:0x3ffd3b00 0x4008e9f3:0x3ffd3b20 0x400d4a72:0x3ffd3b60 0x400d3c0b:0x3ffd3b90 0x400d40ce:0x3ffd3bc0 0x4011534e:0x3ffd3c00 0x40115871:0x3ffd3c20 0x401164b2:0x3ffd3c40 0x40116840:0x3ffd3c80 0x40117710:0x3ffd3cc0 0x4011921f:0x3ffd3f30 0x400e762e:0x3ffd40a0 0x4016266d:0x3ffd40c0 0x400d384e:0x3ffd40e0 0x400d2e14:0x3ffd4180 0x400d2759:0x3ffd41b0 0x400d29f2:0x3ffd41f0 0x40090876:0x3ffd4220
18:36:10.638 -> 
18:36:10.638 -> 
18:36:10.638 -> 
18:36:10.638 -> 
18:36:10.638 -> ELF file SHA256: 2d8a6cbdc5ae68dc
18:36:10.638 -> 
1

Des idées du problème ?

Cordialement.

Pierre.

Bonsoir @ChPr

  1. Pourquoi créer un nouveau fil de discussion et ne pas poser ta question là où tu as lancé l'échange sur le multi tâche :roll_eyes:
xTaskCreatePinnedToCore(&Traitement, "Traitement", 2048, NULL, 1, NULL, 1);

Stack canary watchpoint triggered (Traitement) 
  1. Une vague idée de non spécialiste : les 2048 octets alloués à la pile de la tâche ne suffisent pas, elle déborde .

  2. plus généralement un décodeur de backtrace existe , en y copiant le contenu de la 'backtrace' tu verras apparaître l'enchaînement des derniers appels de fonctions avant l'incident, ça aide souvent

Là, je suis sur un point particulier lié à des paramètres. Ça sort du cadre général de fonctionnement

Pour un non spécialiste, tu as vu juste :slightly_smiling_face:

J'ai vu plusieurs articles parlant de cette pile, mais aucun ne précise ce qui la compose.

Dans mon cas, je suis passé de 2048 à 4096 et ça a fonctionné. Pour autant, ce ne sont que 48 octets que j'y passe.

Cordialement.

Pierre.

Non, il y a aussi les variables locales. Il doit aussi y avoir de la sauvegarde de contexte. Comme tu appelles une fonction qui ouvre un fichier il y a peut-être aussi le buffer pour un bloc, les variables associées à la gestion de la SD card.

Comme l'indique @fdufnews la pile ne sauvegarde pas que les paramètres d'une fonction.
il faudrait que tu identifie ce qu'il y a dans la pile d'appel, avant de l'augmenter, car cela pourrait être un signe d'une mauvaise gestion des paramètres que tu passes à tes fonctions ou d'appel récursif mal maitrisés.

Bon, je vais peut-être pouvoir me passer du multi-tâche. Pas sûr encore, mais ...

Pour transférer mes données de la carte SD vers un PC ou smartphone, j'envisageais de copier ces données dans la mémoire Flash de l'ESP32 puis d'utiliser le WiFi avec le contenu de la mémoire Flash. En scindant les transferts par le multi_tâche. d'où l'utilité des sémaphores.

J'ai fait un premier essai avec les fonctions suivantes de la bibliothèque ESPAsyncWebServer.h.

  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ // Handle the root URL
    request->send(SD, "/index.html", "text/html");
  });


  server.on("/download", HTTP_GET, [](AsyncWebServerRequest *request){ // Handle the download button
    request->send(SD, "/data.txt", String(), true);
  });

  
  server.on("/view-data", HTTP_GET, [](AsyncWebServerRequest *request){ // Handle the View Data button
    request->send(SD, "/data.txt", "text/plain", false);
  });

en ayant mes fonctions d'acquisition et de mémorisation de ces données dans la carte SD simplement dans la loop() avec une récurrence de l'ordre de 800 mS.

  pActif = PowerAndUIrms(pin_Commun, pin_Tension, pin_Courant, 1.025, 0.06, 200000, &vRMS, &iRMS);   // acquisition des données par calcul sur 10 périodes du 50 Hz
  getLocalTime(&timeinfo);
  strftime( message1, 24, "%d/%m/%Y %H:%M:%S,", &timeinfo); // mise en forme de la date et de l'heure
  sprintf(message2, "%.1f,%.1f,%.1f", pActif, vRMS, iRMS); // mise en forme des données
  Serial.print(message1); // Affichage
  Serial.print("  ");
  Serial.print(message2); // Affichage
  t0 = millis();
  if (appendFile2(SD, "/Valeurs.txt", message1, message2) == 1) // enregistrement des données sur la carte SD
    Serial.println("Problème");
  t1 = millis()-t0;  
  Serial.print("  ");
  Serial.println(t1); // durée de l'enregistrement de mes données incluses entre une ouverture et fermeture de fichier
  t0 = t1;

Voilà l'affichage de ce que ça donne. Lorsque je n'active pas le transfert via le WiFi, la durée d'enregistrement des données sur la carte SD est de 81 mS. Si j'active le transfert, qui dure environ 5 S, ce temps passe à 130 mS. Pour autant, les données sont bien enregistrées, et la récurrence est respectée. Mon problème est (pour l'instant) potentiellement résolu.

11:46:47.980 -> 28/12/2024 11:46:49,  -3.3,225.6,0.3  81
11:46:48.780 -> 28/12/2024 11:46:50,  -1.5,225.6,0.2  81
11:46:49.542 -> 28/12/2024 11:46:50,  -2.0,225.5,0.2  81
11:46:50.326 -> 28/12/2024 11:46:51,  -3.5,226.4,0.3  81
11:46:51.117 -> 28/12/2024 11:46:52,  -5.4,215.6,0.3  128
11:46:52.004 -> 28/12/2024 11:46:53,  2.9,203.3,0.2  129
11:46:52.811 -> 28/12/2024 11:46:54,  -3.2,226.2,0.3  130
11:46:53.695 -> 28/12/2024 11:46:55,  -4.9,242.8,0.4  129
11:46:54.532 -> 28/12/2024 11:46:55,  -4.0,239.9,0.2  129
11:46:55.340 -> 28/12/2024 11:46:56,  -7.6,244.4,0.2  130
11:46:56.188 -> 28/12/2024 11:46:57,  -1.4,226.2,0.3  89
11:46:56.997 -> 28/12/2024 11:46:58,  -2.7,226.8,0.2  81
11:46:57.765 -> 28/12/2024 11:46:59,  -2.1,226.8,0.3  81
11:46:58.527 -> 28/12/2024 11:46:59,  -1.5,227.8,0.3  81

Je suppose que le transfert de la carte SD via le WiFi vers un PC se faire via une mémoire RAM et non Flash.

Cordialement.

Pierre.

la bibliothèque lit le contenu du fichier dans un buffer qui est ensuite envoyé, donc oui ça passe par la RAM.

Je viens de re-regarder mon tableau de valeurs lues et enregistrées : elles sont sérieusement chahutées (± 10 % sur la tension de 226 V) lors de la transmission WiFi :

11:46:47.980 -> 28/12/2024 11:46:49, -3.3,225.6,0.3 81
11:46:48.780 -> 28/12/2024 11:46:50, -1.5,225.6,0.2 81
11:46:49.542 -> 28/12/2024 11:46:50, -2.0,225.5,0.2 81
11:46:50.326 -> 28/12/2024 11:46:51, -3.5,226.4,0.3 81
11:46:51.117 -> 28/12/2024 11:46:52, -5.4,215.6,0.3 128
11:46:52.004 -> 28/12/2024 11:46:53, 2.9,203.3,0.2 129
11:46:52.811 -> 28/12/2024 11:46:54, -3.2,226.2,0.3 130
11:46:53.695 -> 28/12/2024 11:46:55, -4.9,242.8,0.4 129
11:46:54.532 -> 28/12/2024 11:46:55, -4.0,239.9,0.2 129
11:46:55.340 -> 28/12/2024 11:46:56, -7.6,244.4,0.2 130
11:46:56.188 -> 28/12/2024 11:46:57, -1.4,226.2,0.3 89
11:46:56.997 -> 28/12/2024 11:46:58, -2.7,226.8,0.2 81
11:46:57.765 -> 28/12/2024 11:46:59, -2.1,226.8,0.3 81
11:46:58.527 -> 28/12/2024 11:46:59, -1.5,227.8,0.3 81

Je suppose que ce sont les radios fréquences qui polluent les CAN car mes capteurs - sonde de courant et transformateur pour la tension - sont assez loin ; environ 1 mètre ?

Cordialement.

Pierre.

quels types de capteurs ?

Sonde de courant. Modèle 30 A --> 1 V. Ne déphase pratiquement pas. Suivi d'un pont diviseur pour ne pas dépasser 0.4 V pour 30 A.

Transformateur. Modèle 220 V --> 5 V. Déphasage avance de 18 °. Suivi d'un pont diviseur déphaseur (18 ° à 50 Hz) pour ne pas dépasser 0.4 V pour 340 Vcrête.

Les liaisons entre l'ESP32 et les capteurs sont composées de 2 fils jointifs non tordadés mais ne sont pas blindées (c'est du bricolage pour l'instant).

Cordialement.

Pierre.

La lecture est en analogique alors ?

Ben oui, j'utilise les fonctions analogReadMilliVolts().

Cordialement.

Pierre.

Bonsoir
Des filtres passe-bas (RC) sur les trajets :

  • Transfo de courant -> entrée analogique
  • Transfo de tension -> entrée analogique

Permettraient probablement de réduire le 'chahut' sur les mesures
Si j'ai bien compris ce qui t'intéresse est à 50Hz, peut être les premières harmoniques.....

Tu n'utiliserais pas des entrées analogiques qui entre sur l'ADC2?


Cet ADC est utilisé par le WiFi.

image

A priori non, j'utilise les entrées 34, 35 et 36.

Cordialement.

Pierre.

Des filtres passe-bas impactent les harmoniques.

Je filtre en utilisant une moyenne sur 10 périodes.

Cordialement.

Pierre.

Sur ESP32 ?

Que je sache, il n'y a que le ESP32 qui intègre cette fonction ?

Cordialement.

Pierre.

Effectivement - j’avais en tête une fonction perso je ne sais pas pourquoi

Lorsque le module Wi-Fi est actif, des pics de courant se produisent, générant du bruit électrique qui peut altérer les mesures analogiques car les circuits du Wi-Fi et de l’ADC partagent une alimentation et peuvent s’influencer mutuellement, en particulier si une alimentation insuffisamment filtrée est utilisée.

Si vous mettez des condensateurs (par exemple, 0,1 µF et 10 µF) près des broches analogiques pour réduire le bruit, voyez vous une différence ?

J'ai déjà un tel découplage au pied de la carte ESP32 entre le 3.3 V et le GND et le même sur le point commun des mesures (entrée 34). Peut-être qu'un câblage plus soigné diminuera ce problème.

En soi, avoir quelques mesures bruitées d'une dizaine de % ne me gène pas trop.

Cordialement.

Pierre.