[Résolue] Serial pour en contrôler un autre avec telle données

Bonjour tous le monde :slight_smile:

Je crée ce topic car je ne trouve la solution, je souhaite en quelque sorte activer la réception d'un Serial par la réception de données sur un autre Serial.

Je m'explique:
Le Serial3 dois recevoir des données pour que le Serial2 puisse recevoir et enregistrer ces valeurs dans un tableau.

Je teste d'abord par des valeurs simple (6,17,0) pour l'ouverture et (6,1,0) pour la fermeture

Voici mon programme:

boolean recept = false;
byte consult[28];
int read_byte;
long sent = 6 + 41 + 0 + 41 + 127 + 41 + 122 + 41 + 15 + 41 + 30 + 41 + 58 + 41 + 29 + 41 + 117 + 41 + 57 + 41 + 121 + 41 + 31 + 41 + 125 + 41 + 123 + 41 + 116 + 41 + 118 + 41 + 56 + 41 + 112 + 41 + 111 + 0;
int diag = 6 + 17 + 0;
int closef = 6 + 1 + 0;

void setup() {
  Serial.begin(9600);
  Serial2.begin(9600);
  Serial3.begin(9600);
}

void loop() {

  if ( recept == false) {
    if (Serial3.available() > 0) {
      read_byte = Serial3.read();
      Serial.println(read_byte);
    }
    if (read_byte == diag) {
      //Serial2.readBytes(consult, 28);
      Serial.println("OK");
      recept = true;
    }
  }

  if ( recept == true) {
    if (Serial3.available() > 0) {
      read_byte = Serial3.read();
    }
    if (read_byte == closef) {
      Serial.println("Close");
      recept = false;
    }
  }


}//End Loop

voici le code receptionner par l'arduino que je souhaite utiliser pour active le Serial2(en commentaire actuellement pour les test:

6
29
0
29
7F
29
7A
29
F
29
1E
29
3A
29
1D
29
75
29
39
29
79
29
1F
29
7D
29
7B
29
74
29
76
29
38
29
70
29
6F
0
---------
6 // fermeture
1
0

Mon souci est que je ne trouve pas le moyen de faire une action par rapport à un ensemble de données et non pas une.

Pourriez-vous m'aidez ?

Imprimez - juste pour voir - ce que vous avez mis dans sent, diag et closef....

Il faut utiliser des tableaux pour mémoriser les étapes et gérer correctement le port série

Si vous lisez l'anglais cet article vous aidera à écrire un code structuré pour gérer le port série

J-M-L:
Imprimez - juste pour voir - ce que vous avez mis dans sent, diag et closef....

Il faut utiliser des tableaux pour mémoriser les étapes et gérer correctement le port série

Si vous lisez l'anglais cet article vous aidera à écrire un code structuré pour gérer le port série

Effectivement, je n'ai pas pensé à imprimer le "sent", faut que j’arrête de faire ça le soir après le taf ^^

Merci pour l'article, vous m'aviez déjà fait part de cet article et je ne l'ai pas encore traduis car je comprend pas tous.

C'est bon j'ai trouvé la solution :

boolean recept = false;

byte display1[37];//Open Display

//Consult
byte consult[28]; //Consult Gauges

void setup() {
  Serial.begin(9600);
  Serial2.begin(9600);
  Serial3.begin(9600);
}

void loop() {

  while (recept == true) {
    goto Consult;
  }

  if ( recept == false) {
    displayO();
  }

  
Consult:  Serial2.readBytes(consult, 28);




}//End Loop

//-----------------------Open Display-----------------------//
void displayO() {
  Serial3.readBytes(display1, 37);
  if ((display1[0] == 6) && (display1[1] == 41) && (display1[3] == 41) && (display1[35] == 41)) {
    Serial.println("Open Display");
    recept = true;
  }
}

Merci :wink:

  while (recept == true) {
    goto Consult;
  }
 [color=red]****** <--- si votre code arrive ici, vu le while au dessus, que vaut recept?[/color]
  if ( recept == false) {
    displayO();
  }

beurk    goto Consult; :roll_eyes: :roll_eyes: :roll_eyes: :astonished: :astonished:

Avec ça Serial2.readBytes(consult, 28);vous n'êtes pas garanti de lire tous vos octets... la fonction peut faire un timeOut

J-M-L:
while (recept == true) {
goto Consult;
}
****** <--- si votre code arrive ici, vu le while au dessus, que vaut recept?
if ( recept == false) {
displayO();
}

En faite j'ai fait comme ça car avant j'avais plus de paramètre pendant mes tests :

boolean recept = false;
boolean recept1 = false;

byte display1[37];//Open Display
byte display2[2];//Close Diplay
byte diag[2]; //Open/close Diag

//Consult
byte consult[28];

int batt;
int tps;
int water;

void setup() {
  Serial.begin(9600);
  Serial2.begin(9600);
  Serial3.begin(9600);
}

void loop() {

  if (recept == true) {
    goto Consult;
  }

  if ( recept == false) {
    displayO();
  }

  if ( recept == true) {
    displayC();
  }

  if ( recept1 == false) {
    diagO();
  }

  if ( recept1 == true) {
    diagC();
  }


Consult:  Serial2.readBytes(consult, 28);

  if (consult[0] == 0xFF) {
        Print();
  }


}//End Loop

//-----------------------Open Display-----------------------//
void displayO() {
  Serial3.readBytes(display1, 37);
  if ((display1[0] == 6) && (display1[1] == 41) && (display1[3] == 41) && (display1[35] == 41)) {
    Serial.println("Open Display");
    recept = true;
  }
}
//-----------------------Close Display-----------------------//
void displayC() {
  Serial3.readBytes(display2, 2);
  if ((display2[0] == 6) && (display2[1] == 1) && (display2[2] == 1)) {
    Serial.println("Close Display");
    recept = false;
  }
}
//-----------------------Open Diag-----------------------//
void diagO() {
  Serial3.readBytes(diag, 2);
  if ((diag[0] == 6) && (diag[1] == 23) && (diag[2] == 0)) {
    Serial.println("Open Diag");
    recept1 = true;
  }
}
//-----------------------Close Diag-----------------------//
void diagC() {
  Serial3.readBytes(diag, 2);
  if ((diag[0] == 6) && (diag[1] == 1) && (diag[2] == 1)) {
    Serial.println("Close Diag");
    recept1 = false;
  }
}

void Print() {
  Serial.print("Water Temp C="); Serial.println(water);
  Serial.print("Battery="); Serial.println(batt);
  Serial.print("Throttle="); Serial.println(tps);
}

Donc une fois le Display ouvert le reste est sauté.

J-M-L:
beurk :roll_eyes: :roll_eyes: :roll_eyes: :astonished: :astonished:

Pourquoi ?

J-M-L:
Avec ça Serial2.readBytes(consult, 28); vous n'êtes pas garanti de lire tous vos octets... la fonction peut faire un timeOut

Que suggérez vous ?

Vous faites un goto, ce qui n'est pas considéré super propre par les puristes du C ou C+, pour sauter des if... pourquoi ne pas faire un if/else... le goto ne se justifie absolument pas

Sinon vaut mieux lire par vous même les données quand elles arrivent

D'accord, vous pouvez donnez un exemple à suivre pour lire les données, c'est plus rapide ?

Vous pouvez lire cet Article (en anglais) sur la bonne gestion du port série

Tenez je me suis amusé à faire un petit exemple

const uint8_t magicPhrase[] = {'m', 'a', 'g', 'i', 'c'}; // pas obligatoirement des caractères
const uint8_t localBufferSize = sizeof(magicPhrase); // attention faire -1 si vous utilisez une c-string pour initialiser la phrase magique
uint8_t localBuffer[localBufferSize]; // buffer circulaire de la bonne taille

boolean gotMagicPhrase()
{
  boolean magicFound = false;
  static byte index = 0; // là où on est en train d'écrire dans le buffer circulaire

  while (Serial.available() > 0) {
    localBuffer[index] = (uint8_t) Serial.read();

    // *******************************************************************
    // DEBUG SI VOUS VOULEZ VOIR LE BUFFER CIRCULAIRE QUI SE CONSTRUIT
    //            VOUS POUVEZ VIRER CE CODE QUI NE SERT A RIEN
    // *******************************************************************
    Serial.print("[");
    for (byte i = 0; i < localBufferSize; i++) {
      Serial.print((char) localBuffer[i]); // en ASCII
    }
    Serial.print("] --> ");

    Serial.print("{ ");
    for (byte i = 0; i < localBufferSize; i++) {
      Serial.print("0x"); Serial.print(localBuffer[i], HEX); Serial.print(" "); // en HEXA
    }
    Serial.println("}");
    // *******************************************************************


    magicFound = true;
    for (int i = 0; i < localBufferSize; i++) {
      if (localBuffer[(index + 1 + i) % localBufferSize] != magicPhrase[i]) {
        magicFound = false;
        break; // pas la peine de continuer, le buffer n'est pas bon
      }
    }

    index++; // le prochain caractère ira dans cette case
    if (index == localBufferSize) index = 0; // on boucle dans le buffer circulaire

    if (magicFound) break;
  }

  return magicFound;
}


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

  // pas nécessaire pour une variable globale mais pour vous montrer comment faire
  // si vous aviez besoin de mettre le buffer à vide
  // memset(localBuffer, '\0', localBufferSize);

}

void loop() {
  static boolean foundMagicPhrase = false;
  if (!foundMagicPhrase) {
    foundMagicPhrase = gotMagicPhrase(); // on va voir si on a reçu la phrase
    if (foundMagicPhrase) {
      Serial.println("Bingo");
    } else {
      // *******************************************************************
      // ici vous faites ce que vous voulez, en attendant la phrase magique
      // *******************************************************************


      // *******************************************************************
    }
  } else {
    // *******************************************************************
    // ici vous faites ce que vous voulez, on a reçu la phrase magique
    // *******************************************************************


    // *******************************************************************

  }
}

le code écoute ce qu'il se dit sur le port Serial

S'il voit passer la suite d'octet m a g i c (définie dans la constante magicPhrase) alors il affiche Bingo dans la console

le code utilise la technique du buffer circulaire pour conserver en mémoire les n derniers octets reçus ou n correspond à la longueur de la séquence magique que l'on attend pour démarrer.

le code est non bloquant. vous pouvez faire autre chose en attendant la séquence magique et autre chose une fois la séquence magique reçue. C'est traité directement dans la loop()

Pour tester, ouvrez la console à 115200 bauds, désactivez l'envoi de toute fin de ligne
tapez [color=blue]Bonjour[/color] vous verrez le buffer se construire.
tapez ensuite [color=blue]Salut[color=red]magic[/color]1234[/color] et vous verrez Bingo apparaître dès que

magic

est reconnu. les octets suivant [color=blue]1234[/color] ne sont pas lus et restent dans le buffer de Serial.

voici l'affichage sur la console que vous devriez voir

</sub> <sub>[color=blue][nobbc][B][/nobbc] --> { 0x42 0x0 0x0 0x0 0x0 } [Bo] --> { 0x42 0x6F 0x0 0x0 0x0 } [Bon] --> { 0x42 0x6F 0x6E 0x0 0x0 } [Bonj] --> { 0x42 0x6F 0x6E 0x6A 0x0 } [Bonjo] --> { 0x42 0x6F 0x6E 0x6A 0x6F } [uonjo] --> { 0x75 0x6F 0x6E 0x6A 0x6F } [urnjo] --> { 0x75 0x72 0x6E 0x6A 0x6F } [urSjo] --> { 0x75 0x72 0x53 0x6A 0x6F } [urSao] --> { 0x75 0x72 0x53 0x61 0x6F } [urSal] --> { 0x75 0x72 0x53 0x61 0x6C } [urSal] --> { 0x75 0x72 0x53 0x61 0x6C } [utSal] --> { 0x75 0x74 0x53 0x61 0x6C } [utmal] --> { 0x75 0x74 0x6D 0x61 0x6C } [utmal] --> { 0x75 0x74 0x6D 0x61 0x6C } [utmag] --> { 0x75 0x74 0x6D 0x61 0x67 } [itmag] --> { 0x69 0x74 0x6D 0x61 0x67 } [[color=red]icmag[/color]] --> { 0x69 0x63 0x6D 0x61 0x67 } [color=black][b]Bingo[/b][/color] [/color]</sub> <sub>

On voit bien le rôle du buffer circulaire, [color=red]magic[/color] n'est pas écrit du début à la fin du buffer mais c'est pas grave, le code gère cela avec la boucle suivante

    magicFound = true;
    for (int i = 0; i < localBufferSize; i++) {
      if (localBuffer[(index + 1 + i) % localBufferSize] != magicPhrase[i]) {
        magicFound = false;
        break; // pas la peine de continuer, le buffer n'est pas bon
      }
    }

qui regarde les derniers caractères reçus à partir du bon endroit

:o

Ça c'est très sympa de votre part, Merci à vous :slight_smile:

je vais étudier ce programme, et reviens vers vous.

J'ai donc regardé de plus prèt et modifier avec mes valeurs/code, je n'ai pas réussi/pas compris :

const uint8_t SendPC[] = {6,29,0,29,0x7F,29,0x7A,29,0xF,29,0x1E,29,0x3A,29,0x1D,29,75,29,39,29,79,29,0x1F,29,0x7D,29,0x7B,29,74,29,76,29,38,29,70,29,0x6F,0}; // pas obligatoirement des caractères
const uint8_t localBufferSize = sizeof(SendPC); // attention faire -1 si vous utilisez une c-string pour initialiser la phrase magique
uint8_t localBuffer[localBufferSize]; // buffer circulaire de la bonne taille

boolean gotSendPC()
{
  boolean SendFound = false;
  static byte index = 0; // là où on est en train d'écrire dans le buffer circulaire

  while (Serial2.available() > 0) {
    localBuffer[index] = (uint8_t) Serial2.read();
    SendFound = true;
    for (int i = 0; i < localBufferSize; i++) {
      if (localBuffer[(index + 1 + i) % localBufferSize] != SendPC[i]) {
        SendFound = false;
        break; // pas la peine de continuer, le buffer n'est pas bon
      }
    }

    index++; // le prochain caractère ira dans cette case
    if (index == localBufferSize) index = 0; // on boucle dans le buffer circulaire

    if (SendFound) break;
  }

  return SendFound;
}


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

  // pas nécessaire pour une variable globale mais pour vous montrer comment faire
  // si vous aviez besoin de mettre le buffer à vide
  // memset(localBuffer, '\0', localBufferSize);

}

void loop() {
  static boolean foundSendPC = false;
  if (!foundSendPC) {
    foundSendPC = gotSendPC(); // on va voir si on a reçu la phrase
    if (foundSendPC) {
      Serial.println("Display Gauges Actived");
    } else {
      // *******************************************************************
      // ici vous faites ce que vous voulez, en attendant la phrase magique
      // *******************************************************************


      // *******************************************************************
    }
  } else {
    // *******************************************************************
    // ici vous faites ce que vous voulez, on a reçu la phrase magique
    // *******************************************************************


    // *******************************************************************

  }
}

Il peut aussi être grand comme programme par rapport à ce que je dois faire ?

Voici mon programme fonctionnel en version light:

/* R13 Consult Auto Transmission By 200sx200*/
boolean recept = false;
boolean displayP = false;
byte display1[37];//Open Display
//Consult
byte consult[28];
//int gauges
int tps;
int sped;
// Led remplace solenoid
const int Solenoid_A = 31;
const int Solenoid_B = 33;
const int Solenoid_Clutch = 35;
const int Solenoid_Lockup = 37;
//const int Solenoid_Pressure = 39;
// on when pin is high
// off when pin is low
const int SON = LOW;
const int SOFF = HIGH;
//vitesse
int vitesse = 1;


//setup
void setup() {
  Serial.begin(9600);
  Serial2.begin(9600);
  Serial3.begin(9600);
  pinMode(Solenoid_A, OUTPUT);        //solenoid A
  pinMode(Solenoid_B, OUTPUT);        //solenoid B
  pinMode(Solenoid_Clutch, OUTPUT);   //solenoid Overrun Clutch
  pinMode(Solenoid_Lockup, OUTPUT);  //solenoid Lock-up
  //pinMode(Solenoid_Pressure, OUTPUT); //solenoid Line Pressure
}

void loop() {

  if ( recept == false) {
    displayO();
  }

  while (recept == true) {
    Serial2.readBytes(consult, 28);

    if (consult[0] == 0xFF) {
      byteconsult();
      //Print();



      //-----------------------------Gearbox----------------------------------//
      if (recept == true) {
        byteconsult();

        if (tps >= 3) { // 100% => D1->D2->D3->D4
          if (sped < 10) {
            Vitesse1();
          }
          if (sped > 10 && sped <= 14) { //OEM=45->49
            Vitesse2();
          }
        }
      }
      //-----------------------------Gearbox----------------------------------//
    }
  }


}//End Loop



//-----------------------Open Display-----------------------//
void displayO() {
  Serial3.readBytes(display1, 37);
  if ((display1[0] == 6) && (display1[1] == 41) && (display1[3] == 41) && (display1[35] == 41)) {
    Serial.println("Open Display detected");
    recept = true;
  }
}

void byteconsult() {
  //Speed kph
  sped = consult[4] * 2;
  //Throttle Position voltage
  tps = consult[11];
  tps = ((tps * 20) / 1000.0);
}

void Print() {
  Serial.print("Speed kph="); Serial.println(sped);
  Serial.print("Throttle="); Serial.println(tps);
}

// 1 => BC
void Vitesse1() {
  Serial.println("Vitesse1");
  digitalWrite(Solenoid_A, SON);
  digitalWrite(Solenoid_B, SON);
  digitalWrite(Solenoid_Clutch, SON);
  digitalWrite(Solenoid_Lockup, SOFF);
  //digitalWrite(Solenoid_Pressure, SOFF);
}

// 2 => ABDEG
void Vitesse2() {
  Serial.println("Vitesse2");
  digitalWrite(Solenoid_A, SOFF);
  digitalWrite(Solenoid_B, SON);
  digitalWrite(Solenoid_Clutch, SON);
  digitalWrite(Solenoid_Lockup, SOFF);
  //digitalWrite(Solenoid_Pressure, SOFF);
}

Sur la fonction Display(), il n'y aura pas d'octet supplémentaire possible(provenance PC).

Dans la version light vous attendez quoi comme code pour commencer ?

J-M-L:
Dans la version light vous attendez quoi comme code pour commencer ?

Dans le void display0:

void displayO() {
  Serial3.readBytes(display1, 37);
  if ((display1[0] == 6) && (display1[1] == 41) && (display1[3] == 41) && (display1[35] == 41)) {
    Serial.println("Open Display detected");
    recept = true;  }}

Les bytes 0,1,3,35 suffissent comme code, seulement les 2 premiers aurais pue suffire.
Ils n'y a pas beaucoup de transmission via le PC :wink:

Pourquoi attendez vous alors de recevoir ça pour commencer ?

SendPC[] = {6,29,0,29,0x7F,29,0x7A,29,0xF,29,0x1E,29,0x3A,29,0x1D,29,75,29,39,29,79,29,0x1F,29,0x7D,29,0x7B,29,74,29,76,29,38,29,70,29,0x6F,0};

Je vois aussi qu'il y a de l'hexadeximal et du décimal . Le 29 par exemple, c'est 29 ou 0x29?

J-M-L:
Pourquoi attendez vous alors de recevoir ça pour commencer ?

Bonne question, j'ai zappé le coté "les octets suivant ne sont pas lus"

J-M-L:
Je vois aussi qu'il y a de l'hexadeximal et du décimal . Le 29 par exemple, c'est 29 ou 0x29?

Oui, j'ai pas pensé à les remplacés :confused:
L'arduino prendrais des valeurs de plusieurs types ?

C'est le compilateur qui interprète ce que vous tapez en C++, ensuite c'est codé en binaire, des 1 et des 0 en mémoire

Si vous écrivez

A = 11;
B = 0x11;
C = 011;
D = 11B;

Et que vous imprimez ces valeurs vous verrez qu'elles sont toutes différentes

A est en décimal (base 10) ce que vous utilisez dans la vraie vie
B est en hexadécimal (base 16)
C est en octal (base 8 )
D est en binaire (base 2)

Donc dans le tableau si c'est important de tester l'ensemble de la communication il faut bien mettre toutes les bonnes valeurs dans la base que vous voulez mais il faut que ça corresponde. Si vous vous fichez d'avoir reçu toute la chaîne et que seul le dernier caractère compte (et n'arrive pas plusieurs fois dans la chaîne) alors ne mettez que le dernier caractère à écouter. Vous ne pouvez pas mettre 0 pour dire je me fiche de cette valeur (ou alors modifiez le test de validité) il faut que tout corresponde

D'accord, mais s'il y avait des valeurs identiques ? je peux choisir le numéro de la valeurs comme dans le tableau byte ? ex: tableau[2] et tableau[11]

Ou il faudrait enregistrer les valeurs reçues dans un tableau pour ensuite choisir telle valeur ?

mon code attend une suite de valeurs - ce n'est pas grave s'il y en a 2 identiques, l'important c'est que la suite de valeurs soit dans le bon ordre. Si au lieu de magic vous mettez hello par exemple, les 2 l ne sont pas un soucis. tant que vous ne tapez pas hello la détection ne fonctionne pas.

si vous vouliez dire "je me fiche du caractère qui est à tel endroit" vous pourriez modifier le code. par exemple dire que le caractère '?' veut dire n'importe quel valeur de cet octet est OK et en tenir compte dans le code de test dans le buffer.

par exemple en mettant comme phrase à détecter ma?ic alors magic va fonctionner mais aussi maRic ou maTic ou ce que vous voulez pour le troisième octet. c'est vous qui contrôlez ce qui est acceptable par votre code de test.

voici le code modifié pour tenir compte d'un point d'interrogation comme caractère générique

const uint8_t genericByte = '?';

const uint8_t magicPhrase[] = {'m', 'a', '?', 'i', 'c'}; // pas obligatoirement des caractères

const uint8_t localBufferSize = sizeof(magicPhrase); // attention faire -1 si vous utilisez une c-string pour initialiser la phrase magique
uint8_t localBuffer[localBufferSize]; // buffer circulaire de la bonne taille

boolean gotMagicPhrase()
{
  boolean magicFound = false;
  static byte index = 0; // là où on est en train d'écrire dans le buffer circulaire

  while (Serial.available() > 0) {
    localBuffer[index] = (uint8_t) Serial.read();

    // *******************************************************************
    // DEBUG SI VOUS VOULEZ VOIR LE BUFFER CIRCULAIRE QUI SE CONSTRUIT
    //            VOUS POUVEZ VIRER CE CODE QUI NE SERT A RIEN
    // *******************************************************************
    Serial.print("[");
    for (byte i = 0; i < localBufferSize; i++) {
      Serial.print((char) localBuffer[i]); // en ASCII
    }
    Serial.print("] --> ");

    Serial.print("{ ");
    for (byte i = 0; i < localBufferSize; i++) {
      Serial.print("0x"); Serial.print(localBuffer[i], HEX); Serial.print(" "); // en HEXA
    }
    Serial.println("}");
    // *******************************************************************


    magicFound = true;
    for (int i = 0; i < localBufferSize; i++) {
      if (magicPhrase[i] != genericByte) { // le genericByte correspond à n'importe quel octet donc on le saute
        if (localBuffer[(index + 1 + i) % localBufferSize] != magicPhrase[i]) {
          magicFound = false;
          break; // pas la peine de continuer, le buffer n'est pas bon
        }
      }
    }

    index++; // le prochain caractère ira dans cette case
    if (index == localBufferSize) index = 0; // on boucle dans le buffer circulaire

    if (magicFound) break;
  }

  return magicFound;
}


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

  // pas nécessaire pour une variable globale mais pour vous montrer comment faire
  // si vous aviez besoin de mettre le buffer à vide
  // memset(localBuffer, '\0', localBufferSize);

}

void loop() {
  static boolean foundMagicPhrase = false;
  if (!foundMagicPhrase) {
    foundMagicPhrase = gotMagicPhrase(); // on va voir si on a reçu la phrase
    if (foundMagicPhrase) {
      Serial.println("Bingo");
    } else {
      // *******************************************************************
      // ici vous faites ce que vous voulez, en attendant la phrase magique
      // *******************************************************************


      // *******************************************************************
    }
  } else {
    // *******************************************************************
    // ici vous faites ce que vous voulez, on a reçu la phrase magique
    // *******************************************************************


    // *******************************************************************

  }
}

on définit la phrase clé comme étant

const uint8_t magicPhrase[] = {'m', 'a', '?', 'i', 'c'}; // pas obligatoirement des caractères

et si je tape [color=blue]coucou[color=red]matic[/color]1234[/color] la sortie me dit

[sub][color=blue][c] --> { 0x63 0x0 0x0 0x0 0x0 }
[co] --> { 0x63 0x6F 0x0 0x0 0x0 }
[cou] --> { 0x63 0x6F 0x75 0x0 0x0 }
[couc] --> { 0x63 0x6F 0x75 0x63 0x0 }
[couco] --> { 0x63 0x6F 0x75 0x63 0x6F }
[uouco] --> { 0x75 0x6F 0x75 0x63 0x6F }
[u[color=red]m[/color]uco] --> { 0x75 0x6D 0x75 0x63 0x6F }
[u[color=red]ma[/color]co] --> { 0x75 0x6D 0x61 0x63 0x6F }
[u[color=red]mat[/color]o] --> { 0x75 0x6D 0x61 0x74 0x6F }
[u[color=red]mati[/color]] --> { 0x75 0x6D 0x61 0x74 0x69 }
[[color=red]cmati[/color]] --> { 0x63 0x6D 0x61 0x74 0x69 }
[color=black][b]Bingo[/b][/color]
[/color][/sub]

On voit donc bien que le '?' a bien été considéré comme générique et matic est une bonne entrée
OK ?

oui oui d'accord mais si je souhaite pas exemple faire de "magic" l'octet 1,2,3 et 35 . (3er octet et dernier)

Avec un tableau c'est "octet[1]&&octet[2]&&octet[3]&&octet[35]"

Mais le sa voudrais dire que je dois faire "const uint8_t magicPhrase[] = {'1', '2', '3', '?xfois'(jusqu'à 34 ?), '35'}; ?