Contrôler des LED avec des chaînes de caractères

Bonjour,
Je souhaiterais contrôler des LED de couleurs avec des chaînes de caractères.
Exemple: pouvoir écrire, allumer rouge et la led rouge s’allume. Faire pareil pour les éteindre.
Mon code ne fonctionne pas et se contente juste de lire ce que j’écris sans le “comprendre”. Par exemple, si j’écris “allumer bleu”, le code va seulement écrire “allumer bleu” dans le moniteur série sans allumer la LED bleu.
Mon code est en piece jointe.

Merci de votre aide. :slight_smile:

test_2.ino (1.42 KB)

Probablement un problème de '\r' + '\n' qui traîne en fin de chaîne.

Sur quelle plateforme ? UNO, MEGA ou autre ?

Bonjour,

Mets ton programme entre balises de code.

La pin 2 (entre autres) n'est pas une pin PWM, donc on ne peut pas utiliser analogWrite(). Utiliser digitalWrite().
Cependant je ne pense pas que ce soit ça le problème car dans ce cas le framework utilise digitalWrite().

Verifies ton cablage. Comment sont cablées tes leds?

hbachetti a peut être mis le doigt sur le problème. Fais
    msg.trim();après réception

Il n'y a pas que ça. Même avec une D2 avec PWM cela ne marcherait pas.

Je vais développer un peu.

Si tu as "Pas de fin de ligne" en paramètre fin de ligne dans le terminal cela marchera.

Si tu as "Les deux NL et CR" en paramètre fin de ligne dans le terminal il faudrait enlever "\r\n".

C'est peut être un peu plus clair ...

Ensuite utiliser String avec un ATMEGA328 est discutable (refrain habituel).

Bonjour,

je possède une carte Arduino NANO et les branchements de mes LED sont corrects. Voici le code :

 String msg;

void setup() {
  pinMode(2,OUTPUT);
  pinMode(3,OUTPUT);
  pinMode(4,OUTPUT);
  pinMode(5,OUTPUT);
  pinMode(6,OUTPUT);
  pinMode(7,OUTPUT);
  // initialisation de la liaison série à 9600 bits/seconde 
  Serial.begin(9600);
  while (!Serial) { 
  } // ne rien faire tant que la liaison série n'est pas établie
}
 
void loop() {
  // on attend qu'il y ait des données sur la liaison série
  if (Serial.available()>0) {  
    // on lit les données reçue (dans la variable "donnee")
    msg=Serial.readString();
    Serial.println(msg);
 

    //allumer
    if (msg=="allumer bleu") {
      Serial.println("Allumer bleu");
      analogWrite(2,200); //intensité lumineuse de 0 à 255
    }
     if (msg=="allumer cyan") {
      Serial.println("Allumer cyan");
      analogWrite(3,200);
    }
     if (msg=="allumer vert") {
      Serial.println("Allumer vert");
      analogWrite(4,200);
    }
     if (msg=="allumer ambre") {
      Serial.println("Allumer ambre");
      analogWrite(5,200);
    }
     if (msg=="allumer orange") {
      Serial.println("Allumer orange");
      analogWrite(6,200);
    }
     if (msg=="allumer rouge") {
      Serial.println("Allumer rouge");
      analogWrite(7,200);
    }

   //éteindre
   // if (msg=="éteindre bleu" && analogWrite >0) {
    //  Serial.println("éteindre bleu");
    //  analogWrite(2,0);
   // }
     
    
    
 
  }
}

Merci pour vos réponses

Tu as essayé de mettre msg.trim(); après la réception?

Je viens de tester de rejouter msg.trim(); après la réception et cela fonctionne :slight_smile:
Merci pour vos réponses.

C’était bien le problème pointé par hbachetti: ton terminal est configuré pour envoyer les caractères de fin de ligne.

Sommes-nous que le fonctionnement est correct avec ce code si le terminal est configuré avec “Pas de fin de ligne” ?

Par contre si tu enlèves les caractères fin de ligne comme ceci :

    msg = Serial.readString();
    msg.trim();

Le code fonctionnera quelle que soit la configuration du terminal.

Par contre tu auras peut être remarqué que la réaction est lente.
Ceci est la conséquence du timeout de 1 seconde de readString().

Dommage de perdre autant de temps.

    msg = Serial.readStringUntil('\r');

readStringUntil permet d’arrêter la lecture lorsque CarriageReturn (CR = ‘\r’ = 13) est reçu.
Cette fois-ci si le terminal est configuré avec “CR” ou “NL + CR”, la réaction est instantanée.
Si le terminal est configuré avec “Pas de fin de ligne” ou “NL seulement”, le timeout est toujours présent, mais cela marche quand même.

Ensuite utiliser String avec un ATMEGA328 est discutable. Cela peut provoquer une fragmentation de la mémoire.
Si c’est un petit essai pour jouer ce n’est pas grave, mais s’il s’agit d’un projet sérieux il serait plus sûr de recevoir les caractères un par un avec Serial.read() dans une C string.

Dernier point :

kamill:
La pin 2 (entre autres) n’est pas une pin PWM

Arduino NANO PWM : 3, 5, 6, 9, 10, 11

Pour lire n caractères dans une C string il y a aussi readBytesUntil() :

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

void loop()
{
  char buf[256];

  if (Serial.available()) {
    int n = Serial.readBytesUntil('\r', buf, 256);
    buf[n] = '\0';
    if (n == 1 && buf[0] == '\n') {
      return;
    }
    Serial.println(buf);
    if (!strcmp(buf, "bonjour")) {
      Serial.println("bienvenue");
    }
    else if (!strcmp(buf, "au revoir")) {
      Serial.println("à bientôt");
    }
  }
}

Vous pouvez jeter un oeil à mon petit tuto sur le sujet d'écoute du port série.

Ensuite un test avec strstr() sur le buffer reçu pourra vous dire si le message contient ce que vous cherchez

Bonjour

La lecture de ce topic m'interresse fortement car dans mon projet avec le nextion,
j'utilise une bibliothèque (qui va pas trop mal), mais qui utilise des String.

Est-ce que sur Mega 2560 le soucis est le même svp ?. Si oui j'essaierais de me débrouiller autrement, mais c'est pas gagné. (j'ai lu le tuto de JML)

Je met un exemple du code pour que vous jugiez

void loop() {
  bp = digitalRead(bpPin);

  potarValue = analogRead(potarPin);
  voltage = potarValue * (30.0 / 1023.0);
  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  //String command1 = "A.t2.txt=\"" + String(voltage, 1) + "C\"";//+  A PROSCRIRE meme avec un Mega ?
  //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  if (bp == HIGH) {
    myNextion.sendCommand("sleep=1");
  }

  myNextion.setComponentText("t2", String(voltage, 1));
  myNextion.setComponentText("t3", String(potarValue));

  //delay (400);
  //++++++++++++++++++++++++++++++++++++++
  String message = myNextion.listen(); //+ A PROSCRIRE meme avec un Mega ?
  //++++++++++++++++++++++++++++++++++++++++
  if (message.startsWith("68")) {
    myNextion.sendCommand("sleep=0");
  }

  if (message != "") {
    Serial.println(message);

  }

Merci

le problème avec les String ce n'est pas la classe en elle même, c'est le fait que vous allouez et potentiellement dé-allouez la mémoire dans un ordre arbitraire ce qui fait que au bout d'un moment il peut y avoir des difficultés à allouer de la mémoire.

sur un UNO il y a très peu de mémoire donc on voit vite le souci
sur un MEGA ce sera un peu plus tard mais pas longtemps après
sur un ESP encore plus tard...

mais si vous comprenez ce que vous faites, évitez de faire des + entre String etc, et allouez / dé-allouez en mode LIFO alors pas de souci.. mais si vous apprenez à travailler avec des cStrings vous serez plus tranquille.

Merci de votre réponse

Donc c'est clair, je laisse tomber

Comme je ne comprend pas trop ce que je fais (avec la com), et que c'est un projet qui doit durer,

je laisse tomber cette bibliothèque, et les Strings.

Je vais essayer d'apprendre avec les cstrings...

Je pense que vous allez me revoir....

vous pouvez regardez les fonctions sur les cString (tableaux de caractères terminés par un caractère null) qui sont dans les bibliothèques C standard: stdlib.h ou encore string.h. c'est ce qui est utilisé dans la classe String d'ailleurs :slight_smile:

J'ai regardé ça, mais j'avoue que ça rajoute a ma confusion.(je ne vois pas non plus comment charger la bib).

J'ai essayé (vite fais) un exemple du blog d'eskimo, mais je n'affiche rien
de ce qui arrive du nextion.

je vais essayer de comprendre...

pas besoin de charger une librairie, c'est en standard quand vous compilez

je n'utilise pas de nextion car ils n'ont pas d'outils pour mac :slight_smile:

Ah Ok.

Comment pourrais-je remplacer la ligne qui est entourée (et qui contient un String command1), simplement?

int potarPin = A0;
int potarValue = 0;
float envoi = 0;
void setup()
{
  Serial1.begin(9600);
  Serial.begin(9600);
}

void loop()
{
  potarValue = analogRead(potarPin);
  envoi = potarValue * (30.0 / 1023.0);

  // variable contenant le caractère à lire
  char carlu = 0;
  // variable contenant le nombre de caractère disponibles dans le buffer
  int cardispo = 0;

  cardispo = Serial1.available();

  while (cardispo > 0) // tant qu'il y a des caractères à lire
  {
    carlu = Serial1.read(); // on lit le caractère
    Serial.print(carlu); // puis on le renvoi à l’expéditeur tel quel
    cardispo = Serial1.available(); // on relit le nombre de caractères dispo
  }
  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  String command1 = "A.t3.txt=\"" + String(envoi, 1) + "C\""; +
  //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  Serial1.print(command1);
  Serial1.write(0xFF);               //  envoie 3x le charactere n°255 en decimal ou FF en exadecimal sur le port serie
  Serial1.write(0xFF);
  Serial1.write(0xFF);
  // Serial.print(command1);
  //delay (500);
}

D'avance merci beaucoup pour votre aide.

ps:dois-je ouvrir un autre fil, car j'aurais d'autres questions?

  String command1 = "A.t3.txt=\"" + String(envoi, 1) + "C\""; +
  Serial1.print(command1);

pour dégager la String --> c'est simple il suffit d'écrire les éléments séparément. Le port série il s'en fiche, il les reçoit de toutes façons séquentiellement

Serial1.print(F("A.t3.txt=\""));
Serial1.print(envoi, 1);
Serial1.print(F("C\""));

comme ça non seulement vous ne perdez pas de mémoire avec la commande intermédiaire, vous n'avez pas d'allocation dynamique de mémoire avec le '+' entre Strings, vous pouvez gagner 1.5ko de mémoire flash si vous n'utilisez pas la classe String et ça va tourner plus vite...

Ah Ok, je vais essayer cela

Alors, avec les exemples d’eskimon, j’arrive a chopper des “gris-gris” en provenance du nextion.

Merci beaucoup

ps: le nextion se rapproche de la poubelle…
heureusement j’aurais une semaine pour me calmer