Go Down

Topic: [Résolue] Serial pour en contrôler un autre avec telle données  (Read 351 times) previous topic - next topic

200sx200

Bonjour tous le monde :)

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:

Code: [Select]

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:
Code: [Select]

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 ?

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
Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

200sx200

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.

200sx200

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

Code: [Select]

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 ;)

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();
  }



beurk
Code: [Select]
    goto Consult;  :smiley-roll-blue:  :smiley-roll-blue:  :smiley-roll-blue:  :smiley-eek:  :smiley-eek:

Avec ça
Code: [Select]
Serial2.readBytes(consult, 28);vous n'êtes pas garanti de lire tous vos octets... la fonction peut faire un timeOut
Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

200sx200

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 :

Code: [Select]

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é.

beurk :smiley-roll-blue:  :smiley-roll-blue:  :smiley-roll-blue:  :smiley-eek:  :smiley-eek:
Pourquoi ?

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 ?

J-M-L

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
Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

200sx200

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

J-M-L

Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

J-M-L

Tenez je me suis amusé à faire un petit exemple
Code: [Select]
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 Bonjour vous verrez le buffer se construire.
tapez ensuite Salutmagic1234 et vous verrez Bingo apparaître dès que magic est reconnu. les octets suivant 1234 ne sont pas lus et restent dans le buffer de Serial.

voici l'affichage sur la console que vous devriez voir
[B] --> { 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 }
[icmag] --> { 0x69 0x63 0x6D 0x61 0x67 }
Bingo


On voit bien le rôle du buffer circulaire, magic 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
Code: [Select]
    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

Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

200sx200

 :o

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

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

200sx200

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

Code: [Select]

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:
Code: [Select]

/* 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).

J-M-L

Dans la version light vous attendez quoi comme code pour commencer ?
Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

200sx200

Dans la version light vous attendez quoi comme code pour commencer ?
Dans le void display0:

Code: [Select]

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 ;)

J-M-L

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?
Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

Go Up