Commander un servo moteur.
Pour commander un servo moteur il suffit d'envoyer un signal (positionner la broche de commande du servo moteur à +5V) d'une durée allant de 1ms à 2ms toutes les 20ms. Un signal de 1ms correspond a une extrémité du servo et 2ms correspond a l'autre extrémité du servo moteur.
Problématique.
Donc pour commander un servo moteur on lui envoi la position désirée et le servo se positionne. Dans le cadre d'un programme informatique il peut être plus qu'important de connaitre la position d'un servo moteur. En effet cette valeur peut servir pour savoir si le servo moteur a atteint la position envoyée ou s'il est encore entrain d'effectuer la rotation. En effet dans le cadre d'un robot de type hexapode il peut être utile de savoir les états des servos tout simplement pour savoir a quel moment continuer le mouvement. Effectivement une solution pourrait être de calculer le temps d'exécution d'un mouvement de 0 a 180° afin de prévoir ensuite la position du servo en fonction du temps. Cependant cette technique ne marche plus si par exemple la batterie s'est un peu déchargée, ou alors s'il y a, à ce moment là une contrainte mécanique sur le servo moteur.
Solution de retour de position par le servo.
Un servo moteur est constitué d'un moteur avec réducteurs d'une carte électronique et d'un potentiomètre linéaire qui permet à la carte électronique de vérifier la position actuelle du servo. Je vous propose d'utiliser cette valeur envoyée par le potentiomètre afin de connaitre la position du servo moteur. En effet le potentiomètre est mécaniquement lié directement au palonnier du servo moteur. Donc la résistance obtenue au bornes du potentiomètre correspond à la position du palonnier.
Le programme informatique devra évidement effectuer un genre d'étalonnage au début de l'exécution. Positionner le servo tout a droite, et voire la valeur du capteur, puis positionner le servo tout a gauche et voir la valeur du capteur. Ces deux valeurs vont nous servir de référence min et max de la variation. En effet la variation mesurée est de 1.7V - 0.9V = 0.8V. Votre entrée analogie doit avoir une définition suffisante pour avoir un peu de précision. En effet sur une variation de 0.8V il s'agit de représenter théoriquement les 180° de rotation. Donc l'entrée analogique devra être capable de reperer des variations de 5mV pour avoir une précision d'environ 1°. Il va de sois qu'il est aussi envisageable d'enregistrer les valeurs minimales et maximales de la tension obtenue au bornes du potar pour ne pas avoir a effectuer l'étalonnage a chaque initialisation.
Par ailleurs j'utilise la lib officielle de arduino pour commander le servo moteur. Dans ma boucle principale j'effectue bien évidement la mesure du potentiomètre pour indiquer a l'écran la position actuelle du servo moteur.
Vous pouvez tout a fait aussi déconnecter la patte de la commande du servo et faire tourner a la main le servo moteur, vous verrez alors l'indicateur se déplacer a l'écran indiquant toujours la position actuelle du servo moteur.
#includeDocumentation annexe#include LiquidCrystal lcd(6, 7, 10, 11, 12, 13); Servo myservo; int pos = 1; // variable to store the servo position int sensorPin = 38; int sensorValue = 0; int sense = 1; int sensorMax = 0; int sensorMin = 0; int sensorNorm = 0; int sensorOld = 0; void setup() { myservo.attach(9); // attaches the servo on pin 9 to the servo object lcd.begin(16, 2); } void loop() { myservo.write(1); delay(2000); sensorMin = analogRead(sensorPin); myservo.write(180); delay(2000); sensorMax = analogRead(sensorPin); lcd.clear(); lcd.setCursor(4,0); lcd.print(String("Min :") + sensorMin); lcd.setCursor(4,1); lcd.print(String("Max:") + sensorMax); delay(4000); while(true) { sensorValue = analogRead(sensorPin); sensorOld = sensorNorm; sensorNorm = map(sensorValue, sensorMin, sensorMax, 1, 180); if ((sensorNorm > 0) && (sensorNorm <= 180)) { if (abs(sensorOld - sensorNorm) < 2) { lcd.clear(); lcd.setCursor(0,0); lcd.print(indic(sensorNorm)); } } pos += sense; if ((pos <= 1) || (pos >= 180)) { sense *= -1; } myservo.write(pos); delay(10); } } String indic(int sensor) { String result = ""; int sensorNorm = map(sensor, 1, 180, 0, 14); result = "["; for (int i =0; i < 14; i ++) { if (i == sensorNorm) { result += "O"; } else { result += "-"; } } result += "]"; return result; }
http://fribotte.free.fr/bdtech/pic/pic_et_servo.html
ça n'as pas fonctionner avec le HS-322HD comment dois je faire pour résoudre le problème
RépondreSupprimerCeci fonctionne pour un servo moteur à rotation continu ?
RépondreSupprimerBonjour,
RépondreSupprimerCeci ne fonctionnera pas a priori avec un servomoteur a rotation continue, car le principe d'un servo a rotation continue c'est justement de découpler le potar de l'axe du moteur.
Je te conseil de mettre des optocoupleurs. =)
étant donner que duration*cycle=coef_tour...
RépondreSupprimerduration c'est delay(ms) entre mouve et stop.
et cycle c'est le nombre de fois que tu vas le faire...
mais ça derive donc besoin de resynchroniser...
je suis rendu la et bien sure garder le tous en politique device...
ça fait beaucoup de points pour eviter les couches soft....
bref utilise : write(1000)delay(xx);write(1500)= 1 cycle en 5ms ~ 360 cycle pour un tour
Bonjour a vous, j'ai pas bien compris le probleme de dérivation et de nécessité de resynchro que vous rencontrez... Mon script ne fait que de lire la valeur de la tension au bord du potentiometre de position du servo moteur. Donc a priori le calcul a chaque itération est au plus près de ce qui se passe mécaniquement dans le dispositif...
Supprimer