Parlons Arduino > Vos projets
RailCom: Générateur de CutOut
lebelge2:
Bonjour.
Certaines centrales DCC notamment les DIY ne sont pas compatibles RailCom car ne génèrent pas le CutOut.
Ce petit montage à base, seulement d’un Arduino Uno, Nano ou Micro s’insère entre la centrale et le Booster.
Il génère le CutOut afin de la rendre compatible RailCom.
Testé sur un Booster L298N et L6203.
Si dessous, le code et le schéma.
Bien à vous.
--- Code: ---// RailCom: Programme pour insérer un CutOut dans les trames DCC. Arduino Uno, Nano, Micro.
// Testé avec Bridge Driver L6203 et L298N
// V.1.0. 24-04-24
// lebelge2@yahoo.fr
volatile uint8_t dccrecState;
volatile uint8_t tempByte;
#define WAIT_PREAMBLE 0
#define WAIT_START_BIT 1
#define WAIT_DATA 2
#define WAIT_END_BIT 3
#define MaxDccSize 6 // DCC messages can have a length upto this valu
#define PinIn1 3 // Entrée signalDcc sans CutOut
#define PinOut1 4 // Sortie signal DCC avec CutOut
#define PinOut2 5 // Sortie signal DCC inversé avec CutOut
class DccMessage {
public:
volatile uint8_t size;
volatile uint8_t data[MaxDccSize]; // The contents of the last dcc message received
} dccMessage;
struct {
uint8_t bitCount; // Count number of preamble bits / if we have a byte
volatile uint8_t tempMessage[MaxDccSize]; // Once we have a byte, we store it in the temp message
volatile uint8_t tempMessageSize; // Here we keep track of the size, including XOR
} dccrec; // The received DCC message is assembled here
struct {
uint8_t port;
uint8_t bit; // Bitmask for reading the input Port
volatile uint8_t *portRegister;
} dccIn;
void setup() {
Serial.begin(9600);
pinMode(PinIn1, INPUT);
pinMode(PinOut1, OUTPUT);
pinMode(PinOut2, OUTPUT);
init_timer2();
attachInterrupt(digitalPinToInterrupt(PinIn1), Dcc_Interrupt, CHANGE );
dccIn.port = digitalPinToPort(PinIn1);
dccIn.bit = digitalPinToBitMask(PinIn1);
dccIn.portRegister = portInputRegister(dccIn.port);
Serial.println ("SetUp OK");
}
void loop() {
}
void CutOut(void) {
delayMicroseconds(8);
asm("sbi 0x0B, 4");
asm("sbi 0x0B, 5");
delayMicroseconds(425);
asm("cbi 0x0B, 4");
asm("cbi 0x0B, 5");
}
//----------------------------------------------------------------------------------------------------------
void init_timer2(void) {
#define T2_PRESCALER 8
#define T2_PRESCALER_BITS ((0<<CS02)|(1<<CS01)|(0<<CS00))
#define T77US (F_CPU * 77L / T2_PRESCALER / 1000000L)
#if (T77US > 254)
#warning T77US too big, use either larger prescaler or slower processor
#endif
#if (T77US < 32)
#warning T77US too small, use either smaller prescaler or faster processor
#endif
noInterrupts(); // disable all interrupts
TCCR2A = 0; // should be zero for our purpose
TCCR2B = 0; // 0 => timer is stopped
TCNT2 = 256L - T77US; // preload the timer
TIMSK2 |= (1 << TOIE2); // the timer is used in overflow interrupt mode
interrupts(); // enable all interrupts
}
//----------------------------------------------------------------------------------------
void Dcc_Interrupt() {
if (digitalRead(PinIn1) == true) {
asm("cbi 0x0B, 5");
asm("sbi 0x0B, 4");
TCCR2B |= (T2_PRESCALER_BITS); // Start Timer 2
}
else {
asm("cbi 0x0B, 4");
asm("sbi 0x0B, 5");
}
}
//-----------------------------------------------------------------------------------
ISR(TIMER2_OVF_vect) {
uint8_t DccBitVal;
DccBitVal = !(*dccIn.portRegister & dccIn.bit);
TCCR2B = 0; // 0 => timer is stopped
TCNT2 = 256L - T77US; // preload the timer
dccrec.bitCount++;
switch (dccrecState) {
case WAIT_PREAMBLE:
if (DccBitVal) { // a "1" bit is received
if (dccrec.bitCount >= 10)
dccrecState = WAIT_START_BIT;
}
else
dccrec.bitCount = 0; // not a valid preamble.
break;
case WAIT_START_BIT:
if ( !DccBitVal ) { // a "0" bit is received
dccrecState = WAIT_DATA;
dccrec.tempMessageSize = 0;
uint8_t i;
for (i = 0; i < MaxDccSize; i++ )
dccrec.tempMessage[i] = 0;
dccrec.bitCount = 0;
}
break;
case WAIT_DATA:
if ( dccrec.bitCount == 8 ) { // byte is complete
if (dccrec.tempMessageSize == MaxDccSize ) { // Packet is too long - abort
dccrecState = WAIT_PREAMBLE;
dccrec.bitCount = 0;
}
else
dccrecState = WAIT_END_BIT; // Wait for next byte or end of packet
}
break;
case WAIT_END_BIT:
if ( DccBitVal ) { // End of packet?
CutOut();
dccrecState = WAIT_PREAMBLE;
}
else // Get next Byte
dccrecState = WAIT_DATA;
dccrec.bitCount = 0; // prepare for the next byte
}
}
--- Fin du code ---
trimarco232:
Bonjour,
encore une réalisation remarquable , bravo !
bobyAndCo:
Bonjour lebelge,
Je suis très intéressé et en même temps certaines choses m'étonnent.
Je comprends bien le principe adopté pour insérer le cutout à la place de certains bits du préambule. Mais encore faut il qu'il y ait assez de bits ! Si la centrale ne génère que 16 bits de préambule, ou 14 ? Avec une centrale en DIY, on peut générer le nombre de bits que l'on veut, mais une centrale du commerce ?
Par ailleurs, pour activer le transfert, il faut que le booster court-circuite la sortie pour que le décodeur envoie un courant dans la boucle ainsi créée. Or je ne vois pas comment tu réalises cela ici ? Avec un LMD18200 qui dispose d'une entrée BRAKE, c'est très simple. Sur un L603 je crois que l'on peut le faire avec la pin ENABLE1 et ENABLE1 (mais je ne vois pas cela dans ton montage). Et avec un L298N ?
Merci pour tes réponses.
Christophe
CATPLUS:
Bonjour LeBelge
Trés intéressé et voir plus, un autre ami est sur le même projet (en cours de mise au point). Pour le soft (je me garderais bien de faire une remarque, "Christophe est beaucoup plus compétent")
4 questions:
Sur le schéma, la sortie de la centrale a un seul fil via la broche "3" du Nano, la question où brancher le second fil de la centrale?
Les centrales ont 2 bornes de sorties "J & K" merci de nous donner les branchements.
En cas de court-circuit, comment réagi le montage?
Une centrale réglée pour 4 voir plus ampères, garde-t-on la puissance?
Je soupçonne que vous avez tester votre montage, auriez-vous une photo ou vidéo
Merci pour votre réponse
Marcel
trimarco232:
--- Citation de: bobyAndCo le avril 24, 2024, 11:54:39 pm ---(...) on peut générer le nombre de bits que l'on veut, mais une centrale du commerce ?
--- Fin de citation ---
je me permets de répondre , en fonction de ce que j'ai cru comprendre)
avec une centrale du commerce , il faut connaître le preamble pour savoir si c'est compatible (vous noterez le niveau de réflexion) ; en général , c'est compatible , si non c'est sniffer + scheduler , pas la même approche
--- Citer ---on peut le faire avec la pin ENABLE1 et ENABLE1 (mais je ne vois pas cela dans ton montage). Et avec un L298N ?
(...)
--- Fin de citation ---
en l'état , c'est prévu pour un IC pont en H classique , cad. 1/0 = 1/0 , 0/1 = 0/1 et , pour le cutout , 1/1 = 0/0
pour des IC ou des shields avec une entrée brake dédiée , il faut adapter/compléter le soft
Navigation
[#] Page suivante
Utiliser la version classique