h f
©Patrice Barthélemy 2017
ligne
Décodeur de signaux
f
Décodeur d'aiguillages
ligne

Le cahier des charges de ce type de décodeurs est simple: piloter des moteurs d'aiguillages. La réalisation s'est avérée plus complexe que prévu même si au final elle est extrèmement simple.

Après bien des essais non satisfaisants, j'ai enfin homologué une solution simple et fonctionnelle même si le setup est un peu fastidieux.

J'ai volontairement limité à 5 le nombre d'aiguillages pilotés par l 'Arduino Nano. Cette limitation permet de mieux répartir les décodeurs sur le réseau et, comme le décodeur fini ne coûte que 6,20 Euros (contre 40,00 Euros pour un décodeur Lenz LS 150) le prix n'est plus un critère.

C'est un décodeur parmi les plus simples de la série, son shéma est visible ci-dessous:

lkiuh

Le circuit imprimé est exécuté en simple face pour une question de coût.

Outre le décodeur qui renvoie les sorties sur un connecteur 20 pôles pour câble plat, il intégre 4 bus d'alimentation: DCC, 12V-dc, 18V-ac, 5V-dc.

kjzhg

Le circuit définitif (pas encore fabriqué)

poij

Le circuit est modifié pour pouvoir utiliser des servomoteurs. Seules 5 positions sont modifiées

 

 

kjh

Le circuit définitif (pas encore fabriqué)

 

 

hgjgfvu

Seules les 5 premières positions sont utilisables

 

et, le programme pour l'Arduino Nano

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Décodeur pour 5 aiguillages sur Arduino Nano
*
* Les aiguillages sont actionnés par des servomoteurs SG90
* Programme librement interprete par Babar sur la base de celui de Ruud Boer du 23 avril 2015
*
* Babar: septembre 2017
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include <DCC_Decoder.h>
#include <Servo.h>
#define kDCC_INTERRUPT 0

const byte maxservos = 5; // Nombre de servos pilotés par la carte
const byte servotimer = 10; // Vitesse du servo: plus le nombre est petit plus le servo va vite

unsigned long timetoupdatesetpoint = millis() + servotimer;

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* DEFINITION DES SERVOMOTEURS

*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

struct servoItem {
int address; // Adresse DCC du servo
byte output; // Etat du servo: 1=on, 0=off
byte angle;
byte setpoint;
byte offangle; // Position aiguillage droit
byte onangle; // Position aiguillage devié
Servo servo;
};
servoItem servos[maxservos];

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* CONFIGUTATION DES SERVOMOTEURS
* L'adresse est a definir pour chaque décodeur
* offangle et onangle permettent d ajuster finemenmt les positions
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

void ConfigureFunctionsAndServos()
{
servos[0].address = 501; // Adresse DCC du 1er servo attention enlever 4 pour les systèmes Roco
servos[0].servo.attach(3); // broche de commande du servo
servos[0].offangle = 45; // Angle du servo pour aiguillage droit à ajuster après montage
servos[0].onangle = 135; // Angle du servo pour aiguillage devié à ajuster après montage

servos[1].address = 502; // Adresse DCC du 2ème servo attention enlever 4 pour les systèmes Roco
servos[1].servo.attach(5); // broche de commande du servo
servos[1].offangle = 45; // Angle du servo pour aiguillage droit à ajuster après montage
servos[1].onangle = 90; // Angle du servo pour aiguillage devié à ajuster après montage

servos[2].address = 503; // Adresse DCC du 3ème servo attention enlever 4 pour les systèmes Roco
servos[2].servo.attach(7); // broche de commande du servo
servos[2].offangle = 45; // Angle du servo pour aiguillage droit à ajuster après montage
servos[2].onangle = 135; // Angle du servo pour aiguillage devié à ajuster après montage

servos[3].address = 504; // Adresse DCC du 4ème servo attention enlever 4 pour les systèmes Roco
servos[3].servo.attach(9); // broche de commande du servo
servos[3].offangle = 45; // Angle du servo pour aiguillage droit à ajuster après montage
servos[3].onangle = 135; // Angle du servo pour aiguillage devié à ajuster après montage

servos[4].address = 505; // Adresse DCC du 5ème servo attention enlever 4 pour les systèmes Roco
servos[4].servo.attach(11); // broche de commande du servo
servos[4].offangle = 45; // Angle du servo pour aiguillage droit à ajuster après montage
servos[4].onangle = 135; // Angle du servo pour aiguillage devié à ajuster après montage

 

} // Fin de la configuration des servomoteurs

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* DECODAGE DES COMMANDES DCC
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

void BasicAccDecoderPacket_Handler(int address, boolean activate, byte data)
{
// Conversion des paquets NMRA en langage compréhensible!
address -= 1;
address *= 4;
address += 1;
address += (data & 0x06) >> 1;

boolean enable = (data & 0x01) ? 1 : 0;

for(int i=0; i<maxservos; i++)
{
if(address == servos[i].address)
{
if(enable) servos[i].output = 1;
else servos[i].output = 0;
}
}
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* SET UP
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

void setup()
{
DCC.SetBasicAccessoryDecoderPacketHandler(BasicAccDecoderPacket_Handler, true);

ConfigureFunctionsAndServos();
for(int i=0; i<maxservos; i++)
{
servos[i].angle = servos[i].offangle; // Met les aiguillages en position "droit"
}

DCC.SetupDecoder( 0x00, 0x00, kDCC_INTERRUPT );
pinMode(2,INPUT_PULLUP);
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* BOUCLE PRINCIPALE
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

void loop()
{
static int addr = 0;

DCC.loop(); // Librairie DCC

if(++addr >= maxservos) addr = 0;


// Chaque "servotimer" ms avance le servo d'un pas (si c'est necessaire)
if (millis() > timetoupdatesetpoint)
{
timetoupdatesetpoint = millis() + servotimer;
for (int n=0; n<maxservos; n++)
{
if (servos[n].output) servos[n].setpoint=servos[n].onangle;
else servos[n].setpoint=servos[n].offangle;

if (servos[n].angle < servos[n].setpoint) servos[n].angle++;
if (servos[n].angle > servos[n].setpoint) servos[n].angle--;
servos[n].servo.write(servos[n].angle);
}
}

} //FIN de la boucle principale

 

La liste de pièces et les coûts

Décodeur
Nom Référence  Prix pièces par jeu Prix par jeu
Print décodeur 1
2,37
Bornier 2p 0,05 8
0,39
Prise cable plat 20p 0,49 1
0,49
Microcontroleur Arduino nano 1,85 1
1,85
Diode 1N4148 0,01 1
0,01
résistance 10k 0,01 2
0,01
résistance 1k 0,01 1
0,01
Dupport dip8 0,02 1
0,02
Optocoupler 6N137 0,76 1
0,76
bornier nano 0,10 2
0,19
Prix de revient
6,10
Interface
Nom Référence  Prix pièces par jeu Prix par jeu
Print interface 1
1,07
Prise cable plat 20p 0,49 1
0,49
Connecteur cable 3x 0,06 8
0,50
Prix de revient
2,06

Rappel: 1 jeu = 5 aiguillages

 

 

ligneligneligne
Décodeur d'aiguillages