Aller au contenu


Photo
* * * * * 1 note(s)

Commander mon robot via une telecommande et un recepteur infrarouge


  • Veuillez vous connecter pour répondre
29 réponses à ce sujet

#1 Newbies

Newbies

    Membre passionné

  • Membres
  • PipPipPip
  • 487 messages
  • Gender:Male
  • Location:Paris

Posté 10 avril 2013 - 06:18

Voila, j'ai construit il y a peut un robot ( qui marche cette fois ! ) et je me suis dit que je pourrais lui rajouter des fonctions.
J'ai alors eu une idée, pouvoir le telecommander via une telecommande infrarouge et pouvoir le faire passer en " mode autonome " depuis cette même telecomande. J'ai donc ensuite récupérer une vielle telecommande et un recepteur infrarouge et j'ai aussi trouver un post sur instructable.com d'un gars qui explique comment faire Mon lien.

Ayant suivi ces instruction j'ai réussi a récupérer les signaux des touches de ma telecommande qui m'interesait :

En avant : A16E6C93
Tourner a gauche : A16E40BF
En arriere : A16EE817
Tourner a droite : A16E00FF
Mode autonome : A16EC03F

Et j'ai aussi réussi a allumer ou éteindre une LED via cette telecommande.

Je me suis donc dit qu'il suffisait de remplacer l'action d'allumer ou d’éteindre la LED par allumer ou éteindre mes moteurs. Mais, au moment du test, rien ne se passe. Je reçois bien les information sur la touche pressé dans le moniteur série mais cela ne fais pas bouger le robot d'un poil a pars quelques micros impulsion de temps en temps.

Voila le code de test :
#include <IRremote.h>

unsigned long someValue = 0xA16EC03F; // where XXXXXXXX is on our your remote's values.
int motor1Pin1 = 3; // pin 2 on L293D
int motor1Pin2 = 4;
int motor2Pin1 = 5; // pin 2 on L293D
int motor2Pin2 = 6;
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;

int enablePin = 9; 
int enable2Pin = 10;

// the setup routine runs once when you press reset:
void setup() {               

Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver

  // initialize the digital pin as an output.
pinMode(motor1Pin1, OUTPUT);
pinMode(motor1Pin2, OUTPUT);  
pinMode(motor2Pin1, OUTPUT);
pinMode(motor2Pin2, OUTPUT);
digitalWrite(enablePin, HIGH);
digitalWrite(enable2Pin, HIGH);
}

// the loop routine runs over and over again forever:
void loop() {

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

if(results.value == someValue) {
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);// turn the LED on (HIGH is the voltage level)               // wait for a second
}
else { 
digitalWrite(motor1Pin1, LOW); // 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, LOW);
}

}


PS: Je contrôle mes moteurs grâce a un L293D

#2 Newbies

Newbies

    Membre passionné

  • Membres
  • PipPipPip
  • 487 messages
  • Gender:Male
  • Location:Paris

Posté 10 avril 2013 - 06:41

Hop, voila quelques photos de la bête :D

Image(s) jointe(s)

  • DSC_0315.JPG
  • DSC_0316.JPG
  • DSC_0319.JPG
  • DSC_0320.JPG


#3 Cypaubr

Cypaubr

    Nouveau membre

  • Membres
  • 2 messages
  • Gender:Male
  • Location:Nancy

Posté 10 avril 2013 - 06:52

La télécommande que tu utilises fonctionne avec de l'infrarouge (qui a une portée assez limitée et qui ne fonctionne pas en plein soleil) je te conseille la technologie 2.1 GHz en vente dans les magazins de modélisme. Renseigne toi ;) !

#4 thermo_nono

thermo_nono

    Membre chevronné

  • Membres
  • PipPipPipPip
  • 825 messages

Posté 10 avril 2013 - 07:28

bravo.
et merci pour le partage d'expérience.
:thank_you:

#5 Newbies

Newbies

    Membre passionné

  • Membres
  • PipPipPip
  • 487 messages
  • Gender:Male
  • Location:Paris

Posté 10 avril 2013 - 07:29

J'ai une telecommande 2,4GhZ hobbyking mais je l'utilise, ainsi que le récepteur pour faire voler des avions RC. C'est pour cela que je voulais utiliser cette solution car je ne voulais pas racheter un récepteur et que le but premier du robot n'est pas d’être telecommandé.

J'utiliserais surement mais grosse telecommande sur un autre projet :)

En plus je trouve sa cool de contrôler son robot via une telecommande d'appareil photo :D

Est ce normal que le titre ai changé ? J'avoue qu'il n’était pas très explicite ^^

#6 sky99

sky99

    Habitué

  • Membres
  • PipPip
  • 271 messages
  • Gender:Male

Posté 10 avril 2013 - 08:01

Ne serait-ce pas un problème de "refresh"? je veux dire, la commande IR dure un certain temps, et peut être que cette impulsion ne suffit pas
à faire bouger significativement les moteurs.

Je veux dire, si j'ai bien compris, tu veux qu'en maintenant la touche avant, le robot avance, jusqu'à ce que tu lâches?
Mais la nature de la télécommande envoie des signaux IR discrets, et non continus, donc des impulsions "avance". Du coup,
peut être qu'avec un algo du genre "cliquer sur avancer pour que le robot commence à avancer", puis sur une autre touche pour l'arrêter, ça marcherait?

Une autre solution peut être serait de faire en sorte que chaque appui sur avancer déclenche un mouvement pour une durée suffisante (par exemple 0.1s).

Enfin bonne chance :)

Mon site principal : http://www.nagashur.com/ (format blog, un wiki y est aussi)

Mon profil sur hackaday.io : https://hackaday.io/sky99 (hackerspace en anglais, j'y ai plein de projets)

Mon Github : https://github.com/sarinkhan/


#7 Newbies

Newbies

    Membre passionné

  • Membres
  • PipPipPip
  • 487 messages
  • Gender:Male
  • Location:Paris

Posté 10 avril 2013 - 08:47

Ne serait-ce pas un problème de "refresh"? je veux dire, la commande IR dure un certain temps, et peut être que cette impulsion ne suffit pas
à faire bouger significativement les moteurs.


J'avais pas pensez a ca, je fais un test en mettant une duré determiner et je regarde si sa marche. :)

#8 Newbies

Newbies

    Membre passionné

  • Membres
  • PipPipPip
  • 487 messages
  • Gender:Male
  • Location:Paris

Posté 10 avril 2013 - 09:00

Je viens de faire le test en rajoutant "delay ( 1000); " apré la commande avancer et sa marche !

Après faudra peut être que je trouve le moyen de faire comme tu dit, appuyer pour commancer et pour finir l'action mais je n'ai aucune idée de comment faire sa x) parce que si tout les mouvement sont prédéfini sa perd un peut du plaisir du pilotage :D

En tout cas merci beaucoup :)

#9 Newbies

Newbies

    Membre passionné

  • Membres
  • PipPipPip
  • 487 messages
  • Gender:Male
  • Location:Paris

Posté 10 avril 2013 - 09:17

oups, je rectifie, la commande avancer marche nickel mais la commande tourner a gauche ne marche pas comme l'autre. Au lieu de fonctionner 0,5 seconde comme le code le dit, les chenilles tourne en continue puis une des deux s’arrête mais l'autre non, même si j'appuis sur une autre touche? De plus je ne peut pas faire tourner mes moteurs trop longtemps car mon L293D chauffe trop.

Je pense que c'est lié a ma batterie qui ma l'air très déchargé que sa ne fonctionne pas correctement.

#10 sky99

sky99

    Habitué

  • Membres
  • PipPip
  • 271 messages
  • Gender:Male

Posté 11 avril 2013 - 12:31

Je viens de faire le test en rajoutant "delay ( 1000); " apré la commande avancer et sa marche !

Après faudra peut être que je trouve le moyen de faire comme tu dit, appuyer pour commancer et pour finir l'action mais je n'ai aucune idée de comment faire sa x) parce que si tout les mouvement sont prédéfini sa perd un peut du plaisir du pilotage :D/>

En tout cas merci beaucoup :)/>

certes, mais je ne dis pas de faire des programmes prédéfinis, mais plutot que chaque bouton servirait soit:
-a exécuter une commande en boucle, jusqu'à ce qu'on change
-a exécuter une commande durant un certain temps.

La première solution ferait que du coup si on clique sur "avancer", le robot avance en ligne droite jusqu'à ce qu'il reçoive une autre commande. Donc plutot que de maintenir avant, on appuie une fois. Une solution serait de devoir réappuyer pour arrêter d'avancer. Ou chaque appui sur avant augmente la vitesse vers l'avant, chaque appui sur arrière réduit la vitesse, voire inverse la marche du robot.

La seconde solution peut donner un feeling télécommande de voiture téléguidée si on time bien le tout : par exemple si on définit que la commande "avancer" dure 0.05s (delay(50), et que les commandes
de la télécomande se répetent toutes les 50ms également, on peut avoir les sensations normales d'un appui continu qui fait avancer le robot en continu jusqu'a ce qu'on lâche...

oups, je rectifie, la commande avancer marche nickel mais la commande tourner a gauche ne marche pas comme l'autre. Au lieu de fonctionner 0,5 seconde comme le code le dit, les chenilles tourne en continue puis une des deux s’arrête mais l'autre non, même si j'appuis sur une autre touche? De plus je ne peut pas faire tourner mes moteurs trop longtemps car mon L293D chauffe trop.
Je pense que c'est lié a ma batterie qui ma l'air très déchargé que sa ne fonctionne pas correctement.

Si tu as bien un L293D, il est très sous évalué pour ces moteurs. La boite de vitesse Tamiya (j'ai la même, avec les chenilles) est donnée pour 2100mA. Je n'ai pas pu savoir si c'est 2100mA par moteur, ou au total (je penche plus pour le total, en tous cas j'espere sinon c'est un gouffre à énergie, cette boite...)

Le L293D est donné pour 600mA en régime continu, par moteur. Donc si la boite consomme 2100 mA au total, cela donne 1050mA par moteur. ça fait quand même beaucoup plus que les spécifications du L293D.
Et si c'est 2100mA par moteur, alors la, c'est énormément plus ^^
Du coup, dans tous les cas, le L293D ne suffit pas.

Pour info, j'ai fait un rapide test avec un L293D, sans charge pour le robot (les roues tournaient dans le vide), donc les moteurs ne consommaient pas autant
que nécéssaire, et dans ce contexte, le L293D chauffait énormément. j'ai essayé quelques secondes pour voir si ma boite fonctionnait, et je n'ai pas réessayé.
J'ai noté également que les mouvements n'étaient pas ceux attendus (un coté tournait à une vitesse normale, l'autre très lentement), donc je penche pour ça.

Moi je te conseillerais de multiplier les L293D en parallèle, ou trouver une puce plus puissante.

Mon site principal : http://www.nagashur.com/ (format blog, un wiki y est aussi)

Mon profil sur hackaday.io : https://hackaday.io/sky99 (hackerspace en anglais, j'y ai plein de projets)

Mon Github : https://github.com/sarinkhan/


#11 sky99

sky99

    Habitué

  • Membres
  • PipPip
  • 271 messages
  • Gender:Male

Posté 11 avril 2013 - 12:39

J'ai fouillé la doc plus en détail, et le moteur est le F130RA-18100, dont les caractéristiques sont visibles sur cette page. Malheureusement, c'est le pire des cas : le courant nécessaire peut monter à 2.1A pour chaque moteur. Donc pour chaque canal, on est à plus du triple des capacités du L293D. Et même si on prend le courant en pointe du L293D, 1.2A par canal, ça ne suffit pas!

Pour ma part, je vais continuer à ne pas me servir de ce système jusqu'à ce que je puisse mettre des moteurs plus raisonnables. C'est dommage, car le design des chenilles me plaisait bien, avec la forme trapezoidale parfaite pour franchir des obstacles! (par contre les chenilles me semblent fragiles).

Mon site principal : http://www.nagashur.com/ (format blog, un wiki y est aussi)

Mon profil sur hackaday.io : https://hackaday.io/sky99 (hackerspace en anglais, j'y ai plein de projets)

Mon Github : https://github.com/sarinkhan/


#12 Mike118

Mike118

    Staff Robot Maker

  • Administrateur
  • PipPipPipPipPip
  • 9 963 messages
  • Gender:Male
  • Location:Anglet

Posté 11 avril 2013 - 01:45

Pour ma part, je vais continuer à ne pas me servir de ce système jusqu'à ce que je puisse mettre des moteurs plus raisonnables. C'est dommage, car le design des chenilles me plaisait bien, avec la forme trapezoidale parfaite pour franchir des obstacles! (par contre les chenilles me semblent fragiles).

Si c'est uniquement le manque de puissance de tes driver pour moteur qui te dérange sache que tu as le L298 qui est pas mal pouvant conduire 2A en continu et 3A ampère en pointe ! Sinon tu as aussi le LMD18200 mais là c'est plus exactement le même joujou et le prix n'est plus le même non plus ^^

alors que le L298 me coute 4 euros le LMD18200 me coute 8 euros et il ne contient qu'un pont en H alors que le L298 en contient deux ...

Si mon commentaire vous a plus laissez nous un avis  !  :thank_you:

Nouveau sur Robot Maker ? 

Jetez un oeil aux blogs, aux tutoriels, aux ouvrages, au robotscope  aux articles,  à la boutique  et aux différents services disponible !
En attendant qu'une bibliothèque de fichiers 3D soit mise en place n'hésitez pas à demander si vous avez besoin du fichier 3D d'un des produits de la boutique... On l'a peut être ! 
Si vous souhaitez un robot pilotable par internet n'hésitez pas à visiter www.vigibot.com et à lire le sous forum dédié à vigibot!

 

Les réalisations de Mike118  

 

 

 


#13 sky99

sky99

    Habitué

  • Membres
  • PipPip
  • 271 messages
  • Gender:Male

Posté 11 avril 2013 - 03:49

Si c'est uniquement le manque de puissance de tes driver pour moteur qui te dérange sache que tu as le L298 qui est pas mal pouvant conduire 2A en continu et 3A ampère en pointe ! Sinon tu as aussi le LMD18200 mais là c'est plus exactement le même joujou et le prix n'est plus le même non plus ^^

alors que le L298 me coute 4 euros le LMD18200 me coute 8 euros et il ne contient qu'un pont en H alors que le L298 en contient deux ...

Faudrait que je me procure quelques L298 :)
Mais 2100mA ça fait beaucoup, donc peu d'autonomie potentielle!
AU passage, les moteurs du bidule Tamiya sont prévus pour du 3V, ce qui ne m'arrange pas des masses :)
Mais en effet, faudrait que je m'équipe d'autres drivers ^^

Mon site principal : http://www.nagashur.com/ (format blog, un wiki y est aussi)

Mon profil sur hackaday.io : https://hackaday.io/sky99 (hackerspace en anglais, j'y ai plein de projets)

Mon Github : https://github.com/sarinkhan/


#14 Mike118

Mike118

    Staff Robot Maker

  • Administrateur
  • PipPipPipPipPip
  • 9 963 messages
  • Gender:Male
  • Location:Anglet

Posté 11 avril 2013 - 01:29

Faudrait que je me procure quelques L298 :)/>
Mais 2100mA ça fait beaucoup, donc peu d'autonomie potentielle!
AU passage, les moteurs du bidule Tamiya sont prévus pour du 3V, ce qui ne m'arrange pas des masses :)/>
Mais en effet, faudrait que je m'équipe d'autres drivers ^^



Perso je survolte presque toujours les moteur CC ... et j'en ai cramé encore aucun !
Pourtant du 24V sur un moteur spécifié 3V c'est pas un petit survoltage ^^ Mais ça booste sacrément les moteurs !

Si mon commentaire vous a plus laissez nous un avis  !  :thank_you:

Nouveau sur Robot Maker ? 

Jetez un oeil aux blogs, aux tutoriels, aux ouvrages, au robotscope  aux articles,  à la boutique  et aux différents services disponible !
En attendant qu'une bibliothèque de fichiers 3D soit mise en place n'hésitez pas à demander si vous avez besoin du fichier 3D d'un des produits de la boutique... On l'a peut être ! 
Si vous souhaitez un robot pilotable par internet n'hésitez pas à visiter www.vigibot.com et à lire le sous forum dédié à vigibot!

 

Les réalisations de Mike118  

 

 

 


#15 Newbies

Newbies

    Membre passionné

  • Membres
  • PipPipPip
  • 487 messages
  • Gender:Male
  • Location:Paris

Posté 11 avril 2013 - 06:57

voila , j'ai fais une demande d’échantillons gratuit pour des L298N chez ST microelectronics ( le meme site ou j'ai eu mes L293D ) qui sont très sympas.

Sinon, j'ai aussi trouver un contrôler de moteur SN754410 qui, en plus de pouvoir supporter 1,2 A par moteur, a les même PIN de sorti que le L293D ce qui me permettrais de ne pas devoir refaire un shield une deuxième fois. Le seul problème c'est qu'il est dispo que chez Texas instruments et qu'il est trés difficile de recevoir des echantilions gratuits.

Je pense opter pour l'option qui consiste a appuyer une fois pour démarrer l'action et re appuyer pour la finir. J'aimerais aussi que si l'on appuis sur une autre touche quand une action est en cour, elle s’arrête et commence l'autre action sans que l'utilisateur ai besoin de re appuyer sur la première touche avant d'appuyer sur la deuxième. Quelqu'un a t il une idée en gros du code pour faire cela ( je suis a l'aise seulement avec les fonction IF et ELSE c'est pour
ca ^^ )

PS: J'alimente mes moteur via une batterie 4.8V 620mah ( au passage, que signifie mAh pas rapport a mA ? ) et mon arduino via une pile 9V

#16 Newbies

Newbies

    Membre passionné

  • Membres
  • PipPipPip
  • 487 messages
  • Gender:Male
  • Location:Paris

Posté 12 avril 2013 - 10:12

La seconde solution peut donner un feeling télécommande de voiture téléguidée si on time bien le tout : par exemple si on définit que la commande "avancer" dure 0.05s (delay(50), et que les commandes
de la télécommande se répètent toutes les 50ms également, on peut avoir les sensations normales d'un appui continu qui fait avancer le robot en continu jusqu’à ce qu'on lâche...


je viens d'essayer cette solution mais j'ai, malgré de nombreux essai, pas réussi a trouver le bon timing ce qui donc un résultat vraiment saccadé. Faudrait que je trouve un moyen de connaitre presicement a quel fréquence les signaux sont envoyé de manière a calé le truc sur ce timing.

PS: Je voulais rajouter un capteur sur le coté pour plus de précision et j'ai arraché un transistor au moment de le décollé d'un autre robot la poisse non ? ^^

#17 sky99

sky99

    Habitué

  • Membres
  • PipPip
  • 271 messages
  • Gender:Male

Posté 12 avril 2013 - 04:10

Perso je survolte presque toujours les moteur CC ... et j'en ai cramé encore aucun !
Pourtant du 24V sur un moteur spécifié 3V c'est pas un petit survoltage ^^ Mais ça booste sacrément les moteurs !

C'est bon à savoir :) C'est vrai qu'après tout un moteur c'est juste une bobine de fil et des aimants...
Mais bon, quand ça sera un moteur a 50€ je respecterai quand même les spécifications :D


voila , j'ai fais une demande d’échantillons gratuit pour des L298N chez ST microelectronics ( le meme site ou j'ai eu mes L293D ) qui sont très sympas.

Sinon, j'ai aussi trouver un contrôler de moteur SN754410 qui, en plus de pouvoir supporter 1,2 A par moteur, a les même PIN de sorti que le L293D ce qui me permettrais de ne pas devoir refaire un shield une deuxième fois. Le seul problème c'est qu'il est dispo que chez Texas instruments et qu'il est trés difficile de recevoir des echantilions gratuits.

Je pense opter pour l'option qui consiste a appuyer une fois pour démarrer l'action et re appuyer pour la finir. J'aimerais aussi que si l'on appuis sur une autre touche quand une action est en cour, elle s’arrête et commence l'autre action sans que l'utilisateur ai besoin de re appuyer sur la première touche avant d'appuyer sur la deuxième. Quelqu'un a t il une idée en gros du code pour faire cela ( je suis a l'aise seulement avec les fonction IF et ELSE c'est pour
ca ^^ )

PS: J'alimente mes moteur via une batterie 4.8V 620mah ( au passage, que signifie mAh pas rapport a mA ? ) et mon arduino via une pile 9V

Le IC dont tu parles (SN754410) est vendu chez pololu. Je trouve cette puce très intéréssante en effet, pour son brochage identique au L293D.
Par contre comme les specs des moteurs parlent de 2100mA par moteur, ça veut dire qu'il te faut DEUX SN754410 en parallèle...

Concernant ce que tu veux faire, ce n'est pas trop compliqué. Simplement, tu fais une boucle du genre :
int action=0;
int lecture=0;

void effectuerAction(int action)
{
  if(action==avancer)
  {
    enable1=1;
    enable2=1;
    ...
  }
  else if(...)
  {
    
  }
  ...
  else
  {
    ...
  }
  delay(Y);
}

loop()
{
lecture=lire_capteur(IR);
if(lecture==1)
  {
    action=avancer;
  }
else if(lecture==2)
  {
    action==tourner
  }
...
else
  {
    action=action_par_defaut_pour_les_autres_touches;
    ou bien ne rien faire du  tout et laisser l'action précédente si ça ne correspond pas à une touche qui nous intéresse
  }

  effectuer(action);
  delay(X);
}

EN gros, tu lis l'instruction à chaque fois. Si rien n'est lu, tu ne modifies pas la commande "action". ta fonction "effectuer(action)" continue donc
jusqu'à ce qu'on modifie action. Du coup si on lit autre chose, tu auras un changement d'action, et le robot continuera à le faire jusqu'à nouvel ordre.

Cependant, tu peux affiner, et faire en sorte que le robot tourne un certain temps fixe avant de recommencer à avancer, car si il se met à tourner en rond, c'est peut être dur à controler. Donc par exemple, après avoir tourné 0.1s, le robot s'arrête de tourner, et attend une autre commande, ou bien reprend la précédente commande par exemple, si c'était avancer ou reculer.

Bref, en jouant sur la variable action dans les bons if, tu peux adapter le comportement.

Du coup tu peux carrément programmer la touche droite pour faire tourner le robot par petits bouts, une autre touche pour le faire tourner jusqu'à nouvel ordre, et une troisième pour le faire tourner de 90° par exemple!

La ou ça devient intéressant, c'est que ta télécommande à plein de boutons, donc tu peux programmer plein de choses :
avancer jusqu'à nouvel ordre, avancer d'un mètre puis s'arrêter, etc...
En utilisant le squelette ci dessus il suffit de modifier/ajouter des delay, et éventuellement modifier la valeur de action :)


je viens d'essayer cette solution mais j'ai, malgré de nombreux essai, pas réussi a trouver le bon timing ce qui donc un résultat vraiment saccadé. Faudrait que je trouve un moyen de connaitre presicement a quel fréquence les signaux sont envoyé de manière a calé le truc sur ce timing.
PS: Je voulais rajouter un capteur sur le coté pour plus de précision et j'ai arraché un transistor au moment de le décollé d'un autre robot la poisse non ? ^^

Bah pour faire simple, je dirais que tu augmentes le delay après chaque action, jusqu'à ce que l'action dure au moins aussi longtemps que le délai entre le renvoi de la commande. Donc tu peux partir par exemple de 0.5s. Si c'est trop, tu essaies 0.25s. SI c'est encore trop, tu divises par 2, si c'est pas assez, tu essaies pile entre 0.25 et 0.5. Et ainsi de suite. C'est une recherche dichotomique, et ça te mène forcément près de ta solution en très peu de coups :)

Le fait est que la télécomande a un délai entre deux envois de la même commande, et il faut trouver ce délai!

Mon site principal : http://www.nagashur.com/ (format blog, un wiki y est aussi)

Mon profil sur hackaday.io : https://hackaday.io/sky99 (hackerspace en anglais, j'y ai plein de projets)

Mon Github : https://github.com/sarinkhan/


#18 Newbies

Newbies

    Membre passionné

  • Membres
  • PipPipPip
  • 487 messages
  • Gender:Male
  • Location:Paris

Posté 12 avril 2013 - 06:42

OUAH ! Merci pour cette super réponse :D

J'ai commencé a écrire un code en suivant ton "plan" mais j'ai encore quelques question a propos de celui ci.

-La parti de code que tu a écrite est elle dans la fonction loop ? Ou bien c'est la fonction " loop " dans ton code qui fais office de loop ? ( si 'est le cas je ne savais pas que l'on pouvais mettre une boucle quelconque avant la boucle principal " loop " )

-Je n'ai pas bien compris ce qu'il faudrait mettre dans les " else "

- Pourquoi y'a t il un delay a la fin de la boucle " effectuer une action ?

- Et enfin a quoi sert cela : effectuer(action); a la fin de ton code ?
delay(X);

Voila le code que j'ai commencé a écrire ( je n'ai rien mis dans l'action autonome pour l'instant pour ne pas trop embrouiller le 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 ;
int Avant ;
int Arriere ;
int TGauche ;
int TDroite ;
int Autonome ;
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;
int led = 13;
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);

// set all the other pins you're using as outputs:
pinMode(motor1Pin1, OUTPUT);
pinMode(motor1Pin2, OUTPUT);
pinMode(motor2Pin1, OUTPUT);
pinMode(motor2Pin2, OUTPUT);
pinMode(enablePin, OUTPUT);
pinMode(enable2Pin, OUTPUT);

// set enablePin high so that motor can turn on:
digitalWrite(enablePin, HIGH);
digitalWrite(enable2Pin, HIGH);
}

 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 == Arriere){
     
action == Arriere ;
   }
   
         else if(results.value == Autonome){
     
action == Autonome ;
   }
   
   
   
     
    void effectueraction
    
    {   
    if (action == Avant) {
       
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);
     }
     
     else if ( action == TGauche) {
       
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);
     }
     
     else if ( action == TDroite ) {
       
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);
     }
     
     else if ( action == Arriere) {
       
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);
     }
     
     else {
       
digitalWrite(motor1Pin1, LOW); // 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, LOW);
     }
   }

et voici les messages d'erreurs du compilateur
CODE_ROBOT_IR.ino: In function 'void loop()':
CODE_ROBOT_IR:84: error: a function-definition is not allowed here before '{' token
CODE_ROBOT_IR:125: error: expected `}' at end of input

Merci encore pour votre aide :D

#19 sky99

sky99

    Habitué

  • Membres
  • PipPip
  • 271 messages
  • Gender:Male

Posté 13 avril 2013 - 05:23

OUAH ! Merci pour cette super réponse :D/>
J'ai commencé a écrire un code en suivant ton "plan" mais j'ai encore quelques question a propos de celui ci.

-La parti de code que tu a écrite est elle dans la fonction loop ? Ou bien c'est la fonction " loop " dans ton code qui fais office de loop ? ( si 'est le cas je ne savais pas que l'on pouvais mettre une boucle quelconque avant la boucle principal " loop " )

Oui, en effet, la fonction loop dans le squelette de code que je présente, correspond au corps du void loop() de l'arduino :)
donc ce n'est pas une nouvelle fonction.

En revanche, tu peux avoir une fonction avec une boucle sans problème, tant que tu l'appelle dans la "loop()" principale :) mais il faut un autre nom bien sur.


-Je n'ai pas bien compris ce qu'il faudrait mettre dans les " else "

en fait, c'est une habitude que j'ai, mais ça n'est probablement pas nécéssaire. Ici, ce serait pour prévoir une action si on appuie sur l'une des touches que tu n'utilises pas par exemple. Mais si tu souhaites ne rien faire quand on appuie ou il ne faut pas, on peut carrément enlever les else()


- Pourquoi y'a t il un delay a la fin de la boucle " effectuer une action ?

ça aussi, c'est une habitude, sur le raspberry pi, comme le processeur fait plusieurs tâches, je mets un delay pour ne pas faire trop les appels trop souvent. Sur le Arduino, je le fais aussi, car les capteurs ont une fréquence de rafraichissement. Par exemple, mon capteur à ultra sons donne la distance 20 fois par seconde, donc si je regarde la distance toutes les millisecondes, je passerai mon temps à analyser la même valeur. donc je fais un delay(50) pour regarder la valeur toutes les 50ms, soit 20 fois par seconde.

Dans ton cas, à toi de voir, au pire si tu ne mets pas de delay, les commandes seront ré-évaluées très rapidement. Par contre il faudra des delay pour laisser le temps aux moteurs de bouger.

- Et enfin a quoi sert cela : effectuer(action); a la fin de ton code ?
delay(X);


L'idée ici, c'est que plutôt que de mettre les actions directement dans la boucle loop, j'ai fait une fonction qui fait quelquechose en fonction du paramètre. Du coup, effectuer(avancer) va appeller avancer().
effectuer(tourner_a_gauche) va appeller toutnerAGauche(), et ainsi de suite. La boucle lit donc la valeur de la télécomande, et si quelquechose est reçu, la variable action est modifiée.

Après avoir fait cela, j'appelle la fonction effectuer(action), qui se chargera d'avancer, reculer, tourner, etc, selon la valeur de action... Et si je n'ai rien reçu, ben on reste sur la précédente valeur de action, donc le robot continue à faire ce qu'il faisait.
L'intérêt c'est que tu peux aussi modifier la valeur de action dans les sous fonctions, par exemple, tu peux décider qu'après avoir tourné un certain temps, le robot s'arrête automatiquement de tourner (comme ça il tourne toujours d'un angle fixe à chaque fois, par exemple 45°), sauf si l'utilisateur ré-appuie sur le bouton "tourner"...

Maintenant l'un des deux delay est inutile, soit tu mets le delay dans loop(), soit dans effectuer(action).

De même, tu pourrais aussi bien intégrer le code de effectuer(action) directement dans loop. C'est juste une habitude que j'ai de faire des petits modules à chaque fois. ça permet par exemple de garder le même code de "effectuer(action)" pour différents robots, quel que soit le mode de contrôle... dans un cas action peut etre défini par la télécomande, dans l'autre par une fonction en utilisant des capteurs pour déterminer automatiquement ce qu'il faut faire.

Voila le code que j'ai commencé a écrire ( je n'ai rien mis dans l'action autonome pour l'instant pour ne pas trop embrouiller le code)


voici ce que je pense que devrait faire ton 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= ... ;//a toi d'addigner une touche pour l'arrêt des moteurs

int Avant ;
int Arriere ;
int TGauche ;
int TDroite ;
int Autonome ;
int Stop ;
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;
int led = 13;
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);

// set all the other pins you're using as outputs:
pinMode(motor1Pin1, OUTPUT);
pinMode(motor1Pin2, OUTPUT);
pinMode(motor2Pin1, OUTPUT);
pinMode(motor2Pin2, OUTPUT);
pinMode(enablePin, OUTPUT);
pinMode(enable2Pin, OUTPUT);

// set enablePin high so that motor can turn on:
//digitalWrite(enablePin, HIGH); //si tu fais ça les moteurs ne s'arrêtent jamais!
//digitalWrite(enable2Pin, HIGH);//idem. Il faut faire le enable quand tu veux que le robot avance... Sauf si tu veux que ton robot soit toujours en mouvement.
}

/**
 * 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 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)
     {
       //traitements à faire en mode autonome , par exemple :
       int dist=lireCapteurDistance();//la fonction lireCapteurDistance() doit être implémentée
       if(dist<30)
       {tournerGauche();}//c'est ici que tu vois l'intérêt d'avoir fait des fonctions : ça t'évite de retaper les 4 lignes pour activer les moteurs!
       else
       {avancer();}
     }

   }

Voila. Ce code devrait compiler, et en plus je t'ai corrigé d'autres erreurs. Regarde les commentaires, il y a certains points qu'il est très important de comprendre, sinon ça ne marchera pas.
En programmation, tu dois prendre ton temps, et y aller par étapes :) C'est un conseil que je donne à mes étudiants : fais un petit bout, vérifie qu'il fonctionne comme il faut. Une fois que c'est fait, tu te sers de ce que tu as fait pour faire une chose un peu plus compliquée, et tu valides. Tu répètes l'opération autant de fois que c'est nécéssaire, et à la fin tu peux réussir à faire de gros programmes très complexes, si tu t'y prends ainsi,
petit à petit.
Avec le robot c'est pareil. Il faut d'abord faire fonctionner les moteurs, et quand c'est fait, tester les capteurs, puis ensuite faire une fonction pour avancer tout droit, la tester, etc etc...
Et à la fin tu fais tout on algorithme d'évitement d'obstacle, et tu peux programmer ton robot pour qu'il poursuive John Connor :)

Mon site principal : http://www.nagashur.com/ (format blog, un wiki y est aussi)

Mon profil sur hackaday.io : https://hackaday.io/sky99 (hackerspace en anglais, j'y ai plein de projets)

Mon Github : https://github.com/sarinkhan/


#20 Newbies

Newbies

    Membre passionné

  • Membres
  • PipPipPip
  • 487 messages
  • Gender:Male
  • Location:Paris

Posté 13 avril 2013 - 09:26

Merci encore pour cette super réponse :D

Je viens de suivre tes instructions sur le code et, après compilation, le robot s'est mis a avancer en continue avec les deux moteurs. J'ai donc vérifier avec le moniteur série qu'il recevait bien les signaux de la telecommande et c’était bien le cas. Je me suis donc dit que l'erreur venait surement de la petite modification que j'ai fais au code en intégrant l'action "autonome" dans une fonction avec les autres commandes.

PS: J'ai remarquer que sur le moniteur serie les valeurs lue par le capteur n’apparaisse pas. Elle apparaisse peut etre que quand on appelle la fonction "autonome".


Avec le robot c'est pareil. Il faut d'abord faire fonctionner les moteurs, et quand c'est fait, tester les capteurs, puis ensuite faire une fonction pour avancer tout droit, la tester, etc etc...


C'est ce que j'ai fais et toutes les partis ont l'air de fonctionner correctement ;) Je fait des tests fréquemment pour voir si rien n'a cramé :D

Et à la fin tu fais tout on algorithme d'évitement d'obstacle, et tu peux programmer ton robot pour qu'il poursuive John Connor


Pourquoi poursuivre ? Moi je veut qu'il le rattrape et qu'il le renvoi dans le future :D ( même si avec une gearbox tamiya sa me parait difficile :))


Voila le code ( que tu doit maintenant connaitre mieux que moi ^^ )
#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();
     }

   }

Merci encore :D




0 utilisateur(s) li(sen)t ce sujet

0 members, 0 guests, 0 anonymous users