L’Arduino et le système de commande numérique DCC

Présentation de la norme DCC

. Par : Dominique. URL : https://www.locoduino.org/spip.php?article14

Avec ses multiples entrées/sorties facilement programmables et ses processeurs dotés de fonctions analogiques et numériques, l’Arduino ne peut que bien se prêter aux applications dans le domaines des trains miniatures comme il l’est dans d’autres domaines comme l’aéromodélisme, par exemple.

Cette série d’articles a pour but de vous amener progressivement dans la réalisation pas à pas d’une mini-centrale de pilotage numérique de vos trains et accessoires, selon la norme DCC, ainsi que dans celle de décodeurs DCC pour piloter vos accessoires.

Elle a pour but de vous présenter les notions essentielles à connaitre pour vous permettre ensuite d’adapter ces connaissances à votre propre réalisation.

Qu’est ce que le DCC ?

DCC signifie « Digital Command Control », en français « Système de Commande Numérique ».

C’est un standard utilisé dans le modélisme ferroviaire pour commander individuellement des locomotives ou des accessoires de voie en modulant la tension d’alimentation de la voie.
Ce système défini par une norme du NMRA (National Model Railroad Association) a été ensuite adopté par le MOROP (Union Européenne des Modélistes Ferroviaires et des Amis des Chemins de Fer).
Les locomotives et leurs accessoires (feux, effets sonores des engins moteurs) ainsi que les accessoires du réseau (aiguillages, itinéraires) possèdent chacun une adresse unique. Le signal codé envoyé sur la voie donne des ordres aux équipements tout en fournissant la puissance.

Cette définition est un extrait de l’encyclopédie libre Wikipédia [1] que je vous invite à lire pour en connaitre les possibilités et aussi la complexité, ses avantages et inconvénients.

Lorsque j’ai voulu rénover le petit circuit qui dormait depuis plus de 15 ans dans le grenier, alimenté par un bête transformateur et son gros bouton de réglage de vitesse, j’ai décidé de m’orienter vers le DCC qui m’offre des possibilités d’évolutions indéniables (au début, on ne sait pas toujours exactement où l’on va !). Avec le recul, maintenant, je vois mieux l’intérêt du DCC et je ne regrette pas mon choix.

Mais à cause de cette alimentation spéciale qui combine la transmission de données sur la voie avec la fourniture de la puissance, il faut forcément un organe électronique : la centrale et son booster.

L’Arduino comme centrale DCC

La principale difficulté réside dans la production du signal DCC, conformément à la norme NMRA [2], [3], [4].

Ainsi que la version française du MOROP [5], [6]

Mais envoyer des 0 et des 1 à un rythme prédéfini correspond bien aux possibilités de ce micro-contrôleur.

Un bit 1 est constitué de 2 parties de durée égale à 58 micro-seconde (entre 55 et 61 selon la norme) et de polarité opposées. Un bit 0 est constitué de 2 parties de durée au moins égale à 100 micro-seconde et de polarité opposées.

C’est une sorte de tension alternative à 2 fréquences. Cela permet au décodeur placé dans une machine de redresser cette tension pour fournir l’énergie de traction au moteur à courant continu (12 à 18 V), ainsi que l’alimentation (3,3 ou 5 V) au micro-contrôleurs qui fera le décodage en détectant les fronts (montant ou descendant) du signal DCC et la durée entre 2 fronts consécutifs (58 ou 100 micro-secondes), ce qui restitue bien les 0 et les 1.

La seule vraie contrainte est de produire ce signal en tâche de fond, c’est à dire sans empêcher notre Arduino de faire des quantités d’autres tâches que nous verront plus loin, qui, réciproquement, ne doivent pas géner la production automatique de ce signal DCC.

On pourra se reporter, pour comprendre cela, à d’autres articles qui seront prochainement publiés sur les entrées-sorties, les interruptions, les automates, etc...

Quel est donc ce signal DCC ?

Voici 3 exemples simples de trame DCC couramment envoyées sur les rails, à destination des locomotives :

Une commande de vitesse est décrite par la succession de bits 0 et 1 suivants :

111111111111 0 0AAAAAAA 0 01DCSSSS 0 EEEEEEEE 1
.............. le temps s’écoule dans ce sens .................>

  • 111111111111 est le préambule qui doit contenir au moins 12 bits 1,
  • le 0 suivant marque le début de l’adresse qui suit,
  • 0AAAAAAA est l’adresse de la loco (par exemple pour l’adresse 55 : 00110111),
  • le 0 suivant marque le début de la commande qui suit,
  • 01DCSSSS est la commande de direction et vitesse :
  • D = 1 pour la marche avant, D = 0 pour la marche arrière
  • CSSSS est la vitesse codée en 28 pas dans chaque sens (par exemple pour la vitesse 6 en avant : 01110100),
  • le 0 suivant marque le début de la détection d’erreur,
  • EEEEEEEE est un OU Exclusif (XOR) des octets précédents (préambule excepté puisque ce n’est pas un octet) qui sert à verifier la bonne transmission de la commande : le décodeur va calculer le OU Exclusif des octets reçus (sauf celui-là) de son coté et si le résultat qu’il trouve est égal à cet octet reçu, alors il considère que la commande est bien transmise et il exécute la commande,
  • enfin, le dernier 1 termine la commande, une autre commande pouvant suivre.

Quelques remarques : la transmission est du type série, les bits sont émis un par un, bit de poids fort en tête, poids de poids faible en queue. Un bit 0 sert de séparateur entre 2 octets (8 bits) : il permet au récepteur de prendre le temps de mémoriser l’octet précédent juste avant de recevoir le suivant.
Quand l’adresse est codée sur un seul octet, cet octet commence par un 0 (donc la commande ne peut accéder qu’aux adresses inférieures à 128). Pour les adresses supérieures, le premier bit est à 1 et l’adresse est codée sur 2 octets. Les adresses 00, 126 et 127 sont interdites car réservées à des opérations spéciales.

L’exemple donnés correspond à ce qu’on appelle un paquet de base (un octet d’adresse + un octet de commande). Mais il existe d’autres structures dites paquet étendu dans lesquelles l’adresse est sur 1 ou 2 octets et la commande sur 1 à 3 octets.

On trouvera plus de détails en français dans le document du MOROP : NEM671 pour les commandes de base et dans le document de NMRA : RP-9.2.1 pour les paquets étendus.

Pour cette commande de base, cela donne le signal suivant, si l’on utilise un oscilloscope :

qui représente une commande de vitesse de valeur 6 en marche avant pour la loco 37.

Une commande de lumière est décrite par :

111111111111 0 0AAAAAAA 0 100L0000 0 EEEEEEEE 1

  • 111111111111 est le préambule,
  • le 0 suivant marque le début de l’adresse qui suit,
  • 0AAAAAAA est l’adresse de la loco (par exemple pour l’adresse 3 : 00000011),
  • le 0 suivant marque le début de la commande qui suit,
  • 100L0000 est la commande de lumière :
  • L = 1 pour allumée, L = 0 pour éteinte
  • le 0 suivant marque le début de la détection d’erreur,
  • EEEEEEEE est le OU Exclusif des octets précédents pour la détection d’erreur.

Une trame IDLE est émise quand il n’y a pas de trame de commande à envoyer, de façon à alimenter continuellement la voie :

111111111111 0 11111111 0 00000000 0 11111111 1

On comprend ainsi que l’adresse 255 est interdite !

Bien entendu il existe des quantités de commandes possibles, pour commander les diverses fonctions des locomotives, selon le décodeur qui y est installé, des commandes d’accessoires de voie (aiguilles, feux, passages à niveau, dételeurs, plaques tournantes, lumières de décor, etc..), là aussi selon les décodeurs installés. Sans oublier les commandes de programmation des CVs des décodeurs !!!

C’est d’ailleurs dans cette diversité de commandes que réside la complexité du DCC.

Une autre difficulté vient du fait que les informations sont transmises par les rails en même temps que la puissance. On sait tous que les mauvais contacts sont légion et une partie des commandes sont perdues (notamment lors de vérification du XOR de détection d’erreur).

La norme DCC recommande donc de répéter les commandes autant que possible, en laissant toutefois un petit délai de 5 milli-secondes entre commandes destinées à un même décodeur.
Cela correspond à 45 bits 1, c’est à dire bien plus qu’un préambule. Le mieux est donc d’intercaler des trames IDLE.

Quelle est la durée d’une commande DCC ?

Si on additionne les durées de bits 1 et 0 de l’exemple ci-dessus, on trouve 5900 micro-secondes.

Mais la durée des bits 0 et 1 peut varier d’une centrale à une autre (les décodeurs sont conçus pour s’y retrouver quand même) et les commandes n’ont pas le même nombre de 0 et de 1. Elles sont aussi souvent plus longues (par exemple pour le codage de vitesse en 128 pas).

Nous arrivons à une durée de commande comprise en 6 et 10 milli-secondes environ, ce qui se traduit par un nombre de 100 à 150 commandes par seconde au grand maximum !

Ce n’est pas énorme mais cela permet tout de même de piloter beaucoup de trains et d’accessoires sur la même voie. Cependant, plus le nombre d’éléments à piloter augmente, plus le risque augmente de voir un élément ne pas obéir ou agir à retardement, notamment parce que certaines commandes sont perdues lors des perturbations (mauvais contacts).

Il faudra donc en tenir compte pour les grands réseaux : On n’a pas forcément intérêt à faire passer TOUTES les commandes en DCC, les Arduino nous offrant d’intéressantes alternatives.

On verra plus loin qu’il existe aussi des outils permettant de voir et surveiller les transmissions DCC, lorsque le doute s’installe !

L’Arduino est-il capable de générer un signal DCC ?

La réponse est assurément OUI puisque ce signal consiste en une suite de 0 et de 1 séparés par une délai de 58 ou 116 microsecondes, ce qui correspond, au pire, à un signal "audio" de l’ordre de 10 KHz. Mais ne pensez pas tout de même qu’il suffit simplement d’utiliser l’instruction tone() !

De même, il n’est pas conseillé d’utiliser l’instruction delay comme dans l’exemple ci-dessous :

void bit_un(){              // génère un bit à 1
    digitalWrite(dcc_pin, LOW);   // dcc_pin à 0
    delayMicroseconds(58);        // pause de 55 microsecondes      
    digitalWrite(dcc_pin, HIGH);  // dcc_pin à 1
    delayMicroseconds(58);        // pause de 55 microsecondes  
}

void bit_zero(){           // génère un bit à 0
    digitalWrite(dcc_pin, LOW);   // dcc_pin à 0
    delayMicroseconds(116);       // pause de 100 microsecondes      
    digitalWrite(dcc_pin, HIGH);   // dcc_pin à 1
    delayMicroseconds(116);       // pause de 100 microsecondes
}  

car le processeur ne peut pas faire autre chose pendant ces delay.

L’utilisation des interruptions est de loin préférable.

L’article suivant, « Comment piloter trains et accessoires en DCC avec un Arduino (1) » va vous présenter deux méthodes permettant de produire ce signal DCC.
D’autres articles, ensuite vous permettront de mieux connaitre une librairie dédiée au DCC et de construire une mini-centrale avec quelques compléments nécessaires comme le Booster et quelques composants électroniques.

L’Arduino est-il capable de décoder un signal DCC ?

Comme on l’a expliqué plus haut, la forme du signal DCC se prête bien à un décodage des 0 et des 1 et ensuite des paquets (adresses et commandes).

D’autres articles vous présenteront comment construire un décodeur DCC universel, utilisant aussi une librairie dédiée. Dans ce domaine le champ d’applications est très large.
Ou encore comment voir les commandes DCC qui circulent sur les rails.