Bibliothèque Accessories (1)

Les grands principes

. Par : Thierry. URL : http://www.locoduino.org/spip.php?article178

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 UAD

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 nouvelle version. 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 du circuit, tandis que l’accessoire est connecté aux sorties du circuit.

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 DEL   (les choses qui illuminent…).

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.

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.

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.

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. 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.

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.

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

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 l’accessoire qui lui est relié physiquement…

l’EEPROM

Nouveauté par rapport à UAD, Accessories ajoute 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 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 :

  1. //#define NO_GROUP
  2. //#define NO_MOTOR
  3. //#define NO_SERVO
  4. //#define NO_STEPPER
  5. //#define NO_LIGHT
  6. //#define NO_SHIELDL293D
  7. //#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.

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 !

IDE Arduino

Sur l’IDE Arduino version 1.6.11 et précédentes, la compilation fera apparaître une erreur de compilation de type fichier manquant sur DIO2.H . Il suffit d’utiliser l’option ’Croquis/Include Library’, de sélectionner DIO2, et tout rentre dans l’ordre. Ce type d’erreur n’existe pas avec les versions 1.6.12 et plus récentes.

Le bibliothèque est disponible ici : Forge Locoduino

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 !