LOCODUINO

Bibliothèque Accessories

Bibliothèque Accessories (1)

Les grands principes

.
Par : Thierry

DIFFICULTÉ :

Accessories permet de piloter finement tous vos accessoires, qu’il s’agisse de moteurs rotatifs ou linéaires, de servos, de moteurs pas à pas, de solénoïdes ou de DELs et ce quel que soit le type de circuit d’alimentation utilisé. Des fonctions basiques et communes à tous les types d’accessoires rendent son utilisation très simple. La gestion de groupes de DEL ou de moteurs est aussi possible...

Petite info pour les utilisateurs de Universal Accessory Decoder, ou UAD pour les intîmes
 
Accessories n’est pas juste un copié/collé de Un décodeur d’accessoires universel (1) dont on aurait retiré la partie Commanders : de gros changements structurels sont intervenus dans cette revisite. Ils ont été inspirés par la volonté de rendre l’utilisation de la bibliothèque la plus simple et la plus compréhensible possible, grâce à la disparition quasi totale du recours à des pointeurs, à la disparition des ’Drivers’ utilisant des ports, remplacés par les ports eux même, et au recours systématique à des constructeurs sans arguments puis à des ’begin’ à peu près identiques. Outre la simplicité, le gain concerne également la mémoire utilisée, dorénavant presque intégralement rapportée par le rapport de fin de compilation de l’IDE, et moins chargée grâce à la disparition des Drivers.
Dernier avantage et pas des moindres, UAD fournissait un certain nombre (assez réduit) de drivers : relais, shield L293D, L298N et Arduino. En dehors de ces circuits, point de salut. Accessories a choisi de se détacher de cette contrainte en proposant à son utilisateur de définir lui même les ports nécessaires en fonction de sa configuration. Cela permet de virtuellement adresser n’importe quel circuit de puissance, et même de câbler un circuit classique en dehors de son utilisation normale, comme de brancher une DEL ou un servo sur une des sorties d’un LMD18200 au lieu d’un moteur ! Un retour silencieux et involontaire vers l’universalité ?
Mais revenons à nos moutons et faisons comme si on ne connaissait pas UAD...

Pourquoi Accessories ?

Le but de cette bibliothèque est de faire bouger ou d’illuminer vos accessoires. Ces petites choses étant quelquefois un peu trop dispendieuses, il faut souvent intercaler un circuit de puissance entre l’Arduino et eux. Ce circuit va transmettre grâce à une alimentation extérieure une puissance beaucoup plus importante que ce que le petit Arduino pourrait délivrer. L’Arduino est donc relié aux entrées de pilotage du circuit, tandis que l’accessoire est connecté aux sorties de puissance du circuit.

JPEG - 72.7 kio
Un méga relié à un moteur à solénoïde via un driver ULN2803

Les classes

Accessories regroupe deux grandes familles d’objet : les accessoires et les ports.

Accessoires

Là encore, division en deux sous-familles : les moteurs (les choses qui bougent), et les DELs (les choses qui brillent...).

AccessoryMotorOneWay avec durée d’activation
Moteurs à mouvement ponctuel

Typiquement, on parle là des moteurs d’aiguillage Kato ou de rails de découplage. Dotés d’un seul solénoïde, ils doivent être activés sur une durée limitée pour ne pas griller. Surtout que cette technologie implique souvent une consommation électrique assez importante... Certains sont heureusement équipés de contacts de fin de course qui coupent l’alimentation une fois le déplacement terminé.

AccessoryMotorTwoWays avec limite de durée
Moteurs à mouvement ponctuel dans deux directions

Rentrent dans cette catégorie tous les moteurs qui nécessitent deux fils d’alimentation. Ils sont dotés de deux solénoïdes comme la plupart des aiguillages classiques, à part Kato. Ils ont deux directions possibles et sont limités dans le temps, mais leur vitesse est réglable, tout comme la direction du mouvement.

PNG - 41.9 kio
En haut à gauche, un rail de dételage. A ses côtés quelques aiguillages plus ou moins récents...

AccessoryMotorOneWay sans limite de durée
Moteurs à mouvement continu

Ce sont des moteurs utilisés pour des animations, comme un moulin ou une roue de fête foraine, ou alors pour un ventilateur de confort...
Ces moteurs n’ont qu’un sens de fonctionnement possible et ne sont pas limités dans le temps, mais leur vitesse est souvent réglable.

AccessoryMotorTwoWays sans limite de durée
Moteurs à mouvement continu

Ce sont des moteurs similaires à ce que l’on trouve dans nos engins moteur. Ils ont deux directions possibles et ne sont pas limités dans le temps. Leur vitesse est éventuellement réglable.

PNG - 46.3 kio
Quelques moteurs rotatifs...

AccessoryServo
Servo moteur

Très utilisés dans le monde modéliste pour l’aviation, la marine et les voitures, ils sont aussi utiles pour nos trains comme moteurs lents pour les aiguillages ou les passages à niveau. Ils disposent d’une course rotative souvent réduite à moins d’un demi tour, et peuvent se déplacer à une position particulière au degré près.

PNG - 39.2 kio
Des servo-moteurs dans différentes gammes de prix...

AccessoryStepper
Moteurs pas à pas

Ces moteurs rotatifs au placement très précis permettent de piloter essentiellement des plaques tournantes, des ponts secteur ou des ponts transbordeurs. Ils peuvent se déplacer à différentes vitesses vers une position particulière et disposent d’un débattement intégral : un tour complet ne leur fait pas peur ! Le nombre de positions atteignables est fixé par la mécanique du moteur et le besoin de précision doit conditionner son choix au moment de l’achat.

PNG - 26.5 kio
Des moteurs pas à pas, dont en haut à gauche le célèbre 28BYJ-48 économique et très fréquent autour de l’Arduino...

AccessoryLight
Une DEL

Là, c’est un peu plus simple. Une DEL peut s’allumer ou s’éteindre. Une nuance apparaît si l’on veut utiliser un allumage ou une extinction progressifs, si l’on veut faire clignoter.

PNG - 177.8 kio
Des DEL de différentes formes et couleurs. La cinquième est à deux couleurs...

AccessoryLightMulti
Un groupe de DEL

Il s’agit d’un groupe de DELs, comme un feu de signalisation ou un éclairage urbain. L’activation se fait à partir de motifs (’pattern’ dans la langue de Sir Sean Connery) qui décrivent les DELs allumées, les DELs éteintes, et éventuellement celles qui clignotent !

Ports

Le port constitue l’interface entre l’Arduino et le circuit de puissance cité plus haut. Quand un regain de puissance n’est pas nécessaire, il est directement l’interface entre l’Arduino et l’accessoire lui même (DEL ou servo-moteur...) !
Cet objet détient les broches utilisées, ainsi que la manière de les utiliser. Selon l’accessoire à piloter et le circuit de puissance utilisé, le type de port peut changer.

PortOnePin

C’est le port le plus simple : un broche commandée en digital ou en PWM. C’est celui à utiliser pour un accessoire à un seul fil de commande, par exemple une DEL ou un moteur type solénoïde simple (rail dételeur, aiguillage Kato...). C’est aussi celui à utiliser si l’on veut piloter un relais ou un transistor.

PortTwoPins

Deux broches en digital ou en PWM, à utiliser pour les moteurs rotatifs dont la direction est donnée par la polarité, ou les moteurs d’aiguillage à double solénoïde en n’oubliant pas de préciser une durée de fonctionnement.

PortTwoPinsEnable

Certains circuits de puissance ont besoin d’une broche supplémentaire ’Enable’ qui, comme son nom l’indique dans la langue de George Clooney, lance ou pas l’alimentation de ce qui est connecté sur les deux autres fils. Selon le circuit alimenté, les broches principales peuvent être digitale ou PWM, et la broche ’Enable’ supplémentaire peut aussi être configurée digitale ou PWM. Elle fixe la vitesse du moteur dans ce dernier cas.

PortSpeedDirBrake

D’autres circuits, comme le LMD18200, fonctionnent avec une broche en PWM qui fixe la vitesse du moteur, une broche ’Dir’ qui donne le sens de rotation, et ’Brake’ qui active ou pas l’alimentation.

PortServo

Un servo se pilote avec une seule broche digitale, mais il a besoin d’une gestion particulière. C’est pourquoi PortOnePin n’est pas utilisable. Des fonctions spéciales lui sont dédiées et permettent de déplacer précisément le moteur.

PortStepper

Là encore, un stepper (ou moteur pas à pas dans la langue de Joey Starr), a besoin d’un comportement particulier lié à sa technologie. Les moteurs à deux fils et à quatre fils sont possibles. Le deux-fils n’est pas testé, je n’en avais pas sous la main !
La difficulté dans ces moteurs concerne les phases qui doivent être envoyées dans un ordre précis pour le déplacer. L’ordre doit être le bon, sinon ça tourne quand même, mais un peu n’importe comment ! C’est ce qui a motivé l’argument optionnel permettant de fixer la bonne séquence d’envoi. La valeur par défaut correspond à ce qui est nécessaire pour faire bouger le fameux moteur économique 28BYJ48 que l’on trouve dans tous les kits de démarrage Arduino, ou pour pas cher sur la baie. A noter, la librairie ’stepper’ livrée avec l’IDE Arduino ne convient pas à ce petit moteur !

PortShieldL293d

Ce type de port est dédié au shield L293d. Ce composant possède quatre sorties pour deux moteurs classiques, ou un moteur pas à pas. La puissance est limitée à 0.6A par canal. Ce shield, remplacé depuis par d’autres plus performants, est disponible à moins de dix euros au pays de Mao. Sur un Uno il interdit tout autre shield au-dessus de lui. Sur un Méga, certaines broches analogiques et digitales restent accessibles, mais aucune capable de faire du PWM...

Shield L293D
Shield L293D

Ce sont donc quatre ports de type PortShieldL293d, plus deux ports de type PortServo utilisant forcément les broches 9 et 10, qui sont disponibles. Deux ports pour moteurs pas à pas peuvent remplacer les quatre moteurs classiques.

Oui mais quoi ?

C’est vrai ça, comment choisir le bon port ?

Accessoire OnePin TwoPins/Enable SpeedDirBrake Servo Stepper
DEL x
Dételeur x
1 solénoïde x
2 solénoïdes x
Moteur x x
Servo x
Stepper x

Le premier choix concerne le type d’accessoire. Pour un servo, pas d’autre choix que PortServo. Pour un stepper, même absence de choix, ce sera PortStepper !

Reste les DEL et les moteurs classiques. Normalement, une DEL, un rail dételeur ou un aiguillage Kato n’ont besoin que d’un seul fil, c’est donc un PortOnePin.
Pour un moteur à un solénoïde, on peut également utiliser un PortOnePin. Pour les moteurs à deux solénoïdes comme les aiguillages courants, c’est PortTwoPins.

Pour les autres, le mieux est de regarder comment l’accessoire doit être raccordé à son alimentation. Une broche PWM, une broche digitale, deux ? Une broche Enable ? Des broches Dir, Brake ? Le choix sera fait selon le mode de branchement réclamé par le circuit de puissance...

Comment ça marche ?

Les principes

Accessories fonctionne sur la base d’ordres reçus qui vont déclencher des comportements des accessoires déclarés. Les ordres peuvent être donnés depuis un bouton codé localement en utilisant des fonctions basiques comme n’importe quel programme Arduino commun, ou via des événements interprétés par ces mêmes accessoires.

Evénements

Tout comme dans la Bibliothèque Commanders, chaque accessoire est activé par un événement qui lui est destiné. Les événements ont exactement la même forme : un identifiant qui est un entier long non signé (entre 0 et 4 294 967 295 !), un type extrait de l’enum ACCESSORIES_EVENT_TYPE, copie conforme de l’enum COMMANDERS_EVENT_TYPE de la bibliothèque Commanders, et un entier signé donnant une info supplémentaire, comme la position à atteindre...
Chaque accessoire se voit doté d’un ou plusieurs identifiants. Si l’événement reçu le concerne, il tentera d’effectuer ce qui est demandé par le type, éventuellement aidé par l’info en plus.

Plus concrètement, prenons l’exemple d’un servo moteur. Quatre positions ont été définies pour lui, chacune identifiée par un code et une position absolue : 100 à 10°, 101 à 20°, 102 à 45° et 103 à 160°. Si un événement est reçu avec comme identifiant l’un des quatre déclarés par le servo (100, 101, 102 ou 103), selon le type d’événement la réaction sera différente :

  • ACCESSORIES_EVENT_TOGGLE demande au servo moteur de passer à la position suivante parmi les quatre déclarées : le servo passera de la position courante, par exemple 102, à la position suivante : 103. Arrivé à la dernière position, il recommence au début, à 100.
  • ACCESSORIES_EVENT_MOVEID demande au servo de se déplacer à la position identifiée : par exemple si l’id est 102 alors il ira à 45°.
  • ACCESSORIES_EVENT_MOVEPOSITION demande au servo de se déplacer directement à la position demandée par l’info supplémentaire, probablement un angle entre 0 et 180°, et ce quel que soit l’identifiant utilisé.

Pour un moteur rotatif classique, on va plutôt utiliser l’événement ACCESSORIES_EVENT_MOVE, là encore copie conforme de l’enum COMMANDERS_EVENT_MOVE, avec l’info supplémentaire à la valeur de l’enum ACCESSORIES_MOVE_TYPE, de ACCESSORIES_MOVE_ON ou OFF pour le mettre en marche ou l’arrêter.

Fonctions de base

Il n’est pas obligatoire d’utiliser les événements pour activer un accessoire. Chaque type d’accessoire dispose d’un jeu de fonctions dédiées qui permettent de faire la même chose. Par exemple pour une DEL, les fonctions LightOn, LightOff ou Blink sont disponibles... Pour un moteur , on parlera de MoveLeftDir, MoveRightDir et MoveStop.

Au final, que l’on passe par un événement ou une fonction basique, l’Arduino va demander au port d’activer ou désactiver la(les) bonne(s) broche(s), et ainsi mettre en route ou arrêter l’accessoire qui lui est relié physiquement...

l’EEPROM

Accessories va faire la sauvegarde de l’état de tous les accessoires dans la mémoire EEPROM de l’Arduino. Il suffit de lui dire depuis quelle adresse et sur quelle plage mémoire la sauvegarde peut se faire (Accessories.::begin(10, 500);), et à chaque changement d’état d’un accessoire la nouvelle configuration sera sauvée. Pour ceux que ça ne branche pas, un simple Accessories::begin(); sans argument fera fonctionner la bibliothèque sans la sauvegarde.
Si la sauvegarde a été faite, au redémarrage de l’Arduino, il ira seul remettre tout en place : les lumières reprendront leur état : éteintes, allumées ou clignotantes, les moteurs se rappelleront de leur dernière position et de leur vitesse à ce moment là. Les servos retrouveront leur position, tout comme les moteurs pas à pas. C’est d’autant plus important pour ces derniers parce qu’ils n’ont pas de repère absolu, pas de valeur zéro. Et leur position n’est pas mesurable...
La sauvegarde utilise le principe de la classe CircularBuffer décrite dans la Bibliothèque EEPROMextent, mais sans utiliser la bibliothèque. Cette classe permet d’optimiser la sauvegarde en écrivant à une place différente à chaque fois et ainsi minimiser l’usure de l’EEPROM. Cet emplacement sera forcément compris en 10 et 510 dans notre exemple. soit à partir de l’adresse de début 10, et en utilisant au maximum l’espace de 500 octets proposé. D’autres sauvegardes utilisant EEPROM.write ou EEPROM.update seraient possibles pour d’autres usages avant 10 et au delà de 510.
Enfin, si la bibliothèque devait être mise à jour sur cet Arduino, ou si le nombre d’accessoires devait changer, la sauvegarde serait perdue. Ceci afin de préserver l’intégrité des accessoires pilotés. Il vaut mieux repartir d’un état de démarrage que d’essayer d’envoyer tous les moteurs sur la lune parce les données lues ne correspondent plus a ce qui a été sauvé !

L’avenir

Une bibliothèque comme Accessories promet de n’être jamais terminée ! D’autres accessoires se profilent déjà, comme les DEL multicolores RGB WB2812. D’autres types de port aussi avec le traitement des multiplicateurs de port comme les 74HC595 en digital ou le PCA9685 en PWM. Bref, encore du pain sur la planche...

La bibliothèque

 [1]

Optimisations

On le sait, l’Arduino est une plateforme puissante et passionnante, mais qui manque cruellement de mémoire. Une bibliothèque comme celle ci, qui tente d’unifier des comportements disparates en offrant de multiples fonctionnalités est confrontée tôt ou tard à des problèmes de compatibilité et de mémoire.
Dans le fichier Accessories.h qui se trouve dans le répertoire de la bibliothèque elle même, vous verrez :

//#define NO_GROUP
//#define NO_MOTOR
//#define NO_SERVO
//#define NO_STEPPER
//#define NO_LIGHT
//#define NO_SHIELDL293D
//#define NO_EEPROM

Cette litanie de #define NO_ est là pour vous permettre d’exclure définitivement des parties de la bibliothèque qui ne vous sont pas utiles à l’instant T. Enlevez le ’//’ devant le #define NO_STEPPER, et tout le code correspondant aux moteurs pas à pas sera purement et simplement éliminé de la compilation ! Le compilateur tente bien de faire ce travail tout seul, mais il peut échouer dans certains cas particuliers. Vous gagnerez ainsi un peu de mémoire programme, et peut être aussi un peu de mémoire dynamique, mais pas forcément.
L’autre usage concerne l’emploi de bibliothèques extérieures qui ne sont pas toujours présentes. Ce n’est pas le cas dans Accessories, mais on est pas à l’abri d’une évolution...
Le NO_EEPROM quant à lui évite de surcharger le code avec la sauvegarde sur EEPROM si elle n’est pas nécessaire.

La mise au point

C’est toujours difficile sur un Arduino de trouver la ligne qui fait que rien ne se passe comme prévu... J’ai inclus deux mécanismes pour aider a faire marcher le programme.

Dans le fichier Accessories.h qui se trouve dans le répertoire de la bibliothèque elle même, dans les toutes premières lignes, vous verrez :

//#define ACCESSORIES_DEBUG_MODE

Retirez les deux ’//’ qui représentent le début d’un commentaire. En faisant cela, vous verrez apparaître sur la console série (si elle est initialisée avec une vitesse comme Serial.begin(115200); ) tout un tas de messages d’initialisation, et éventuellement d’erreur. Avant de passer à la suite corrigez ces erreurs, inutile d’aller plus loin si Accessories lui même vous signale des problèmes ! Pendant l’exécution, vous verrez aussi passer des messages vous informant du fonctionnement de la bibliothèque : activation d’un accessoire, réception d’un événement, etc...
Je vous ai mis à disposition une fonction PrintEvent qui formatte et affiche un événement sur la console... Utile pour savoir si Accessories a bien reçu l’ordre voulu, quel que soit le canal d’envoi.

Ces affichages augmentent considérablement la taille du programme et affectent aussi un peu sa vitesse. Avant de mettre l’Arduino en production, il vaut mieux penser à remettre le ’//’ à sa place pour revenir à un programme léger et réactif ! D’ailleurs il peut arriver que j’oublie de remettre le ’//’ avant de construire le .zip de la bibliothèque. Normalement en fonctionnement, Accessories n’envoie strictement rien sur la console. Donc si vous voyez apparaître le Copyright et d’autres choses, remettez le ’//’ en place !

Où ça se passe...

La plupart de mes bibliothèques, comme Accessories, Commanders ou DIO2, sont maintenant référencées par l’IDE Arduino. Cela implique que pour les installer, il vous suffit de demander à l’IDE via sa commande ’Gestionnaire de bibliothèques’ de les trouver.

Sinon, la bibliothèque est disponible ici sous sa forme brute : Forge Locoduino. Si vous l’installez vous même, pensez à renommer le répertoire d’installation en ’Accessories’ et pas ’Accessories-master’ !

Notez qu’un fois intallée, vous trouverez dans le répertoire ’extras/Doc’ une documentation html visible sur n’importe quel système avec n’importe quel navigateur un peu moderne. Cette documentation reprend en Anglais l’ensemble des informations données ici et détaille plus précisément les rôles de chaque classe, de leurs fonctions et de leurs arguments. Sous Windows pour la lancer, il suffit de double cliquer sur le fichier StartDoc.bat présent dans le répertoire de la bibliothèque, sinon il faut manuellement double-cliquer sur le fichier ’extras/Doc/index.html’ . La page ’Revision History’ donne la liste des versions et les changements apportés en français et en anglais !

Accessories utilise une autre bibliothèque, appelée DIO2, qui gère des accès plus rapide aux broches qu’avec les fonctions natives de l’Arduino. Son usage est transparent pour l’utilisateur de Accessories, mais nécessaire pour réduire les temps de traitement. Cette bibliothèque annexe est disponible dans le répertoire ’extras’ présent avec les sources de la bibliothèque Accessories. Elle est également disponible sur la Forge Locoduino.

Dans le prochain article de la série, nous verrons ce qui différencie un croquis Accessories de son équivalent sans bibliothèque, puis nous étudierons quelques cas réels dans le détail pour mieux comprendre les rouages de son usage. Je compte aussi sur vous amis lecteurs pour me soumettre ici ou sur le forum des idées de réalisations concrètes qui pourraient nous servir d’exemples pour tout le monde !

[1Le fin de l’article est très similaire à ce que j’ai déjà écrit pour Commanders, ne soyez pas surpris !

4 Messages

  • Bibliothèque Accessories (1) 23 novembre 2016 11:54, par pat95

    Bonjour,
    Il y a là un travail extraordinaire, cela va faire un an que j’apprends le langage Arduino et C++, je commençais à comprendre mais la je décroche...
    Heureusement il y a les exemples Locoduino1 locoduino2 ... qui m’ont permis de mettre du concret dans les codes, toutefois j’ai une question :
    dans l’article je lis :

    Fonctions de base

    Il n’est pas obligatoire d’utiliser les événements pour activer un accessoire. Chaque type d’accessoire dispose d’un jeu de fonctions dédiées qui permettent de faire la même chose. Par exemple pour une DEL, les fonctions LightOn, LightOff ou Blink sont disponibles... Pour un moteur , on parlera de MoveLeftDir, MoveRightDir et MoveStop.

    Où je trouve les fonctions comme LightOn,LightOff etc...?
    J’ai cherché mais pas trouvé. Merci.

    Répondre

  • Bibliothèque Accessories (1) 23 novembre 2016 14:57, par Thierry

    Bonjour.

    Merci de vous intéresser à Accessories qui est effectivement le fruit d’un travail acharné depuis plusieurs mois... Et même plus si l’on considère qu’une grande partie de son code provient de Universal Accessory Decoder.

    Ces fonctions sont directement accessible via l’objet concerné : ainsi si une déclaration a été faite comme AccessoryLight lumiere; alors il est possible d’écrire lumiere.LightOn() ou lumiere.LightOff() . Je vais faire une retouche à l’article pour mieux expliquer ce point...

    Par contre, si l’on parle du code de ces fonctions dans mes sources, elles sont directement écrites dans AccessoryLight.hpp sous la forme d’une indirection vers le AccessoryBaseLight inclus (this->pLight) .

    Répondre

  • Bibliothèque Accessories (1) 23 novembre 2016 19:04, par pat95

    Bonjour suite,
    merci pour la réponse et j’ai bien trouvé les fonctions LightOn, LightOff quant pour les moteurs je verrai plus tard.
    Je profite de votre patience pour un autre problème :
    je fais l’essai de l’exemple locoduino.org programme1 et c’est parfait la led s’allume. Je passe à l’exemple suivant programme2 sans modifier mon montage et la pas de led qui s’allume !!! Que dois-je faire ? Reprendre toute la lecture.
    Amicalement d’un néophyte.

    Répondre

    • Bibliothèque Accessories (1) 6 décembre 2016 17:44, par Thierry

      J’ai poussé une nouvelle version de Accessories hier sur la forge. Certains problèmes ont été corrigés. L’article qui détaille ces programmes paraîtra en fin de semaine si tout va bien...

      Répondre

Réagissez à « Bibliothèque Accessories (1) »

Qui êtes-vous ?
Votre message

Pour créer des paragraphes, laissez simplement des lignes vides.

Lien hypertexte

(Si votre message se réfère à un article publié sur le Web, ou à une page fournissant plus d’informations, vous pouvez indiquer ci-après le titre de la page et son adresse.)

Rubrique « Bibliothèques »

Les derniers articles

Les articles les plus lus