Simulateur de capteur, envoie de trame de données sur liaison série

du coup j'ai tester mais en #include <SoftwareSerial.h>

et faisant :

SoftwareSerial RS232(10, 11,true);  // RX, TX // true pour logic RS232/TTL

d'après ce que j'ai lu, ca inverse la logic TTL/RS232

donc je (re)confirme, mon capteur c'est bien du RS232, j'ai maintenant avec 0x55,AA en flag1,2 :

Trame reçue :
0x04 0x00 0x01 0xBE 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0x02 0x15 0x00 0x00
0x00 0x14 0x12
-> CKSUM calculé 0x00
Trame reçue :
0x05 0x00 0x01 0xC0 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0x02 0x10 0x15 0x00
0x02 0x17 0xFA
-> CKSUM calculé 0x00
Trame reçue :
0x06 0x00 0x01 0xC0 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0xAA 0xBA 0x00 0x00
0x03 0x00 0xD2
-> CKSUM calculé 0x00`

Je sais maintenant qu'il est possible de lire du RS232, pour l'écriture je vais attendre le convertisseur.

En attendant merci à tous pour votre, temps, patience (il en faut avec les débutants) et vos conseils

et surtout Joyeuses fêtes :santa:

C’est avec votre méthode la somme sur toute la trame? (Donc c’est pour ça que vous avez 0 tout le temps)

Joyeuses fêtes à vous aussi (et à toutes et tous)

Rebonjour a tous,

Oui c'est bien ça.

Pour ce qui est du convertisseur, je confirme j'arrive désormais a avoir une detection de la part de mon hote = > capteur present mais valeur co2 a 0.

Pour identifier d'ou vient le problème j'aurais besoin de lire la trame de mon capteur en décimal => je soupcone les LowByte/Highbyte.

Je patauge un peu sur la syntaxe pour lire la partie "waveform " sur le moniteur serie.

image

Je suis pas loin du but, merci pour votre aide

Ta documentation indique que c'est MSB, donc bits de poids fort en premier et je crois que quelqu'un t'avais indiqué que l'arduino est en little endian.
Il faut donc que tu échange les deux octets pour le wave.
Plus haut tu as le code correspondant je crois.
Tu sais dans les trames que tu as récupéré les valeurs transmise ?

Voir la discussion autour du post 12.

Bonjour à tous et meilleurs vœux !

J'ai enfin réussi a rendre fonctionnel mon simulateur. ( merci au passage pour les tuto Bouton de @J-M-L bien utile pour finir mon projet ) .

Je voudrais ajouter une fonction de lecture de la trame capteur (base @J-M-L ci dessous) ,pour les octets waveform mais j'ai du mal avec la syntaxe.

#include <SoftwareSerial.h>
SoftwareSerial RS232(10, 11,true);  // RX, TX // true pour logic RS232/TTL
const uint8_t flag1 = 0xAA;
const uint8_t flag2 = 0x55;

byte frame[19]; // sans les flags

bool frameRecue() {
  static enum : uint8_t {F1, F2, TRAME} etape = F1;
  bool receptionOK = false;
  static uint8_t compteur = 0;
  if (RS232.available() == 0) return false; // rien à lire
  uint8_t recu = RS232.read();
  switch (etape) {
    case F1:
      if (recu == flag1) etape = F2;
      break;

    case F2:
      if (recu == flag2) {
        compteur = 0;
        etape = TRAME;
      } else if (recu != flag1) {
        etape = F1;
      }
      break;

    case TRAME:
      frame[compteur++] = recu;
      receptionOK = (compteur >= sizeof frame);
      if (receptionOK) etape = F1; // on se prépare à recevoir la prochaine trame
  }
  return receptionOK;
  }

}


}


void setup() {
  Serial.begin(115200); Serial.println();
  RS232.begin (9600);  //9600 selon doc
  Serial.println(F("Prêt à recevoir des trames"));
}

void loop() {
  if (frameRecue()) {
    uint8_t cksum = 0;
    Serial.print(F("Trame reçue : "));
    for (uint8_t index = 0; index < sizeof frame; index++) {
      uint8_t b = frame[index];
      cksum += b;
      if (index % 8 == 0) Serial.print(F("\n\t"));
      Serial.print(F("0x"));
      if (b < 0x10) Serial.write('0');
      Serial.print(b, HEX);
      if (isprint(b)) {
        Serial.print(F("('"));
        Serial.write(b);
        Serial.print(F("')"));
      }
      Serial.write(' ');
    }
    cksum = ~cksum + 1;
    Serial.print(F("\n-> CKSUM calculé "));
    Serial.print(F("0x"));
    if (cksum < 0x10) Serial.write('0');
    Serial.println(cksum, HEX);
  } else delay(1); // pour ne pas bombarder en permanence le port virtuel
}

Comment concaténer les groupes de 2 octets (Hi/Low) on utilise aussi highByte/lowByte pour la lecture ou ca ne sert que pour l'écriture ?

il faut jouer un peu avec la réception pour passer en little endian

  • recevez la trame "brute" dans le tableau frame
  • ensuite une fois reçue, échangez les octets correspondant pour les octets waveform (permutation des octets).
    ➜ on sait que trame[0] c'est l'ID
    ➜ on sait que trame[1] c'est STS
    ➜ Ensuite on a 10 octets à inverser entre trame[2] et trame[11]
byte temp;
for(byte i=2; i<11; i+=2) {
  temp = trame[i];
  trame[i] = trame[i+1];
  trame[i+1] = temp;
}
  • ensuite pour simplifier la lecture, créez une structure qui correspond au format de la trame
struct __attribute__((packed)) t_frame {
  uint8_t id;
  uint8_t sts;
  uint16_t waweFormData[5]; // attention BIG ENDIAN à l'origine
  uint8_t slowData[6];
  uint8_t chk;
};

et il suffit de coller la trame dedans

t_frame uneFrame;
memcpy(&uneFrame, trame, sizeof uneFrame);

ensuite vous pouvez imprimer les champs

➜ un exemple


uint8_t trameRecue[] = {
  0x02,                                 // ID
  0x02,                                 // STS
  0x01, 0xEA,                           // WaveForm 0 big endian
  0x00, 0x00,                           // WaveForm 1 big endian
  0x00, 0x00,                           // WaveForm 2 big endian
  0x00, 0x00,                           // WaveForm 3 big endian
  0x00, 0x00,                           // WaveForm 4 big endian
  0xFF, 0x26, 0x00, 0x00, 0x03, 0xB6,   // Slow Data
  0x33                                  // CHK
};

struct __attribute__((packed)) t_frame {
  uint8_t id;
  uint8_t sts;
  uint16_t waweFormData[5]; // attention BIG ENDIAN à l'origine, il faut permuter
  uint8_t slowData[6];
  uint8_t chk;
};

t_frame uneFrame;

void permutationWaweFormData(uint8_t * trame) {
  byte temp;
  for (byte i = 2; i < 11; i += 2) {
    temp = trame[i];
    trame[i] = trame[i + 1];
    trame[i + 1] = temp;
  }
}

void imprimeTrame(t_frame & laTrame) {
  Serial.print(F("id: 0x")); Serial.println(laTrame.id, HEX);
  Serial.print(F("sts: 0x")); Serial.println(laTrame.sts, HEX);
  Serial.print(F("waweFormData: "));
  for (byte i = 0; i < 5; i++) {
    Serial.print(F("0x"));
    Serial.print(laTrame. waweFormData[i], HEX);
    Serial.write(' ');
  }
  Serial.println();
  Serial.print(F("slowData: "));
  for (byte i = 0; i < 6; i++) {
    Serial.print(F("0x"));
    Serial.print(laTrame. slowData[i], HEX);
    Serial.write(' ');
  }
  Serial.println();
  Serial.print(F("chk: 0x")); Serial.println(laTrame. chk, HEX);
}

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

  permutationWaweFormData(trameRecue);
  memcpy(&uneFrame, trameRecue, sizeof uneFrame);
  imprimeTrame(uneFrame);
}

void loop() {}

Bonjour à tous,

j'ai reviens un peu sur ce sujet, j'ai a peu près réussi a faire ce que je voulais et l'afficher sur le lecteur série, à savoir

  • capter la trame
  • isoler les octets qui m'intéresse
  • faire des conversions

Alors c'est certainement pas optimisé, mais c'est fonctionnel.

#include <SoftwareSerial.h>
SoftwareSerial RS232(10, 11);  // RX, TX //
const uint8_t flag1 = 0xAA;
const uint8_t flag2 = 0x55;

byte frame[19];  // sans les flags

bool frameRecue() {
  static enum : uint8_t { F1,
                          F2,
                          TRAME } etape = F1;
  bool receptionOK = false;
  static uint8_t compteur = 0;
  if (RS232.available() == 0) return false;  // rien à lire
  uint8_t recu = RS232.read();
  switch (etape) {
    case F1:
      if (recu == flag1) etape = F2;
      break;

    case F2:
      if (recu == flag2) {
        compteur = 0;
        etape = TRAME;
      } else if (recu != flag1) {
        etape = F1;
      }
      break;

    case TRAME:
      frame[compteur++] = recu;
      receptionOK = (compteur >= sizeof frame);
      if (receptionOK) etape = F1;  // on se prépare à recevoir la prochaine trame
  }
  return receptionOK;
}

void setup() {
  Serial.begin(115200);
  Serial.println();
  RS232.begin(9600);  //9600 selon doc
  Serial.println(F("Prêt à recevoir des trames"));
}

int valCO2() {
  if (frameRecue()) {
    int id = frame[0];
    float waveform0 = word(frame[2], frame[3]);  // CO2 en %vol valeur HD dispo sur chaque trame 0- 2500 pour 0,00- 25,00%
    uint16_t CO2exp;                             //CO2 expiré en %VOL sur 1 octet  0-250 pour 0 à 25%
    int Patm;                                    // valeur HD de Patm en Kpa 500 à 1300 pour 50.0 à 130.0 Kpa
    int PmmHg;                                   // valeur convertie en mmHg

    if (id == 0x03) Patm = word(frame[16], frame[17]);
    PmmHg = ((Patm * 7.5) / 10);  // conversion Kpa en mmHg
    if (id == 0x01) {
      CO2exp = (frame[12] / 10 * PmmHg) / 100;  // conversion CO2exp de %vol à mmHg
    }
    float P_CO2 = ((waveform0 / 100) * PmmHg) / 100;  // conversion CO2 HD de %vol à mmHg
    int CO2;
    CO2 = (P_CO2 * 100) / 100;  // juste pour afficher un entier
    return (CO2);
    //return (CO2exp) // je ne sais pas encore laquelle des deux je vais utilisé
  }
}

void loop() {

 
  Serial.print("CO2:");
  Serial.println(valCO2());
}

Mon souci maintenant, je voudrais afficher ma valeur sur un petit afficheur Oled 0,91 type SSD1306" acheté sur Ali, pour ca j'utilise la bibli U8G2.h => la seule que j'ai réussi a faire fonctionner avec mon afficheur (celle adafruit ne fonctionne pas)

mais a partir du moment ou j'intègre de l'affichage, ma fonction initiale me retourne des valeurs incohérentes.
Au niveau de l'affichage ca va...enfin ce sont les mêmes valeurs que dans le lecteur série

pour exemple :

#include <SoftwareSerial.h>
SoftwareSerial RS232(10, 11);  // RX, TX // true pour logic RS232/TTL
#include <Arduino.h>           //getsion aff
#include <U8g2lib.h>           //getsion aff

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);

const uint8_t flag1 = 0xAA;
const uint8_t flag2 = 0x55;

byte frame[19];  // sans les flags

bool frameRecue() {
  static enum : uint8_t { F1,
                          F2,
                          TRAME } etape = F1;
  bool receptionOK = false;
  static uint8_t compteur = 0;
  if (RS232.available() == 0) return false;  // rien à lire
  uint8_t recu = RS232.read();
  switch (etape) {
    case F1:
      if (recu == flag1) etape = F2;
      break;

    case F2:
      if (recu == flag2) {
        compteur = 0;
        etape = TRAME;
      } else if (recu != flag1) {
        etape = F1;
      }
      break;

    case TRAME:
      frame[compteur++] = recu;
      receptionOK = (compteur >= sizeof frame);
      if (receptionOK) etape = F1;  // on se prépare à recevoir la prochaine trame
  }
  return receptionOK;
}

int valCO2() {
  if (frameRecue()) {
    int id = frame[0];
    float waveform0 = word(frame[2], frame[3]);  // CO2 en %vol valeur HD dispo sur chaque trame 0- 2500 pour 0,00- 25,00%
    uint16_t CO2exp;                             //CO2 expiré en %VOL sur 1 octet  0-250 pour 0 à 25%
    int Patm;                                    // valeur HD de Patm en Kpa 500 à 1300 pour 50.0 à 130.0 Kpa
    int PmmHg;                                   // valeur convertie en mmHg

    if (id == 0x03) Patm = word(frame[16], frame[17]);
    PmmHg = ((Patm * 7.5) / 10);  // conversion Kpa en mmHg
    if (id == 0x01) {
      CO2exp = (frame[12] / 10 * PmmHg) / 100;  // conversion CO2exp de %vol à mmHg
    }
    float P_CO2 = ((waveform0 / 100) * PmmHg) / 100;  // conversion CO2 HD de %vol à mmHg
    int CO2;
    CO2 = (P_CO2 * 100) / 100;  // juste pour afficher un entier
    return (CO2);
  }
}
void setup() {
  u8g2.begin();  //Start Screen
  Serial.begin(115200);
  Serial.println();
  RS232.begin(9600);  //9600 selon doc
  Serial.println(F("Prêt à recevoir des trames"));
}



void loop() {


  Serial.println(valCO2());

  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_timB18_tr);
  u8g2.drawStr(1, 25, "Co2: ");
  u8g2.setFont(u8g2_font_timB10_tr);
  u8g2.drawStr(85, 25, "mmHg");
  u8g2.sendBuffer();
  u8g2.setFont(u8g2_font_timB18_tr);
  u8g2.setCursor(55, 25);
  u8g2.print(valCO2());
  u8g2.sendBuffer();

  delay(10);
}

1ere question , est t'il possible d'exploiter sur Arduino, la lecture série et en plus affiché via un protocole I2C ?

2e question, est ce que ca peut être simplement lié à la structure de mon code ?

Merci pour vos retours

je n'ai pas lu le code en détail mais techniquement oui

cependant ici vous utilisez SoftwareSerial qui est assez gourmand au niveau interruptions et peut-être que ça rentre en conflit avec les besoin de votre écran.

idéalement il faudrait tester un port série matériel au lieu d'une émulation par SoftwareSerial

valCO2() ne retourne rien si frameRecue est false.

Merci pour le retour, si je veux passer en matériel sans émulation, jusqu'ici je ne m'étais pas posé la question [puisque ça marche], comment je dois procéder ? Sachant que j'utilise un convertisseur ?
Merci @J-M-L

Il faudrait un arduino avec plusieurs ports série comme la MEGA

@fdufnews a raison, il faut corriger cela

Merci pour vos retour,

La bonne nouvelle c'est que le problème ne vient a priori pas d'un conflit, j'ai testé sur Mega2560 Idem ou alors le fai d'utiliser un port physique ne change rien.

J'ai ajouté un un "else return (99) "dans ma fonction valCO2 et du coup je reçois 99 :frowning:

Je ne sais pas d'où ca peut venir? je perds des paquets ? ca fonctionne parfaitement sans l'affichage..... si vous avez des pistes je suis preneur

le code :

//#include <SoftwareSerial.h>
//SoftwareSerial RS232(10, 11);  // RX, TX // true pour logic RS232/TTL
#include <Arduino.h>  //getsion aff
#include <U8g2lib.h>  //getsion aff

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);

const uint8_t flag1 = 0xAA;
const uint8_t flag2 = 0x55;

byte frame[19];  // sans les flags

bool frameRecue() {
  static enum : uint8_t { F1,
                          F2,
                          TRAME } etape = F1;
  bool receptionOK = false;
  static uint8_t compteur = 0;
  if (Serial1.available() == 0) return false;  // rien à lire
  uint8_t recu = Serial1.read();
  switch (etape) {
    case F1:
      if (recu == flag1) etape = F2;
      break;

    case F2:
      if (recu == flag2) {
        compteur = 0;
        etape = TRAME;
      } else if (recu != flag1) {
        etape = F1;
      }
      break;

    case TRAME:
      frame[compteur++] = recu;
      receptionOK = (compteur >= sizeof frame);
      if (receptionOK) etape = F1;  // on se prépare à recevoir la prochaine trame
  }
  return receptionOK;
}

int valCO2() {
  if (frameRecue()) {
    int id = frame[0];
    float waveform0 = word(frame[2], frame[3]);  // CO2 en %vol valeur HD dispo sur chaque trame 0- 2500 pour 0,00- 25,00%
    uint16_t CO2exp;                             //CO2 expiré en %VOL sur 1 octet  0-250 pour 0 à 25%
    int Patm;                                    // valeur HD de Patm en Kpa 500 à 1300 pour 50.0 à 130.0 Kpa
    int PmmHg;                                   // valeur convertie en mmHg

    if (id == 0x03) Patm = word(frame[16], frame[17]);
    PmmHg = ((Patm * 7.5) / 10);  // conversion Kpa en mmHg
    if (id == 0x01) {
      CO2exp = (frame[12] / 10 * PmmHg) / 100;  // conversion CO2exp de %vol à mmHg
    }
    float P_CO2 = ((waveform0 / 100) * PmmHg) / 100;  // conversion CO2 HD de %vol à mmHg
    int CO2;
    CO2 = (P_CO2 * 100) / 100;  // juste pour afficher un entier
    return (CO2);
  } else {
    return (99);
  }
}
void setup() {
  u8g2.begin();  //Start Screen
  Serial.begin(115200);
  Serial.println();
  Serial1.begin(9600);  //9600 selon doc
  Serial.println(F("Prêt à recevoir des trames"));
}



void loop() {


  Serial.println(valCO2());

  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_timB18_tr);
  u8g2.drawStr(1, 25, "Co2: ");
  u8g2.setFont(u8g2_font_timB10_tr);
  u8g2.drawStr(85, 25, "mmHg");
  u8g2.sendBuffer();
  u8g2.setFont(u8g2_font_timB18_tr);
  u8g2.setCursor(55, 25);
  u8g2.print(valCO2());
  u8g2.sendBuffer();

  delay(10);
}

c'est possible. si l'affichage est très lent et que les paquets arrivent vite, le buffer du port série ne peut stocker que 64 octets et donc vous pouvez peut être saturé ce buffer

Du coup, si je comprend bien l'affichage I2c et le port serie utilise le meme buffer ?

Ya t'il un moyen d'eviter la saturation de ce dernier, avec un clear ou autre ?

Pour rappel le capteur envoie 21 octets toute les 50ms.

non c'est séparé

en 153ms vous avez rempli le buffer série. Si l'Arduino est occupé pendant longtemps à effectuer de l'affichage (plus de 153ms) alors le buffer série se remplit en parallèle et vous n'allez pas le vider


à relire le code vous faites trop d'affichages. il ne faut afficher que quand valCO2() est dispo (et a changée même) pas à chaque tour de loop


et à relire le code, il semble que CO2exp ne sert à rien

la loop devrait faire

void loop() {
  if (frameRecue()) {
    // extraire les données et calculer la nouvelle valeur de CO2
    ...
   // comparer la valeur calculée de CO2 avec la valeur précédente
   ...
   // si changement, alors effectuer l'affichage
    ...
    // mémoriser la nouvelle valeur de CO2
  }
}

Hello,

j'ai réussi, plus de conflit et l'affichage marche parfaitement, je pense que ca venait des conversion et plus précisément des types de variable ?

Merci pour vos conseils

le code :

#include <U8g2lib.h>
#include "simpleBouton.h"
#include "simpleBouton.h"
#include <SoftwareSerial.h>

///configuration pin///
SoftwareSerial RS232(10, 11);  // RX, TX  => nécessite un convertisseur TTL vers RS232
simpleBouton bfonc(12);        // pin du bouton fonction

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);


bool btnState = true;  // etat initial btn

const uint8_t flag1 = 0xAA;
const uint8_t flag2 = 0x55;

byte waveformData[19];  // sans les flags
float CO2 = 0.0;
float Patm = 0.0;   // valeur par défaut de Patm
float Etco2 = 0.0;  // valeur par défaut de EtCO2

bool etatbouton() {
  if (bfonc) {
    btnState = !btnState;
  }
  return btnState;
}

// Conversion de % vol en mmHg
float volToMmHg(float vol, float Patm) {
  return ((vol / 100.0) * Patm);
}

bool receiveWaveform() {
  static enum : uint8_t { F1,
                          F2,
                          TRAME } etape = F1;
  bool receptionOK = false;
  static uint8_t compteur = 0;
  if (RS232.available() == 0) return false;  // rien à lire
  uint8_t recu = RS232.read();
  switch (etape) {
    case F1:
      if (recu == flag1) etape = F2;
      break;

    case F2:
      if (recu == flag2) {
        compteur = 0;
        etape = TRAME;
      } else if (recu != flag1) {
        etape = F1;
      }
      break;

    case TRAME:
      waveformData[compteur++] = recu;
      receptionOK = (compteur >= sizeof(waveformData));
      if (receptionOK) {
        etape = F1;  // on se prépare à recevoir la prochaine trame
        uint8_t id = waveformData[0];
        if (id == 0x03) {
          float newPatm = word(waveformData[16], waveformData[17]) * 7.5 / 10.0;
          if (newPatm != 0) Patm = newPatm;
        }
        if (id == 0x01) {
          float newEtco2 = (waveformData[12]) / 10;
          if (newEtco2 != Etco2) Etco2 = newEtco2;
        }
      }
  }
  return receptionOK;
}

void CO2play() {
  if (receiveWaveform()) {
    if (etatbouton() == true) {
      CO2 = word(waveformData[2], waveformData[3]) / 100.0;
      Serial.print("CO2 (en %vol) : ");
      Serial.println(CO2, 0);  //Affiche la valeur de CO2 sans décimale



      // Conversion de % vol en mmHg
      float CO2_mmHg = volToMmHg(CO2, Patm);

      // Affichage de la valeur de CO2 sur l'afficheur OLED
      u8g2.clearBuffer();
      u8g2.setFont(u8g2_font_timB18_tr);
      u8g2.drawStr(1, 25, "Co2: ");
      u8g2.setFont(u8g2_font_timB18_tr);
      u8g2.setCursor(55, 25);
      u8g2.print((int)CO2_mmHg);
      u8g2.setFont(u8g2_font_timB10_tr);
      u8g2.drawStr(85, 25, "mmHg");
      u8g2.sendBuffer();
    }

    if (etatbouton() == false) {

      float Etco2_mmHg = volToMmHg(Etco2, Patm);

      Serial.print("EtCO2 :  ");
      Serial.println(Etco2_mmHg, 0);

      // Affichage de la valeur de CO2 sur l'afficheur OLED
      u8g2.clearBuffer();
      u8g2.setFont(u8g2_font_timB12_tr);
      u8g2.drawStr(1, 25, "EtCo2: ");
      u8g2.setFont(u8g2_font_timB18_tr);
      u8g2.setCursor(55, 25);
      u8g2.print((int)Etco2_mmHg);
      u8g2.setFont(u8g2_font_timB10_tr);
      u8g2.drawStr(85, 25, "mmHg");
      u8g2.sendBuffer();
    }
  }
}

void setup() {
  Serial.begin(9600);
  RS232.begin(9600);
  u8g2.begin();  //Initialise l'afficheur OLED
}

void loop() {
  CO2play();
}

Non c’est vraiment que vous passiez votre temps à essayer d’afficher au lieu d’écouter pour voir s’il y avait une nouvelle trame de dispo

Cool si ça fonctionne maintenant