LOCODUINO

Forum de discussion
Dépôt GIT Locoduino
Flux RSS

lundi 25 septembre 2017

49 visiteurs en ce moment

Un décodeur DCC pour les signaux à deux ou trois feux sur Arduino NANO/UNO

. Par : JPClaude

Sur nos réseaux il est nécessaire de contrôler un certain nombre d’articles comme la détection de présence avec le cantonnement et la position des aiguillages qui ont un impact direct avec le roulement de nos trains et d’autres articles, plus pour l’esthétique, comme les animations ou les feux de signalisation. La détection a été abordée avec le bus S88 et maintenant avec le travail de mes collègues avec le bus CAN beaucoup plus performant. Le contrôle des aiguillages à solénoïde a également été abordé dans un article précédent. Nous souhaitons ici proposer une solution pour réaliser un décodeur de feux de signalisation à deux ou trois feux gérés par des commandes DCC  .

Réalisation de la carte décodeur

Les feux de signalisation sur nos réseaux n’ont aucune influence sur le roulement de nos trains, ils sont juste là pour créer un environnement réaliste. Si vous êtes comme moi un peu réfractaire à comprendre la complexité des signaux SNCF, je me limite, au moins pour l’instant, à des signaux à deux ou trois feux. Je vous propose donc de réaliser un décodeur pour ce type de signaux.

Feux de signalisation

Le principe est assez simple puisque cela revient à allumer ou éteindre des leds, ce que nos Arduino font très bien. Les signaux en DCC   sont considérés comme des accessoires possédant une adresse (dans le cas des signaux à deux feux) ou deux adresses (dans le cas des signaux à trois feux). Il suffit donc de coller un capteur de signaux DCC   à un Arduino qui exécutera la commande reçue et allumera (ou éteindra) les bonnes leds. Dans notre approche l’alimentation des leds est faite par le courant DCC.
Le schéma suivant reprend la capture des signaux DCC classique basée sur un 6N137 auquel on ajoute en parallèle un pont et un régulateur 8V pour l’alimentation de l’Arduino et des leds. Cela est raisonnable car nous le verrons dans le cas des signaux à trois feux il n’y aura que 5 leds allumées et dans le cas des signaux à deux feux, 8 leds allumées. Un strap a été prévu suivant la polarité des signaux (leds avec commun positif ou négatif). L’Arduino reçoit les commandes DCC sur la broche 2 (interruption 0) et renvoie le résultat sur les broches 3 à A4 suivant les cas. Cela tient sur une carte classique 6x10 et est la même que ce soit des signaux à deux ou trois feux.

Carte décodeur signalisation


Architecture de la carte

Et voici le typon correspondant :

Typon de la carte décodeur

(NB : petite astuce pour ceux qui se lance dans la réalisation, le problème est d’aligner convenablement le perçage pour l’Arduino NANO. Pour cela j’utilise une plaque d’essai qui me sert de guide :

Perçage de la carte décodeur

Et tout se passe bien.)
Pour ceux qui connaissent Eagle et qui font leur carte via des fournisseurs voici les fichiers Eagle :

Fichiers Eagle

et le zip Gerber qui va avec :

Fichier Gerber

et obtient des cartes quasi professionnelles :

signalisation carte


signalisation carte montée

L’algorithme

Le programme permet de gérer aussi bien les signaux à deux feux que ceux à trois feux. Par contre on ne peut mélanger les deux types sur une même carte.
Pour les signaux à trois feux la carte admet 5 signaux dont les leds sont contrôlées par les broches 3 à A3 en triplet.

Signal1 broches 3,4,5
Signal2 broches 6,7,8
Signal3 broches 9,10,11
Signal4 broches 12,13,A0
Signal5 broches A1,A2,A3

Les adresses paires correspondent aux leds vertes et rouges.
Les adresses impaires correspondent aux leds jaunes.

Pour les signaux à deux feux la carte admet 8 signaux dont les leds sont contrôlées par les broches 3 à A4 par paire.

Signal1 broches 3,4
Signal2 broches 5,6
Signal3 broches 7,8
Signal4 broches 9,10
Signal5 broches 11,12
Signal6 broches 13, A0
Signal7 broches A1, A2
Signal8 broches A3, A4

Chaque signal possède une adresse unique.

L’algorithme est simple et ne demande que trois paramètres de configuration :
MODE : détermine le niveau de commande des leds en fonction de la polarité commune, LOW si le commun est positif, HIGH si le commun est négatif.
FIRST_ID_DCC : correspond à la première adresse des signaux, les adresses des signaux suivants en découleront (linéaire dans le cas BICOLOR, par paire dans le cas TRICOLOR).
NB_TRAFFIC_LIGHT : détermine la nature des signaux, TRICOLOR pour des signaux à trois feux ou BICOLOR pour des signaux à deux feux.
Un dernier paramètre ne sert qu’à permettre de visualiser la bonne configuration et peut être omis par la suite, c’est le paramètre CONSOLE.

Le reste de l’algorithme reste inchangé quel que soit le type de signaux.

Paramètres internes

Ils déterminent les paramètres du DCC (insertion de la librairie Minabay, broche d’interruption), évitent les commandes multiples ayant même adresse et/ou même commande (previous_address/previous_position) et si une mise à jour est nécessaire (update_light).

Ils décrivent les signaux (BICOLOR ou TRICOLOR), la broche de départ des leds des signaux (FIRST_PIN) et les couleurs possibles (GREEN, RED, YELLOW).
Ils définissent la structure d’un signal (light) qui possède une adresse (address), une couleur courante (current_position), les broches des leds associées (green, red et yellow) et si une requête de changement est demandée (activation_request).
L’ensemble des signaux est regroupé dans un tableau (traffic_light[]).
Le setup instancie le DCC et détermine les adresses des signaux (address), linéaire dans le cas BICOLOR, par paire dans le cas TRICOLOR, les broches des leds (green, red, yellow) et positionne tous les signaux au rouge. Voici par exemple des configurations :

Pour des signaux à deux feux :

traffic light0
green led on pin : 3 , DCC address : 90/0
red led on pin : 4 , DCC address : 90/1
traffic light1
green led on pin : 5 , DCC address : 91/0
red led on pin : 6 , DCC address : 91/1
traffic light2
green led on pin : 7 , DCC address : 92/0
red led on pin : 8 , DCC address : 92/1
traffic light3
green led on pin : 9 , DCC address : 93/0
red led on pin : 10 , DCC address : 93/1
traffic light4
green led on pin : 11 , DCC address : 94/0
red led on pin : 12 , DCC address : 94/1
traffic light5
green led on pin : 13 , DCC address : 95/0
red led on pin : 14 , DCC address : 95/1
traffic light6
green led on pin : 15 , DCC address : 96/0
red led on pin : 16 , DCC address : 96/1
traffic light7
green led on pin : 17 , DCC address : 97/0
red led on pin : 18 , DCC address : 97/1

Et des signaux pour trois feux :

traffic light0
green led on pin : 3 , DCC address : 90/0
red led on pin : 4 , DCC address : 90/1
yellow led on pin : 5 , DCC address : 91/0
traffic light1
green led on pin : 6 , DCC address : 92/0
red led on pin : 7 , DCC address : 92/1
yellow led on pin : 8 , DCC address : 93/0
traffic light2
green led on pin : 9 , DCC address : 94/0
red led on pin : 10 , DCC address : 94/1
yellow led on pin : 11 , DCC address : 95/0
traffic light3
green led on pin : 12 , DCC address : 96/0
red led on pin : 13 , DCC address : 96/1
yellow led on pin : 14 , DCC address : 97/0
traffic light4
green led on pin : 15 , DCC address : 98/0
red led on pin : 16 , DCC address : 98/1
yellow led on pin : 17 , DCC address : 99/0

L’algorithme consiste à tester le DCC (méthode BasicDecoderPacket_Handler).
Ce dernier décode l’adresse reçue, vérifie s’il y a un changement depuis la dernière fois (cela évite les commandes multiples). S’il y a changement en fonction du type de signal (BICOLOR ou TRICOLOR) on calcule l’index du signal concerné en fonction de l’adresse reçue et la led concernée. Dans le cas TRICOLOR il y a deux adresses par signal, si l’adresse est impaire c’est le signal jaune qui est concerné. Le DCC met à jour les paramètres du signal et prévient d’un changement.
Si un changement a eu lieu on le propage au bon signal (méthode activation_traffic_light). Cette méthode recherche les signaux en attente de traitement (activation_request) et exécute les commutations des leds du signal en fonction de la demande (current_position).

Le programme Arduino

  1. /*
  2.  * Decoder for traffic light with three or two leds on ARDUINO NANO
  3.  *
  4.  * by default the red leds are switched on
  5.  * pin 2 receives DCC interrupts
  6.  *
  7.  * TRAFFIC LIGHT WITH THREE leds (GREEN, RED, YELLOW)
  8.  * 5 decoders of traffic lights with three leds on Arduino NANO/UNO
  9.  * the leds are controlled by pins 3 to A3 by triplet
  10.  * traffic light 1 : 3,4,5
  11.  * traffic light 2 : 6,7,8
  12.  * traffic light 3 : 9,10,11
  13.  * traffic light 4 : 12,13,A0
  14.  * traffic light 5 : A1,A2,A3
  15.  * two addresses by traffic light
  16.  * even addresses for green and red lights
  17.  * odd addresses for yellow light
  18.  *
  19.  * TRAFFIC LIGHT WITH TWO leds (GREEN, RED)
  20.  * 8 decoders of traffic lights with two leds on Arduino NANO/UNO
  21.  * the leds are controlled by pins 3 to A4 by pair
  22.  * traffic light 1 : 3,4
  23.  * traffic light 2 : 5,6
  24.  * traffic light 3 : 7,8
  25.  * traffic light 4 : 9,10
  26.  * traffic light 5 : 11,12
  27.  * traffic light 6 : 13,A0
  28.  * traffic light 7 : A1,A2
  29.  * traffic light 8 : A3,A4
  30.  * one address by traffic light
  31.  *
  32.  * CONFIGURATION
  33.  * MODE : determined by the common of the led, LOW if common = HIGH, HIGH if common = LOW
  34.  * FIRST_ID_DCC : DCC address of the first traffic light
  35.  * NB_TRAFFIC_LIGHT : determined by the kind of traffic light, BICOLOR for two leds, TRICOLOR for three leds
  36.  *
  37.  */
  38.  
  39. /***************************************************************************************
  40.  * CONFIGURATION SETTING
  41.  *
  42.  ****************************************************************************************/
  43.  
  44. #define CONSOLE // output console, delete this after checking the configuration
  45. #define MODE LOW // LOW or HIGH
  46. #define FIRST_ID_DCC 90 // first DCC address, DCC_CODE
  47. #define NB_TRAFFIC_LIGHT TRICOLOR // TRICOLOR or BICOLOR
  48.  
  49. /**********************************************************************************
  50.  * DON'T CHANGE THE FOLLOWING
  51.  *********************************************************************************/
  52.  
  53. /******************************************************************************
  54.  * INTERNAL PARAMETERS
  55.  *
  56.  ********************************************************************************/
  57.  
  58. // DCC
  59.  
  60. #include <DCC_Decoder.h> // Minabay library
  61. #define kDCC_INTERRUPT 0 // pin 2 receives DCC interrupts
  62. int previous_address = 0; // avoids multiple DCC addresses
  63. int previous_position = 2; // avoids multiple DCC orders
  64. volatile boolean update_light; // set if an update should be processed after DCC control
  65.  
  66. // traffic light
  67.  
  68. #define BICOLOR 8 // 8 traffic lights with two leds
  69. #define TRICOLOR 5 // 5 traffic lights with three leds
  70. #define FIRST_PIN 3 // pin of the first traffic light
  71. #define GREEN 0 // address DCC/0
  72. #define RED 1 // address DCC/1
  73. #define YELLOW 2 // address DCC+1/0
  74.  
  75. // traffic light definition
  76.  
  77. struct light {
  78. int address; // its DCC address
  79. int current_position; // green / red / yellow
  80. int green; // pin of the green led
  81. int red; // pin of the red led
  82. int yellow; // pin of the yellow led
  83. boolean activation_request; // request of activation
  84. };
  85. light traffic_light[NB_TRAFFIC_LIGHT]; // the set of traffic light
  86.  
  87. /********************************************************************
  88.  * method called if a request is made by the DCC
  89.  *
  90.  *******************************************************************/
  91.  
  92. void activation_traffic_light() {
  93. for (int i = 0; i < NB_TRAFFIC_LIGHT; i++) // for all traffic lights
  94. {
  95. if (traffic_light[i].activation_request == true) // if the traffic_light is waiting for activation
  96. {
  97. switch(traffic_light[i].current_position) // we look the current position
  98. {
  99. case GREEN :{ // if green led
  100. digitalWrite(traffic_light[i].green,MODE); // switch on green
  101. digitalWrite(traffic_light[i].red,!MODE); // switch off red
  102. if ( NB_TRAFFIC_LIGHT == TRICOLOR){digitalWrite(traffic_light[i].yellow,!MODE);} // switch off yellow
  103. #ifdef CONSOLE
  104. Serial.print("activation -> traffic light");Serial.print(i);Serial.println(" : green led");
  105. #endif
  106. break;}
  107. case RED : { // if red led
  108. digitalWrite(traffic_light[i].green,!MODE); // switch off green
  109. digitalWrite(traffic_light[i].red,MODE); // switch on red
  110. if ( NB_TRAFFIC_LIGHT == TRICOLOR){digitalWrite(traffic_light[i].yellow,!MODE);} // switch off yellow
  111. #ifdef CONSOLE
  112. Serial.print("activation -> traffic light");Serial.print(i);Serial.println(" : red led");
  113. #endif
  114. break;}
  115. case YELLOW : { // if yellow led
  116. digitalWrite(traffic_light[i].green,!MODE); // switch off green
  117. digitalWrite(traffic_light[i].red,!MODE); // switch off red
  118. digitalWrite(traffic_light[i].yellow,MODE); // switch on yellow
  119. #ifdef CONSOLE
  120. Serial.print("activation -> traffic light");Serial.print(i);Serial.println(" : yellow led");
  121. #endif
  122. break;}
  123. }
  124. }
  125. traffic_light[i].activation_request = false; // the traffic light is updated
  126. }
  127. update_light = false; // all updates are made
  128. }
  129.  
  130. /*************************************************************************************
  131.  * DCC method
  132.  *
  133.  ***********************************************************************************/
  134.  
  135. void BasicAccDecoderPacket_Handler(int address, boolean activate, byte data)
  136. {
  137.  
  138. address -= 1; address *= 4; address += 1; address += (data & 0x06) >> 1; // DCC address decoding
  139. int led = (data & 0x01) ? GREEN : RED; // DCC/0 or DCC/1
  140. int traffic_light_index = address; // index of a traffic light
  141. int color = led; // the color of the led
  142. boolean activation = false;
  143. if ((address != previous_address) || ((led != previous_position)&&(address == previous_address))){ // if we change the address or the led
  144. switch (NB_TRAFFIC_LIGHT) {
  145. case BICOLOR : { // if the address is in our range for traffic light with two leds
  146. if ((address >= FIRST_ID_DCC) && (address < FIRST_ID_DCC + NB_TRAFFIC_LIGHT)){
  147. traffic_light_index = address - FIRST_ID_DCC; // index of the traffic light
  148. activation = true;}
  149. break;}
  150. case TRICOLOR : { // if the address is in our range for traffic light with three leds
  151. if ((address >= FIRST_ID_DCC) && (address < FIRST_ID_DCC + (2*NB_TRAFFIC_LIGHT))){
  152. if (address%2 != 0) { traffic_light_index = address - 1; color = YELLOW;} // if odd address => yellow led
  153. traffic_light_index = (traffic_light_index - FIRST_ID_DCC)/2; // index of the traffic light
  154. activation = true;}
  155. break;}
  156. }
  157. traffic_light[traffic_light_index].activation_request = activation; // activation is requested
  158. traffic_light[traffic_light_index].current_position = color; // state is requested (color of the led)
  159. update_light = activation; // traffic light update is requested
  160. }
  161. previous_address = address; previous_position = led; // the current activation is saved
  162. }
  163. /**********************************************************************************************
  164.  * setup
  165.  *
  166.  ******************************************************************************************/
  167.  
  168. void setup() {
  169. int pin_jump = 0; // a jump for traffic light pins
  170. int traffic_light_jump = 0; // a jump for traffic light number
  171. for (int i=0; i<NB_TRAFFIC_LIGHT; i++){ // for all the traffic lights
  172. traffic_light[i].activation_request = false; // no activation request
  173. traffic_light[i].green = pin_jump + FIRST_PIN; // pin number of the green led
  174. pinMode(traffic_light[i].green, OUTPUT); // green led in output(ID DCC/0)
  175. digitalWrite(traffic_light[i].green, !MODE); // green led switch off
  176. traffic_light[i].red = 1+ pin_jump + FIRST_PIN; // pin number of the red led
  177. pinMode(traffic_light[i].red, OUTPUT); // red led in output (ID DCC/1)
  178. digitalWrite(traffic_light[i].red, MODE); // red led switch on
  179. if (NB_TRAFFIC_LIGHT == TRICOLOR) { // if three leds
  180. traffic_light[i].address = traffic_light_jump + FIRST_ID_DCC + i; // its DCC ID
  181. traffic_light[i].yellow = 2+ pin_jump + FIRST_PIN; // pin number of the yellow led
  182. pinMode(traffic_light[i].yellow, OUTPUT); // yellow led in output (ID DCC+1/0)
  183. digitalWrite(traffic_light[i].yellow, !MODE); // yellow led switch off
  184. traffic_light_jump++; // the following traffic light
  185. pin_jump+=3; // the following pin for three leds
  186. }
  187. else { // if two leds
  188. traffic_light[i].address = FIRST_ID_DCC + i; // its DCC ID
  189. pin_jump+=2; // the following pin for two leds
  190. }
  191.  
  192. }
  193.  
  194. DCC.SetBasicAccessoryDecoderPacketHandler(BasicAccDecoderPacket_Handler, true); // instanciate the DCC
  195. DCC.SetupDecoder( 0x00, 0x00, kDCC_INTERRUPT ); // its IT
  196. update_light = false; // no update
  197.  
  198. #ifdef CONSOLE
  199. Serial.begin(115200);
  200. for (int i=0; i<NB_TRAFFIC_LIGHT; i++){
  201. Serial.print("traffic light");Serial.println(i);
  202. Serial.print("\t green led on pin : ");Serial.print(traffic_light[i].green);Serial.print(" , DCC address : ");Serial.print(traffic_light[i].address);Serial.println("/0");
  203. Serial.print("\t red led on pin : ");Serial.print(traffic_light[i].red);Serial.print(" , DCC address : ");Serial.print(traffic_light[i].address);Serial.println("/1");
  204. if (NB_TRAFFIC_LIGHT == TRICOLOR) {
  205. Serial.print("\t yellow led on pin : ");Serial.print(traffic_light[i].yellow);Serial.print(" , DCC address : ");Serial.print(traffic_light[i].address+1);Serial.println("/0");
  206. }
  207. }
  208. #endif
  209. }
  210.  
  211. /*************************************************************************
  212.  * loop
  213.  *
  214.  ******************************************************************/
  215.  
  216. void loop() {
  217. DCC.loop(); // Is there a DCC command ?
  218. if (update_light) {activation_traffic_light();} // if yes, activation of traffic lights
  219. }

Le programme à télécharger ici :

Decoder traffic light

Ce petit décodeur de signaux est facile à réaliser pour un coût très modique. Il marche très bien sur mon réseau avec mon ECOS et TrainController. Pour ceux qui possède une Cameo silhouette on peut même réaliser ses propres feux et potence dont voici une première ébauche.

Potence en papier

et son utilisation avec une ECOS :

signalisation ECOS


signalisation portique

la bibliothèque minabay pour le DCC

minabay dcc decoder

23 Messages

Réagissez à « Un décodeur DCC pour les signaux à deux ou trois feux sur Arduino NANO/UNO »

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 « Projets »

Un chenillard de DEL

Enseigne de magasin

Feux tricolores

Multi-animations lumineuses

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

Un décodeur d’accessoire DCC versatile basé sur Arduino

Un moniteur de signaux DCC

Une barrière infrarouge

Un capteur RFID

Un TCO xpressnet

Une animation sonore

L’Arduino au coeur des systèmes de pilotage analogiques ou numériques

Calcul de la vitesse d’un train miniature avec l’Arduino

La génèse d’un réseau 100% Arduino

Une horloge à échelle H0

Simulateur de soudure à arc

Un automatisme de Passage à Niveau

La rétro-signalisation sur Arduino

Décodeur pour aiguillage à solénoïdes sur Arduino

Un décodeur DCC pour les signaux à deux ou trois feux sur Arduino NANO/UNO

Etude d’un passage à niveau universel

Réalisation pratique d’un système de mesure de vitesse à l’échelle N

Une Passerelle entre le bus S88 et le bus CAN pour la rétro signalisation

Un décodeur DCC pour 16 feux tricolores

Block Automatique Lumineux avec la carte shield "Arduino 4 relays"

Réalisation d’un affichage de gare ARRIVEE DEPART

Comment piloter trains et accessoires en DCC avec un Arduino (1)

Comment piloter trains et accessoires en DCC avec un Arduino (2)

Comment piloter trains et accessoires en DCC avec un Arduino (3)

Comment piloter trains et accessoires en DCC avec un Arduino (4)

SGDD : Système de Gestion DD (1)

SGDD : Système de Gestion DD (2)

SGDD : Système de Gestion DD (3)

La PWM : Qu’est-ce que c’est ? (1)

La PWM : Qu’est-ce que c’est ? (2)

La PWM : Qu’est ce que c’est ? (3)

La PWM : Qu’est ce que c’est ? (4)

Mise en oeuvre du Bus CAN entre modules Arduino (1)

Mise en oeuvre du Bus CAN entre modules Arduino (2)

Un gestionnaire en C++ pour votre réseau (1)

Un gestionnaire en C++ pour votre réseau (2)

Un gestionnaire en C++ pour votre réseau (3)

Un gestionnaire en C++ pour votre réseau (4)

Réalisation de centrales DCC avec le logiciel libre DCC++ (1)

Réalisation de centrales DCC avec le logiciel libre DCC++ (2)

Réalisation de centrales DCC avec le logiciel libre DCC++ (3)

Contrôleur à télécommande infrarouge pour centrale DCC++

Gestion d’une gare cachée (1)

Gestion d’une gare cachée (2)

Gestion d’une gare cachée (3)

Les derniers articles

La PWM : Qu’est ce que c’est ? (4)


Jean-Luc

Block Automatique Lumineux avec la carte shield "Arduino 4 relays"


Christian

Réalisation d’un affichage de gare ARRIVEE DEPART


Gilbert

Contrôleur à télécommande infrarouge pour centrale DCC++


Daniel

La PWM : Qu’est ce que c’est ? (3)


Jean-Luc

Réalisation de centrales DCC avec le logiciel libre DCC++ (3)


bobyAndCo

Un gestionnaire en C++ pour votre réseau (4)


Pierre59

Un décodeur DCC pour 16 feux tricolores


Dominique, JPClaude, Thierry

Réalisation de centrales DCC avec le logiciel libre DCC++ (2)


bobyAndCo

Réalisation de centrales DCC avec le logiciel libre DCC++ (1)


Dominique

Les articles les plus lus

Comment piloter trains et accessoires en DCC avec un Arduino (1)

La PWM : Qu’est-ce que c’est ? (1)

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

Comment piloter trains et accessoires en DCC avec un Arduino (3)

L’Arduino au coeur des systèmes de pilotage analogiques ou numériques

La rétro-signalisation sur Arduino

Mise en oeuvre du Bus CAN entre modules Arduino (2)

Réalisation de centrales DCC avec le logiciel libre DCC++ (1)

Une barrière infrarouge

Enseigne de magasin