Code pour controler moteur DC

Bonjours à tous, nous sommes un groupe de terminale S-SI et nous revenons vers le forum, car nous rencontrons un problème avec la programmation de notre aduino uno pour notre porjet de terminale .
Notre projet consiste à commander 2 groupes de 2 moteurs par le moniteur série (liaison direct) dans un premier temps puis par la suite par avec une liaison radio en utlisant toujours le moniteur séries et un émetteur et recepteur 433 Hz.

Cependant, le problème que nous rencontrons actuellement est que nous n'arrivons pas a commander de manière continue les moteurs. L'idée est que nous voulions au départ était: lorsque qu'on reste appuyé sur, par exemple la touche "Z" le robot avance, donc un groupe de moteur tourne "en avant/sens indirect" et puis l'autre groupe symetriqument opposé tourne en "arrière/sens direct" et dès qu'on relache la touche, le moteurs s'arrête.
Mais les moteurs ne fonctionnent que durant un laps de temps puis il s'arrete par la suite. =(
On demande votre aide car nous ne comprenons pas notre problème et nous tournons en rond malheureusment :blush:

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"

Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_DCMotor *moteurGauche = AFMS.getMotor(1);
Adafruit_DCMotor *moteurDroit = AFMS.getMotor(3);

char touche;

void setup() 
{
  Serial.begin(9600);
  Serial.println("Robot curiosity TS6 SI");

  AFMS.begin();


  moteurGauche->setSpeed(50);
  moteurDroit->setSpeed(50);
  moteurGauche->run(FORWARD);
  moteurDroit->run(BACKWARD);
 
  moteurGauche->run(RELEASE);
  moteurDroit->run(RELEASE);
}

void loop() 
{
  uint8_t i;

  if (Serial.available() > 0) // On detecte un appui sur une touche
  {
    touche = Serial.read(); // On lit la valeur de la touche appuyée

    if (touche == 'Z')
    {  
      Serial.print("Avancer");

      moteurGauche->run(FORWARD);
      moteurDroit->run(FORWARD);
      for (i=0; i<255; i++) 
      {
        moteurGauche->setSpeed(i);
        moteurDroit->setSpeed(i);
          
      }
      for (i=255; i!=0; i--) 
      {
        moteurGauche->setSpeed(i);
        moteurDroit->setSpeed(i);
          
      }
    }

    if (touche == 'S')
    {
      Serial.print("Reculer");

      moteurGauche->run(BACKWARD);
      moteurDroit->run(BACKWARD);
      for (i=0; i<255; i++) {
        moteurGauche->setSpeed(i);
        moteurDroit->setSpeed(i);  
      }
      for (i=255; i!=0; i--) 
      {
        moteurGauche->setSpeed(i);
        moteurDroit->setSpeed(i);  
      }


    }    
    if (touche == 'Q')
    {
      Serial.print("Tourner a gauche");

      moteurGauche->run(BACKWARD);
      moteurDroit->run(FORWARD);
      for (i=0; i<255; i++) 
      {
        moteurGauche->setSpeed(i);
        moteurDroit->setSpeed(i);  
      }
      for (i=255; i!=0; i--) 
      {
        moteurGauche->setSpeed(i);
        moteurDroit->setSpeed(i);  
      }
    }
    if (touche == 'D')
    {
      Serial.print("Tourner a droite");

      moteurGauche->run(FORWARD);  
      moteurDroit->run(BACKWARD);
      for (i=0; i<255; i++) 
      {
        moteurGauche->setSpeed(i);
        moteurDroit->setSpeed(i);  
      }
      for (i=255; i!=0; i--) 
      {
        moteurGauche->setSpeed(i);
        moteurDroit->setSpeed(i);  
      }   
      if (touche == 'W')
      {
        Serial.print("Pause");
        moteurGauche->run(RELEASE);
        moteurDroit->run(RELEASE);
        delay(1000);
      }
      if (touche==0)
      {
        moteurGauche->run(RELEASE);
        moteurDroit->run(RELEASE);
      }
    }
  }
}

merci d'avance :slight_smile:

Bonjour,
Il vaudrait mieux utiliser un contact type bouton poussoir car le clavier ne réalise qu'un envoi momentané.
Tu envois la touche 'Z', le code l’interprète, tu lance ta fonction et ça s'arrête car tu as relâché le clavier.
Sinon il faudrait que tu envoie en boucle le caractère en question pour que le programme puisse valider la condition VRAI à chaque fois.

// read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);

  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  if (buttonState == HIGH) {     
    // turn LED on:    
    digitalWrite(ledPin, HIGH);  
  } 
  else {
    // turn LED off:
    digitalWrite(ledPin, LOW); 
  }

Il faut mémoriser avec un flag le fait qu'on a appuyé sur la touche pour avancer, et tant qu'on n'a pas appuyé sur autre chose, faire une boucle qui répète l'action sur les moteurs.

Oui c'est une autre solution à laquelle je n'avais pas pensé :wink:

Le soucis c'est que nous avons critères des depart et nous voudrons car l'idée de piloter le robot depuis le moniteur série..

Christian_R:
Il faut mémoriser avec un flag le fait qu'on a appuyé sur la touche pour avancer, et tant qu'on n'a pas appuyé sur autre chose, faire une boucle qui répète l'action sur les moteurs.

Un flag ???? :astonished:

Un "drapeau", c'est tout simplement une variable binaire qui mémorise l'état appuyé ou pas du bouton.

Nous avons trouvé comment faire un flag.
Mais nous avons toujours le même problème, c'est a dire que lorsque l'on appuie sur une autre touche de "Z" pour avancer par exemple, les moteurs continuent à avancer et on reste dans la boucle qui a mémoriser la valeur de la variable binaire sans pouvoir changer la valeur de la variable binaire (on a une boucle infini :~ )
Je vous remet le code avec la variable:

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"

boolean flag=false;

Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_DCMotor *moteurGauche = AFMS.getMotor(1);
Adafruit_DCMotor *moteurDroit = AFMS.getMotor(3);

char touche;

void setup() 
{
  Serial.begin(9600);
  Serial.println("Robot curiosity TS6 SI");

  AFMS.begin();


  moteurGauche->setSpeed(250);
  moteurDroit->setSpeed(250);
  moteurGauche->run(FORWARD);
  moteurDroit->run(BACKWARD);
 
  moteurGauche->run(RELEASE);
  moteurDroit->run(RELEASE);
}

void loop() 
{
  uint8_t i;

  if (Serial.available() > 0) // On detecte un appui sur une touche
  {
    touche = Serial.read(); // On lit la valeur de la touche appuyée
    
    if (touche == 'Z')
    { flag= true;
      while (flag=true)
      {
        Serial.print("Avancer");

        moteurGauche->run(FORWARD);
        moteurDroit->run(FORWARD);
          for (i=0; i<255; i++) 
          {
            moteurGauche->setSpeed(i);
            moteurDroit->setSpeed(i);
          }
          for (i=255; i!=0; i--) 
          {
            moteurGauche->setSpeed(i);
            moteurDroit->setSpeed(i);
          }
         if (touche=='S'|| touche=='Q' || touche=='D'|| touche=='W')
         {
          flag=false;
         }   
        }  
      }
    }

    if (touche == 'S')
    { flag=false;
      delay(10);
      flag=true;
      while(flag=true){
      Serial.print("Reculer");

      moteurGauche->run(BACKWARD);
      moteurDroit->run(BACKWARD);
      for (i=0; i<255; i++) {
        moteurGauche->setSpeed(i);
        moteurDroit->setSpeed(i);  
      }
      for (i=255; i!=0; i--) 
      {
        moteurGauche->setSpeed(i);
        moteurDroit->setSpeed(i);  
       }
      }


    }    
    if (touche == 'Q')
    {
      Serial.print("Tourner a gauche");

      moteurGauche->run(BACKWARD);
      moteurDroit->run(FORWARD);
      for (i=0; i<255; i++) 
      {
        moteurGauche->setSpeed(i);
        moteurDroit->setSpeed(i);  
      }
      for (i=255; i!=0; i--) 
      {
        moteurGauche->setSpeed(i);
        moteurDroit->setSpeed(i);  
      }
    }
    if (touche == 'D')
    {
      Serial.print("Tourner a droite");

      moteurGauche->run(FORWARD);  
      moteurDroit->run(BACKWARD);
      for (i=0; i<255; i++) 
      {
        moteurGauche->setSpeed(i);
        moteurDroit->setSpeed(i);  
      }
      for (i=255; i!=0; i--) 
      {
        moteurGauche->setSpeed(i);
        moteurDroit->setSpeed(i);  
      }   
      if (touche == 'W')
      {
        Serial.print("Pause");
        moteurGauche->run(RELEASE);
        moteurDroit->run(RELEASE);
        delay(1000);
      }
      if (touche==0)
      {
        moteurGauche->run(RELEASE);
        moteurDroit->run(RELEASE);
      }
    }
  }

bonjour,
déjà que vient faire cette ligne?

         if (touche=='S'|| touche=='Q' || touche=='D'|| touche=='W')

le mieux serait d'utiliser switch case
ca te permettrait peut être de voir que ton

if (Serial.available() > 0) // On detecte un appui sur une touche
  {

s'arrête avant

    if (touche == 'S')

donc normal que tu ne sorte pas de ta boucle, vu que les autres possibilités ne sont pas reconnues.

Sur les conseils de infobarquee nous avons essayer ceci:

 if (Serial.available() > 0) // On detecte un appui sur une touche
  {
    int touche = Serial.read(); // On lit la valeur de la touche appuyée
    switch (touche){
       case "Z":
         Serial.print("Avancer");

         moteurGauche->run(FORWARD);
         moteurDroit->run(FORWARD);
         for (i=0; i<255; i++) 
          {
           moteurGauche->setSpeed(i);
           moteurDroit->setSpeed(i);
          }
         for (i=255; i!=0; i--) 
          {
           moteurGauche->setSpeed(i);
           moteurDroit->setSpeed(i);
          }
          break;
        case "S":
         Serial.print("Reculer");

        moteurGauche->run(BACKWARD);
        moteurDroit->run(BACKWARD);
        for (i=0; i<255; i++) {
          moteurGauche->setSpeed(i);
          moteurDroit->setSpeed(i);  
          }
        for (i=255; i!=0; i--) 
        {
        moteurGauche->setSpeed(i);
        moteurDroit->setSpeed(i);  
        }
        break;
  }
  }
}

et nous avons les erreurs suivantes:
_2.ino: In function 'void loop()':
_2:38: error: case label does not reduce to an integer constant
_2:54: error: case label does not reduce to an integer constant

Nous avons essayer de chercher sur internet ce que cela signifiait et on pense que les constantes ne peuvent pas être compiler.
Comment utiliser un switch en disant lorsque l'on appuie sur "Z", les moteurs avancent.. Lorsque on appuies "S", les moteurs reculent..
Faut-il définir toutes les touches de commande comme variables dès le début du programme ?

Veuillez nous excuser d'avance pour toute ces questions qui peuvent surement être idiotes, mais nous somme bloqués et nous aimerions bien avancer tout en apprenant :slight_smile:

case Z :
case S :

http://www.mon-club-elec.fr/pmwiki_reference_arduino/pmwiki.php?n=Main.ChainesCaracteres

Bonjour tous le monde, nous avons modifié le code comme vous nous l'avez suggéré.
Le problème c'est qu'avec le switch le programme ne fonctionne plus :~

Voici le code:

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"


int Z=0;
int S=0;

Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_DCMotor *moteurGauche = AFMS.getMotor(1);
Adafruit_DCMotor *moteurDroit = AFMS.getMotor(3);

char touche;

void setup() 
{
  Serial.begin(9600);
  Serial.println("Robot curiosity TS6 SI");

  AFMS.begin();


  moteurGauche->setSpeed(250);
  moteurDroit->setSpeed(250);
  moteurGauche->run(FORWARD);
  moteurDroit->run(BACKWARD);
 
  moteurGauche->run(RELEASE);
  moteurDroit->run(RELEASE);
  
}

void loop() 
{
  uint8_t i;

  if (Serial.available() > 0) // On detecte un appui sur une touche
  {
    int touche = Serial.read(); // On lit la valeur de la touche appuyée
    switch (touche){
       case 1:
        
         Serial.print("Avancer");

         moteurGauche->run(FORWARD);
         moteurDroit->run(FORWARD);
         for (i=0; i<255; i++) 
          {
           moteurGauche->setSpeed(i);
           moteurDroit->setSpeed(i);
          }
         for (i=255; i!=0; i--) 
          {
           moteurGauche->setSpeed(i);
           moteurDroit->setSpeed(i);
          
         }
          break;
        case 2:
        
         Serial.print("Reculer");

        moteurGauche->run(BACKWARD);
        moteurDroit->run(BACKWARD);
        for (i=0; i<255; i++) {
          moteurGauche->setSpeed(i);
          moteurDroit->setSpeed(i);  
          }
        for (i=255; i!=0; i--) 
        {
        moteurGauche->setSpeed(i);
        moteurDroit->setSpeed(i);  
        }
        
        break;
    }
  }
}

Nous avons essayé en remplaçant

case 1:
case 2:

par

case Z //puisque Z est la touche correspond a la touche qui permette "d'avancer"
case S // correspond a la touche permettant de "reculer"

et nous avons l'erreur suivante:

_2.ino: In function 'void loop()':
_2:41: error: 'Z' cannot appear in a constant-expression
_2:59: error: 'S' cannot appear in a constant-expression

Nous comprenons pas très bien l'erreur en elle-même seulement nous pensons que la variables Z et S ne peuvent pas être considérées comme une condition ?
Qu'est ce que nous avons loupé pour que notre programme fonctionne s'il vous plait :slight_smile: ?

Boujour,
Dans le case il faut indiquer le nombre ascii de la touche. A = 65 , B= 66, $ = 36, *= 42

ou simplement 'A', 'B', '$' ... :wink: