La position de mon servo moteur n'est pas celle demandée

Bonjour à tous.

J'ai eu envie de m'intéresser aux servo-moteurs.

J'ai donc commandé un DS3218mg sur le site au nom de fleuve, qui est surement un import direct du pays du soleil levant.

Lorsque je teste ce produit d'apparence plutôt qualitative, il s'avère qu'après avoir trouvé la position 0, lorsque je demande celle de 90°, il est plutôt vers 120°.

Si je veux 90°, la commande doit être de 65° (après tests empiriques).
Si je veux 180°, la commande doit être de 130°.

Est-ce selon vous un problème de matériel de piètre qualité ? Ou je m'y prends mal ?

J'alimentais le servo depuis l'Arduino Uno, j'ai donc pensé qu'il consommait trop et que le soucis venait de là, mais les résultats sont les mêmes en alimentant de l'extérieur.

Pour le code, rien de compliqué :

#include "Servo.h"

Servo servo; // création de l'objet "servo"

void setup() {
  servo.attach(10); // attache le servo au pin spécifié
}

void loop() {
  servo.write(65); // demande au servo de se déplacer à cette position
  delay(1000); // attend 1000 ms entre changement de position

  servo.write(0); // demande au servo de se déplacer à cette position
  delay(1000); // attend 1000 ms entre changement de position


}

Merci d'avance pour votre aide.

Bonjour
Il existe 2 types des 180 ou des 270 qui ne reagissent pas de la meme facon pour un pulse donné.

Forte chance que ce soit un 270.

Les servos sont pilotés par la durée d'une impulsion envoyée périodiquement.
Il n'y a pas vraiment de norme pour les servos donc pour une durée d'impulsion donnée suivant le servo on peut avoir une position différente. D'où les commandes de calibration que l'on trouve sur les télécommandes de modèles réduits.
La méthode write() de la librairie servo peut recevoir en argument soit un angle, soit une durée d'impulsion. Lorsque tu donnes un angle, le code fait une conversion "au mieux" avec les valeurs les plus courantes soit un angle entre 0 et 180° pour une impulsion entre 1 et 2ms.

Si ton servo ne colle pas tout à fait à ces valeurs tu as 2 possibilités:

  • piloter le servo en passant une durée d'impulsion à la méthode write()
  • tu peux passer des arguments supplémentaires à attach() pour corriger le décalage et/ou un problème d'angle min/max voir ici
    Servo - attach() - Arduino Reference

Dans les 2 cas, il faudra trouver les valeurs des impulsions min et max en tâtonnant un peu.
Il faut essayer différentes valeurs. Lorsque l'impulsion est trop courte ou trop longue en général le servo broute car il n'arrive pas à atteindre la position demandée.

1 Like

Oui c'est un 270°. Cela change la façon de le "piloter" ?

D'accord, merci, je vais regarder ce que tu m'as conseillé.

Bonsoir franju59

Oui, malheureusement, la méthode write(valeur) prends tout ce qui est valeur < que 200 comme un angle et tout ce qui est >= comme une largeur d'impulsion,

  void write(int value);             // if value is < 200 its treated as an angle, otherwise as pulse width in microseconds 

Pris dans Servo.h

donc, 270° va à être pris pour une largeur d'impulsion et tu dois commander ton servo par write(largeurDimpulsion)

Cordialement
jpbbricole

Alors, entrer les valeurs min et max de la data sheet n'a rien changé. Je suppose qu'elles sont déjà standard (500-2500 sur la datasheet).

En pilotant par la durée d'impulsion, j'arrive à quelque chose de plus conforme.
En tâtonnant, j'ai pu descendre à 350us pour le 0°, et monter à 2600us pour le 270°.

Donc cela signifie-t-il que pour chaque servo, on doit se faire une table de valeurs qu'on est allé chercher à tâtons ?

Merci jpbbricole, c'est bon à savoir, et je l'ignorais. Même si je m'étais posé la question, mais en considérant plutôt des valeurs >300, puisqu'il y a des servos à 270°. Donc, bref, j'étais à côté.

Mais cela n'explique pas mon décalage de 90°.

Faut-il donc calibrer chaque servo par tâtonnement ?

Si on veut couvrir l'amplitude complète du servo, oui sans doute.
Si on utilise qu'une partie de l'angle couvert par le servo un simple offset permet de caler le servo correctement.

Cela s'explique si tu as un servo qui couvre 270°. La différence entre 270° et 180° c'est 90°.

En fait, je parlais du fait qu'entre la position pour le write (0) et celle pour le write(90), j'ai plutôt 110 ou 120 degrés.

Bonsoir franju59

Oui, avec des ordres servo.write(microsecondes) tu recherches les 2 extrêmes que tu ajoutes à servo.attach(pin, min, max).

Après pour l'usage, avec map(), tu fais, pour un servo de 270° et un angle de 125°, servo.write(map(125, 0, 270, min, max)).

Cordialement
jpbbricole

Bon, du coup je me suis rendu compte des points suivants :

  • l'angle de rotation max fait 315°
  • la commande en us la plus basse donnant une position est 350
  • la commande en us la plus haute donnant une position est 2600

En entrant ces valeurs et en considérant que 180° équivaut en fait à 100%, avec un produit en croix, j'obtiens une équivalence 90° observé sur le servo pour une commande de 52°. Le 180° pour commande de 104°, et le 270° pour une commande de 156°. Le tout à une demie vache près, puisque je passe par quelques approximations.

Ce qui m'étonne, c'est que je comprends en vous lisant que je devrai faire çà pour chaque servo que j'utiliserai ? Je pensais que c'était un peu plus "plug&play" ^^

Pour ce qui est de map(), je crois qu'il m'a inversé le sens de rotation, mis le zéro ailleurs, et/ou autre, je n'ai pas tout compris. Je m'y repencherai à tête reposée.

Merci pour votre aide, j'ai déjà appris pal mal ce soir sur ces bébêtes que je ne connaissais pas du tout ...

Alors du coup j'ai quand même regardé un peu plus, et en fait dès que je demande moins de 26°, il me met en position 315°. Sinon de 26° à 315° les positions sont bonnes.

Je ne comprends pas. Je mets le code ici, des fois que j'ai fait une boulette ?

saisiss#include "Servo.h"

Servo servo; // création de l'objet "servo"

void setup() {
  servo.attach(10, 360, 2600); // attache le servo au pin spécifié
}

void loop() {
  servo.write(map(26, 0, 315, 360, 2600)); // demande au servo de se déplacer à cette position
  delay(1000); // attend 1000 ms entre changement de position




}ez ou collez du code ici

Voilà ce que fait map()

long map(long x, long in_min, long in_max, long out_min, long out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

Si tu veux contraindre le résultat de map() sur la fourchette out_min, out_max il faut utiliser constraint() sur le résultat retourné par map()

La seule commande pour les servo est une commande en durée d'impulsion.
Voir le chapitre servomoteur des Tuto d'Eskimon.

Sauf bouleversement récent, la bibliothèque arduino part du principe que le servo est un 180°.
La bibliothèque arduino transforme les degrés en temps, puis elle commande le servo en temps.
L'astuce indiquée pour reconnaitre automatiquement une commande en temps ou en degré ne peut fonctionner qu'avec des servos 180°.

Pour compliquer un peu plus, les temps min et max ne sont pas une norme.
Ils dépendent de l'électronique incluse dans le servo.
Il y a le principe basique exposé par Eskimon et il y a maintenant des circuits intégrés spécialisés.

Cerise sur le gâteau quand je m'étais intéressé aux servos, j'avais commandé plusieurs modèles et pour des 180° ou des 270° la course variait de ±5 degrés selon la marque.
Après ouverture, j'en ai déduit que cela provenait de la différence de forme de la butée mécanique qui protège de la destruction le potentiomètre de retour d'information.

Pour des servo de meilleure qualité que ceux habituellement géré par les bibliothèques arduino, il faut tout vérifier, comme tu as déjà pu le constater par toi-même

Merci à tous pour votre aide, je vais donc me dépatouiller avec tout çà, cela devrait le faire.
En gros, je vois que ce n'est pas exactement 180° ou 270°, que la bibliothèque ne connait que 180°, et que donc il faut faire des tests et ajuster les valeurs en fonction du résultat.

Merci pour ces explications.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.