Dans cet article je vais vous détailler le code que j’ai utilisé pour mon décodeur. Je n’ai pas de connaissance particulière donc je vais expliquer avec mes mots les parties de code à customiser. Les lignes qui n’ont pas besoin d’être retouchées pour rendre le décodeur fonctionnel ne seront pas expliquées.

Le code proposé ici est une variante de celui livré dans les exemples de la bibliothèque, il est téléchargeable ci dessous. Tout ce qui est précédé par les signes // sont des commentaires.

/*************************************************************
project: <DCC Accessory Decoder>
author: <Thierry PARIS>
description: <4 servos driven by dcc arduino>
*************************************************************/

#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            0
// REGLAGE DE LA PIN D'ENTREE  DU SIGNAL DCC ICI POUR UN UNO PIN 2

///////////////////////////////////////////////////////////////
// The target is to move 4 servos, by DCC adress, DEFINITION DES SERVOS

#define AccessoryServoNumber      4

#define SERVO1 0
#define SERVO2 1
#define SERVO3 2
#define SERVO4 3


#define SERVO1_PORT 0
#define SERVO2_PORT 1
#define SERVO3_PORT 2
#define SERVO4_PORT 3

// Accessories

Accessories accessories;
DccCommander dccCommander;


// Drivers

DriverArduino *arduino;

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

    // Setup of Dcc commander
 dccCommander.Setup(0x00, 0x00, kDCC_INTERRUPT);
 dccCommander.SetStatusLedPin(13);

  

 // Drivers setups

    // List of the ports on the Arduino. Pors 9,10 and 11 are handled in analog mode for fading.
 arduino = new DriverArduino(0,AccessoryServoNumber); // IMPORTANT DE LAISSER LE 0 SI UNIQUEMENT DES SERVOS
 arduino->Setup();
 arduino->SetupPortServo(SERVO1_PORT, 4); // LE SERVO_PORT1 CORRESPONDANT AU SERVO 1 EST CONNECTE PIN 4
 arduino->SetupPortServo(SERVO2_PORT, 5);
 arduino->SetupPortServo(SERVO3_PORT, 6);
 arduino->SetupPortServo(SERVO4_PORT, 7);
 
 // Accessories setups

    // Declare accessories with Dcc codes.
 accessories.Setup(
 AccessoryServoNumber,
 new AccessoryServo(27, 0, 27, 1, 20), // PREMIER SERVO ADRESSE DCC 27 SUR LA CENTRALE, OU 31 CHEZ ROCO CAR DECALLEGE DE + 4
 new AccessoryServo(28, 0, 28, 1, 20), // 0 CORRESPOND AU PREMIER BOUTON DE LA CENTRALE  POUR BOUGER UN AIGUILLAGE A L'ANGLE MINI DEFINI
 new AccessoryServo(29, 0, 29, 1, 20), // 1 CORRESPOND AU DEUXIEME BOUTON DE LA CENTRALE POUR ANGLE MAXI
 new AccessoryServo(30, 0, 30, 1, 20) // 20 CORRESPOND A TEMPS EN MS ENTRE CHAQUE DECALLAGE DE 1DEGRES DU SERVO
    );
    
    // Attach the servos to their driver/ports.
    
 SERVO(accessories, SERVO1)->Setup(arduino, SERVO1_PORT, 20, 145); // SERVO 1 ATTACHE AU PORT 1 DONC PIN 4 ARDUINO BOUGE DE 20 A 145 DEGRE
 SERVO(accessories, SERVO2)->Setup(arduino, SERVO2_PORT, 20, 90);
 SERVO(accessories, SERVO3)->Setup(arduino, SERVO3_PORT, 0, 145);
 SERVO(accessories, SERVO4)->Setup(arduino, SERVO4_PORT, 20, 180);


 UAD_EndSetup();
}

void loop()
{
    // Run the Loop on all items, if Dcc Loop agrees !
 if (dccCommander.Loop())
 {
 accessories.Loop();

 }
}

Voyons un peu en détail les lignes de code :

Cette première ligne fait appel à la bibliothèque que nous avons installé dans le premier article. Il ne faut pas la modifier.

#include "UniversalAccessoryDecoder.h"

 

Voici la première ligne qu’on doit modifier. Selon le tableau apparaissant avant dans le code en commentaire, on doit définir sur quelle broche de l’Arduino le signal DCC arrive. Je rappelle qu’il faut utiliser un montage avec optocoupleur pour relier le bus DCC à l’Arduino. Voir l’article précédent.
Dans l’exemple le 0 correspond au init.0 dans le tableau, et pour ma carte Arduino uno à la broche 2.
Si on possède un Arduino mega et qu’on veut se connecter à la broche 20, il faudra remplacer le 0 par 3 sur cette ligne.

#define kDCC_INTERRUPT            0

 

Ici nous disons en premier lieu combien de servos nous allons contrôler : 4

Dans UAD les accessoires sont numérotés à partir de 0. De fait pour 4 servos, on parlera des accessoires 0 à 3 !
Pour clarifier le code on définit ici ces accessoires en les liants à un « mot » plus clair pour notre compréhension. Donc l’accessoire 0 sera nommé SERVO1, mais on aurait très bien pu l’appeler TJD, ou ENTREEGARE, ou PIERRE……. comme cela nous arrange.

Les SERVO_PORT* sont des intermédiaires entre l’accessoire UAD purement virtuel et la broche de l’Arduino bien physique qui le pilote.

Bien entendu si on ajoute ou retire des servos il faut adapter ces lignes en fonction du nombre de servos utilisés.

#define AccessoryServoNumber      4

#define SERVO1 0
#define SERVO2 1
#define SERVO3 2
#define SERVO4 3


#define SERVO1_PORT 0
#define SERVO2_PORT 1
#define SERVO3_PORT 2
#define SERVO4_PORT 3

 

Nous disons ici que c’est l’Arduino qui pilote directement les servos. Il n’y aura pas de relais ou tout autre “shield” de présent dans notre montage.

DriverArduino *arduino;

 

Nous disons que l’organe qui pilotera notre Arduino est le bus DCC et nous appelons la broche sur laquelle cette info arrive (kDCC_INTERRUPT). Par la même occasion nous définissons la led interne de l’Arduino (13 sur un Uno/Mega) pour qu’elle s’allume lorsqu’il reçoit des infos arrivant du bus DCC.

    // Setup of Dcc commander
 dccCommander.Setup(0x00, 0x00, kDCC_INTERRUPT);
 dccCommander.SetStatusLedPin(13);

 

Nous allons maintenant définir sur quelles broches de l’Arduino sont connectés nos servos, et pour cela on utilise les ports virtuels créés au début:
Tout d’abord nous disons combien de broches le DriverArduino va devoir piloter en réutilisant l’AccessoryServoNumber puisqu’il y a autant de broches à piloter que de servos !

Puis le setup continue en liant chaque SERVO_PORT à une broche de l’Arduino, ici le port 1 à la broche 4, ce qui correspond à connecter le SERVO 1 (lié au SERVO_PORT1, car ce sont tous les deux l’accessoire 0 dans la numérotation interne) à la broche 4 de l’Arduino.

 arduino = new DriverArduino(0,AccessoryServoNumber); // IMPORTANT DE LAISSER LE 0 SI UNIQUEMENT DES SERVOS
 arduino->Setup();
 arduino->SetupPortServo(SERVO1_PORT, 4); // LE SERVO_PORT1 CORRESPONDANT AU SERVO 1 EST CONNECTE PIN 4
 arduino->SetupPortServo(SERVO2_PORT, 5);
 arduino->SetupPortServo(SERVO3_PORT, 6);
 arduino->SetupPortServo(SERVO4_PORT, 7);

 

L’étape suivante consiste à déclarer les adresses DCC que la centrale enverra pour piloter nos servos.
Il y a autant de lignes que de servos à définir. Étudions la première ligne, les suivantes ne sont que des variantes. Voyons donc la signification de chaque valeur:

  • 27: correspond à l’adresse DCC de “l’aiguillage” à piloter. Il y a ici un cas particulier pour les utilisateurs de centrale ROCO multimaus comme moi. En effet les adresses chez ROCO pour les accessoires sont décalés de 4 par rapport à la norme. Donc en programmant l’adresse 27 dans l’arduino, il faudra que je demande à l’aiguillage N° 31 sur la centrale de bouger pour que le servo 1 s’actionne.
  • 0: correspond au code du premier bouton de manoeuvre des aiguillages sur la centrale
  • 27: correspond de nouveau à l’adresse DCC
  • 1: correspond au deuxième bouton de manoeuvre des aiguillages sur la centrale
  • 20 correspond au temps en milli-seconde que le programme attend entre chaque mouvement de 1°. Plus ce chiffre est grand, plus le servo bougera lentement. Ainsi le servo bouge de 1° attend 20ms, bouge de 1° et ainsi de suite…..
    // Declare accessories with Dcc codes.
 accessories.Setup(
 AccessoryServoNumber,
 new AccessoryServo(27, 0, 27, 1, 20), // PREMIER SERVO ADRESSE DCC 27 SUR LA CENTRALE, OU 31 CHEZ ROCO CAR DECALLEGE DE + 4
 new AccessoryServo(28, 0, 28, 1, 20), // 0 CORRESPOND AU PREMIER BOUTON DE LA CENTRALE  POUR BOUGER UN AIGUILLAGE A L'ANGLE MINI DEFINI
 new AccessoryServo(29, 0, 29, 1, 20), // 1 CORRESPOND AU DEUXIEME BOUTON DE LA CENTRALE POUR ANGLE MAXI
 new AccessoryServo(30, 0, 30, 1, 20) // 20 CORRESPOND A TEMPS EN MS ENTRE CHAQUE DECALLAGE DE 1DEGRES DU SERVO
    );

 

Nous terminons la partie modifiable du programme pour la liaison entre les objets SERVO et leur port virtuels SERVO_PORT. C’est ici aussi que nous définissons les angles mini et maxi de mouvement. Sur la première ligne le servo 1 bougera:

  • de la position minimum 20°
  • à la position maximum 145°
SERVO(accessories, SERVO1)->Setup(arduino, SERVO1_PORT, 20, 145); // SERVO 1 ATTACHE AU PORT 1 DONC PIN 4 ARDUINO BOUGE DE 20 A 145 DEGRE
 SERVO(accessories, SERVO2)->Setup(arduino, SERVO2_PORT, 20, 90);
 SERVO(accessories, SERVO3)->Setup(arduino, SERVO3_PORT, 0, 145);
 SERVO(accessories, SERVO4)->Setup(arduino, SERVO4_PORT, 20, 180);

 

Le reste du programme reste tel quel dans notre cas.

Pour résumer le fonctionnement:

Lorsque que je sélectionne l’adresse 31 en mode aiguillage sur ma multimaus et que j’appuie sur le bouton gauche:

  • le signal arrive sur la pin 2 de mon arduino via le montage à base d’optocoupleur
  • le programme interprète l’adresse 31 ROCO, comme adresse 27 et le bouton gauche comme le port 0 et mémorise qu’il devra faire des poses de 20ms entre chaque degré de mouvement
  • il envoi  SERVO_PORT 1 à la position minimum de 20°
  • le SERVO_PORT1 est donc l’accessoire 0 que l’on a appelé SERVO1 (mais qui pourrait s’appeler Pierre, Paul ou Jacques) donc le programme envoi le signal de mouvement à la pin 4 de l’arduino

Voila j’espère avoir été le plus clair possible dans mes explications. Dans l’article suivant je détaillerais le câblage de ce décodeur avec les servos, sachant que l’Arduino n’a pas la capacité à alimenter la puissance de 4 servo par sa sortie 5v.