Robot explorateur le retour (arduino)
Hello, je me repenche sur mon projet de robot. J'en avais déja parlé sur ce blog il y a plusieurs mois. Voici la version 2 sur laquelle le capteur de distance tourne indépendamment du robot. C'est à base d'arduino. Je vous explique dans ce billet la base du robot (il va évoluer). En espérant que ça puisse inspirer certains lecteurs.
Vidéo de quelques secondes:
Description du robot
Le chassis du robot provient d'un kit
Moteurs
Le robot contient deux roues motorisées chacune par un moteur courant continu (5 à 12V) et une bille comme dernier point d'équilibre. Pour tourner, on gère les moteurs indépendamment, d'où l’intérêt de pouvoir inverser le courant afin que le robot puisse tourner sur lui même (plus classe).
j'ai laissé tombé le prototypage de deux ponts en H (énorméments de connexions à souder). je les ai remplacé par un sheet L239d (qui remplace deux ponts en H) et me permet aussi d'alimenter les moteurs directement sur les piles (7,5V) séparément à la tension générée par l'arduino (pas assez forte).
La gestion des moteurs sur le L239d (et leur sens de courants) prend 4 pins numériques. (D2,D3, D4,D5 dans mon cas).
Capteur de distance qui tourne
Un capteur de distance SHARP et un servo moteur. Le capteur IR prend un PIN analogique, le servo moteur un PIN numérique de l'arduino.
Le servo que j'ai utilisé ne sait que tourner sur 120° d'apres la doc (et d'après ce que j'ai constaté); Cependant En utilisant la lib servo.h je lui envoie des valeurs de 0 à 180 afin qu'il tourne completement. Il doit y avoir un raté de mon coté quelque part.
Schéma électronique:
Pour le speaker; pour le moment il n'est pas utilisé. Il me servira à faire le bruit des clignotants et/ou le bruit de l'engin de chantier qui recule Beeeep beeep. Sa résistance à 220 ohms, c'est parceque c'est la résistance la plus faible que j'ai trouvé. Mais une 100 ohms conviendrait mieux.
Le condensateur 25V 100uF permet à la plaque arduino de mieux encaisser la surcharge lors du démarrage des moteurs CC. Sur d'autres sites, ils conseillent un condensateur 50V 10uF.
La plaque recto
la plaque verso
Le principe des plaques à pastilles, c'est de faire proprement le crado: Les soudures doivent déborder pour établir les liaisons proches. Pour les liaisons éloignées, j'ai mis des fils. Il n'y a pas beaucoup de composants, je pensais que ce serait torché en une grosse heure... Finalement le coupage, dénudage des fils au ciseau, les soudures, les dé-soudages lorsque ça avait trop bavé; j'ai manipulé le fer à souder pendant une journée entière.
Code arduino
Voici un premier jet de code basique qui permet au robot de se déplacer en évitant les obstacles. Ce n'est pas encore au point car il lui arrive de foncer dans un obstacle que le couple Servo+detecteurIR n'a pas eu le temps de détecter en raison du délai de ballayage des 180°.
#include <Servo.h> /* * Code par Gnieark https://blog-du-grouik.tinad.fr/ nov 2013 * libre d'utilisation, citez simplement la source ça me fera plaisir. */ int motor1Pin1 = 2; int motor1Pin2 = 3; int motor2Pin1 = 4; int motor2Pin2 = 5; int enablePin = 9; int const capteurDistanceTeteDuRobotPin= A0; int distance=0; /*attention la variable distance correspondra à la mesure faite par * l'arduino. C'est une courbe dans ce genre: * * | * Mesure * analogique * | * * | * * | * * | * * | * * |* * * * * ----------------distance (cm)--> * * */ int distanceMax=400; //servo int servoTeteDuRobotPin = 8; int servoTeteDuRobotAngle=0; Servo servoTeteDuRobot; bool robotAvance; bool robotTourne; bool mieuxVautAllerAGauche; bool obstacle(){ /* * note: l'angle 0 est à la gauche du robot * * balaye rapidement sur 180 degres pour relever la distance * tous les 10 degres * * Indique s'il y a un obstacle et renseigne le bool mieuxVautAllerAGauche */ //laisser la tete se replacer for(int i=0;i<18;i++){ servoTeteDuRobot.write(i * 10); //laisser un peu de temps au moteur pour tourner avant de prendre la mesure delay(120); distance=analogRead(capteurDistanceTeteDuRobotPin); if (distance>distanceMax){ if(i<9){ mieuxVautAllerAGauche=true; }else{ mieuxVautAllerAGauche=false; } return true; } } //idem dans l'autre sens for(int i=17;i>-1;i--){ servoTeteDuRobot.write(i * 10); //laisser un peu de temps au moteur pour tourner avant de prendre la mesure delay(120); distance=analogRead(capteurDistanceTeteDuRobotPin); if (distance>distanceMax){ if(i<9){ mieuxVautAllerAGauche=true; }else{ mieuxVautAllerAGauche=false; } /* *comme il y a un obstacle, on sort de suite de la fonction * et on arrete de balayage des distances en cours * afin de permettre au programme d'éviter l'obstacle * immédiatement */ return true; } } return false; } void avance(){ digitalWrite(motor1Pin1, LOW); digitalWrite(motor1Pin2, HIGH); digitalWrite(motor2Pin1, LOW); digitalWrite(motor2Pin2, HIGH); robotAvance=true; robotTourne=false; } void recule(){ digitalWrite(motor1Pin1, HIGH); digitalWrite(motor1Pin2, LOW); digitalWrite(motor2Pin1, HIGH); digitalWrite(motor2Pin2, LOW); } void tourneDroite(){ digitalWrite(motor1Pin1, HIGH); digitalWrite(motor1Pin2, LOW); digitalWrite(motor2Pin1, LOW); digitalWrite(motor2Pin2, HIGH); robotAvance=false; robotTourne=true; } void tourneGauche(){ digitalWrite(motor1Pin1, LOW); digitalWrite(motor1Pin2, HIGH); digitalWrite(motor2Pin1, HIGH); digitalWrite(motor2Pin2, LOW); robotAvance=false; robotTourne=true; } void stop(){ digitalWrite(motor1Pin1, LOW); digitalWrite(motor1Pin2, LOW); digitalWrite(motor2Pin1, LOW); digitalWrite(motor2Pin2, LOW); robotAvance=false; robotTourne=false; } void setup() { Serial.begin(9600); //init servo servoTeteDuRobot.attach(servoTeteDuRobotPin); servoTeteDuRobot.write(90); // set all the other pins you're using as outputs: pinMode(motor1Pin1, OUTPUT); pinMode(motor1Pin2, OUTPUT); pinMode(motor2Pin1, OUTPUT); pinMode(motor2Pin2, OUTPUT); avance(); } void loop() { if(robotAvance){ Serial.println(distance); if (obstacle()){ stop(); //trop pret d'un obstacle pour continuer tout droit if(mieuxVautAllerAGauche){ tourneGauche(); //on décale la tete du robot servoTeteDuRobot.write(70); }else{ tourneDroite(); //on décale la tete du robot servoTeteDuRobot.write(110); //delai minimum de virage delay(200); } } } if(robotTourne){ distance=analogRead(capteurDistanceTeteDuRobotPin); if (distance < 100){ //y'a de la place, tu peux avancer avance(); } } }
Les améliorations prévues:
- améliorer l'évitement des obstacle
- Le look: des clignotants et des phares
- Bien plus tard, un repérage spatial plus intelligent (à l'aide d'une boussole électronique)