LOCODUINO

Bibliothèque Accessories

Bibliothèque Accessories (2)

Que mettre dans son croquis ?

.
Par : Thierry

DIFFICULTÉ :

Accessories n’est pas qu’un assemblage de classes et de lignes de code. Le but est quand même de faire bouger des moteurs ou d’allumer des DELs ! Alors après un premier article plutôt théorique, voyons maintenant le côté pratique.

Cas d’école

Prenons un cas simple, la gestion d’une simple DEL via un bouton poussoir et comparons diverses possibilités de codage.

D’abord la version classique sans bibliothèques :

// Programme 1

const int buttonPin = 2;     // broche du poussoir
 
void setup() 
{
  // initialise la DEL interne de l'Arduino comme sortie
  pinMode(LED_BUILTIN, OUTPUT);
  // initialise le poussoir comme entrée
  pinMode(buttonPin, INPUT);
}
 
void loop() 
{
  // Selon l'état du bouton, on allume ou éteint la DEL
  if (digitalRead(buttonPin)== HIGH) {
    digitalWrite(LED_BUILTIN, HIGH);  // Allume la DEL
  } else {
    digitalWrite(LED_BUILTIN, LOW);  // Eteint la DEL
  }
}

C’est la version minimaliste : pas de gestion des rebonds sur le poussoir, la DEL directement reliée à l’état de sa broche... La constante LED_BUILTIN qui définit la broche de la DEL interne utilisée est à 13 pour la plupart des Arduino, mais par exemple elle est à 6 pour un MKR1000 !

Ajoutons maintenant la bibliothèque Accessories :

// Programme 2

#include <Accessories.h>

const int buttonPin = 2;     // broche du poussoir

AccessoryLight light;  // La DEL
PortOnePin port;  // La connexion entre l'Arduino et la DEL.

void setup() 
{
  Accessories::begin();

  port.begin(LED_BUILTIN, DIGITAL);  // broche 13 sur un Uno, broche digitale.

  light.begin(&port, 100); // On branche la DEL sur le port, et on lui assigne le No 100

  // initialise le poussoir comme entrée
  pinMode(buttonPin, INPUT);
}

void loop() 
{
  // Selon l'état du bouton, on allume ou éteint la DEL
  if (digitalRead(buttonPin)== HIGH) {
    light.LightOn();  // Allume la DEL
  } else {
    light.LightOff();  // Eteint la DEL
  }
}

Accessories va permettre d’utiliser un objet light identifié par un entier (100 ici). L’exemple est très simple, il n’y a toujours pas de gestion des rebonds du bouton, mais ajouter un allumage ou une extinction progressive façon vieille ampoule en passant par une broche PWM ne coûterais qu’une légère modification : signaler le port comme analogique, puis spécifier les paramètres pour la vitesse de passage d’un état à l’autre :

void setup() 
{
  ...

  // déclaration de la broche 3 en PWM (analogique)
  port.begin(3, ANALOG);

  ...
  // déclaration des vitesses (pas, durée sur ce pas...)
  light.SetFading(5, 10);  
  ...
}

Par exemple pour allumer une DEL raccordée à une broche PWM et passer d’une valeur analogique de 0 (éteint) à 255 (allumé pleine puissance) par pas de 5 pendant 10ms chacun et inversement pour l’extinction...

Troisième option, ajoutons Commanders pour gérer le bouton et la communication avec les accessoires :

// Programme 3

#include <Accessories.h>
#include <Commanders.h>

const int buttonPin = 2;     // broche du poussoir

ButtonsCommanderPush push; // Le bouton
AccessoryLight light; // La DEL
PortOnePin port;    // La connexion entre l'Arduino et la DEL.

void setup() 
{
  Commanders::begin();
  Accessories::begin();

  port.begin(LED_BUILTIN, DIGITAL);  // broche 13 sur un Uno, broche digitale.

  light.begin(&port, 100); // On branche la DEL sur le port, et on lui assigne le No 100

  // initialise le poussoir comme entrée
  // l'identifiant du bouton à 100 indique que c'est l'accessoire '100' qui sera affecté si le bouton est pressé.
  push.begin(100, buttonPin);
}

void loop() 
{
  unsigned long id = Commanders::loop();

  if (id != UNDEFINED_ID)
  {
    // Renvoie l'événement reçu de Commanders, vers les accessoires...
    Accessories::RaiseEvent(id, (ACCESSORIES_EVENT_TYPE) Commanders::GetLastEventType(), Commanders::GetLastEventData());
  }

  Accessories::loop();
}

La version Commanders+Accessories peut sembler plus complexe que la toute première, mais elle assure en interne la prise en compte des événements via le RaiseEvent(), plus la gestion des rebonds pour le poussoir.
Et ajouter le traitement via un bus DCC par exemple, ne réclame qu’une seule ligne supplémentaire :

void setup() 
{
  ...

  // identifiants fabricant et produit, puis le numéro d'interruption, ici sur la broche 3.
  DccCommander.begin(0x00, 0x00, digitalPinToInterrupt(3));

  ...
}

Si un message DCC arrive, il sera décodé et s’il désigne l’identifiant 100, la DEL va réagir aussi ! Et le bouton est toujours actif... Qui a dit que c’était compliqué ?

Sur un exemple très simple, il est difficile de voir le gain apporté par l’utilisation de ces bibliothèques, alors parlons de vrais cas...

Des cas concrets

Deux aiguillages simples, et un rail de découplage

Imaginons une partie de réseau avec une voie d’évitement équipée à une extrémité d’un rail électrique de découplage. Les aiguillages sont de modèles courants, à deux solénoïdes et donc trois fils.

PNG - 13.2 kio

Nous allons le coder à la fois pour un TCO analogique, et une entrée DCC. Les deux ne sont pas incompatibles et peuvent cohabiter. A l’inverse, même si le codage des deux versions (TCO+DCC) est inclus, l’absence de l’un ou l’autre ne posera pas de problème...
Il est bien évident que dans le cas d’un contrôle extérieur (gestionnaire de trajets, logiciel de pilotage...) la présence d’une possibilité manuelle de basculement d’aiguille peut être perturbatrice. Dans ce cas le mieux est de retirer la partie TCO.

Le programme :

// Programme 4

#include <Accessories.h>
#include <Commanders.h>

// Les boutons du TCO...
ButtonsCommanderPush boutonDecoupleur;
ButtonsCommanderSwitch boutonAiguillageGauche;
ButtonsCommanderSwitch boutonAiguillageDroite;

// Les trois moteurs
AccessoryMotorTwoWays aiguillageGauche;
AccessoryMotorTwoWays aiguillageDroite;
AccessoryMotorOneWay decouplage;

// Les ports pour connecter les moteurs.
PortTwoPins portAiguillageGauche;
PortTwoPins portAiguillageDroite;
PortOnePin portDecoupleur;

void setup()
{
  Commanders::begin(LED_BUILTIN);
  // Memoriser les positions des moteurs dans l'EEPROM.
  Accessories::begin(0, 500);

  // Activation de la reception de messages DCC
  // Ne fera rien en analogique... Mais on peut carrement enlever la ligne si besoin de mémoire.
  // Le dernier argument à true, c'est pour voir la DEL LED_BUILTIN déclarée plus haut clignoter si un signal DCC est présent.
  // Mieux vaut remettre à false une fois le programme mis au point.
  DccCommander.begin(0x00, 0x00, digitalPinToInterrupt(3), true);

  // Gestion des boutons pour le TCO.
  // Ne fera rien si aucun bouton n'est branché, mais on peut enlever si besoin de mémoire.

  // Le switch d'aiguillage a deux positions, chacune associée à un Id DCC.
  boutonAiguillageGauche.begin();
  // DCC 15 /0 et broche 2
  boutonAiguillageGauche.AddEvent(DCCINT(15, 0), 2);
  // DCC 15 / 1 et broche 7
  boutonAiguillageGauche.AddEvent(DCCINT(15, 1), 7);

  boutonAiguillageDroite.begin();
  boutonAiguillageDroite.AddEvent(DCCINT(16, 0), 4);
  boutonAiguillageDroite.AddEvent(DCCINT(16, 1), 5);

  // Un seul evenement pour le découpleur
  boutonDecoupleur.begin(DCCINT(17, 0), 6);

  // Les ports avec leurs broches en digital (pas PWM)
  portAiguillageGauche.begin(8, 9, DIGITAL);
  portAiguillageDroite.begin(10, 11, DIGITAL);
  portDecoupleur.begin(12, DIGITAL);

  // Les accessoires avec pour chacun le port utilisé et le ou les identifiants associés à chaque position. 
  // 255 est la vitesse, ici au maxi, et 400 est la durée d'activation du moteur en millisecondes.
  // C'est encore un peu long pour des solénoïdes. Il faudra adapter selon le modèle de moteur...
  aiguillageGauche.beginTwoWays(&portAiguillageGauche, DCCINT(15, 0), DCCINT(15, 1), 255, 400);
  aiguillageDroite.beginTwoWays(&portAiguillageDroite, DCCINT(16, 0), DCCINT(16, 1), 255, 400);
  decouplage.begin(&portDecoupleur, DCCINT(17, 0), 255, 400);
}

void loop()
{
  unsigned long id = Commanders::loop();

  if (id != UNDEFINED_ID)
  {
    // Renvoie l'événement reçu de Commanders, vers les accessoires...
    Accessories::RaiseEvent(id, (ACCESSORIES_EVENT_TYPE) Commanders::GetLastEventType(), Commanders::GetLastEventData());
  }

  Accessories::loop();
}

Le schéma est toujours le même : dans l’entête les déclarations pour les boutons, les accessoires, et les ports pour les piloter.
Dans le setup(), des begin() sur les bibliothèques, puis les begin() sur les boutons, les accessoires et les ports. C’est à ce moment que l’on va fixer les broches utilisées, dire qui est connecté à quoi, adapter les comportements des boutons, des accessoires et des ports, comme le clignotement d’une DEL ou une durée d’activation. Les boutons vont recevoir des identifiants, et les accessoires associés à ces boutons vont recevoir les mêmes identifiants.
Enfin le loop() qui ne fait que prendre les événements reçus par Commanders et les renvoyer à Accessories avec RaiseEvent(). A la fin du loop général, c’est le loop() de Accessories qui va véritablement traiter ces événements et faire bouger ou changer l’état des accessoires concernés.

Ainsi quand le bouton du découpleur sera pressé, qu’il y ait ou pas une centrale DCC branchée, l’événement généré aura l’identifiant DCCINT(17, 0). Et lorsque Accessories recevra l’événement (renvoyé par RaiseEvent(), rappelons-le), il ira activer l’accessoire dont l’identifiant est DCCINT(17, 0), et c’est bien du découpleur qu’il s’agit ! Bien sûr, si un centrale est présente et que c’est elle qui envoie une demande de mouvement de l’accessoire 17, Accessories recevra le même identifiant DCC(17, 0), et le découpleur réagira de la même manière.

Un croisement de quatre aiguillages plus un servo

Imaginons un croisement de quatre aiguillages animés ensembles, avec deux positions seulement : droit ou dévié, activés par un interrupteur.

PNG - 20 kio

On va bien déclarer les quatre moteurs à deux solénoïdes, puis un groupe qui les réunit pour créer deux états, un droit avec un identifiant DCC, et un dévié avec un autre identifiant. Enfin, comme ces moteurs ont tendance à beaucoup consommer d’énergie pendant leurs mouvements, on va s’assurer qu’ils fonctionnent en séquence, et pas simultanément. Ainsi la consommation sera d’un seul moteur à la fois, mais il faudra un peu plus de temps pour changer d’état.

// Programme 5

#include <Accessories.h>
#include <Commanders.h>
 
// Les boutons du TCO...
ButtonsCommanderSwitch boutonCroisement;
 
// Les moteurs
AccessoryMotorTwoWays aiguillageHautGauche;
AccessoryMotorTwoWays aiguillageHautDroite;
AccessoryMotorTwoWays aiguillageBasGauche;
AccessoryMotorTwoWays aiguillageBasDroite;
 
// Le groupe pour les moteurs
AccessoryGroup groupeCroisement;
 
// Les ports pour connecter les moteurs.
PortTwoPins portAiguillageHautGauche;
PortTwoPins portAiguillageHautDroite;
PortTwoPins portAiguillageBasGauche;
PortTwoPins portAiguillageBasDroite;
 
void setup()
{
  Commanders::begin(LED_BUILTIN);
  // Memoriser les positions des moteurs dans l'EEPROM.
  Accessories::begin(0, 500);
 
  // Activation de la reception de messages DCC
  // Ne fera rien en analogique... Mais on peut carrement enlever la ligne si besoin de mémoire.
  // Le dernier argument à true, c'est pour voir la DEL LED_BUILTIN clignoter si un signal DCC est présent.
  // Mieux vaut remettre à false une fois le programme mis au point.
  DccCommander.begin(0x00, 0x00, digitalPinToInterrupt(3), true);
 
  // Gestion des boutons pour le TCO.
  // Ne fera rien si aucun bouton n'est branché, mais on peut enlever si besoin de mémoire.
 
  // Le switch de croisement a deux positions, chacune associée à un Id DCC.
  boutonCroisement.begin();
  // DCC 15 /0 et broche 4 pour l'interrupteur
  boutonCroisement.AddEvent(DCCINT(15, 0), 4);
  // dcc 15 / 1 et broche 5 pour l'interrupteur
  boutonCroisement.AddEvent(DCCINT(15, 1), 5);
 
  // Les ports avec leurs broches en digital (pas PWM)
  portAiguillageHautGauche.begin(7, 8, DIGITAL);
  portAiguillageHautDroite.begin(9, 10, DIGITAL);
  portAiguillageBasGauche.begin(11, 12, DIGITAL);
  portAiguillageBasDroite.begin(14, 15, DIGITAL);
 
  // Les accessoires avec pour chaque, le port utilisé et le ou les identifiants associés à chaque position. 
  // 255 est la vitesse, ici au maxi, et 400 est la durée d'activation du moteur en millisecondes.
  // C'est encore un peu long pour des solénoïdes. Il faudra adapter selon le modèle de moteur...
  // Les identifiants sont volontairement non significatifs (1000 et plus...)
  // puisqu'aucun événement ne doit faire bouger ces moteurs individuellement.
  aiguillageHautGauche.beginTwoWays(&portAiguillageHautGauche, 1000, 1001, 255, 400);
  aiguillageHautDroite.beginTwoWays(&portAiguillageHautDroite, 1002, 1003, 255, 400);
  aiguillageBasGauche.beginTwoWays(&portAiguillageBasGauche, 1004, 1005, 255, 400);
  aiguillageBasDroite.beginTwoWays(&portAiguillageBasDroite, 1006, 1007, 255, 400);
 
  // Fabriquons le groupe de quatre moteurs à deux états
  groupeCroisement.begin();
 
  // Premier état, tous les moteurs droits.
  // L'argument 'false' signifie pas d'exécution simultanée. Les moteurs bougeront les uns après les autres.
  groupeCroisement.AddState(DCCINT(15, 0), false);
  // Arbitrairement, LEFT signifie droit (première broche activée)
  groupeCroisement.AddStateItem(DCCINT(15, 0), aiguillageHautGauche, LEFT);
  groupeCroisement.AddStateItem(DCCINT(15, 0), aiguillageHautDroite, LEFT);
  groupeCroisement.AddStateItem(DCCINT(15, 0), aiguillageBasGauche, LEFT);
  groupeCroisement.AddStateItem(DCCINT(15, 0), aiguillageBasDroite, LEFT);
 
  // Second état, tous les moteurs déviés.
  // Arbitrairement, RIGHT signifie dévié (seconde broche activée)
  groupeCroisement.AddState(DCCINT(15, 1), false);
  groupeCroisement.AddStateItem(DCCINT(15, 1), aiguillageHautGauche, RIGHT);
  groupeCroisement.AddStateItem(DCCINT(15, 1), aiguillageHautDroite, RIGHT);
  groupeCroisement.AddStateItem(DCCINT(15, 1), aiguillageBasGauche, RIGHT);
  groupeCroisement.AddStateItem(DCCINT(15, 1), aiguillageBasDroite, RIGHT);
}
 
void loop()
{
  unsigned long id = Commanders::loop();
 
  if (id != UNDEFINED_ID)
  {
    // Renvoie l'événement reçu de Commanders, vers les accessoires...
    Accessories::RaiseEvent(id, (ACCESSORIES_EVENT_TYPE) Commanders::GetLastEventType(), Commanders::GetLastEventData());
  }
 
  Accessories::loop();
}

Le code est assez direct, surtout que pour le laisser compréhensible, je n’ai pas utilisé de boucles qui auraient sans doute un peu réduit la taille du programme.
Comme d’habitude, on déclare les boutons, les moteurs, le groupe et les ports. Puis dans le setup() on va initialiser les boutons, les moteurs et les ports. Une fois la partie matérielle fixée, reste à déclarer le groupe et ses différents états. Le premier, activé par un code DCC 15/0 activera la première broche de tous les aiguillages, tour à tour grâce au dernier argument du AddState() à false. Le second, activé par 15/1, fera de même avec la seconde broche. Bien sûr, cela suppose que les aiguillages soient branchés dans le bon sens ! Sinon il suffit d’inverser deux fils, ou encore plus simple, d’inverser les deux broches dans le begin() du port correspondant. Rien à changer dans la loop()...

Un passage à niveau avec feu clignotant

Prenons maintenant un passage à niveau sur une voie unique et mono directionnelle (on fait simple...), activé par un ils posé sur la voie un peu avant le passage, et qui active un moteur pour faire descendre les deux barrières tout en faisant clignoter deux feux sur la route, un de chaque côté. Au bout d’une tempo, le tout revient en position de repos : barrières ouvertes et feux éteints.
Le montage est autonome et n’est piloté par personne : pas de bouton, pas de DCC !

PNG - 7.8 kio

Nous allons déclarer un bouton poussoir. En effet, un ILS est assimilable à un poussoir activé par le passage d’un aimant. On y ajoute un servo et deux DELs.

// Programme 6

#include <Accessories.h>
#include <Commanders.h>
 
#define TEMPO  20000

// L'ILS ...
ButtonsCommanderPush boutonILS;
 
// Le moteur
AccessoryServo PN;

// Les DELS
AccessoryLightMulti Dels;
 
// Les ports pour connecter le moteur et les DELs.
PortServo portPN;
PortOnePin portLight1;
PortOnePin portLight2;
 
void setup()
{
  Commanders::begin(LED_BUILTIN);

  Accessories::begin();
 
  // Un seul bouton, mais deux événements pour le PN
  boutonILS.begin(1234, 6); // premier événement pour le déclanchement
 
  // Les ports avec leurs broches en digital (pas PWM)
  portPN.begin(14);
  portLight1.begin(7, DIGITAL_INVERTED);
  portLight2.begin(8, DIGITAL_INVERTED);

  // begin de l'accessoire de 2 Dels qui doivent clignoter à 500ms d'intervalle. 
  Dels.begin(0, 2, 500);

  // Les DELs avec pour chaque, le port utilisé. 
  Dels.beginLight(0, &portLight1);
  Dels.beginLight(1, &portLight2);

  // On fait clignoter les leds...
  Dels.SetBlinking(0, 500);
  Dels.SetBlinking(1, 500);

  // Le servo : pas de durée de mouvement, un débattement entre 95 et 135 degres
  // et deux positions stables annoncées avec des identifiants inutiles (mais obligatoires)
  PN.begin(&portPN, 50, 95, 135, 1);
  // Les deux positions sont au mini et au maxi :
  PN.AddMinMaxMovingPositions(456, 789);
}
 
unsigned long dateFermeture = 0;

void loop()
{
  Accessories::loop();

  unsigned long id = Commanders::loop();
 
  // si l'ils est activé !
  if (id == 1234)
  {
    if (dateFermeture== 0)
    {
      dateFermeture = millis();

      // mise en route clignotement
      Dels.Blink();

      // mouvement servo : fermeture
      PN.MoveMinimum();

      // Plus rien à faire, attendons l'étape suivante.
      return;
    }
    else
    {
      dateFermeture = millis();
    }
  }

  if (dateFermeture > 0)
  {
	  if (millis() - dateFermeture > TEMPO)
	  {
		  // Fin de l'animation. On ouvre les barrières et on éteint les Dels...
		  dateFermeture = 0;
		  PN.MoveMaximum();
		  Dels.LightOff();
	  }
  }
}

Les déclarations sont assez simples, avec juste l’apparition du AccessoryLightMulti qui permet de piloter plusieurs DELs à la fois. L’ordre Blink() permet de les faire toutes clignoter à la fréquence fixée par le délai du lights.begin() .
Le loop() utilise une date de mise en route du cycle. A début du cycle on lance l’ouverture des barrières. J’ai supposé que la position minimum du servo correspond à la position haute des barrières. On lance en même temps le clignotement des Dels. Une TEMPO plus tard, on lance l’ouverture avec le MoveMaximum(), et on arrête le clignotement avec le LightOff. Petite astuce : si l’ILS est à nouveau activé alors que le cycle est en cours (delaiFermeture != 0), la date de départ est rafraîchie pour laisser le temps au nouveau train de passer !

Pour rappel, le bibliothèque est disponible ici : Forge Locoduino

A noter que tous les programmes de cet article sont présents dans les exemples livrés avec la bibliothèque sous le nom de locoduino.org .

36 Messages

  • Bibliothèque Accessories (2) 18 décembre 2016 09:05, par Cédric

    Bravo pour ce développement qui représente probablement quelques centaines d’heures de boulot.

    Maintenant il y a tout de même une certaine complexité (probablement nécessaire) qui risque de rendre ce développement difficile à généraliser. Je vous propose non pas de critique mais des suggestions si vous le voulez bien :
    Dans l’exemple, le mélange avec le dcc porte un coup fatal je trouve, même si c’est une possibilité offerte qu’il n’est pas du tout nécessaire d’utiliser.
    On devrait pouvoir encore simplifier en liant les accessoires aux ports directement depuis leur classe peut-être en typant.
    Vous avez créé des classes techniques totalement polyvalentes on pourrait intégrer une nouvelle déclinaison de vos classes pour cette fois mettre du fonctionnel ce qui simplifierait grandement.
    Les cas d’usage sont assez connus dans le milieu du modélisme et pourquoi ne pas faire une bibliothèque métier avec des classes aiguillage (plusieurs types), PN, grande roue, téléphérique, feu de signalisation, Incendie, détection canton, lampadaire, etc. En faisant ça, le code sera très facilement généralisable ainsi que les arduino. Les "pro" pourront toujours créer leur propre type.
    Ce n’est qu’une suggestion et je le répète, je ne critique surtout pas ce travail extraordinaire.

    Répondre

    • Bibliothèque Accessories (2) 19 décembre 2016 17:43, par Thierry

      Bonjour, et merci pour vos remarques (que je ne prend pas pour des critiques :) ).

      Voyons point par point.
      La présence du DCC dans les exemples ne fait que souligner la possibilité de son usage, puis qu’aujourd’hui cette forme de pilotage de loco devient la norme. Mais c’est vrai que c’est tout à fait facultatif.
      Les typages forts dont vous parlez sont exactement l’inverse du but recherché : l’universalité. Comment dire à une DEL qu’elle utilise la broche gérée par un shield L293D et pas une simple broche directe sans typer fortement ce port ? Je veux bien croire que la déclaration supplémentaire que cela engendre créé de la complexité, par ailleurs réduite par rapport à UAD qui nécessitait un Driver en plus... Mais il me semble que c’est le prix à payer pour être ouvert à toutes les configurations possibles et sans doute pas encore imaginées.
      Dans le même ordre d’idées, typer fortement les applications possibles de la bibliothèque revient à faire une bibliothèque spécialisée, et donc limitée à ce qu’elle propose. Le but d’Accessories est précisément de fournir les outils de base pour inventer vos propres animations ! Par ailleurs, Locoduino a déjà des bibliothèques thématiques comme celles sur les animations lumineuses...

      Répondre

  • Bibliothèque Accessories (2) 15 février 2017 12:58, par Roland

    Je lis avec beaucoup d’intérêt ;)
    Avec mes aiguilles LGB, j’ai déjà trouvé le pont-H TB6612FNG pour les piloter...
    J’attend par ailleurs mes interfaces CAN qui viennent de Chine...
    Bref... il n’y a plus qu’à intégrer tout ça... sauf :
    je pensais utiliser les inverseurs d’aiguille (option LGB) pour valider la position...
    le cas échéant en cas de manoeuvre manuelle...
    pas vraiment un problème puisqu’il suffit de "lire" un inverseur...
    mais je pense à coordonner l’état (donc connu) de l’aiguille avec sa commande...
    Comment verriez-vous les choses ?

    Répondre

  • Bibliothèque Accessories (2) 15 février 2017 14:38, par Thierry

    Bonjour. Le problème est intéressant... Je n’ai effectivement pas prévu de remontée d’information, ou de mise à jour de l’état d’un accessoire suite à une intervention extérieure. Ajouter la fonctionnalité se ferait en deux étapes : une fonction de base permettant de mettre à jour l’état sans activation de l’accessoire, et un type d’événement dédié, traité par Accessories::ReceiveEvent(), qui permettrait de mettre à jour l’état depuis l’extérieur de la bibliothèque. Le tout est assez simple à coder. A voir dans un moment creux, sauf si c’est urgent !

    Répondre

  • Bibliothèque Accessories (2) 15 février 2017 20:41, par Thierry

    Après réflexion, j’ai poussé sur la forge une nouvelle version 0.60 d’Accessories qui ajoute une fonction ExternalMove() à tous les moteurs. Il s’agit de forcer l’état courant du moteur à RIGHT ou LEFT. La partie électrique n’est pas sollicitée. Seul l’état interne d’Accessories change. D’autre part un nouvel événement ACCESSORIES_EVENT_EXTERNALMOVE peut être envoyé à Accessories::ReceiveEvent() avec dans l’argument ’data’, la nouvelle valeur de l’état.
    Dites moi si cela répond au problème posé.

    Répondre

    • Bibliothèque Accessories (2) 17 février 2017 18:23, par Roland

      Je n’ai pas encore analysé les mécanismes de manière approfondie...
      L’idée est d’avoir un retour fiable quant à la position effective de l’aiguille et de déclencher toute action nécessaire : informer, verrouiller...

      Répondre

  • Bibliothèque Accessories (2) 17 février 2017 20:09, par pat95

    Bonjour,j’ai réalisé avec l’aide du projet "Réalisation de centrales DCC avec le logiciel libre DCC++ en HTML" avec succès et c’est super. Maintenant je dois réaliser les commandes des appareils de mon réseau avec les bibliothèques "Accessories et "Commanders" et là j’ai une question : je teste le programme 4 des exemples et ça fonctionne mais je souhaite faire les commandes par l’intermédiaire de la console de l’IDE en Serial. Est-ce possible et comment ? j’ai bien essayé de gérer avec les événements mais sans succès... Merci.

    Répondre

    • Bibliothèque Accessories (2) 18 février 2017 10:51, par Thierry

      Oui c’est possible. Commanders a un exemple tout prêt pour ça, c’est SerialCommander. La syntaxe à envoyer sur la ligne série, que ce soit par l’IDE ou un programme, est simple et décrite dans le code source de TextInterpreter.hpp :

      // The accepted syntax is
      // id separator event separator data
      // where id can be a number from 0 to 4 000 000 000,
      // where separator can be ’,’ , ’ ;’ , ’/’ or ’ ’
      // where event can be any string of 9 characters long maximum, but must begin with
      // ’t’ to toggle
      // ’m’ to make a move, data is necessary a COMMANDERS_MOVE_TYPE enum value in this case
      // ’p’ to make a move to a given position, data is necessary in this case
      // ’c’ to change configuration, data is necessary in this case : high byte is the address, low byte the value.
      // and where the data can be a COMMANDERS_MOVE_TYPE enum value if this is a MOVE event,
      // or any number between -32767 and 32768 for a move position event.
      //
      // id can be dccid:dccacc for Dcc id, where dccid is the dcc address and dccacc 0 or 1.
      //
      // ex : 123 means ID 123 toggled
      // ex : 456 | T means ID 456 toggled
      // ex : 789 , p , 100 means ID 789 make an absolute movement to 100 .
      // ex : 20:0 T means Dcc id 20/0 toggled

      Si Accessories est ’branché’ derrière pour recevoir les événements, alors elle exécutera les ordres !

      Répondre

      • Bibliothèque Accessories (2) 18 février 2017 13:54, par pat95

        Merci, je comprenais bien le paragraphe "liaison série exploitation" de commanders mais je n’avais pas intégré les principales lignes de l’exemple de SerialCommander dans mon programme. Maintenant tout fonctionne à merveille je peux saisir mes commandes dans la console IDE et l’appareil exécute. Merci.

        Répondre

  • Event sur HIGH et LOW 23 février 2017 22:11, par Benoit

    Bonjour, Merci beaucoup pour tout ce travail.
    Est-il possible d’avoir des événements sur les changements d’état HIGH vers LOW ?
    En effet, je cherche à gérer ma détection de présence de train par conso de courant.
    Je le gère comme un bouton push. Si détection de courant, passage en état HIGH, génération de l’événement, cela coupe le relais en utilisant un accessoire type light. Mais comment le désactiver s’il n’y a pas d’événement au passage à l’état LOW ?
    Pour un aiguillage, cela permettrait aussi d’économiser une broche l’état LOW représentant un sens, l’état HIGH un autre sens.
    Merci de votre aide

    Répondre

    • Event sur HIGH et LOW 1er mars 2017 12:54, par Benoit

      Bonjour,
      Pour affiner ma remarque, sur les boutons de type switch, il serait intéressant de gérer un événement de passage de HIGH vers LOW. Pour les boutons de type push, ce n’est effectivement pas utile.
      Cdt

      Répondre

  • Bibliothèque Accessories (2) 1er mars 2017 16:47

    Bonjour, et pardon pour le délai.
    Si je comprends bien, il s’agit de savoir quand le switch quitte un état avant d’en atteindre un autre ?

    Répondre

    • Bibliothèque Accessories (2) 1er mars 2017 19:23, par Benoit

      Bonsoir,
      oui, exactement. Si j’ai bien compris le fonctionnement actuel, l’événement est produit uniquement lors du passage de l’état low vers l’état high. Mon idée est de retrouver les changements d’état de la librairie Bounce2 (rose() et fell()).
      Dans le cas d’un aiguillage à 2 positions, cela permettrait de gérer les 2 positions avec une seule broche.
      Dans le cas d’un détecteur d’occupation de voie (que je traiterai comme un switch), cela permet de d’avoir l’événement au moment où le canton est occupé (passage du low vers high dans mon cas) et quand il est libéré, passage du high vers low.

      Répondre

  • Bibliothèque Accessories (2) 30 août 2018 19:49, par Pierre

    Bonjour,

    J’essaie d’utiliser cette bibliothèque pour commander tout simplement mes aiguillages avec des servos moteurs.

    J’ai déjà réalisé un de vos exemples avec un bouton poussoir et ça marche, mais pour remplacer le bouton poussoir par du DCC, là je cale...

    J’ai bien réalisé l’interface avec l’opto-coupleur, et branché sur la broche 3(interruption) de l’Arduino Nano.

    J’ai beaucoup de mal à comprendre où l’on doit mettre dans le programme le n° de l’accessoire ( aiguillage manoeuvré par servo dans mon cas ).

    Exemple : sur mon Intellibox1, si j’appui sur un bouton commandant un aiguillage, à quel endroit du code est-ce que je doit insérer le N° de l’accessoire ?

    Et sous quelle forme ? 1 pour le bouton 1, 2 pour le bouton 2, ou y a t-il un codage particulier à chaque centrale ?

    Cordialement

    Répondre

  • Bibliothèque Accessories (2) 30 août 2018 20:41, par Thierry

    Attention, je pense qu’il y a confusion entre Accessories dont le rôle est de piloter des accessoires, et Commanders qui s’occupe de recevoir les ordres, par des boutons, un bus CAN ou DCC.

    Il y a deux sources importantes d’information :

    1 : la documentation incluse dans toutes mes bibliothèques et que l’on peut consulter en double cliquant sur le fichier extras/Doc/index.html de Arduino/Libraries/Accessories, ou en lançant le fichier StartDoc.bat du même répertoire sous Windows. Elle est en Anglais, mais je pense qu’elle reste compréhensible par le plus grand nombre. Idem pour Commanders, évidemment.

    2 : les exemples. Dans ce cas précis, l’exemple Accessories/examples/Servos est le plus proche de votre besoin. Le numéro 20, celui associé à l’action est bien l’adresse DCC de l’accessoire. Le mieux est de lire la documentation de la classe DccCommanderClass dans Commanders.

    Répondre

    • Bibliothèque Accessories (2) 30 août 2018 22:18, par Pierre

      Bonsoir,

      Evidemment, j’ai confondu Accessories et Commander, mais le sujet est si vaste que l’on se perd facilement.

      Je vais relire tout ça, merci encore de votre super travail.
      .
      Cordialement

      Répondre

      • Bibliothèque Accessories (2) 31 août 2018 19:14

        Bonsoir,

        Je crois avoir trouvé, dans ’Commanders.h’, j’ai commenté la ligne :

        • #define NO_DCCCOMMANDER

        //#define NO_BUTTONSCOMMANDERPUSH
        //#define NO_BUTTONSCOMMANDERANALOGPUSHES
        //#define NO_BUTTONSCOMMANDERSWITCH
        //#define NO_BUTTONSCOMMANDERPOTENTIOMETER
        #define NO_CANCOMMANDER
        //#define NO_DCCCOMMANDER
        #define NO_I2CCOMMANDER
        //#define NO_SERIALCOMMANDER
        //#define NO_EVENTSSEQUENCER

        Je pense que en commentant cette ligne, on évite la routine qui désactive dans le programme ce qui concerne le DCC

        Depuis, la compilation se fait, c’est bien ça ?

        Cordialement

        Répondre

    • Bibliothèque Accessories (2) 31 août 2018 12:25, par Pierre

      Bonjour,

      La compilation de l’exemple Servo, me renvoie systématiquement le message :

      "Dcc commander was not declared in this scope’, ainsi que tous les exemples incluant cette ligne.

      Il me semble pourtant avoir décompacter toutes les bibliothèques, une idée ???

      Cordialement

      Répondre

      • Bibliothèque Accessories (2) 1er septembre 2018 22:28, par Thierry

        Oui, c’est bien ça. Si on compilait tout, la mémoire serait fortement impactée sans réelle utilité. Donc presque tout est désactivé par défaut, il faut activer le nécessaire, et juste ça, dans Commanders.h.

        Répondre

  • Bibliothèque Accessories (2) 11 septembre 2018 11:10, par pat95

    Bonjour,
    J’ai posté un message à Thierry qui n’est plus nécessaire mille excuses.
    J’avais réussi à faire fonctionner le programme 4 de locoduino et après un plantage ordinateur j’ai été obligé de réinstaller l’IDE arduino, la bibliothèque et évidemment le programme 4 ne fonctionnait plus pourquoi ?
    Pour les débutants comme moi ne pas oublier de vérifier les modifs que l’on a fait dans les bibliothèques Commanders et Accessories surtout les "//NO..." vous gagnerez du temps et moins d’énervement. Puis recompléter la librairie d’Aduino qui évidemment des éléments avaient disparu.
    Thierry ne tient pas compte de mon dernier message tout fonctionne.
    Cordialement.

    Répondre

  • Bibliothèque Accessories (2) 11 septembre 2018 11:58

    Ok, c’est noté. Cela dit, je suis conscient du problème posé par la modification de fichiers livrés avec la bibliothèque. Le .h doit de plus être adapté à chaque changement de projet à compiler... Et je suis sans doute le plus impacté puisque pour mes tests je passe mon temps changer de projet, et donc à modifier ce .h ...
    Bref je suis preneur de toute solution alternative permettant de changer le comportement d’une bibliothèque pour un projet précis...

    Répondre

  • Bibliothèque Accessories (2) 2 novembre 2019 16:58, par David

    Bonjour à tous
    Je lis le sujet avec beaucoup d’intérêt et j’essaie de reproduire les différents exemples donnés.

    Mon problème va sans doute vous paraître bête mais je ne parviens pas à faire fonctionner le programme2
    J’ai chargé la librairie, le televersement se fait sans problème et pourtant ma Led ne s’allume pas.
    J’ai également essayé avec les librairies présentes dans le dossier Hystory mais rien n’y fait.

    J’utilise une carte uno (une version non officielle)
    Peut être que le problème viens de là ??
    Si quelqu’un peu éclairer ma lanterne
    Cordialement

    Répondre

  • Bibliothèque Accessories (2) 3 novembre 2019 12:14, par David

    Bonjour a tous

    Je reviens vers vous pour présenter mes excuses pour mon précédent post
    Je me suis rendu compte de mon erreur (vraiment très bête effectivement !) mais cela fait partie de mon apprentissage
    Il semble que je me suis emmêlé les pinceaux entre Commanders et Accessories
    Tout fonctionne comme il faut , je poursuis donc mes investigations
    Un grand merci pour avoir crée ces librairies pleines de promesses en ce qui me concerne
    Très cordialement
    Ps : Peut être que mes 2 derniers messages peuvent être supprimer , histoire de ne pas polluer inutilement la page, merci d’avance

    Répondre

  • Bibliothèque Accessories (2) 4 novembre 2019 09:14

    Bonjour David

    Oui, l’apprentissage passe par des erreurs, Rome ne s’est pas faite en un jour... Bon courage !

    Répondre

  • Bibliothèque Accessories (2) 12 avril 2020 15:48, par Jerome

    Bonjour

    A la fin du programme 2, ne manque t il pas cette ligne :
    Accessories::loop() ; ?

    Le programme 2 ne fonctionnait pas du tout.
    Le programme 3 fonctionnait.
    En comparant le programme 2 avec tous les programmes suivants, je ne vois que cette différence.
    Pour autant, après cette modification, le programme 2 ne conserve pas la LED allumée quand le poussoir est relâché, comme cela se passe dans le 3. Est ce normal ?

    Répondre

  • Bibliothèque Accessories (2) 29 octobre 2021 19:42, par pat95

    Bonsoir à tous.
    Suite à changement de matériel j’en profite pour installer une version plus récente de IDE arduino vers 1.8.16 ainsi que les différentes bibliothèques que j’aie utilisées.
    Et là premier problème avec Accessories j’ai le message d’erreur suivant : #include "SparkFunSX1509.h" // Include SX1509 library. Qu’est-ce cette librairie qui ne m’était pas demandée auparavant ?
    Merci pour votre aide.

    Répondre

    • Bibliothèque Accessories (2) 29 octobre 2021 21:23, par msport

      Eh oui, les bibliothèques intègrent de nouveaux composants quand quelques uns ont besoin de les utiliser ...
      Google donne la réponse et si vous avez besoin de la bibliothèque :

      Voir en ligne : Github

      Répondre

      • Bibliothèque Accessories (2) 23 avril 2023 23:03, par cy83

        Bonjour à vous,

        je découvre LOCODUINO. J’ai réussi a faire marcher mon premier programme pour aiguillages solenoides avec UAD mais j’ai dru comprendre qu’il fallait maintenant utiliser Commanders et accesories.

        J’utilise donc le programme4 pour les aiguillages présents dans les exemples de ACCESSORIES

        L’IDE me dit qu’il manque les librairies Commanders.zip et DIO2.zip que j’ai trouvé dans le répertoire /extras de accesories.

        Par la suite, il me dit qu’il manque le programme #include "SparkFunSX1509.h" // Include SX1509 library que j’ai téléchargé sur le site de GuitHub comme mentionné par msport (29 octobre 2021)
        ==> SX1509_IO-Expander-master.zip

        Maintenant, il me dit qu’il manque le fichier ShiftRegister74HC595.h ?

        c :\Users\Cyril\Documents\Arduino\libraries\Accessories\src/PortExpander74HC595.h:9:10 : fatal error : ShiftRegister74HC595.h : No such file or directory
        #include "ShiftRegister74HC595.h"

        et du coup, je suis perdu !!! merci par avance
        cyril

        Répondre

        • ShiftRegister 74HC595 Arduino Library 24 avril 2023 10:20, par msport

          Ce doit être par là ...

          Voir en ligne : ShiftRegister 74HC595 Arduino Library

          Répondre

          • ShiftRegister 74HC595 Arduino Library 24 avril 2023 21:36, par cy83

            Bonsoir Msport...

            Merci pour votre message et réponse rapide ce matin.
            Je me faisais une joie de tester cette nouvelle librairie mais j’ai à nouveau des messages d’erreur. Je pensais qu’il fallait seulement rechercher les libriairies manquantes sur internet, mais ca n’a pas l’air d’être le cas !!!

            Je suis sincèrement désolé de solliciter les gens pour si peu. J’essaye de lire le forum en détail mais beaucoup de choses m’échappent...

            Voici mon message d’erreur :
            In file included from c :\Users\Cyril\Documents\Arduino\libraries\Accessories\src/Accessories.h:605:0,
            from C :\Users\Cyril\Documents\MES PROJETS\TRAIN_MINIATURE\Locoduino\Accessories\examples\Locoduino.org\Programme4\Programme4.ino:2 :
            c :\Users\Cyril\Documents\Arduino\libraries\Accessories\src/PortExpanderMCP23017.hpp:10:10 : fatal error : Adafruit_MCP23017.h : No such file or directory
            #include "Adafruit_MCP23017.h" // Include MCP23017 library

            J’ai donc essayé de télécharger la librairie Adafruit_MCP23017.h en vain !!!

            Répondre

            • ShiftRegister 74HC595 Arduino Library 24 avril 2023 21:56, par msport

              Télécharger la librairie Adafruit_MCP23017.h :
              ça coince où ?

              Voir en ligne : mizraith / mizraith_MCP23017

              Répondre

              • ShiftRegister 74HC595 Arduino Library 24 avril 2023 22:38, par cy83

                bonsoir,

                Merci pour votre aide.
                Je ne comprends pas pourquoi il n’y a pas un endroit où il y a l’ensemble des librairies nécessaires. Dés que je prends une librairie, j’ai l’impression que ce n’est pas la bonne ..
                JE crois que ce n’est pas fait pour moi pourtant ce n’est pas faute d’essayer de comprendre...
                et pourtant, je charge le programme de base "2 aiguillages" :-( !!!!

                C :\Users\Cyril\Documents\MES PROJETS\TRAIN_MINIATURE\Locoduino\Accessories\examples\Locoduino.org\Programme4\Programme4.ino : In function ’void setup()’ :
                C :\Users\Cyril\Documents\MES PROJETS\TRAIN_MINIATURE\Locoduino\Accessories\examples\Locoduino.org\Programme4\Programme4.ino:32:3 : error : ’DccCommander’ was not declared in this scope
                DccCommander.begin(0x00, 0x00, digitalPinToInterrupt(3), true) ;

                C :\Users\Cyril\Documents\MES PROJETS\TRAIN_MINIATURE\Locoduino\Accessories\examples\Locoduino.org\Programme4\Programme4.ino:32:3 : note : suggested alternative : ’Commander’
                DccCommander.begin(0x00, 0x00, digitalPinToInterrupt(3), true) ;

                Commander

                Répondre

  • Bibliothèque Accessories (2) 30 octobre 2021 09:58, par Thierry

    Cela dit, c’est tout à fait vrai que si j’ai bien prévu les exclusions correspondantes aux extenders dans Accessories.h :

    //#define NO_EXPANDER_SX1509
    //#define NO_EXPANDER_74HC595
    //#define NO_EXPANDER_PCA9505_06
    //#define NO_EXPANDER_MCP23017

    Ils ne sont pas utilisés comme il se doit. Je dois faire une nouvelle version de la bibliothèque pour corriger ça. En attendant, comme le dit msport, le bon workaround est de récupérer ces bibliothèques.

    Répondre

    • Bibliothèque Accessories (2) 30 octobre 2021 14:19, par pat95

      Merci pour vos réponses.
      He oui j’aurai dû m’en douter qu’il y aurait des "#define NO_" mais comme mes programmes fonctionnaient avant ma mise à jour je n’ai pas cherché.
      Maintenant ça fonctionne.

      Répondre

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

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