/*
* Décodeur pour signaux à 3 feux basé sur un controleur Arduino Nano.
*
* Programme librement interprété par Babar sur la base de celui de JPClaude du 3 avril 2016.
*
* Les feux sont rouges par défaut
* La broche 2 reçoit les interruptions DCC
*
* Signal à 3 couleurs ROUGE; VERT; JAUNE.
* 5 décodeurs par microcontrolleur
* Les leds sont connectées aux broches 3 a A3 par groupes de 3
* Signal 1: 3,4,5
* Signal 2: 6,7,8
* Signal 3: 9,10,11
* Signal 4: 12,13,A0
* Signal 5: A1,A2,A3
* 2 addresses par signal
* paires pour les feux rouges et verts
* impaires pour les feux jaunes
*
*/
/***************************************************************************************
* CONFIGURATION SETTING
*
* MODE : LOW si le +5V des LEDs est commun, HIGH si la masse est commune
* FIRST_ID_DCC : Adresse DCC du premier signal. Avec les centrales Roco, enlever 4 à la valeur desirée
* NB_TRAFFIC_LIGHT : flag qui donne le nombre de couleurs par feu (2 ou 3)
*
****************************************************************************************/
#define MODE HIGH // LOW ou HIGH
#define FIRST_ID_DCC 206 //210-4 Première adresse DCC (pour les centrales Roco n'oubliez pas de la décaler de 4 )
#define NB_TRAFFIC_LIGHT TRICOLOR // signaux 3 couleurs
/******************************************************************************
* Parametres internes
*
********************************************************************************/
#include <DCC_Decoder.h> // Librairie Minabay
#define kDCC_INTERRUPT 0 // la broche 2 recoit les interrupts DCC
int previous_address = 0; // empêche les multiples adresses DCC
int previous_position = 2; // empêche les multiple ordres DCC
volatile boolean update_light; // décide si une mise à jour est nécessaire après une commande DCC
#define TRICOLOR 5 // 5 signaux à 3 leds
#define FIRST_PIN 3 // Broche du premier signal
#define GREEN 0 // adresse DCC/0
#define RED 1 // adresse DCC/1
#define YELLOW 2 // adresse DCC+1/0
/*********************************************************************************
* Definition des signaux
*
********************************************************************************/
struct light {
int address; // son adresse
int current_position; // green / red / yellow (vert / rouge / jaune )
int green; // broche de la LED verte
int red; // broche de la LED rouge
int yellow; // Broche de la LED jaune
boolean activation_request; // demande d'activation
};
light traffic_light[NB_TRAFFIC_LIGHT];
/********************************************************************
* Routine appelée si une requette est faite par le DCC
*
*******************************************************************/
void activation_traffic_light() {
for (int i = 0; i < NB_TRAFFIC_LIGHT; i++) // contrôle pour tous les signaux
{
if (traffic_light[i].activation_request == true) // si le signal est en attente d'activation
{
switch(traffic_light[i].current_position) // on contrôle son état actuel
{
case GREEN :{ // si c'est vert
digitalWrite(traffic_light[i].green,MODE); // allume le vert
digitalWrite(traffic_light[i].red,!MODE); // éteint le rouge
digitalWrite(traffic_light[i].yellow,!MODE); // éteint le jaune
break;}
case RED : { // si c'est rouge
digitalWrite(traffic_light[i].green,!MODE); // éteint le vert
digitalWrite(traffic_light[i].red,MODE); // allume le rouge
digitalWrite(traffic_light[i].yellow,!MODE); // éteint le jaune
break;}
case YELLOW : { // si c'est jaune
digitalWrite(traffic_light[i].green,!MODE); // éteint le vert
digitalWrite(traffic_light[i].red,!MODE); // éteint le rouge
digitalWrite(traffic_light[i].yellow,MODE); // allume le jaune
break;}
}
}
traffic_light[i].activation_request = false; // le signal est declaré mis à jour
}
update_light = false; // toutes les mises à jour sont faites
}
/*************************************************************************************
* Décodage du DCC
*
***********************************************************************************/
void BasicAccDecoderPacket_Handler(int address, boolean activate, byte data)
{
address -= 1; address *= 4; address += 1; address += (data & 0x06) >> 1; // décodage de l'adresse DCC
int led = (data & 0x01) ? GREEN : RED; // DCC/0 ou DCC/1
int traffic_light_index = address; // Index du signal
int color = led; // Couleur de la LED
boolean activation = false;
if ((address != previous_address) || ((led != previous_position) &&
(address == previous_address))){ // Si on change l'adresse ou l'état
switch (NB_TRAFFIC_LIGHT) {
case TRICOLOR : { // rappel signaux 3 couleurs
if ((address >= FIRST_ID_DCC) && (address < FIRST_ID_DCC + (2*NB_TRAFFIC_LIGHT))){
if (address%2 != 0) { traffic_light_index = address - 1; color = YELLOW;} // si l'adresse est impaire >> couleur jaune
traffic_light_index = (traffic_light_index - FIRST_ID_DCC)/2; // Index du signal
activation = true;}
break;}
}
traffic_light[traffic_light_index].activation_request = activation; // activation demandée
traffic_light[traffic_light_index].current_position = color; // cherche couleur de la LED
update_light = activation; // Mise a jour du signal demandée
}e
previous_address = address; previous_position = led; // l'activation est sauvegardée
}
/**********************************************************************************************
* setup + met les signaux au rouge au démarrage
*
*********************************************************************************************/
void setup() {
int pin_jump = 0; // variable broche
int traffic_light_jump = 0; // variable signal
for (int i=0; i<NB_TRAFFIC_LIGHT; i++){ // pour tous les signaux
traffic_light[i].activation_request = false; // pas de demande d'activation
traffic_light[i].green = pin_jump + FIRST_PIN; // Broche de la LED verte
pinMode(traffic_light[i].green, OUTPUT); // broche LED verte en sortie(ID DCC/0)
digitalWrite(traffic_light[i].green, !MODE); // LED verte éteinte
traffic_light[i].red = 1+ pin_jump + FIRST_PIN; // broche de la LED rouge
pinMode(traffic_light[i].red, OUTPUT); // broche LED rouge en sortie (ID DCC/1)
digitalWrite(traffic_light[i].red, MODE); // LED rouge allumée
traffic_light[i].address = traffic_light_jump + FIRST_ID_DCC + i; // son adresse DCC
traffic_light[i].yellow = 2+ pin_jump + FIRST_PIN; // broche de la LED jaune
pinMode(traffic_light[i].yellow, OUTPUT); // broche LED jaune en sortie (ID DCC+1/0)
digitalWrite(traffic_light[i].yellow, !MODE); // LED jaune eteinte
traffic_light_jump++; // signal suivant
pin_jump+=3; // broche suivante
}
DCC.SetBasicAccessoryDecoderPacketHandler(BasicAccDecoderPacket_Handler, true); // initialise le DCC
DCC.SetupDecoder( 0x00, 0x00, kDCC_INTERRUPT ); // son interrupt
update_light = false; // pas de modification
}
/*************************************************************************
* loop
*
******************************************************************/
void loop() {
DCC.loop(); // y-a t-il une commande DCC ?
if (update_light) {activation_traffic_light();} // si oui routine d'activation des signaux
}
|