LOCODUINO
Parlons Arduino => Bibliothèques => Discussion démarrée par: Jean-Luc le mars 26, 2015, 06:16:57 pm
-
Bonjour à tous,
En me replongeant dans le travail que j'avais effectué pour piloter 8 servo-moteurs, voir la série d'articles sur mon blog (http://modelleisenbahn.triskell.org/spip.php?rubrique22), j'ai voulu remettre les choses à plat.
En effet, quand on pilote un servo-moteur pour bouger les aiguilles d'un aiguillage, on se moque un peu de la manière dont le mouvement est effectué, du moment qu'il est lent. J'avais donc fait un mouvement linéaire sans phase d'accélération ou de décélération. Donc le plus basique possible.
Voulant maintenant manœuvrer des portes de remise, je voulais un mouvement réglable en vitesse, mais aussi que la position angulaire suive une trajectoire qui ne soit pas forcément une droite. Je veux par exemple que la porte vienne en butée puis rebondisse et s'arrête progressivement.
je me suis demandé si il n'existait pas une bibliothèque pour effectuer des mouvements lents sur les servo-moteurs et je n'ai absolument rien trouvé.
J'en ai donc fait une.
On peut donc pour chaque servo :
- définir les positions minimum et maximum ;
- régler la vitesse indépendamment dans chaque sens de déplacement ;
- définir une trajectoire quelconque sous la forme d'une courbe mathématique ;
3 trajectoires sont disponibles toutes faites :
- linéaire
- accélération puis décélération en sinus
- accélération en sinus, rebond sur la butée et décélération en 1/temps
Pour l'instant j'ai un prototype qui tourne mais il faut que je finisse de monter une remise pour montrer le mouvement des portes :) Il faut également que je vérifie que l'Arduino arrive à calculer des fonctions complexes pour 8 servos sans que le mouvement en pâtisse.
Je me servirai de cette bibliothèque pour mettre à jour le logiciel pour piloter 8 servo-moteurs.
Elle disponible via le gestionnaire de bibliothèques de l’IDE
-
Très intéressant comme biblio. Une pile pour le projet locoduino.
Mis en todo pour étudier cela correctement.
En regardant rapidement, il faut que je m'inspire de la fonction update pour la mienne mais comme les objets changent de nom, il faut que je me remettre dedans. La todo est trop longue.
-
J'ai vérifié hier soir que l'on pouvait calculer des fonctions sinus en flottant pour 8 servos sans que le mouvement en soit affecté. J'avais un peu peur qu'au niveau calcul ça ne passe pas mais en fait c'est bon :)
Une fois les valeurs min et max définies via setMin, setMax ou setMinMax pour définir les deux valeurs extrêmes d'un coup. Ces valeurs sont en micro-secondes. La position à atteindre via goTo s'exprime avec un nombre flottant de 0.0 à 1.0
La vitesse (setSpeed, setMinToMaxSpeed et setMaxToMinSpeed) s'exprime aussi avec un nombre flottant. Par défaut la vitesse est de 1.0 (hier c'était 0.0001 mais maintenant je divise par 10000 ce qui est passé à setSpeed, c'est plus sympa d'être autour de 1). On peut descendre en dessous.
-
Hello,
J'ai découvert cette semaine la librairie VarSpeedServo (https://github.com/netlabtoolkit/VarSpeedServo), avec la quelle j'ai un peu joué. C'est pratique, on peut régler la vitesse mais elle n'intègre pas de courbes à proprement parler.
rR
-
J'ai vérifié hier soir que l'on pouvait calculer des fonctions sinus en flottant pour 8 servos sans que le mouvement en soit affecté. J'avais un peu peur qu'au niveau calcul ça ne passe pas mais en fait c'est bon :)
Une fois les valeurs min et max définies via setMin, setMax ou setMinMax pour définir les deux valeurs extrêmes d'un coup. Ces valeurs sont en micro-secondes. La position à atteindre via goTo s'exprime avec un nombre flottant de 0.0 à 1.0
La vitesse (setSpeed, setMinToMaxSpeed et setMaxToMinSpeed) s'exprime aussi avec un nombre flottant. Par défaut la vitesse est de 1.0 (hier c'était 0.0001 mais maintenant je divise par 10000 ce qui est passé à setSpeed, c'est plus sympa d'être autour de 1). On peut descendre en dessous.
La bibliothèque est en effet très interessante, cependant, une question me reste à l'esprit?
A quoi correspond le paramètre vitesse? est ce qu'il y a une conversion à faire entre la valeur qu'on rentre dans le paramètre et la valeur de la vitesse réelle?
Ceci m'amène à une autre question : Ayant commencé la programmation par l'assembleur (sur PIC), je me demandais si avec le C++ on pouvait, tout comme en assembleur, compter le nombre de cycles d'horloge utilisés par instruction? Le C++ étant un language haut niveau, il me parait difficile de déduire des temps précis uniquement grace au programme. Mais peut être que je me trompe?
Tim
-
A quoi correspond le paramètre vitesse? est ce qu'il y a une conversion à faire entre la valeur qu'on rentre dans le paramètre et la valeur de la vitesse réelle?
La position du servo est une fonction du temps. Le temps est la durée en millisecondes depuis l'instant initial où le mouvement est lancé. La vitesse est en fait un facteur multiplicatif du temps. Le temps est normalisé entre 0.0 (position initiale) et 1.0 (position finale). Par défaut la vitesse est de 1, ce qui correspond à 0,0001 de facteur multiplicatif. C'est à dire que pour atteindre un temps normalisé de 1, il faudra 10s. Dans l'exemple la vitesse est mise à 2, il faut donc 5s pour accomplir le mouvement. La position est aussi normalisée en fonction des positions min et max. la vitesse angulaire sera donc différente selon l'écart max-min.
Ceci m'amène à une autre question : Ayant commencé la programmation par l'assembleur (sur PIC), je me demandais si avec le C++ on pouvait, tout comme en assembleur, compter le nombre de cycles d'horloge utilisés par instruction? Le C++ étant un language haut niveau, il me parait difficile de déduire des temps précis uniquement grace au programme. Mais peut être que je me trompe?
On peut mais il faut aller voir le code assembleur généré par le compilateur. Quoiqu'il en soit, ici le temps en compté via un timer et est donc indépendant du code qui s'exécute.
-
J'ai découvert cette semaine la librairie VarSpeedServo (https://github.com/netlabtoolkit/VarSpeedServo), avec la quelle j'ai un peu joué. C'est pratique, on peut régler la vitesse mais elle n'intègre pas de courbes à proprement parler.
C'est une modification de la bibliothèque Servo originale. Effectivement le mouvement est seulement linéaire et on ne peut pas avoir une courbe de position en fonction du temps donc pas de possibilité de simuler des accélérations et décélérations, ni des rebonds.
SlowMotionServo intègre aussi un détachement automatique quand le servo a fini son mouvement avec un délai avant détachement programmable. Cela permet d'éviter qu'il ne grogne en butée contre une force de rappel, typiquement ce que l'on a sur un aiguillage.
La contrainte de SlowMotionServo est d'appeler répétitivement update dans loop.
-
@Jean-Luc, petite proposition pour rendre SlodMotionServo compatible ESP32 :
#include "Arduino.h"
#ifndef ESP32
#include <Servo.h>
#else
#include <ESP32Servo.h>
#endif
;)
-
Ah Merci ! Je m’en occupe. ;)
-
Bonsoir,
Ne serait-Il pas plus judicieux de faire un IF avec les notions #define AVR... au lieu de la librairie Arduino.h
Cordialement
Jean-claude
-
Bonsoir.
Je n’ai pas compris la question.
-
Bonjour Jean-Luc,
Je me suis peut être mal exprimé,
#ifndef ESP32
....
mais ou est définit le ESP32 , nul part , on pourrait coder :
#ifndef TOTO
....
les librairies Locoduino, ne devrait il pas avoir un "header" avec le materiel testé ?
Jean-claude
-
Ah ok :)
La cible est passée par l'IDE lors de l'appel du compilateur via l'option -D.
Pour un ESP32 (ici le Feather d'Adafruit), on aura (entre autres) :
-DARDUINO_FEATHER_ESP32 -DARDUINO_ARCH_ESP32 "-DARDUINO_BOARD=\"FEATHER_ESP32\"" "-DARDUINO_VARIANT=\"feather_esp32\"" -DESP32
Pour un Arduino Uno, on aura (entre autres) :
-DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR
-
Bonjour à tous,
utilisateur à tout va de la librairie SlowMotionServo sur Arduino, je suis bien triste de ne pas pouvoir l'utiliser avec des ESP32.
Je viens de tomber sur ce "vieux" fil mais n'en connais pas la conclusion, peux-t-on utiliser cette librairie avec l4SP32 ou non ? That is the question !
Merci par avance pour vos réponses.
Cordialement
Antoine
-
Ça devrait pouvoir se faire.
Je vais regarder. :)
-
Ça n'a pas l'air trop difficile à faire.
Antoine, comment comptes-tu commander le servo, je ne suis pas sur qu'une impulsion en 3.3V soit reconnue, il faudrait un ampli.
-
Antoine,
Voici SlowMotionServo modifié pour utiliser la lib ESP32Servo (lib qu'il faut donc installer). J'ai pas trop le temps de tester mais ça compile. Dis moi à l'occasion si ça fonctionne.
-
Bonjour Jean-Luc,
si le 3,3V convient bien car il existe une librairie ESP32_Servo.h avec laquelle j'ai pu tester mon cerveau (heu... non, mon servo).
Je fais les essais et reviens vers toi.
Merci en attendant
-
Voila, je viens de finir mes essais et tout semble fonctionner sauf l'instruction
.setReverted(true)
qui n'est pas reconnu dans ma librairie "ESP32Servo.h" si c'est là dedans qu'on la cherche. Il fallait d'ailleurs que je change cette librairie car la mienne s'appelait "ESP32_Servo.h".
Pourrais-tu m'envoyer la librairie "ESP32Servo.h" que tu as utilisé pour les tests ?
En tous les cas un grand merci car je me régale avec SlowMotionServo :)
Bonne soirée
Cordialement
Antoine
-
ESP32Servo est dispo dans le gestionnaire de bibliothèque. L'auteur est Kevin Harrington
Ahhh zut
Je t'ai envoyé une vielle version :(. Voici la version qui est sur le gestionnaire (et donc avec setReverted)
-
Ben voila, tout est parfait, et c'est bien ESP32Servo de Kevin Harrington que j'avais déjà téléchargé.
Encore merci
-
Et donc, Antoine, tu confirmes que SlowMotionServo fonctionne sur ESP32 ?
-
Oui, tout à fait, et grâce à qui ???
Et de plus avec ces 3 include de plus
#include <esp_now.h>
#include <WiFi.h>
#include <SlowMotionServo.h>
#include "DFRobotDFPlayerMini.h"
-
Super !
J'ai pas fait grand chose. ESP32Servo a exactement la même API que Servo. J'ai juste mis dans SlowMotionServo.h :
#ifdef ARDUINO_ARCH_ESP32
#include <ESP32Servo.h>
#else
#include <Servo.h>
#endif
à la place de :
#include <Servo.h>
-
Bonjour Jean-Luc,
je reviens encore vers toi pour cette librairie car je viens de découvrir que les bits > A8 ne sont pas fonctionnelles sur un MEGA. Est-ce volontaire ?
Un produit livré l'année dernière fonctionne très bien sur A9 mais je n'ai pas gardé cette version de librairie et suis un peu dans la m.... pour reprogrammer un MEGA pour cette application.
Merci par avance pour ta réponse.
Bien cordialement
Antoine
-
Bonsoir Antoine
SlowMotionServo fonctionne là où Servo fonctionne.
-
Antoine,
Regarde au début du fichier d'entête Servo.h. Il est possible que la réponse à ton problème soit là :
#define SERVOS_PER_TIMER 12 // the maximum number of servos controlled by one timer
#define MAX_SERVOS (_Nbr_16timers * SERVOS_PER_TIMER)
-
Bonjour et merci pour vos réponses qui malheureusement ne règlent pas mon problème.
à Jean-Luc:
SlowMotionServo fonctionne là où Servo fonctionne.
Il se trouve que Servo fonctionne jusqu'au bit A9 compris et que SlowMotionServo s'arrête à A8.
à Christophe:
Regarde au début du fichier d'entête Servo.h. Il est possible que la réponse à ton problème soit là :
Un changement de cette valeur ne modifie en rien le comportement puisque le test se fait avec 1 seul servo.
Je vous ai mis en PJ les 2 sketchs pour faire des essais quand vous aurez une petite minute. Le plus étrange c'est que j'ai utilisé SlowMotionServo il y a 1 an avec le bit A9 et cela fonctionnait très bien mais je n'ai pas gardé la librairie de l'époque. Comme quoi, quand on fait un dossier complet pour une réalisation qui fonctionne, il vaut mieux sauvegarder tous les éléments, y compris les librairies utilisées.
Antoine
-
Bonjour Antoine,
tu peux réinstaller une ancienne bibliothèque via le gestionnaire de bibliothèques (cf capture) ...
il faut deviner la modification qui te pose problème :
https://github.com/Locoduino/SlowMotionServo
-
Bonjour Michel,
bonne idée que je vais mettre en application ce WE, merci à toi.
Bien que cela n'explique pas le même soucis avec Servo, mais je peux faire les mêmes manips pour trouver une version qui fonctionnait.
-
Antoine,
il y a zéro chance que le SlowMotionServo que tu utilisais il y a un an fonctionne mieux que la version actuelle.
Ceci pour la simple raison que SMS a été mis à jour la dernière fois en décembre 2018 !
Par ailleurs, structurellement, il y a zéro chance que SMS soit fautif pour la simple raison que son interaction avec le servo et les broches passent exclusivement par des appels à Servo. Sauf que ... C'est limité à des numéros de pins de 0 à 63 et que 63 est une valeur spéciale pour dire « pas connecté ». Toujours regarder avant de dire n'importe quoi :)
En revanche, il est possible que la bibliothèque Servo ait changé entretemps car la dernière version date de septembre 2021.
-
Très bonne remarque Jean-Luc, mais tu auras quand même noté que SMS ne fonctionne pas avec A9 alors que Servo oui, sais-tu pourquoi ?
-
Je vais regarder ce WE
-
Bon finalement j'ai regardé tout de suite.
Et c'est bien une limitation de SMS. Je code le numéro de pin sur 6 bits (de 0 à 63) et 63 est la valeur spéciale NOPIN. Or A9 = 63.
J'avais un bit de rab, J'ai donc porté les numéros de pin à 127, 127 étant la valeur spéciale NOPIN, sans augmenter l'empreinte mémoire d'un object SMS.
Donc ça marche avec A9.
Voilà, c'était bien moi le fautif :o
La lib modifiée à télécharger ci-dessous.
Je vais faire la release 1.2.1 ce week-end
-
Merci à toi et bravo pour ta réactivité.
A moi de trouver le soucis avec Servo, je te tiendrai bien sûr au courant (DCC pas analogique :) )
-
Il reste un soucis avec Servo ?
-
Oui, mais c'est peut-être normal, je l'ai indiqué dans mes messages, Servo ne fonctionne que jusqu'à A9, A10 et suite ne fonctionnent pas.
Je viens de faire des essais avec, au lieu de A10, le nombre 64, mais cela ne fonctionne pas non plus alors que 63 (A9) c'est OK.
Mais ne t'embête pas avec cela, mon soucis était surtout le A9 avec SMS qui est utilisé sur une carte loin de chez moi et qui ne fonctionnait plus, c'est rentré dans l'ordre.
Par contre par curiosité, cela vaudrait le coup de comprendre pourquoi A10 à A15 ne fonctionnent pas alors que 42 par exemple fonctionne.
-
Je viens de regarder et ça ne fonctionne pas pour les mêmes raisons : ils utilisent 6 bits pour coder le numéro de broche :
https://github.com/arduino-libraries/Servo/blob/aaaa944c87c4f8b2c827674f90933843a71af19d/src/Servo.h#L95
Donc de 0 à 63. C'est peut-être d'ailleurs pour ça que j'avais moi même limité à un codage sur 6 bits le numéro de broche :)
Or A10 à A15 correspondent aux numéros 64 à 69
J'ai survolé rapidement le code et je ne vois pas d'autre limitation que ce choix arbitraire. J'ai donc modifié Servo.h et remplacé le 6 par un 7 ...
... et ça fonctionne (j'ai testé A10 et A15).
Ligne 98 :
uint8_t nbr : 6; // a pin number from 0 to 63
devient
uint8_t nbr : 7; // a pin number from 0 to 127
-
Beau travail,
il ne me reste qu'à te remercier pour toutes ces recherches et te souhaiter un très bon WE
Bien cordialement
Antoine
-
Merci Antoine :)
Note qu'utiliser un numéro de broche > 63 avec Servo, revient à avoir un numéro de broche modulo 64.
Par conséquent, en attachant le servo à la broche 64, tu le retrouve en fait sur la broche 0. De même, 65 -> 1, 66 -> 2, etc
Ça peut faire des trucs carrément bizarre si ton sketch utilise ces broches pour autre chose. :)