Bonjour/soir,
Je reviens faire un tour de ce coté-ci pour un nouveau projet, j'ai mené à terme l'ancien projet (http://www.robot-maker.com/forum/topic/9212-robot-2wd/?view=findpost&p=59985) de manière un peu laborieuse, je n'avais à l'époque pas encore mon imprimante 3D alors la fixation des moteurs, HC-SR04 et de la batterie a donné quelque chose d'assez bancal, le robot est trop lourd en son centre ce qui oriente les roues vers l'intérieur du robot et crée une contrainte au niveau de l'axe moteur, ça roule, mais pas très droit.
Vous pouvez voir ici deux photos de l'ancienne réalisation :
http://www.noelshack.com/2015-22-1432514568-p5220200.jpg
http://www.noelshack.com/2015-22-1432514570-p5220202.jpg
Je souhaite donc repartir de zéro, avec les nouvelles compétences acquises, et l'imprimante 3D qui pour la partie fixation/mécanique des différentes pièces me sera très utile!
Pour ce robot-ci je compte partir sur de l'arduino, la raspberry pi m'ayant quelque peu déçue.
Je me suis un peu inspirée du robot SUPRA de transistance et de ce site-ci pour le PID (http://www.ferdinandpiette.com/blog/2012/04/asservissement-en-vitesse-dun-moteur-avec-arduino/). Je souhaite faire un robot qui soit mieux concu que l'ancien, qui roule droit cette foit-ci, dont le programme serait lui aussi mieux conçu à la base.
J'ai fait une petite liste des diverses choses qui me seront nécessaire, seules celles n'étant pas dans les dépenses supplémentaires sont à prendre en compte.
J'ai déjà pu faire une petite ébauche de mon programme, incluant un PID
#include <SimpleTimer.h> #include <math.h> const int rightMotorA = 1; const int rightMotorB = 2; const int leftMotorA = 3; const int leftMotorB = 4; const int rightMotorPWM = 5; const int leftMotorPWM = 6; SimpleTimer timer; unsigned int ticks = 0; int speedMotor = 2; // à modifier int freqPID = 50; // fréquence d'exécution du PID float errorCorrection = 0; float sumError = 0; float previousError = 0; float kp = 0; float ki = 0; float kd = 0; void setup() { Serial.begin(115200); pinMode(rightMotorA, OUTPUT); pinMode(rightMotorB, OUTPUT); pinMode(leftMotorA, OUTPUT); pinMode(leftMotorB, OUTPUT); digitalWrite(rightMotorA, LOW); digitalWrite(rightMotorB, LOW); digitalWrite(leftMotorA, LOW); digitalWrite(leftMotorB, LOW); analogWrite(rightMotorPWM, 0); analogWrite(leftMotorPWM, 0); timer.setInterval(1000/freqPID, PID); // on relance la fonction PID toutes les X ms (ici 1000/50 = 20ms) delay(2000); attachInterrupt(0, count, CHANGE); // à chaque changement d'état on lance count(), qui incrémente le nbre de ticks } void loop() { /*Serial.println("Vitesse moteur?"); int speedMotor = Serial.read(); timer.setInterval(1000/freqPID, PID(speedMotor)); // on relance la fonction PID toutes les X ms (ici 1000/50 = 20ms) Serial.println("Point de destination en X?"); int posX = Serial.read(); Serial.println("Point de destination en Y?"); int posY = Serial.read(); double directionXY = direction(posX, posY);*/ timer.run(); delay(2000); } void PID() // fonction s'exécutant toutes les 20ms et remettant ticks à 0, voir time.setInterval // rajouter argument int speedMotor, pour choisir la vitesse du moteur au démarrage du robot { int freqEncoder = freqPID * ticks; // nombre de ticks par 20 ms ramené au nbre de ticks par seconde float speedEncoder = freqEncoder/32/75; /* nbre de ticks par seconde divisé par le nbre de ticks par tour d'axe moteur = nbre de tour d'axe moteur par seconde, divisé par le nombre de tour d'axe moteur par tour de roue = nbre de tours de roue*/ float error = speedMotor - speedEncoder; // l'erreur est la différence entre la vitesse voulue et la vitesse réelle sumError += error; float deltaError = error - previousError; previousError = error; errorCorrection = kp * error; // kp est un coeff. de proportionnalité nous permettant d'approcher l'erreur la plus juste // errorCorrection = kp * error + ki * sumError; // errorCorrection = kp * error + ki * sumError + kd * deltaError; if (errorCorrection < 0) errorCorrection = 0; // normalisation else if (errorCorrection > 255) errorCorrection = 255; // normalisation analogWrite(rightMotorPWM, 0 + errorCorrection); analogWrite(leftMotorPWM, 0 + errorCorrection); ticks = 0; // on remet le nombre de ticks à zéro } void count() { ticks++; } double direction(int posX, int posY) { return ((atan2(posX, posY)/0.017453293)-90); /*on considère le robot orienté en direction 0Y et notre plan XY comme centré au milieu de celui-ci, d'axe X à sa droite et d'axe Y à l'avant*/ }
J'aurais tout de même quelques questions,
les moteurs que j'ai choisi sont ceux-ci http://www.gotronic.fr/art-motoreducteur-75-1-encodeur-rs003-21384.htm
et mes roues http://www.gotronic.fr/art-roue-qfix-50x21mm-percage-4mm-11836.htm
j'ai comme diverses informations :
Résolution de l'encodeur 16 impulsions/tour (soit 75*16 = 1200 impulsions/tour)
Vitesse à vide : 133tours/min
Tours d'arbre par minute : 9975 (= 133*75)
et j'ai pu calculer ceci :
Un tour de roue : rayon = 25mm (=0.025m), périmètre = 2pi*0.025 = 0.15708m = 15.708cm
Distance parcourue : 133*0.15708 = 20.8916m = 2089.16cm
Soit une vitesse de 0.348m/s ou 1.2535km/h
Est-ce que mes calculs sont bons? Si oui, la vitesse ne risque pas d'être trop basse? (le robot circulera en intérieur sur un sol plat, voir du carrelage)
Mes encodeurs vont être assez proches (1~2 centimètres), ils sont à effet Hall, je ne risque pas d'avoir des interférences entre les deux?
Niveau capteurs je ne sais pas encore trop ce qu'il est préférable de prendre, pour le moment j'ai des HC-SR04, mais je vois peu de réalisation un peu évoluée qui utilise ce genre de capteurs, ce sont généralement plutôt des Sharp, ou des ultrasons personnalisés, qu'est-ce qu'il vaut mieux?
Je vais faire mon robot en plusieurs étages, ils seront circulaires, mais je ne sais pas encore trop comment il est préférable de les organiser ces étages, roues + contrôle moteurs sur l'étage du bas, batterie Lipo + capteurs + arduino sur le deuxième étage?
Et dernièrement, dans mon programme je ne sais pas comment utiliser les Serial.read/write et passer un argument (int speedMotor) dans ma fonction PID, quand je les mets dans mes fonctions void loop et void setup le compilateur hurle, malheureusement je ne vois pas où je pourrais les mettre autrement? Dans la fonction PID?
Edit : après réflexion, il va me faire faire deux PIDs, un pour chaque moteur, je n'y avais pas fait attention
je vais devoir aussi réfléchir à comment gérer la marche arrière du robot, ce PID-ci ne gérerait que la marche avant
Le code a été modifié, il y avait une erreur au niveau du previousError, il allait boucler sur 0 tel que le programme était écrit
Merci beaucoup, surtout si vous m'avez lue jusqu'ici
Bonne journée/soirée!