Control my robot with infrared remote

I built some time ago a robot that can move by avoiding obstacles thanks to its sensor. Then add to the robot an infrared receiver so that it can be controlled thanks to an infrared remote control. But after having import the code (see below) the robot start to move straight forward without stopping. I want the robot to move in autonomous mode from the remote.

I control my motors thanks to a L293D, I'm building another shield based on a L298N

I'm french so the code is in french,here some help for you :

Enavant = Go Forward Tourneragauche = Turn Left Enarriere = Go Backward

Tourneradroite = Turn Right

Modeautonome = Autonomous mode

Arret = Stop

Here is the code : 

 

 

 #include <DistanceSRF04.h>
#include <IRremote.h>
int action;
int IRdelay = 40 ;
unsigned long Enavant = 0xA16E6C93 ;
unsigned long Tourneragauche = 0xA16E40BF ;
unsigned long Enarriere = 0xA16EE817 ;
unsigned long Tourneradroite = 0xA16E00FF ;
unsigned long Modeautonome = 0xA16EC03F ;
unsigned long Arret = 0xA16E807F ;
int Avant ;
int Arriere ;
int TGauche ;
int TDroite ;
int Autonome ;
int Stop ;
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results
;
DistanceSRF04 Dist;
int distance;
int motor1Pin1 = 3; // pin 2 on L293D
int motor1Pin2 = 4;
int motor2Pin1 = 5; // pin 2 on L293D
int motor2Pin2 = 6; // pin 7 on L293D
int enablePin = 9;
int enable2Pin = 10;// pin 1 on L293D


void setup()
{
 
Serial.begin(9600);
  irrecv
.enableIRIn();
 
 
Dist.begin(12,13);


pinMode
(motor1Pin1, OUTPUT);
pinMode
(motor1Pin2, OUTPUT);
pinMode
(motor2Pin1, OUTPUT);
pinMode
(motor2Pin2, OUTPUT);
pinMode
(enablePin, OUTPUT);
pinMode
(enable2Pin, OUTPUT);
}


/**
 * Les fonctions ci dessous te permettent de ne pas répéter le code correspondant aux divers endroits. ça t'évite de devoir faire des copier coller.
 * De plus, si tu utilises cette fonction, et que tu veux modifier les noms des variables ou autre, tu n'as qu'à modifier ici, et ce sera bon dans toute la suite du code!
 * De manière générale, c'est une bonne habitude de faire des sous fonctions, et de t'appuyer dessus. Tu commences par une sous fonction, que tu testes à fond.
 * Quand tu es sur que la sous fonction marche bien, tu peux t'en servir dans une nouvelle fonction, et ainsi de suite. ça te permet de valider à chaque étape.
 * En plus ça fait un code propre, et clair, plus facile à lire!
 */

void autonome(){
 
{
distance
= Dist.getDistanceCentimeter();
Serial.print("\nDistance in centimers: ");
Serial.print(distance);
delay
(200); //make it readable
}
if (distance <= 30 ){
  tournerGauche
();
}
else {
  avancer
();
}
}
 

void startMotors()//démarre les moteurs
{
    digitalWrite
(enablePin, HIGH);
    digitalWrite
(enable2Pin, HIGH);
}

void stopMotors()//arrête les moteurs
{
    digitalWrite
(enablePin, LOW);
    digitalWrite
(enable2Pin, LOW);
}

void avancer() //le robot avancera jusqu'à nouvel ordre
{
    startMotors
();
    digitalWrite
(motor1Pin1, LOW); // set pin 2 on L293D low
    digitalWrite
(motor1Pin2, HIGH); // set pin 7 on L293D high
    digitalWrite
(motor2Pin1, LOW); // set pin 2 on L293D low
    digitalWrite
(motor2Pin2, HIGH);
}

void tournerGauche() //le robot tournera à gauche jusqu'à nouvel ordre
{
    startMotors
();
    digitalWrite
(motor1Pin1, LOW); // set pin 2 on L293D low
    digitalWrite
(motor1Pin2, HIGH); // set pin 7 on L293D high
    digitalWrite
(motor2Pin1, HIGH); // set pin 2 on L293D low
    digitalWrite
(motor2Pin2, LOW);
}

void tournerDroite()//le robot tournera à droite jusqu'à nouvel ordre
{
   startMotors
();
   digitalWrite
(motor1Pin1, HIGH); // set pin 2 on L293D low
   digitalWrite
(motor1Pin2, LOW); // set pin 7 on L293D high
   digitalWrite
(motor2Pin1, LOW); // set pin 2 on L293D low
   digitalWrite
(motor2Pin2, HIGH);
}

void reculer()//le robot reculera jusqu'à nouvel ordre
{
    startMotors
();
    digitalWrite
(motor1Pin1, HIGH); // set pin 2 on L293D low
    digitalWrite
(motor1Pin2, LOW); // set pin 7 on L293D high
    digitalWrite
(motor2Pin1, HIGH); // set pin 2 on L293D low
    digitalWrite
(motor2Pin2, LOW);
}

void loop()//boucle principale du programme
{
   
if (irrecv.decode(&results))
   
{
   
Serial.println(results.value, HEX);
    irrecv
.resume(); // Receive the next value
 
}
 
 
if(results.value == Enavant)
 
{
     action
= Avant ; //attention, tu avais mis action == Avant. ça n'aurait pas mis la valeur "Avant" dans action. == ça sert à voir si la valeur de gauche est égale à la valeur de droite. = tout seul sert à mettre la valeur de droite dans la variable de gauche. Attention à ne pas se tromper, ça ne fera pas d'érreur de compilation, mais le programme ne fonctionnera pas comme tu veux!
 
}
 
else if(results.value == Tourneragauche)
 
{
    action
= TGauche ;
 
}
 
else if(results.value == Tourneradroite)
 
{
     action
= TDroite ;
 
}
 
else if(results.value == Arriere)
 
{
     action
= Arriere ;
 
}
 
else if(results.value == Arret)//cas ou tu veux arrêter le robot dans son déplacement!
 
{
     action
= Stop ;
 
}
 
else if(results.value == Autonome)
 
{
     action
= Autonome ;
 
}

   effectueraction
(action);//si tu ne mets pas ça ici, le robot ne fera rien! dans ton exemple il aurait simplement avancé en continu.

}//ne pas oublier de fermer la fonction, il te manquait cela. Tu ne dois pas déclarer une fonction au sein d'une autre, à moins de savoir précisément pourquoi. Ici, tu n'en as pas besoin.
   
   
     
   
void effectueraction(int act)//tu avais oublié les parenthèses pour la fonction!!!
   
{  
   
if (act == Avant)
     
{
        avancer
();
     
}
     
     
else if ( act == TGauche)
     
{
       tournerGauche
();
     
}
     
     
else if ( act == TDroite )
     
{
       tournerDroite
();
     
}
     
     
else if ( act == Arriere)
     
{
       reculer
();
     
}
     
else if ( act == Stop)
     
{
       stopMotors
();
     
}
     
else if(act == Autonome)
     
{
      autonome
();
     
}

   
}

 

  • Actuators / output devices: Tamiya twin gearbox
  • Control method: Autonomous. Manual infra red control planned.
  • CPU: Arduino
  • Power source: 9 volts and 4.8 volts for the motor
  • Sensors / input devices: HC-SR04 ultrasonic sensor

This is a companion discussion topic for the original entry at https://community.robotshop.com/robots/show/control-my-robot-with-infrared-remote

bon boulot

j’aime bien comment tu utilises les sous-programmes dans ton sketch, je vais en prendre exemple pour mon robot.

Merci beaucoup

Congratulations on a clean looking project and good documentation. It’s traditional we post a video as well.   : D

still not working…

I’ve just tried to change that :  

int Avant;

int Arriere ;

int TGauche ;

int TDroite ;

int Autonome ;

to that :

 

int Avant = 0;

int Arriere = 0;

int TGauche = 0;

int TDroite = 0;

int Autonome = 0;

 

 

And the robot continue tu go forward without react to the ir receive.

 

An idea ? Someone ?

 

 

Sympa de voir des francais sur le forum car, étant en seconde, je suis pas vraiment billingue quoi x)

joli code …

Bonjour

Au vu de ton code, j’aurais tendance à rajouter une condition de départ: Dans le setup, appeler stopMotors(); Cela forcera le moteur à l’arrêt tant que pas d’ordre reçu …

Ensuite, dans loop()  j’aurais intégré dans le test if (irrecv.decode(&results)) la partie des if … elsif … . De cette manière on ne réexécute pas de code si pas de nouvel ordre reçu.

Enfin, j’aurais mis une condition “else” à la fin au cas où l’ordre reçu n’est pas compris (toujours utile pour le déboguage).

En résumé, cela donnerait …

void setup()
{
Serial.begin(9600);
irrecv
.enableIRIn();
Dist.begin(12,13);
pinMode
(motor1Pin1, OUTPUT);
pinMode
(motor1Pin2, OUTPUT);
pinMode
(motor2Pin1, OUTPUT);
pinMode
(motor2Pin2, OUTPUT);
pinMode
(enablePin, OUTPUT);
pinMode
(enable2Pin, OUTPUT);
stopMotors(); // initialisation des moteurs a l’arret
}

void loop() {   

 if (irrecv.decode(&results))
{
Serial.println(results.value, HEX);
irrecv
.resume(); // Receive the next value 

// on ne teste le resultat qu’en cas de reception d’une commande
if
(results.value == Enavant)
{
action
= Avant ;
}
else if(results.value == Tourneragauche)
{
action
= TGauche ;
}
… 
else if(results.value == Autonome)
{
action
= Autonome ;
}
else
{  
Serial.println(“unknown received action”);    
action
= Stop ; // par securite on arrete le robot vu qu’on reçoit n’importe quoi …
} // fin des if/elsif/else
   effectueraction(action);
} //fin de irrecv.decode()
} // fin de loop()

Voila …Bon courage …

une autre petite remarque sur le code…

Re …

Dans loop, les tests des if/elsif sont faux pour certains :

Pour moi, il faudrait que tu corriges deux tests :

elsif(results.value == enArriere) au lieu de elsif(results.value == Arriere)
elsif(results.value == Modeautonome) au lieu de elsif(results.value == Autonome)

Ensuite tu devrais initialiser les variables Avant,Arriere,Tgauche,Tdroite,Autonome avec des valeurs différentes entre elles, par exemple
int Avant=1;
int Arrière=2;

car si elles valent toutes 0, la fonction effectueraction() ne pourra pas différentier ce qu’elle a à faire …

voilà …

Bon courage …

 

yep,

Exactly right. This is what I meant by “numbering the states” the robot doesn’t know the difference if all your variables are set to zero. They each need to be set to a unique value so the code can differentiate them.

Je viens d’essayer en

Je viens d’essayer en changeant les valeur de 0 a des nombre different et le robot a reagit au commande mais de facons bizzard ( si je re apouyait sur la touche le robot ne sarretait pas comme dit le code ) et la fonction aller en arriere ne marchais pas.

 

Je vais essayer ce soir avec l’idée de palou car sa me parait effectivement assez probable que le probleme vienne de la :wink:

Je vous dit sa ce soir :slight_smile:

sorry for french language …

… but Newbies semmed to have problems with english (like me :slight_smile: ) …

So I will try to explain what I proposed in english …

  1. Add a call to StopMotors in setup() function to avoid irrelevent state at the begining
  2. In loop(), move tests " (if/elsif…)" into the test" if (irrecv.decode(&results))" to do action only if a command has been received
  3. Add at the end of" if/elsif…" tests an else clause to catch receive errors
  4. Variables used in “if/elsif” tests are not the good ones (Arriere/Autonome)
  5. Variables used to pass order to “executeraction()” function are all initialized to 0 : They must be all different. (Usage of const vars or #define values as argument to the function aught to be better)

 As you can see, my english is not so good, so I prefered to post my comments in french (as Newbies speak french)

I apologize for those i could hurt with french language…

best regards

Palou

still not working…

I’ve just tried Palou’s idea and the result is the same.

The robot only responds to the first order and its impossible to change it eaven if i re push the key or another key.

An idea ?

 

PS: I’ve just receive my L298N to build my new shield :slight_smile:

**palou idea … **

I just rewrote your program with my ideas. If you want try it…

I added some “write” to catch errors …

 #include <DistanceSRF04.h>
 #include <IRremote.h>
 int action;
 int IRdelay = 40 ;
 unsigned long Enavant = 0xA16E6C93 ;
 unsigned long Tourneragauche = 0xA16E40BF ;
 unsigned long Enarriere = 0xA16EE817 ;
 unsigned long Tourneradroite = 0xA16E00FF ;
 unsigned long Modeautonome = 0xA16EC03F ;
 unsigned long Arret = 0xA16E807F ;
 int Avant = 1;
 int Arriere = 2;
 int TGauche = 3;
 int TDroite = 4;
 int Autonome = 5;
 int Stop = 0;
 int RECV_PIN = 11;
 IRrecv irrecv(RECV_PIN);
 decode_results results;
 DistanceSRF04 Dist;
 int distance;
 int motor1Pin1 = 3; // pin 2 on L293D
 int motor1Pin2 = 4;
 int motor2Pin1 = 5; // pin 2 on L293D
 int motor2Pin2 = 6; // pin 7 on L293D
 int enablePin = 9;
 int enable2Pin = 10;// pin 1 on L293D
 
 void setup() { 
 Serial.begin(9600);
 irrecv.enableIRIn();   
 Dist.begin(12,13);
 pinMode(motor1Pin1, OUTPUT);
 pinMode(motor1Pin2, OUTPUT);
 pinMode(motor2Pin1, OUTPUT);
 pinMode(motor2Pin2, OUTPUT);
 pinMode(enablePin, OUTPUT);
 pinMode(enable2Pin, OUTPUT);
}

void autonome() { 
 distance = Dist.getDistanceCentimeter();
 Serial.print("\nDistance in centimers: “);
 Serial.print(distance);
 delay(200); //make it readable

 if (distance <= 30 ) {
  tournerGauche();
 }
 else { 
  avancer();
 }

void startMotors(){
    digitalWrite(enablePin, HIGH);
 digitalWrite(enable2Pin, HIGH);
}

void stopMotors() {
    digitalWrite(enablePin, LOW);
 digitalWrite(enable2Pin, LOW);
}

void avancer() {
    startMotors();
    digitalWrite(motor1Pin1, LOW); // set pin 2 on L293D low   
 digitalWrite(motor1Pin2, HIGH); // set pin 7 on L293D high   
 digitalWrite(motor2Pin1, LOW); // set pin 2 on L293D low   
 digitalWrite(motor2Pin2, HIGH);
}

void tournerGauche() {   
 startMotors();   
 digitalWrite(motor1Pin1, LOW); // set pin 2 on L293D low   
 digitalWrite(motor1Pin2, HIGH); // set pin 7 on L293D high   
 digitalWrite(motor2Pin1, HIGH); // set pin 2 on L293D low   
 digitalWrite(motor2Pin2, LOW);
}

void tournerDroite() {  
 startMotors();  
 digitalWrite(motor1Pin1, HIGH); // set pin 2 on L293D low  
 digitalWrite(motor1Pin2, LOW); // set pin 7 on L293D high  
 digitalWrite(motor2Pin1, LOW); // set pin 2 on L293D low  
 digitalWrite(motor2Pin2, HIGH);
}

void reculer() {   
 startMotors();   
 digitalWrite(motor1Pin1, HIGH); // set pin 2 on L293D low   
 digitalWrite(motor1Pin2, LOW); // set pin 7 on L293D high   
 digitalWrite(motor2Pin1, HIGH); // set pin 2 on L293D low   
 digitalWrite(motor2Pin2, LOW);
}

void loop() {   
 if (irrecv.decode(&results))    {   
  Serial.println(results.value, HEX);   
  irrecv.resume(); // Receive the next value 
  
  if(results.value == Enavant)  {
   action = Avant ;
  } 
  else if(results.value == Tourneragauche)   {
   action = TGauche ; 
  } 
  else if(results.value == Tourneradroite)  {
   action = TDroite ; 
  } 
  else if(results.value == Enarriere)  {
   action = Arriere ; 
  } 
  else if(results.value == Arret)  {
   action = Stop ; 
  } 
  else if(results.value == Modeautonome)  {
   action = Autonome ; 
  }
  else {
   Serial.print(”\nresults.value inconnu : “);
   Serial.print(results.value);
   action = Stop ; 
  } 
  effectueraction(action);
 }
}

void effectueraction(int act)  {
 if (act == Avant)      {
  avancer();    
 }         
 else if ( act == TGauche)      {
  tournerGauche();    
 }         
 else if ( act == TDroite )      {
  tournerDroite();    
 }         
 else if ( act == Arriere)      {      
  reculer();    
 }    
 else if ( act == Stop)      {      
  stopMotors();    
 }    
 else if(act == Autonome)     {
  autonome();    
 }
 else {
  Serial.print(”\nact inconnu : ");
  Serial.print(act);
 }
}