LOCODUINO

Un décodeur d’accessoires universel

Un décodeur d’accessoires universel (3)

.
Par : Thierry

DIFFICULTÉ :

Après la théorie et ses jolis dessins, la pratique et l’âpreté du langage...

Résumé des épisodes précédents...

Universal Accessory Decoder, UAD pour les amis, est une bibliothèque destinée à piloter des accessoires via des circuits de puissances commandés par un Arduino. Les ordres peuvent être reçus par des codes DCC en écoutant les rails, ou par des boutons à actionner manuellement, comme un TCO (Tableau de contrôle optique). Le côté universel tient à la possibilité de piloter tous les types d’accessoires, via tous les types d’alimentation, commandés par tous les types de donneurs d’ordre. Bien sûr, la promesse est alléchante et difficile à tenir... Je compte sur la communauté pour m’aider à approcher l’universalité au plus près !

Le fichier Full.ino

L’exemple Full.ino, livré avec la bibliothèque, pilote quelques accessoires, deux servos et trois leds. Ce n’est qu’une petite partie de ce dont la bibliothèque est capable, mais je compte sur vous pour construire des croquis utilisant UAD avec des cas concrets impliquant plein d’accessoires ! Voyons maintenant comment le source de ce croquis d’exemple est organisé.

Première partie : les déclarations :

/*************************************************************
project: <DCC Accessory Decoder>
author: <Thierry PARIS>
description: <2 servos and 3 leds driven by dcc arduino>
*************************************************************/

#include "UniversalAccessoryDecoder.h"

UniversalAccessoryDecoder.h est le fichier include principal de la bibliothèque.

#define kDCC_INTERRUPT            3

Nous entrons dans le vif du sujet : le décodage DCC a besoin d’un vecteur d’interruption. En clair, il faut lui dire sur quelle pin l’Arduino va recevoir les paquets. Mais évidemment, il faut le faire indirectement sinon ce serai trop simple ! Selon le modèle, chaque numéro de vecteur utilise une pin différente :

Board int 0 int 1 int 2 int 3 int 4 int 5
Uno, Ethernet 2 3
Mega2560 2 3 21 20 19 18
Leonardo 3 2 0 1 7

Source : http://arduino.cc/en/Reference/atta...

J’ai ici utilisé la pin 20 de l’Arduino Mega parce que le shield l293d utilisé pour certains tests me cache les pins 0 à 13 !

#define AccessoryServoNumber      2
 
#define SERVO1                    0
#define SERVO2                    1
 
#define SERVO1_PORT               0
#define SERVO2_PORT               1
 
#define AccessoryMotorLightNumber 3
 
#define LIGHT1                    2
#define LIGHT2                    3
#define LIGHT3                    4
 
#define LIGHT1_PORT               0
#define LIGHT2_PORT               1
#define LIGHT3_PORT               2

Il y a une liste d’accessoires avec deux servos (SERVO1, SERVO2 pour 0 et 1) et trois leds (LIGHT1,2,3 qui sont les accessoires 2, 3 et 4).

Comme chaque accessoire va être un élément dans une liste, pour éviter de faire des erreurs et devoir me rappeler que l’accessoire 4, c’est la led verte, je préfère créer des defines pour chaque objet de la liste. Ça me permettra ensuite de traiter l’accessoire LIGHT3 plutôt que 4 ! J’aurais pu être encore plus précis et mettre LED_VERTE ou LIGHT_GREEN...
Rappelons que des defines sont juste des ordres donnés au compilateur de remplacer la définition LIGHT3 par sa valeur ’4’. Aucune mémoire n’est consommée, tout juste un petit temps supplémentaire de compilation est requis, mais le jeu en vaut la chandelle !

// Accessories
 
Accessories      accessories;
DccCommander     dccCommander;
ButtonsCommander buttonsCommander;
 
AccessoryGroup groupServos;
AccessoryGroup groupLights;
 
// Drivers
 
DriverArduino *arduino;

La liste d’accessoire est déclarée, les commanders utilisés aussi. Suivent les deux groupes ainsi que le driver Arduino dont j’aurai besoin pour cet exemple.

Rentrons dans le Setup.

/////////////////////////////////////////////
// Setup
//
void setup()
{
  UAD_StartSetup();

La fonction UAD_StartSetup() doit être lancée en premier dans le setup() de votre programme. Elle commence par initialiser la console à 115200 bauds pour afficher les messages de debug. Elle mémorise aussi l’état de la mémoire au départ du setup() pour pouvoir vous dire à la fin combien vous en avez consommé...

Initialisation des commanders

dccCommander.Setup(0x00, 0x00, kDCC_INTERRUPT);
dccCommander.SetStatusLedPin(13);
 
buttonsCommander.Setup(3,
	new ButtonsCommanderPush(2),
	new ButtonsCommanderSwitch(2),
	new ButtonsCommanderPotentiometer(321, 0, 20, 145) // Link it to SERVO1,
                                                           // from 20 to 145 degrees
	);

Le commander DCC initialise le numéro d’interruption décrit plus haut, puis définit la led qui clignotera pour témoigner de la présence du signal DCC : 13.

Vient ensuite le commander des boutons. Le premier argument de son Setup(), c’est le nombre de boutons que l’on va utiliser. Viennent ensuite chaque bouton.
Le ButtonCommanderPush est un bouton poussoir, à qui on déclare qu’il aura deux codes DCC à gérer, qu’il enverra en alternance à chaque appui.
Le ButtonCommanderSwitch est un interrupteur, à qui on déclare aussi qu’il aura deux codes DCC à gérer. Chaque position physique de l’interrupteur enverra un code DCC.

Le ButtonCommanderPotentiometer est le potentiomètre. On lui donne le code DCC qui va lui permettre d’identifier l’accessoire à déplacer, puis la plage de valeurs à envoyer à l’accessoire. La valeur brute lue sur un port analogique de l’Arduino est comprise entre 0 et 1023, elle sera mappée sur les valeurs données ici. C’est à dire qu’au minimum, le potentiomètre enverra 20 à l’accessoire, et 145 lorsqu’il sera à son maximum. C’est curieux comme ça ressemble à des angles de servo...

	PUSH(buttonsCommander, 0)->AddDccId(320, 1);
	PUSH(buttonsCommander, 0)->AddDccId(320, 0);
	PUSH(buttonsCommander, 0)->Setup(26);
  
	SWITCH(buttonsCommander, 1)->AddDccId(319, 0, 24);
	SWITCH(buttonsCommander, 1)->AddDccId(319, 1, 25);
	SWITCH(buttonsCommander, 1)->Setup();
  
	POTENTIOMETER(buttonsCommander, 2)->Setup(8);

Une fois construite la liste des boutons, il faut les initialiser avec leur propre Setup(). Pour le bouton poussoir, le bouton de la liste, on donne avec AddDccId les deux codes DCC dont il va s’occuper, puis on fait le Setup() en lui donnant la pin Arduino sur lequel sera raccordé le bouton poussoir physique.

Idem pour le switch, le bouton 1, qui déclare ses deux codes DCC, chacun étant lié à une pin. Avec ce type d’initialisation, on pourrait utiliser un switch à 10 positions de la même manière...

Enfin le potentiomètre déclare la pin qu’il utilise et éventuellement la précision de lecture de la valeur. Une nouvelle valeur doit être en dehors de l’intervalle valeur-précision / valeur+précision pour être prise en compte. Ici la valeur par défaut 1 est utilisée, donc rien à ajouter dans l’appel du Setup...

	// Drivers setups

	arduino = new DriverArduino(AccessoryMotorLightNumber, AccessoryServoNumber);
	arduino->Setup();
	arduino->SetupPortServo(SERVO1_PORT, 2);
	arduino->SetupPortServo(SERVO2_PORT, 3);
	arduino->SetupPortMotor(LIGHT1_PORT, 9, ANALOG);
	arduino->SetupPortMotor(LIGHT2_PORT, 10, ANALOG);
	arduino->SetupPortMotor(LIGHT3_PORT, 11, ANALOG);

Voilà l’initialisation du driver Arduino

Ce driver dispose d’un nombre variable de ports moteur/lumière et de port servos. C’est pourquoi il faut lui dire dans son constructeur combien on veut en utiliser.

La fonction Setup() est ensuite appelée, puis les setups de chaque port. Chaque port utilise une pin et déclare, lorsque que c’est nécessaire, que l’on va les utiliser en analogique/PWM. Les servos utilise la modulation de tension entre 0 et 5v pour savoir à quelle position se placer et doivent donc impérativement utiliser des pins PWM (entre 0 et 13 sur le Mega). Les leds ont aussi besoin de moduler la valeur de la tension pour gérer le fading.

	// Accessories setups

	accessories.Setup(
		AccessoryMotorLightNumber + AccessoryServoNumber,
		new AccessoryServo(316, 0, 20),
		new AccessoryServo(314, 0, 314, 1, 20),
		new AccessoryLight(1, 0),
		new AccessoryLight(1, 1),
		new AccessoryLight(2, 0)
		);

Là on remplit la liste des accessoires. Le constructeur réclame en premier argument le nombre total d’accessoires gérés. C’est la somme de AccessoryMotorLightNumber et AccessoryServoNumber. Viennent ensuite les constructeurs des accessoires. Chacun déclare son ou ses codes DCC. Le dernier argument, optionnel, est la plupart du temps une durée en millisecondes. Par contre, la signification de ce temps change selon le type d’accessoire. Pour un moteur, mettez 0 pour un fonctionnement continu type moulin à vent. toute autre valeur donne le temps d’activation du moteur. Pour un aiguillage à solénoïde, mettez le moins possible, entre 50 et 300ms. A peu près 1000ms pour un dételeur. Pour une lumière, 0 signifie aussi fonctionnement continu, tandis qu’une autre valeur fixera la fréquence d’un clignotement. Enfin pour un servo, ce temps qui représente le délai entre deux mouvements d’un degré va décider de la vitesse du mouvement. A 0ms le mouvement se fait au maximum possible de la vitesse. Entre 1 et 5 millisecondes le mouvement sera plus lent, mais pendant ce temps rien d’autre ne pourra fonctionner, aucun autre accessoire ne bougera, et les ordres passés en DCC ou par les boutons seront perdus. Entre 6 et 20ms, c’est la même chose, mais le temps est suffisant pour mémoriser les ordres donnés par les boutons ou le DCC. Ces ordres seront traités dès que le mouvement du servo sera terminé. Enfin, plus de 20ms le mouvement est lent, traité degré par degré, mais entre deux micro mouvements, les autres accessoires ont le temps de s’activer !

	SERVO(accessories, SERVO1)->Setup(arduino, SERVO1_PORT, 20, 145);
	SERVO(accessories, SERVO2)->Setup(arduino, SERVO2_PORT, 10, 150, 4);
	SERVO(accessories, SERVO2)->AddDccPosition(315, 0, 45);
	SERVO(accessories, SERVO2)->AddDccPosition(315, 1, 135);
  
	SERVO(accessories, SERVO2)->SetPowerCommand(49);

	LIGHT(accessories, LIGHT1)->SetFading(20, 10);
	LIGHT(accessories, LIGHT2)->SetFading(20, 10);
	//LIGHT(accessories, LIGHT3)->SetFading(20, 10);

	LIGHT(accessories, LIGHT1)->Setup(arduino, LIGHT1_PORT);
	LIGHT(accessories, LIGHT2)->Setup(arduino, LIGHT2_PORT);
	LIGHT(accessories, LIGHT3)->Setup(arduino, LIGHT3_PORT);

Il faut dire à UAD qui fait bouger quoi. C’est à dire sur quel port de quel driver chaque accessoire est branché. Tous les Setup() commencent par dire sur quel driver, puis sur quel port le dispositif est branché. Mais là encore, selon le type d’accessoire les arguments suivants n’ont pas la même signification. Dans le cas d’un moteur, on va donner entre 0 et 255 la valeur de la tension utilisée pour le faire bouger. A 255 on est au maxi de ce que fournit l’alimentation, à 0 c’est 0v... Pour une lumière, le même principe est appliqué ce qui va permettre de régler l’intensité lumineuse ! Si rien n’est précisé, on est à 255, le maximum possible. Et pour un servo, il faut donner les valeurs mini et maxi de mouvement en degrés. Éventuellement comme ici, on peut ajouter des positions intermédiaires et leur affecter un code DCC avec AddDccPosition. Sur SERVO2, on ajoute une pin qui va commander l’alimentation du servo et ne s’activera que très peu de temps avant le premier mouvement (délai réglable avec le second argument optionnel), et se désactivera peu de temps aussi après la fin du mouvement. On évite ainsi les mouvements erratiques du servo au repos. Le fading est aussi fixé ici sur les leds, avec la valeur de chaque pas de la progression vers l’intensité voulue, entre 0 et celle donnée plus haut, et en millisecondes le temps à rester sur cette intensité avant de passer au pas suivant.

	GroupState *pServo1 = new GroupState(320, 0, false);
	pServo1->Setup(2,
		new GroupStateItem(accessories[SERVO1], MINIMUM, 500),
		new GroupStateItem(accessories[SERVO2], MINIMUM, 500));

	GroupState *pServo2 = new GroupState(320, 1, false);
	pServo2->Setup(2,
		new GroupStateItem(accessories[SERVO1], MAXIMUM, 500),
		new GroupStateItem(accessories[SERVO2], MAXIMUM, 500));

	groupServos.Setup(2, pServo1, pServo2);

	GroupState *pLight1 = new GroupState(319, 0, true);
	pLight1->Setup(3,
		new GroupStateItem(accessories[LIGHT1], LIGHTON),
		new GroupStateItem(accessories[LIGHT2], LIGHTOFF),
		new GroupStateItem(accessories[LIGHT3], LIGHTON));

	GroupState *pLight2 = new GroupState(319, 1, true);
	pLight2->Setup(3,
		new GroupStateItem(accessories[LIGHT1], LIGHTOFF),
		new GroupStateItem(accessories[LIGHT2], LIGHTON),
		new GroupStateItem(accessories[LIGHT3], LIGHTOFF));

	groupLights.Setup(2, pLight1, pLight2);

Finissons les déclarations avec les groupes. Un groupe est une liste d’états, des GroupState, et chacun d’eux est une liste d’accessoires avec leur état/position.

Pour le groupe des servos, on a besoin de deux états. Le premier, pServo1, sera activé par le code DCC 320/0 et n’autorise pas les mouvement simultanés. Il comprend une position MINIMUM pour le SERVO1, et une position MINIMUM aussi pour le SERVO2. Le dernier argument est un délai à attendre avant de commencer à bouger l’accessoire suivant, ceci pour éviter un éventuel chevauchement de fonctionnement de deux accessoires consécutifs qui ne serait pas voulu. Le second état, pServo2, est activé par le code 320/1 et conduit les deux servos à leur position maximum. Enfin on fait le Setup() du groupe, en donnant le nombre d’états (2), et les états (pServo1 et pServo2).
Le groupe des leds est lui aussi créé sur le même modèle en utilisant deux états, pLight1 et pLight2 activés par les codes 319/0 et 319/1 et allumant ou éteignant les trois leds...

  UAD_EndSetup()
}

Fin du setup ! L’essentiel est fait, et la mémoire dépensée est affichée en mode debug grâce à UAD_EndSetup().

void loop()
{
	if (dccCommander.Loop())
	{
		accessories.Loop();
		groupServos.Loop();
		groupLights.Loop();
		buttonsCommander.Loop();
	}
}

La fonction loop() du sketch est répétée, rappelons le, inlassablement par le micro-contrôleur. Elle est très simple. Le plus sensible est la fonction Loop() du DccCommander qui doit être appelé aussi souvent que possible pour ne pas perdre de paquets. Lorsque lui a fini son travail, sa fonction Loop() retourne true et permet aux autres Loop() de commencer le leur. Les accessoires et les groupes sont appelés pour le traitement des mouvements déjà commencés, des lumières à faire clignoter, ou des groupes à faire passer à l’accessoire suivant...

Ensuite les Loop() des autres commanders qui vont activer les accessoires si nécessaire, et c’est tout !

On en a fini avec l’exemple Full. Si vous voulez voir à quoi ça ressemble en fonctionnement, je vous invite à regarder la vidéo :

https://www.youtube.com/watch?v=qOB...

Voilà. Le codage du fichier .ino est aussi direct que possible, mais vous voyez des améliorations ou des simplifications à faire pour rendre son accès encore plus facile, n’hésitez pas à me le dire !

Merci à l’équipe LOCODUINO pour leur aide pour la rédaction de cet article long et compliqué !

31 Messages

  • Un décodeur d’accessoire universel (3) 18 février 2015 18:58, par LIKIKI

    Bravo pour ce superbe travail.

    Les possibilités sont ENORME.

    Encore bravo.

    Répondre

  • Un décodeur d’accessoire universel (3) 19 février 2015 08:50, par Thierry

    Merci ! D’autres projets tout aussi utiles sont sur le feu !

    Répondre

  • Un décodeur d’accessoire universel (3) 19 février 2015 10:41, par jerome savary

    Bra...vo !!!

    quel site, mais quel site....!

    chapeau bas pour toutes ces infos, le temps passé, l’envie de partager.

    bra...vo !
    jerome

    Répondre

  • Bonjour,

    Merci pour votre travail !!!!

    J’ai une question. Comment utiliser votre code pour alumer/éteindre un LED avec une centrale DCC. Par exemple, avec l’adresse 01 sur la centrale DCC, en appuyant sur la touche F0 ou F1 ou d’autre, le LED s’allume ou s’éteint.

    Merci et bravo !
    Stephan

    Répondre

  • Un décodeur d’accessoire universel (3) 16 octobre 2015 10:54, par Thierry

    Je dirais quelque chose comme ça (compilé mais pas testé !)

    /*************************************************************
    project: <DCC Accessory Decoder>
    author: <Thierry PARIS>
    description: <Test for UAD library, with one light, controled by Dcc.>
    *************************************************************/
    
    #include "UniversalAccessoryDecoder.h"
    
    /* kDCC_INTERRUPT values :
    Board         int.0   int.1   int.2   int.3   int.4   int.5
    Uno, Ethernet   2      3
    Mega2560        2      3      21      20      19      18
    Leonardo        3      2      0       1       7
    */
    #define kDCC_INTERRUPT          5
    
    // Accessories
    
    Accessories accessories;
    DccCommander dccCommander;
    
    // Drivers
    	
    DriverArduino *arduino;
    
    //////////////////////////////////
    //
    // Setup
    //
    void setup()
    {
    	UAD_StartSetup();
    
        // Setup of the Dcc commander.
    	dccCommander.Setup(0x00, 0x00, kDCC_INTERRUPT);
    	dccCommander.SetStatusLedPin(13);
    
    	// Drivers setups
    
        // one light is connected to the arduino.
    	arduino = new DriverArduino(1, 0); // 1 motor/led, 0 servos
    	arduino->Setup();
    	arduino->SetupPortMotor(0, 13); // first port (0), pin 13
    	
    	// Accessories setups
    
        // Assign Dcc code for each accessory.
    	accessories.Setup(1);
    	accessories.Add(new AccessoryLight(1, 0)); // dcc 1/0
    
       // Attach each accessory to its driver/port.
    	LIGHT(accessories, 0)->Setup(arduino, 0); // use port 0 of arduino driver
    
    	UAD_EndSetup();
    }
    
    void loop()
    {
        // Dcc is run first, and if necessary, lets the accessories work.
    	if (dccCommander.Loop())
    	{
    		accessories.Loop();
    	}
    }

    Répondre

  • This is an interesting project !
    I was experimenting with SerialCommander in V4.1 on Arduino Nano.
    In the Loop function the following test :

    if ((int)character < 32 || (int)character > 60)

    is too restrictive. The ’_’ doesn’t pass the test.
    I have found that ’ ’ is allowable in CheckSyntax().
    Thank you.

    Répondre

  • Un décodeur d’accessoires universel (3) 8 novembre 2015 10:41, par Thierry

    Thanks for your comment. SerialCommander is a base or a sample for what you could do with a serial link, but I never tried to use it, so it is probably not functional... Fell free to adapt it to your needs and to share the result with us !

    Répondre

  • Un décodeur d’accessoires universel (3) 29 décembre 2015 17:32, par dudule

    bonjour
    très bonne démo bravo.
    petite remarque pour ce qui est de la commande simultanée de plusieurs appareils : peut on utiliser des optocoupleurs pour relayer les charges en utilisant une alim externe ?

    Répondre

  • Un décodeur d’accessoires universel (3) 14 février 2016 15:56, par Gabor

    Hi !
    I’d just like to ask you, if this UAD also works with the Roco Multimaus (and its commander nr. 10764) ? Because I set up an Uno (with kDCC_Interrupt = 2), where I have attached the optocoupler’s pin 6 to uno’s digital pin 2. But somehow, even the example program "SimpleLED" does not work.
    Is there anything different, that I shall keep in mind while using the Multimaus ?
    Thanks,
    Gabor

    Répondre

  • Un décodeur d’accessoires universel (3) 14 février 2016 17:08, par Thierry

    Hello. Thanks for using UAD. I have heard of a difference in the value of the Dcc code just on the Multimaus, shifted of 4 from the Arduino : if you program a Dcc code of 27 in the Arduino, you have to use the code 31 on your Multimaus ! I dont know why, and i dont have a Multimaus to test and try to solve the problem... With a Trix MS2 and an Ecos, 27 stay 27 !

    Répondre

    • Un décodeur d’accessoires universel (3) 14 février 2016 20:23, par Gabor

      Hello Thierry,

      Thanks for your help. I heard about a difference of 4, while using a Multimaus as controller, but I was not really sure about that.
      I had also a problem with the interrupt : I used the pin’s number for kDCC_INTERRUPT (pin 2), but not the interrupt’s number (like int. 0).
      With kDCC_INTERRUPT = 0 and choosing the address 5 on Multimaus (when the arduino is programmed for address 1) everything works.

      Thanks a lot,
      Gabor (from Hungary)

      Répondre

      • Un décodeur d’accessoires universel (3) 17 février 2016 21:52, par Gabor

        Dear Thierry,

        does the address calculation always work for you ? Because I found out, that - at least in case of using Multimaus -, basic accessory addressing and DCC_Decode::GetAddress, the address calculated by this function is not OK. In case of address 5 on Maus (in reality : 1), it’s okay, but for address 6,7,8 (reality : 2, 3, 4) this does not work. The real calculated address was 3, 5, 7, 13 and so on...

        But after having a look at the address calculation in the other function DCC_Decoder::State_Execute I adapted the code and changed the calculation to Wolfgang Kufer’s (opendcc.de).
        The original code lines were :
        address = gPacket[1] & 0x70 ;
        address = (address<<2) + (gPacket[0] & 0x3F) ;

        The new code lines are (only the second one is changed) :
        address = gPacket[1] & 0x70 ;
        address = (address<<1) | (gPacket[0] & 0x3F) ;

        I tested some addresses and now I get the following "real" addresses :
        Multimaus / variable "address" (should be "Multimaus" minus 4)
        5 / 1
        6 / 2
        7 / 3
        20 / 16
        So for me, it look OK :) And I’m interested, if this also works for e.g. Trix or other controllers (if you have some free time to test it :) )

        Thanks,
        Gabor

        Répondre

        • Un décodeur d’accessoires universel (3) 18 février 2016 09:18, par Thierry

          Good news ! I will check it soon with my MS2. But could you give the exact URL source of the good formula ? I have tried to decrypt opendcc.de, but german is like chinese for me, and even google translator does not want to translate the pages !

          Répondre

  • Un décodeur d’accessoires universel (3) 18 février 2016 20:34, par Gabor

    Hello ! :) It’s like French to me...beautiful language, but I cannot speak or understand it :)

    Well, you can find under "Dekoder" (decoder) a "Download" link on the left side. Thas directs you here : http://opendcc.de/elektronik/opende...

    I only tried to construct an Opendekoder 1 (=Hardware 1), so I took the firmware for "Signaldekoder V0.14" (signalling decoder) from Opendekoder1.
    It’s a ZIP file, where you find a SignalDekoder.c source file. There is a function "analyse_message", which decodes the address, too. (And in the source file, all comments are in English).

    Best regards,
    Gabor

    P.S. : On opendcc.de in the right upper corner, there is a button for English language. But I don’t know, if everything was translated into English - therefore take maybe the german link :)

    Répondre

  • Un décodeur d’accessoires universel (3) 16 juin 2016 15:10, par Boubou

    Bonjour,
    C’est génial, votre programme fonctionne parfaitement chez moi, mais j’ai une question :
    Je désire ajouter des détecteurs de présence avec une détection de frequence sur des entrées du Méga non utiliser. Je fais l’ajout dans la boucle avant le "if (dccCommander.Loop())", mais cà me bloque tous le reste.
    Dois-je créer une fonction pour pas être bloqué ?
    Merci d’avance

    Répondre

    • Un décodeur d’accessoires universel (3) 16 juin 2016 15:36, par Thierry

      Bonjour, et merci pour votre enthousiasme. Ce n’est pas tant de faire une fonction qui est important, mais ce que vous y mettez... Ce code ne doit pas être bloquant, par d’appel à delay() par exemple, pas de boucle infinie, ni même de boucle trop longue qui aurait pour effet de désynchroniser tout le reste. Le mieux serait de poster votre source sur la partie forum, ce qui permettrait à toute la communauté de suivre des échanges qui peuvent être instructifs, et me permettrait de voir de quoi il retourne !

      Répondre

      • Un décodeur d’accessoires universel (3) 16 juin 2016 15:46, par Boubou

        OK, je comprends, voici ce que je veux ajouter :


        void loop()
        {
        for (int a=38; a<46 ; a++ ) {
          int duration = pulseIn(a,HIGH);
          int b=a+8;
            if (duration >450 && duration <1500){
            digitalWrite (b, HIGH); 
          }else {digitalWrite (b, LOW);}
          }
         // Dcc is run first, and if necessary, lets the    accessories work.
          if (dccCommander.Loop())
          
          {
              accessories.Loop();
          }
        }

        Répondre

        • De ce que je comprends, pulseIn peut prendre un temps indéterminé, qui peut au pire osciller entre 450 et 1500 millisecondes pour une seule broche, et vous bouclez sur neuf broches de 38 à 46 ! C’est beaucoup trop long et ne permet pas au reste de fonctionner correctement... La première modification pourrait être de ne faire qu’une seule broche à chaque loop(). Mais même dans ce cas, la plus grande des durées possibles est tout de même d’une seconde et demie ! Un traitement par interruption pourrait faire l’affaire, mais il y a trop de broches concernées... La seule solution viable serait de faire faire ce travail à un autre Arduino, et de les faire discuter via I2C, CAN ou liaison série. Il faut réfléchir davantage...

          Répondre

          • Un décodeur d’accessoires universel (3) 17 juin 2016 09:45, par Jean-Luc

            La solution consiste à ne pas utiliser pulseIn qui est une fonction bloquante.

            Tel que c’est écrit, la boucle bloque longtemps le programme et les messages DCC sont perdus.

            Je dirais même plus que ça risque de bloquer éternellement. Il suffit qu’une seule des entrées ne délivre jamais de pulse.

            Réponse plus complète sur le forum : http://forum.locoduino.org/index.ph...

            Répondre

            • Un décodeur d’accessoires universel (3) 17 juin 2016 10:11, par Boubou

              Hello,

              Merci pour les infos, c’est cool.
              je vais séparer ma détection sur un autre arduino.
              J’ai aussi déplacer la discussion sur le forum comme préconiser.

              Sujet : Ajout fonction à mon programme décodeur d’accessoires universel

              Répondre

  • Un décodeur d’accessoires universel (3) 12 août 2018 13:39, par pierre

    Bonjour,

    J’ai très envie d’utiliser ce décodeur universel, j’utilise déjà la rétrosignalisation décrite dans ce site.

    Mais j’ai 35 aiguillages que je désire commander avec des servos.

    Je n’arrive pas à comprendre combien de servo peut piloter ce décodeur ?

    Cordialement

    Répondre

  • Bonjour, et merci de votre intérêt pour ma librairie.

    Le nombre d’accessoires n’est pas limité par la bibliothèque. Il l’est matériellement par le nombre de broches sur l’Arduino, et par la mémoire disponible pour déclarer les accessoires.
    D’autre part, il est important de ne PAS utiliser cette bibliothèque ! Elle a été remplacée depuis par Commanders pour les entrées (https://www.locoduino.org/spip.php?...) et Accessories pour les sorties (https://www.locoduino.org/spip.php?...) qui reprennent chacun une partie d’UniversalAccessoriesDecoder. Commanders assurera le décodage DCC ou des boutons, tandis qu’Accessories fera bouger les servos.
    Les exemples d’Accessories utilise tous ou presque Commanders, c’est un bon point de départ.

    Bon courage.

    Répondre

    • Un décodeur d’accessoires universel (3) 12 août 2018 18:26, par pierre

      Bonjour,

      Et merci de votre réponse.

      J’ai bien compris en ce qui concerne la bibliothèque, mais alors sur un Arduino Mega 2560, combien de servos pourrais-je connecter en fonction du nombre de broches disponibles.

      Cordialement

      Répondre

      • Le Mega dispose d’une cinquantaine de broches disponibles. La librairie de pilotage de servo livrée avec l’IDE Arduino qui est utilisée en interne par UAD et Accessories permet de piloter 48 servos avec un Mega... Il y a quand même une limite supplémentaire dont je n’ai pas parlé dans ma première réponse, c’est le courant que peut délivrer un Arduino ou un Mega. Pour simplifier, un Mega peut piloter simultanément 4 ou 5 servos, mais guère plus (http://arduino-info.wikispaces.com/...). 48 peuvent être raccordés si 4 ou 5 maximum sont activés en même temps... Si plus sont nécessaires, alors il faut alimenter les servos avec une source de courant extérieure et ne se servir que de la broche de pilotage de l’Arduino, pas de son alimentation.
        Si 35 servos doivent être pilotés, je placerai un Nano pour quatre servos aux endroits stratégiques, chacun recevant ses ordres sur un bus DCC ou autre et traitant ses propres servos. Nul besoin de les raccorder entre eux...

        Répondre

  • Un décodeur d’accessoires universel (3) 6 février 2020 19:14, par Jean François Lesage

    Bonjour,

    j’admire tout le travail qui a été fait ici
    j’ai réalisé le montage proposé avec inter leds et servos tout fonctionne bien
    quand je branche l’arduino sur mon circuit piloté par DCC++ je n’arrive pas à commander ni les servos ni les leds, la led 13 clignote bien , si j’envoie à dcc++ la commande a 19 1 0 le décodeur d’aiguillage jouef correspondant réagit. les commandes a 320 0 0 et autres restent sans effet. Quelle erreur puis-je faire. Merci de votre aide

    Répondre

  • Un décodeur d’accessoires universel (3) 7 février 2020 16:29, par thierry

    Bonjour

    Merci de vous intéresser à UAD, mais cette bibliothèque n’est plus maintenue depuis depuis plusieurs années. Je ne peux que vous conseiller de regarder les bibliothèques Commanders et Accessories qui en sont les héritières. Le fonctionnement est plus simple, les fonctionnalités étendues et elles sont maintenues par mes soins. Convertir votre projet pour elles ne devrait pas être très compliqué...

    Répondre

  • Un décodeur d’accessoires universel (3) 1er janvier 2021 22:24, par BRUNO

    Bonjour , merci pour cet article très complet , j’ai mis en application cette bibliothèque pour une commande de relais avec un attiny13 , le fonctionnement est parfait.
    Il y a quelques semaines j’ai acheté des puces attiny 804 (commande de Servo moteur), sur ces nouvelles puces il n’y a pas de INTO, je ne parvient pas à trouver la formule pour désigner la pin d’interruption, mes compétences sont dépassées !!
    donc est il possible d’utiliser ces nouveaux attiny avec cette bibliothèque et si oui comment faire , merci de votre aide , cordialement Bruno

    Voir en ligne : DCC et megaTinyCore

    Répondre

  • Un décodeur d’accessoires universel (3) 2 janvier 2021 14:15, par Thierry

    Bonjour. D’après le datasheet récupéré sur le site microchip qui développe et diffuse la famille des Atmel AVR dont l’ATTiny804 est l’un des membres (https://ww1.microchip.com/downloads...) , le chapitre 16.3.3 page 140 précise que toutes les broches peuvent piloter des interruptions. Après il faut trouver des exemples, mais ça doit se trouver...
    Je me permet de rappeler que cette bibliothèque n’est plus maintenue et qu’elle a été remplacée par deux bibliothèques : Commanders pour la partie prise de commande, par des boutons, des potars ou un décodeur DCC, et Accessories qui pilote des moteurs et des leds lorsqu’on lui demande gentiment. Bien entendu, ces deux bibs fonctionnent encore mieux ensemble... Accessories a par exemple beaucoup évolué en gérant les multiplicateurs de port (74HC595, MCP23017, PCA9505 ou SX1509...). Commanders dispose maintenant d’un automate qui lui permet de gérer des petits automatismes.

    Répondre

    • Un décodeur d’accessoires universel (3) 2 janvier 2021 14:54, par BRUNO

      Bonjour, oui j’avais parcouru la data, même si cette bibliothèque n’est plus d’actualité, j’ai plusieurs petits programmes que je fais tourner avec des attiny ou un nano et je voudrai pouvoir les transposer vers les nouveaux attiny
      mon problème c’est que je n’arrive pas à assigner une patte pour l’interruption, avec le nano je prenais INT0, mais je coince pour remplacer cette fonction avec l’attiny, Bruno

      Répondre

Réagissez à « Un décodeur d’accessoires universel (3) »

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