Comprendre ce code Arduino pour un Robot

Bonjour,

je suis en 1S-SI et pour mon TPE, j’ai décidé de faire un robot capable de monter une marche très semblable à celui-ci : How to Make a Mars Rover / Rocker bogie Robot - Stair climbing - YouTube
en revanch epour la partie commande, j’ai décidé d’utiliser un Arduino au lieu d’utiliser un contrôleur pré-programmé, ayant pris cette décision tardivement, j’ai pas pu apprendre le langage arduino, même si j’ai commencé avec cet eBook : http://eskimon.fr/ebook-tutoriel-arduino

un ami m’as fait découvrir ce projet opensource : http://www.instructables.com/id/Bluetooth-Controlled-Robot-Using-Android-Mobile/
le code utilisé n’est pas exactement le même car moi j’utilise 6 moteurs au lieu de 6 mais le principe est relativement le même.
Du coup ce que je voudrais faire c’est quand je vais passer à l’oral de tpe le 13 mars en montrant également l’application que le créateur Instructable utilise, je vais aussi expliquer le code en ses grandes lignes, pour ça faudrait que je le comprenne moi même,

Pouvez vous donc m’expliquer rapidement le fonctionnement de ce code ?

vous pouvez télécharger le code dans le lien Instructables plus haut ou le voici :

//-------------------------------ANDROID CONTROLLED ROBOT------------------------------
//---------------------------------PROJECTS GARAGE--------------------------------

// Successfully Tested on Android App --> 'Arduino Bluetooth 
// Terminal'; it is available free on the Google Play Store

int state;
int flag=0;       
void stp();
void fwd();
void left();
void right();
void back();
void setup()
{
    pinMode(7,OUTPUT);                  
    pinMode(8,OUTPUT);                  
    pinMode(5,OUTPUT);                  
    pinMode(6,OUTPUT);                  
Serial.begin(9600);                                         // Baud rate set to 9600bps
}
void loop() {
    if(Serial.available() > 0)      // Ckeck for command Recieved
    {    
      state = Serial.read();
      Serial.println(state);  
      flag=0;
    }  
    if (state == '1')     // Checking Command from User
    {
        stp();
        if(flag == 0){
          Serial.println("Stop");
          flag=1;
       }
    }
    else if (state == '2')
    {
        fwd();
        if(flag == 0)
        {
          Serial.println("Forward");
          flag=1;
         }
    }
    else if (state == '3')
    {
        back();
        if(flag == 0)
        {
          Serial.println("Backward");
          flag=1;
        }
    }
    else if (state == '4')
    {
        left();
        if(flag == 0)
        {
          Serial.println("Left");
          flag=1;
         }
    }
   else if (state == '5')
  {
        right();
        if(flag == 0)
        {
          Serial.println("Right");
          flag=1;
         }
    }
}                                           //loop() ends here
void fwd()          // Forward
{
  digitalWrite(7,HIGH);
  digitalWrite(5,HIGH);
  digitalWrite(6,LOW);
  digitalWrite(8,LOW);
}
void back()          // Backward
{
  digitalWrite(8,HIGH);
  digitalWrite(6,HIGH);
  digitalWrite(7,LOW);
  digitalWrite(5,LOW);
}
void left()          //LEFT
{
  digitalWrite(7,HIGH);
  digitalWrite(5,LOW);
  digitalWrite(8,LOW);
  digitalWrite(6,LOW);
}
void right()          // Right
{
  digitalWrite(7,LOW);
  digitalWrite(5,HIGH);
  digitalWrite(8,LOW);
  digitalWrite(6,LOW);
}
void stp()            // Robot STops
{
  digitalWrite(7,LOW);
  digitalWrite(8,LOW);
  digitalWrite(5,LOW);
  digitalWrite(6,LOW);
}

Déjà, est-ce que tu comprends le montage électronique et le fonctionnement du composant L293D ?
Un extrait de ce site :

Comprendre le composant L293D
Le composant L293D est un pont de puissance composé de plusieurs transistors et relais qui permet d’activer la rotation d’un moteur. Ce composant se trouve facilement sur Ebay et ne coûte pas très cher.

Le L293D est un double pont-H, ce qui signifie qu’il est possible de l’utiliser pour commander quatre moteurs distincts (dans un seul sens) grâce à ses 4 canaux.
Il est également possible de constituer deux pont-h afin de piloter deux moteurs distincts, dans les deux sens et indépendamment l’un de l’autre.

Il est important de noter que le L293D peut délivrer au maximum 600mA, veuillez donc choisir vos moteurs en conséquence.

Si vous avez besoin de plus d’informations, n’hésitez pas à consulter la documentation technique du composant L293D disponible ici.

Caractéristiques techniques du L293D
Voici les caractéristiques techniques du composant L293D:

Nbre de pont-H: 2
Courant Max Régime continu: 600mA (x2)
Courant de pointeMax < 2ms: 1200mA
VS Max Alim moteur: 36v
VSS Max Alim logique: 7v
Nbre de Broches: 16 DIP
Perte de tension: 1.3v

Le code en lui même n’a rien de bien compliqué : il lit une commande envoyée depuis un téléphone (par exemple) en bluetooth et fait des actions selon la commande reçue. Les actions sont des consignes appliquées aux 2 moteurs pour les faire tourner (ou non) dans un sens ou dans l’autre.

Je ne comprends pas bien à quoi sert le flag, mais c’est pas le plus important.

Salut lesept,

merci pour ton lien qui m'as permit de mieux comprendre le fonctionnement d'un l293

d'accord j'ai bien compris le code en ses grandes lignes.

En revanche le jour de mon oral de TPE, il est certain qu'on me posera des questions précises sur mon code, je vais donc expliquer avec ma compréhension et mes mots le code si vous pouviez me dire si mon explication est correcte ou pas :

1--> au tout début, il déclare 2 variables :

int state;
int flag=0;

le type int indique que ces variables ont une valeur en retour (je dis ça mais je ne sais pas ce que ça veut dire)

2-->il crée ensuite des fonctions de type void (sans retour) :

void stp();
void fwd();
void left();
void right();
void back();

3--> vient alors la fonction d'initialisation qui sera exécuté à chaque démarrage et une seule fois

void setup()
{
    pinMode(7,OUTPUT);                  
    pinMode(8,OUTPUT);                  
    pinMode(5,OUTPUT);                  
    pinMode(6,OUTPUT);                  
Serial.begin(9600);                                         // Baud rate set to 9600bps
}

très bien, on initialise les broches ou pin en sortie
mais je ne comprends pas le

Serial.begin(9600);

ne serait ce pas la rapidité du signal envoyé depuis le tel ou autre appareil vers la carte arduino elle même branché à un un shield bluetooth ?

4--> commence alors la partie princiaple avec le loop :

void loop() {
    if(Serial.available() > 0)      // Ckeck for command Recieved
    {    
      state = Serial.read();
      Serial.println(state);  
      flag=0;
    }  
    if (state == '1')     // Checking Command from User
    {
        stp();
        if(flag == 0){
          Serial.println("Stop");
          flag=1;
       }
    }
    else if (state == '2')
    {
        fwd();
        if(flag == 0)
        {
          Serial.println("Forward");
          flag=1;
         }
    }
    else if (state == '3')
    {
        back();
        if(flag == 0)
        {
          Serial.println("Backward");
          flag=1;
        }
    }
    else if (state == '4')
    {
        left();
        if(flag == 0)
        {
          Serial.println("Left");
          flag=1;
         }
    }
   else if (state == '5')
  {
        right();
        if(flag == 0)
        {
          Serial.println("Right");
          flag=1;
         }
    }
}      [/code

bon déjà au début il y a 2 conditions if de suite, c'est autorisé ça ? 

puis là précisément au tout début du loop
[code]

if(Serial.available() > 0)      // Ckeck for command Recieved
    {    
      state = Serial.read();
      Serial.println(state);  
      flag=0;
    }

comme son commentaire le dit, est ce pour vérifier si l'arduino reçoit une commande ou pas depuis un autre appareil ?

mais à quoi correspond ce "serial" précisément qu'il utilise plusieurs fois ?

  • puis
 if (state == '1')     // Checking Command from User
    {
        stp();
        if(flag == 0){
          Serial.println("Stop");
          flag=1;
       }
    }

visiblement il utilise la variable state qui prendre des valeurs de 1 à 5 correspondant aux 5 actions : avancer,reculer,à droite,gauche et stop, ici '1' correspond au stop car il rappelle sa fonction "stp()" qu'il avait déclaré avant le void setup(),
-le "flag" j'ai aucune idée de ce que c'est,
-il utilise encore serial

5--> une fois que void est finie, le programme devrait s'arrêter là non? (je sens que c'est une question bête mais je demande car j'ai lu dans le livre plus haut que dans le code arduino, il y a 2 parties principales, setup et loop, avec loop qui contient le programme principal) or ici il continue même après le loop

il réutilise les 5 fonctions du début pour faire les 5 actions

void fwd()          // Forward
{
  digitalWrite(7,HIGH);
  digitalWrite(5,HIGH);
  digitalWrite(6,LOW);
  digitalWrite(8,LOW);
}
void back()

il met high ou low pour changer le sens et le courant pour avoir le mouvement voulu

merci d'avoir lu jusqu'ici, si vous pouvez m'aider dans mes 5 grands axes, cela m'aiderait beaucoup, de mon côté je vais continuer à lire le livre.

merci beaucoup[/code]

Rifos:
le type int indique que ces variables ont une valeur en retour

Le type int indique que ces variables sont des entiers. Les variables n'ont pas de "valeurs de retour", ce sont les fonctions qui en ont un.

2-->il crée ensuite des fonctions de type void (sans retour) :

Ceci ne crée pas las fonctions, ça les déclare (afin que le compilateur les reconnaisse plus loin dans le code)

mais je ne comprends pas le Serial.begin(9600); 

Serial est un objet qui est créé automatiquement, il s'occupe de la communication par USB. On commence par indiquer à quelle vitesse il fonctionne. Ici c'est 9600 bauds (c-à-d environ 9600 bits/seconde)

bon déjà au début il y a 2 conditions if de suite, c'est autorisé ça ?

Evidemment !
Mais il y a une erreur grave : le premier if devrait entourer tous les autres tests. ! Tu ne dois tester state et agir selon sa valeur que si state vient d'être lu. Dans ce programme, quand tu ne reçois plus de caractères, tu continues indéfiniment l'action correspondant au dernier caractère reçu !

est ce pour vérifier si l'arduino reçoit une commande ou pas depuis un autre appareil ? mais à quoi correspond ce "serial" précisément qu'il utilise plusieurs fois ?

Serial.avalaible() est une fonction (de l'objet Serial) qui indique le nombre de caractères reçus par USB.
Serial.println ( ... ) envoie des caractères sur l'USB. Tu peux les afficher dans la console série de l'IDE Arduino, si tu règles sa vitesse à 9600 - c-à- identique à ce que a mis dans Serial.begin (... )

le "flag" j'ai aucune idée de ce que c'est

Apparement flag sert à éviter d'écrire plusieurs fois de suite le même message, mais c'est mal programmé, car à chaque fois qu'un caractère est disponible, flag est remis à 0. Tel quel, il ne sert à rien.

une fois que void est finie, le programme devrait s'arrêter là non?

Ce n'est pas void qui est fini (ça ne veut rien dire) mais la fonction loop(). Par principe :

  • la fonction setup() est appelée une fois au début
  • la fonction loop(), comme son nom l'indique, est appelée en boucle. C-à-d que dès que son exécution est finie, et bien elle est appelée à nouveau, indéfiniment.

il réutilise les 5 fonctions du début pour faire les 5 actions

Il ne réutilise pas les fonctions, il les définit. Au début on les a déclarées, c-à-d on a dit qu'elles existaient, mais il faut bien les définir, dire ce qu'elle font. C'est ce qui est fait ici.
Le fait de les voir placées dans le code après la fonction loop() ne veut pas dire qu'elles seront execétée après loop(). Elle seront exécutées si et seulement si elles sont appelées depuis l'intérieur de loop().

Biggil a très bien expliqué. Je rajoute que la console sert ici à commander les moteurs.
Lorsque le programme est lancé, tu dois afficher la console en cliquant sur l'icone qui ressemble à une loupe en haut à droit de l'IDE à coté de "Serial Monitor" dans cette image:

Le Serial.begin(9600); initialise la communication entre l'Arduino et ton PC.

Dans la console tu peux entrer des valeurs de 1 à 5 qui seront lues par le state = Serial.read();. La commande if(Serial.available() > 0) sert à attendre que tu entres des valeurs. Le if ... else if ... else if ... teste la valeur que tu as entrée pour faire les actions correspondantes :

  • Stop
  • En avant
  • En arrière
  • Tourne à gauche
  • Tourne à droite
    Les Serial.println("Stop"); affichent la commande exécutée par le robot, pour vérification.

Ceci pourrait être fait en utilisant la fonction switch - case ce qui serait plus joli.

Je t'engage à bien comprendre ce programme, te l'approprier et le modifier afin qu'il te soit plus facile de l'expliquer lors de ton oral. Les explications qu'on te fournit ne sont pas suffisantes, si tu ne comprends pas bien le programme, les profs te poseront des questions auxquelles tu auras des difficultés à répondre.

Salut lesept,

juste pour le monitor, ça me donne 1 msg d'erreur

Arduino: 1.8.5 (Linux), Board: "Arduino/Genuino Uno"

Board at COM1 is not available

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

ps : à part ça, je suis en train de réfléchir à ta réponse et à celle de biggil

Ce message te dit que tu as déclaré que ton Arduino est connecté sur le port COM1 du PC mais que le PC ne l'y trouve pas. Vérifie dans le gestionnaire de périphériques pour voir sur quel port il est branché et déclare ce port correctement dans l'IDE Arduino.
Au besoin tu trouveras des infos ici

Salut biggil,

merci vraiment pour ta réponse détaillé,

le besoin et surtout la curiosité me poussent à aller encore plus loin et vous poser des questions comme un enfant :slight_smile:

1-->

Ceci ne crée pas las fonctions, ça les déclare (afin que le compilateur les reconnaisse plus loin dans le code)

du coup à chaque fois qu'on veut utiliser des fonctions dans notre prg, on les déclare avant le setup c'est ça ?

2-->

Serial est un objet qui est créé automatiquement, il s'occupe de la communication par USB. On commence par indiquer à quelle vitesse il fonctionne. Ici c'est 9600 bauds (c-à-d environ 9600 bits/seconde)

du coup, il est seulement utile lorsque l'Arduino est branché à un PC ?

3-->

On commence par indiquer à quelle vitesse il fonctionne

du coup c'est bien la vitesse à laquelle les infos s'échangent entre le PC et l'Arduino, ici du coup c'est 9600 bits/s un peu comme la connexion internet non ? puis pourquoi on a choisi spécifiquement 9600 bits/s ?

4-->

Mais il y a une erreur grave : le premier if devrait entourer tous les autres tests.

juste au niveau de la syntaxe, j'ai essayé de corriger en déplaçant l'accolade finale du tout 1er if

int state;
int flag=0;       
void stp();
void fwd();
void left();
void right();
void back();
void setup()
{
    pinMode(7,OUTPUT);                  
    pinMode(8,OUTPUT);                  
    pinMode(5,OUTPUT);                  
    pinMode(6,OUTPUT);                  
Serial.begin(9600);                                         // Baud rate set to 9600bps
}
void loop() {
    if(Serial.available() > 0)      // Ckeck for command Recieved
    {    
      state = Serial.read();
      Serial.println(state);  
      flag=0;
                //*****l'accolade qui était ici je l'ai placé à la fin de toutes les conditions juste avant la fin du loop*******
    if (state == '1')     // Checking Command from User
    {
        stp();
        if(flag == 0){
          Serial.println("Stop");
          flag=1;
       }
    }
    else if (state == '2')
    {
        fwd();
        if(flag == 0)
        {
          Serial.println("Forward");
          flag=1;
         }
    }
    else if (state == '3')
    {
        back();
        if(flag == 0)
        {
          Serial.println("Backward");
          flag=1;
        }
    }
    else if (state == '4')
    {
        left();
        if(flag == 0)
        {
          Serial.println("Left");
          flag=1;
         }  
    }
   else if (state == '5')
  {
        right();
        if(flag == 0)
        {
          Serial.println("Right");
          flag=1;
         }
    }
   }  //********************************* j'ai déplacé l'accolade d'en  haut, ici******************************************
}                                           //loop() ends here
void fwd()          // Forward
{
  digitalWrite(7,HIGH);
  digitalWrite(5,HIGH);
  digitalWrite(6,LOW);
  digitalWrite(8,LOW);
}
void back()          // Backward
{
  digitalWrite(8,HIGH);
  digitalWrite(6,HIGH);
  digitalWrite(7,LOW);
  digitalWrite(5,LOW);
}
void left()          //LEFT
{
  digitalWrite(7,HIGH);
  digitalWrite(5,LOW);
  digitalWrite(8,LOW);
  digitalWrite(6,LOW);
}
void right()          // Right
{
  digitalWrite(7,LOW);
  digitalWrite(5,HIGH);
  digitalWrite(8,LOW);
  digitalWrite(6,LOW);
}
void stp()            // Robot STops
{
  digitalWrite(7,LOW);
  digitalWrite(8,LOW);
  digitalWrite(5,LOW);
  digitalWrite(6,LOW);
}

est-ce que le code est correcte maintenant ? si c'est correcte, le 1er if contient tous les autres tests (conditions), ça n'a pas vraiment de sens

5-->

Dans ce programme, quand tu ne reçois plus de caractères, tu continues indéfiniment l'action correspondant au dernier caractère reçu !

ce n'est donc pas ce qu'on recherche ? si non qu'est ce qu'on cherche vraiment ?

6-->

Serial.avalaible() est une fonction (de l'objet Serial) qui indique le nombre de caractères reçus par USB

du coup quand il fait

if(Serial.available() > 0)

il regarde le nbr de caractères qui s'ils sont > à 0 alors il exécute le prg suivant

state = Serial.read();
      Serial.println(state);  
      flag=0;

7-->

Apparement flag sert à éviter d'écrire plusieurs fois de suite le même message

tu parles de quel message ? et comment je peux le rendre utile vu que

mais c'est mal programmé, car à chaque fois qu'un caractère est disponible, flag est remis à 0. Tel quel, il ne sert à rien.

8-->

il les définit. Au début on les a déclarées, c-à-d on a dit qu'elles existaient, mais il faut bien les définir, dire ce qu'elle font. C'est ce qui est fait ici.

eh bien pourquoi ne pas les définir en même temps qu'on les déclare au début ? puis si je veux les définir après, puis je les définir après le setup et avant le loop, çe serait un peu plus logique,

réponse longue mais honnêtment j'ai pas dormi depuis 2 jours tellement je pense à ce code et merci d'avoir lu jusqu'ici

Salut lesept,

J'ai pu résoudre le souci avec le Monitr

[/quote]
Je t'engage à bien comprendre ce programme, te l'approprier et le modifier afin qu'il te soit plus facile de l'expliquer lors de ton oral. Les explications qu'on te fournit ne sont pas suffisantes, si tu ne comprends pas bien le programme, les profs te poseront des questions auxquelles tu auras des difficultés à répondre.[/quote]
merci pour l'intérêt, je suis en ce moment même ton conseil :slight_smile:

Ceci pourrait être fait en utilisant la fonction switch - case ce qui serait plus joli.

j'ai déjà rencontré ce switch quand je galérais à apprendre JS, si le temps m'autorise, je vais essayer changer les tests en switch

1-->

Serial.available() > 0) sert à attendre que tu entres des valeurs. Le if ... else if ... else if

ça reste encore flou pour moi, si on "attend" comme tu le dis, pourquoi y a un opérateur mathématique ?

2-->

Les Serial.println("Stop"); affichent la commande exécutée par le robot, pour vérification.

mais il affiche la commande à qui ? sur l'écran depuis lequel on commande Arduino à savoir le tel ?

3--> je suis sûr que le prof me demandera de traduire le code en algorithmique, je vais essayer de faire ça maintenant, tu pourras voir si j'ai bien compris :

si signal reçu

lire le signal

montrer le signal qui correspond à state (mais montrer à quoi avec "Print" ?)


si state=1

alors appeler la fonction stp()

(puis vient ce code

if(flag == 0){
          Serial.println("Stop");
          flag=1;
       }

que je ne comprends pas, (ça rejoint un peu le 2-->))
si state=2
alors appeler la fonction fwd();

faire la même chose jusqu'à state=5

je comprends le code mieux en mieux mais y a toujours des trucs qui m'échappent !

merci pour ton soutien

ps : quand je compile le code pour les moteurs, y a une erreur

Arduino: 1.8.5 (Linux), Board: "Arduino/Genuino Uno"

/home/hamza/Desktop/TPE/code robot/code robot.ino:7:5: error: redefinition of 'int state'
 int state;
     ^
/home/hamza/Desktop/TPE/code robot/bt.ino:5:5: note: 'int state' previously declared here
 int state;
     ^
/home/hamza/Desktop/TPE/code robot/code robot.ino:8:5: error: redefinition of 'int flag'
 int flag=0;       
     ^
/home/hamza/Desktop/TPE/code robot/bt.ino:6:5: note: 'int flag' previously defined here
 int flag=0;       
     ^
/home/hamza/Desktop/TPE/code robot/code robot.ino: In function 'void setup()':
/home/hamza/Desktop/TPE/code robot/code robot.ino:14:6: error: redefinition of 'void setup()'
 void setup()
      ^
/home/hamza/Desktop/TPE/code robot/bt.ino:12:6: note: 'void setup()' previously defined here
 void setup()
      ^
/home/hamza/Desktop/TPE/code robot/code robot.ino: In function 'void loop()':
/home/hamza/Desktop/TPE/code robot/code robot.ino:22:6: error: redefinition of 'void loop()'
 void loop() {
      ^
/home/hamza/Desktop/TPE/code robot/bt.ino:20:6: note: 'void loop()' previously defined here
 void loop() {
      ^
/home/hamza/Desktop/TPE/code robot/code robot.ino: In function 'void fwd()':
/home/hamza/Desktop/TPE/code robot/code robot.ino:74:6: error: redefinition of 'void fwd()'
 void fwd()          // Forward
      ^
/home/hamza/Desktop/TPE/code robot/bt.ino:73:6: note: 'void fwd()' previously defined here
 void fwd()          // Forward
      ^
/home/hamza/Desktop/TPE/code robot/code robot.ino: In function 'void back()':
/home/hamza/Desktop/TPE/code robot/code robot.ino:81:6: error: redefinition of 'void back()'
 void back()          // Backward
      ^
/home/hamza/Desktop/TPE/code robot/bt.ino:80:6: note: 'void back()' previously defined here
 void back()          // Backward
      ^
/home/hamza/Desktop/TPE/code robot/code robot.ino: In function 'void left()':
/home/hamza/Desktop/TPE/code robot/code robot.ino:88:6: error: redefinition of 'void left()'
 void left()          //LEFT
      ^
/home/hamza/Desktop/TPE/code robot/bt.ino:87:6: note: 'void left()' previously defined here
 void left()          //LEFT
      ^
/home/hamza/Desktop/TPE/code robot/code robot.ino: In function 'void right()':
/home/hamza/Desktop/TPE/code robot/code robot.ino:95:6: error: redefinition of 'void right()'
 void right()          // Right
      ^
/home/hamza/Desktop/TPE/code robot/bt.ino:94:6: note: 'void right()' previously defined here
 void right()          // Right
      ^
/home/hamza/Desktop/TPE/code robot/code robot.ino: In function 'void stp()':
/home/hamza/Desktop/TPE/code robot/code robot.ino:102:6: error: redefinition of 'void stp()'
 void stp()            // Robot STops
      ^
/home/hamza/Desktop/TPE/code robot/bt.ino:101:6: note: 'void stp()' previously defined here
 void stp()            // Robot STops
      ^
exit status 1
Error compiling for board Arduino/Genuino Uno.

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

de quoi s'agit- il ?

1

du coup à chaque fois qu’on veut utiliser des fonctions dans notre prg, on les déclare avant le setup c’est ça ?

C’est la règle générale en langage C. Avant de pouvoir faire un appel de fonction, il faut expliquer au compilateur quels sont les arguments de la fonction (nombre et types), ce que retourne la fonction (une entier, un pointeur, rien (=void) ). Sinon le compilateur te collera une erreur quand il rencontrera l’appel à la fonction.
Donc au minimum, on déclare la fonction, mais on peut aussi la définir. Ce qui veut dire qu’on donne aussi le code qui constitue la fonction.
Donc, au choix :

  • soit tu déclares la fonction au début de ton programme, et tu les définis plus loin dans le code,
  • soit tu définis complètement la fonction en début de programme.
    Quand je dis “en début de programme”, il faut comprendre “avant de placer un appel à cette fonction dans le code”.

2

du coup, Serial est seulement utile lorsque l’Arduino est branché à un PC ?

Oui. A un PC, un Mac ou n’importe quel appareil capable de communiquer sur une ligne série (ce qui inclus l’USB)

3

pourquoi on a choisi spécifiquement 9600 bits/s

tu peux choisir d’autre valeurs (mais pas n’importe lesquelles). Dans le moniteur série de l’IDE Arduino, il y a un menu qui permet de sélectionner la vitesse. Il faut que la valeur choisie pour le moniteur série soit la même que celle de l’objet Serial.

4

est-ce que le code est correcte maintenant ? si c’est correcte, le 1er if contient tous les autres tests (conditions), ça n’a pas vraiment de sens

Ca me parait correct. Tu as un préjugé incorrect sur l’utilisation des if.
D’abord tu devrait vraiment utiliser une indentation correcte. C’est très facile, menu Outils->Formatage automatique. Le code sera plus facile à lire et à comprendre.

Voici ce que fait ta fonction loop()
si un octet est arrivé sur le port série, alors:
si l’octet vaut 1 alors appeler step()
sinon si l’octet vaut 2 alors appeler fwd()
sinon … etc
fin si
fin si

tu vois bien que les test sont imbriqués, il n’y a rien d’anormal à cela.

5

si non qu’est ce qu’on cherche vraiment ?

Elle est bien bonne celle là :astonished:
C’est toi qui veut faire quelque chose avec un Arduino, en principe tu devrais savoir ce que tu veux faire, non ? Moi je peux t’aider sur les détails, mais pas sur le sens de la vie :slight_smile:

6

il regarde le nbr de caractères qui s’ils sont > à 0 alors il exécute le prg suivant

c’est mal dit, mais oui. Moi je dirais "il regarde s’il y a des octet disponibles, si oui il lit le 1er octet disponible (et il l’envoi sur la ligne série).
Au passage, ce qui va s’afficher sur le moniteur série sera illisible. En effet, les valeurs lues sont 1, 2, 3, 4 et 5, et ça, ce sont des octets bruts, et pas des caractères. Pour afficher qque chose de lisible, tu peux faire Serial.println ( '0' + state ); cherche codage ASCII sur le Net avant de me demander pourquoi STP.

7

tu parles de quel message ? et comment je peux le rendre utile

le message = ce que tu envoies au moniteur série par Serial.println (…).
le rendre utile ? qu’est que tu fait si tu trouves un ouvre-boîte alors que tu n’as pas de boîtes ?
Tu prends le problème à l’envers, tu te fixes sur le code existant, alors que tu devrais te demander en priorité ce que tu veux faire.

8

pourquoi ne pas les définir en même temps qu’on les déclare au début ?

C’est possible. Voir la réponse 1.

On continue avec les questions posées à lesept :

1

si on “attend” comme tu le dis, pourquoi y a un opérateur mathématique

Serial.avalaible() est une fonction qui renvoie le nombre d’octets disponibles. Donc on test que ce nombre est non-nul, c-à-d que ce nombre est > 0

2

mais il affiche la commande à qui ? sur l’écran depuis lequel on commande Arduino à savoir le tel ?

Ce qui est écrit part sur la ligne série (donc l’USB). Les caractères sont récupérés par ce qui est au bout du câble USB, donc probablement le PC, à destination du moniteur série de l’IDE.

3

error: redefinition of 'int state'
'int state' previously declared here

de quoi s’agit- il ?

Il faut lire attentivement les messages du compilateur !
il te dit clairement que tu as déclaré la variable state plus d’une fois. Et ça ne lui plaît pas.

Salut Biggil,

Merci d’avoir pris le temps de répondre,

ça a pris du temps mais désormais je suis en mesure d’expliquer le code à qq’un qui me demanderait :slight_smile:

1

Moi je peux t’aider sur les détails, mais pas sur le sens de la vie :slight_smile:

:smiley: non je disais ça parce que j’avais compris de travers une de tes explications. Et non, je ne remettais pas en le programme ni l’univers.

2

cherche codage ASCII sur le Net avant de me demander pourquoi STP.

oufff tqt surtout pas pour ça, j’en ai bien mis la journée à chercher sur ça (entre autres).
Mais je suis obligé de te demander pourquoi :smiley_cat:
en quoi çaSerial.println ( '0' + state ); c’est différent de ça Serial.println (state); ? car tu ne fais qu’ajouter la valeur de state à 0, ce qui ne change rien à la valeur de state, du coup c’est quoi l’intérêt ?

3

Tu prends le problème à l’envers, tu te fixes sur le code existant, alors que tu devrais te demander en priorité ce que tu veux faire.

tout ce que je veux c’est de faire en sorte que le robot fasse 4 mouvements simples à mes commandes, rien de plus (pour le moment). Puis je disais

et comment je peux le rendre utile

car je ne’avais pas compris ton explication sur flag (tjrs pas compris d’ailleurs, je ne trouve quasiment rien sur le NET concernant flag, contrairement à tous les autres outils d’ARDUINO)

4

le rendre utile ? qu’est que tu fait si tu trouves un ouvre-boîte alors que tu n’as pas de boîtes ?

du coup si j’enlève le code qui concerne flag à savoir

if(flag == 0){
Serial.println(“Stop”);
flag=1;
}

dans nos tests, en l’enlevant, cela ne devrait pas détériorer le prgm non ?

5

Serial.avalaible() est une fonction qui renvoie le nombre d’octets disponibles. Donc on test que ce nombre est non-nul, c-à-d que ce nombre est > 0

en gros, Serial.avalaible(); est la secrétaire dans un cabinet médicale qui vérifie s’il y a quelqu’un dans la salle d’attente et l’oriente vers le bon spécialiste selon la personne qui se trouve dans la salle d’attente…

6

il te dit clairement que tu as déclaré la variable state plus d’une fois. Et ça ne lui plaît pas.

state n’est déclarée qu’une seule fois au début, j’ai vérifié

l’érreur a changé quand j’ai modifié le if qui imprique les autres tests

Arduino: 1.8.5 (Linux), Board: "Arduino/Genuino Uno"

/home/hamza/Desktop/TPE/code robot/code robot.ino:7:5: error: redefinition of 'int state'
 int state;
     ^
/home/hamza/Desktop/TPE/code robot/bt.ino:5:5: note: 'int state' previously declared here
 int state;
     ^
/home/hamza/Desktop/TPE/code robot/code robot.ino:8:5: error: redefinition of 'int flag'
 int flag=0;       
     ^
/home/hamza/Desktop/TPE/code robot/bt.ino:6:5: note: 'int flag' previously defined here
 int flag = 0;
     ^
/home/hamza/Desktop/TPE/code robot/code robot.ino: In function 'void setup()':
/home/hamza/Desktop/TPE/code robot/code robot.ino:14:6: error: redefinition of 'void setup()'
 void setup()
      ^
/home/hamza/Desktop/TPE/code robot/bt.ino:13:6: note: 'void setup()' previously defined here
 void setup()
      ^
/home/hamza/Desktop/TPE/code robot/code robot.ino: In function 'void loop()':
/home/hamza/Desktop/TPE/code robot/code robot.ino:22:6: error: redefinition of 'void loop()'
 void loop() {
      ^
/home/hamza/Desktop/TPE/code robot/bt.ino:21:6: note: 'void loop()' previously defined here
 void loop() {
      ^
/home/hamza/Desktop/TPE/code robot/code robot.ino: In function 'void fwd()':
/home/hamza/Desktop/TPE/code robot/code robot.ino:74:6: error: redefinition of 'void fwd()'
 void fwd()          // Forward
      ^
/home/hamza/Desktop/TPE/code robot/bt.ino:74:6: note: 'void fwd()' previously defined here
 void fwd()          // Forward
      ^
/home/hamza/Desktop/TPE/code robot/code robot.ino: In function 'void back()':
/home/hamza/Desktop/TPE/code robot/code robot.ino:81:6: error: redefinition of 'void back()'
 void back()          // Backward
      ^
/home/hamza/Desktop/TPE/code robot/bt.ino:81:6: note: 'void back()' previously defined here
 void back()          // Backward
      ^
/home/hamza/Desktop/TPE/code robot/code robot.ino: In function 'void left()':
/home/hamza/Desktop/TPE/code robot/code robot.ino:88:6: error: redefinition of 'void left()'
 void left()          //LEFT
      ^
/home/hamza/Desktop/TPE/code robot/bt.ino:88:6: note: 'void left()' previously defined here
 void left()          //LEFT
      ^
/home/hamza/Desktop/TPE/code robot/code robot.ino: In function 'void right()':
/home/hamza/Desktop/TPE/code robot/code robot.ino:95:6: error: redefinition of 'void right()'
 void right()          // Right
      ^
/home/hamza/Desktop/TPE/code robot/bt.ino:95:6: note: 'void right()' previously defined here
 void right()          // Right
      ^
/home/hamza/Desktop/TPE/code robot/code robot.ino: In function 'void stp()':
/home/hamza/Desktop/TPE/code robot/code robot.ino:102:6: error: redefinition of 'void stp()'
 void stp()            // Robot STops
      ^
/home/hamza/Desktop/TPE/code robot/bt.ino:102:6: note: 'void stp()' previously defined here
 void stp()            // Robot STops
      ^
exit status 1
Error compiling for board Arduino/Genuino Uno.

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

merci d’avoir lu jusqu’ici :slight_smile:

2
En langage C:

  • 0 est la valeur zéro
  • '0' est la valeur du caractère 0 en code ASCII, c'est-à-dire 48.
    En tapant "codage ASCII" sur Google, la 1ère réponse qui sort est celle-ci.
    Ca me paraît assez clair, non ?
    Tu vois dans la table de caractères que le code du caractère '0' est 48, le code du '1' est 49, etc.
    Donc en ajoutant state (qui vaut 1, 2, 3...) à '0' (qui vaut 48), on obtient respectivement les codes ASCII pour '1', '2', '3', etc.

4

dans nos tests, enlevant flag, cela ne devrait pas détériorer le prgm non ?

Non, si tu fais ça proprement. A toi de voir si tu veux garder Serial.print() ou pas.

5

Serial.avalaible() est la secrétaire dans un cabinet médicale qui vérifie s'il y a quelqu'un dans la salle d'attente et l'oriente vers le bon spécialiste selon la personne qui se trouve dans la salle d'attente..

Non. Cette fonction te dit combien il y a de personnes dans la salle d'attente, et ne fait rien de plus.
C'est Serial.read() qui fait rentrer 1 personne dans le cabinet.

6

state n'est déclarée qu'une seule fois au début, j'ai vérifié

Bin t'as sûrement mal vérifié, car si le compilateur te dit redefinition of 'int state', y'a pas photo : le compilateur a toujours raison !

A ce stade, le plus simple serait que tu repostes le code en l'état actuel, si possible avec les bonnes indentations (CTRL + T dans l'IDE) et en enlevant les lignes vides : on pourra mieux voir pourquoi le compilo pense que tu déclares plusieurs fois et pas toi.

Bonjour,

voici le code

int state;

void stp();
void fwd();
void left();
void right();
void back();

void setup()
{
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  Serial.begin(9600);                                         // Baud rate set to 9600bps,il faut également configurer le moniteur en 9600
}


void loop() {


  if (Serial.available() > 0)      // Ckeck for command Recieved --> on vérifie ici si l'utilisateur a appuyé sur un bouton et donc a envoyé un signal bluetooth ou pas puislis le bouton sur lequel il a appuyé*/
  {
    state = Serial.read();
    Serial.println( '0' + state );  // on ajoute la valeur de state à 0 qui corrspond  à 48 dans le tableau ASCII, car le moniteur peut pas comprendre les bits à l'état brut et non des caractère


    if (state == '1')     // Checking Command from User--> on fait alors des actions selon le bouton appuyé
    {

      stp();

    }

    else if (state == '2')
    {
      fwd();

    }


    else if (state == '3')
    {
      back();

    }


    else if (state == '4')
    {
      left();

    }

    else if (state == '5')
    {
      right();

    }
  }
}                                       //loop() ends here

void fwd()          // Forward
{
  digitalWrite(7, HIGH);
  digitalWrite(5, HIGH);
  digitalWrite(6, LOW);
  digitalWrite(8, LOW);
}
void back()          // Backward
{
  digitalWrite(8, HIGH);
  digitalWrite(6, HIGH);
  digitalWrite(7, LOW);
  digitalWrite(5, LOW);
}
void left()          //LEFT
{
  digitalWrite(7, HIGH);
  digitalWrite(5, LOW);
  digitalWrite(8, LOW);
  digitalWrite(6, LOW);
}
void right()          // Right
{
  digitalWrite(7, LOW);
  digitalWrite(5, HIGH);
  digitalWrite(8, LOW);
  digitalWrite(6, LOW);
}
void stp()            // Robot STops
{
  digitalWrite(7, LOW);
  digitalWrite(8, LOW);
  digitalWrite(5, LOW);
  digitalWrite(6, LOW);
}

-j'ai supprimé le int flag=0; du début ainsi que les 5

if(flag == 0){
          Serial.println("Stop");
          flag=1;
       }

dans nos 5 tests

-j'ai également fait en sorte que le 1er if imprique les autres if et else if comme l'as biggil

le code est désormais encore plus simple

merci

bon ça commence à être pas mal :slight_smile:
tu pourrais avantageusement remplacer les séquence des if ( state == … ) … par

  // Checking Command from User--> on fait alors des actions selon le bouton appuyé
  switch ( state ) {
    case 1 : stp();   break;
    case 2 : fwd();  break;
    case 3 : back(); break;
    case 4 : left();   break;
    case 5 : right(); break;

  }

C’est beaucoup moins … verbeux.
Revois aussi tes commentaires qui sont parfois alambiqués…

Il y une chose que je comprends pas : qu’est-ce qu’il y a à l’autre bout de Serial ?
Si c’est un PC avec le Moniteur série de l’IDE Arduino, tu verras tes messages s’afficher, mais il faudra envoyer les commandes (1, 2, 3, 4 ou 5) par ce même moniteur série, et ça va pas être facile, car ces valeurs, comme on l’a vu, ne correspondent pas à des caractères affichables.

Si c’est un téléphone bluetooth, sans présumer de comment tu le relies au port série de l’Arduino, tu n’afficheras probablement pas les messages imprimés avec Serial.print() … mais ce n’est pas un problème majeur.

Je crois que j’ai compris à quoi servait le ‘flag’. Flag signifie drapeau en anglais, on utilise souvent ce nom pour indiquer un état. Dans le cas présent, l’état c’est “je viens d’afficher un changement de direction”. Lorsque le robot ne lit rien dans la console, la valeur de state ne change pas et donc à chaque passage dans la loop le programme retourne dans la fonction qui correspond à la valeur courante de flag, la dernière qui a été lue dans la console. Donc il réaffiche la direction.
Pour éviter d’avoir des milliers de fois la même chose qui s’affiche, on met flag à 1 la première fois et on teste s’il vaut 1 avant d’afficher ensuite la direction. Lors d’un changement de direction, on remet flag à 0 et on affiche. Je pense que ce passage à 0 avait été oublié dans le programme initial.

Quand à l’erreur de création multiple, je ne vois rien. Est-elle toujours présente ?

Salut Biggil,

excuse cette réponse tardive en raison du TPE,
je vais passer à l'oral blanc demain.

oui, c'est bien un téléphone qui se trouve au bout du port serial.
Tant que le code est fonctionnel, inutile de se compliquer la vie !

merci pour ton aide