Voir les contributions

Cette section vous permet de consulter les contributions (messages, sujets et fichiers joints) d'un utilisateur. Vous ne pourrez voir que les contributions des zones auxquelles vous avez accès.


Sujets - lebelge2

Pages: [1]
1
Le logiciel DCC++ / Logiciel DCC BaseStation avec fonction RailCom
« le: mai 09, 2024, 02:08:47 pm »
Bonjour.

J’ai modifié légèrement ce logiciel pour qu’il insère un CutOut  à la fin des trames.
Donc maintenant compatible RailCom.

Fonctionne sur Mega et Uno.

Dans DCCpp_Uno, chercher l’interruption :  ISR(TIMER1_COMPB_vect)  (Ligne 457)
Remplacer la par le code  ci-dessous.

///////////////////////////////////////////////////////////////////////////////
// NOW USE THE ABOVE MACRO TO CREATE THE CODE FOR EACH INTERRUPT

/* Suivant votre configuration matériel, modifier les Ports et Pins
 *  Dans cet example, L298N et L6203 entrées, IN1=>PB5 =>11.  IN2=>PB7=>13 (Mega)
 *  LMD18200 entrée DIR=>PB6=>12.  Brake=>PB4=>10 (Mega)
 *  Ne pas omettre les Pins en sorties.
*/
bool EndBit;
bool CutOut;
ISR(TIMER1_COMPB_vect) {
  if (CutOut == false) {
    PORTB = PORTB | B10000000;               // PB7 IN1 niveau haut
    PORTB = PORTB &= ~ B00100000;            // PB5 IN2 niveau bas
  } else                                     // CutOut:
    PORTB = PORTB | B10110000;               // IN1, IN2 et Brake (PB4)niveau haut
  DCC_SIGNAL(mainRegs, 1);                   // Vers chargement du timer1
  if (mainRegs.currentBit == 2) {            // Fin Bit Stop
    OCR1B = 450;                             // Le Bit suivant aura un niveau bas de 30µs,
    OCR1A = 7107;                            // puis un niveau haut de 418µs.
    EndBit = true;                           // Validation
  }
}

ISR(TIMER1_COMPA_vect) {
  PORTB = PORTB &= ~ B10000000;              // PB7 IN1 niveau bas
  PORTB = PORTB | B00100000;                 // PB5 IN2 niveau haut
  if (CutOut == true) {
    PORTB = PORTB &= ~ B10110000;            // Fin CutOut, pins IN1, IN2, Brake (PB4) niveaux bas
    EndBit = false;
    CutOut = false;
  }
  if (EndBit == true)
    CutOut = true;
}

Il faut activer la nouvelle interruption. (ISR(TIMER1_COMPA_vect))
A la ligne 309, écrivez :   bitSet(TIMSK1,OCIE1A);   

Testé avec Mega, Uno et L298N, doit fonctionner avec L6203
Je viens de recevoir un LMD18200 mais il est défectueux, pas testé

Bien à vous.



2
Bonjour.

J’ai modifié légèrement ce logiciel pour qu’il insère un CutOut  à la fin des trames.
Donc maintenant compatible RailCom.

Fonctionne sur Mega et Uno.

Restrictions :

Pour le Mega; Dans MotorDriver.h  la Pin 9 est imposée.
    ex: new MotorDriver(7, 9, UNUSED_PIN, UNUSED_PIN, A0, 2.99, 2000, UNUSED_PIN),
Pour l'Uno; Dans MotorDriver.h  la Pin 12 est imposée.
    ex: new MotorDriver(7, 12, UNUSED_PIN, UNUSED_PIN, A0, 2.99, 2000, UNUSED_PIN),

Trois nouvelles sorties pour les signaux (Out1, Out2, CutOut/Brake) sur PC0, PC1, PC2
 (sur Mega 35 36 37, Uno A0 A1 A2)
Bien entendu que toutes les sorties d’origines fonctionnent toujours mais sans CutOut.
Le code est extrêmement simple, les bidouilleurs pourront modifier toutes les sorties.

La modification logiciel :

Tout ce passe dans l’interruption du Timer1 :ISR(TIMER1_OVF_vect)   dans DCCTimerAVR.cpp
Il faut la remplacer par le code que je propose ci-dessous avec les défines et variables.

#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)  // MEGA
#define PINx   PINH             // Pin numéro 9 sur Mega (PH6)     
#define PinIn  6                // new MotorDriver(7, 9, UNUSED_PIN, UNUSED_PIN, A0, 2.99, 2000, UNUSED_PIN),
#define PORTx  PORTC            // Pin de sorties des signaux Out1, Out2, Brake/CutOut sur port C
#define Etat1  B00000100        // -_-_-_   Direct   Pin 35  (In1 pour type L298N, L6203, Dir pour type LMD18200)
#define Etat2  B00000010        // _-_-_-   Inversé  Pin 36  (In2 pour type L298N, L6203, Dir pour type LMD18200)
#define CutOut_ON  B00000111    // __----__          Pin 37  (BraKe Pour Type LMD08200)
#define CutOut_OFF B00000000    // ________
#else                                                           // UNO
#define PINx  PINB              // Pin numéro 12 sur Uno (PB4)
#define PinIn  4                // new MotorDriver(7, 12, UNUSED_PIN, UNUSED_PIN, A0, 2.99, 2000, UNUSED_PIN),
#define PORTx  PORTC
#define Etat1  B00000100
#define Etat2  B00000010
#define CutOut_ON  B00000111
#define CutOut_OFF B00000000
#endif

int i;
int temps;
int oldtemps;
int bitt;
uint8_t bitCount;
uint8_t DccBitVal;
volatile uint8_t dccrecState;
ISR(TIMER1_OVF_vect) {     // ISR called by timer interrupt every 58uS
  temps = (bitRead(PINx, PinIn));
  if (temps == 1)
    PORTx = Etat1;
  else
    PORTx = Etat2;
  interruptHandler();
 temps = (bitRead(PINx, PinIn));
  i++;
  if ((i % 2) == 0) {
    if (temps != oldtemps) {
      bitt += 1;
      DccBitVal = 0;
    }
    else {
      bitt += 2;
      DccBitVal = 1;
    }
    oldtemps = temps;
    if (bitt > 1) {
      bitt = 0;
      bitCount++;
      switch (dccrecState) {
        case 0:
          if (DccBitVal) {
            if (bitCount >= 10)
              dccrecState = 1;
          }
          else {
            bitCount = 0;
          }
          break;
        case  1:
          if (!DccBitVal ) {
            dccrecState = 2;
            bitCount = 0;
          }
          break;
        case 2:
          if (bitCount == 8 ) {
            dccrecState = 3;
          }
          break;
        case 3:
          if ( DccBitVal ) {
            dccrecState = 4;
          }
          else
            dccrecState = 2;
          bitCount = 0;
          break;
        case 4:
          dccrecState = 0;
          PORTx = CutOut_ON;
          delayMicroseconds(420);
          PORTx = CutOut_OFF;
      }
    }
  }
}


Dans le void setup()   (CommandStation-EX), placer le code ci-dessous.

#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)  // MEGA
  pinMode(35, OUTPUT);         // OUT 1  PC0
  pinMode(36, OUTPUT);         // OUT 2  PC1
  pinMode(37, OUTPUT);         // BRAKE  PC2
#else                                                           // UNO
  pinMode(A2, OUTPUT);         // OUT 1  PC0
  pinMode(A1, OUTPUT);         // OUT 2  PC1
  pinMode(A0, OUTPUT);         // BRAKE  PC2
#endif

Testé avec Mega, Uno et L298N, doit fonctionner avec L6203
Je viens de recevoir un LMD18200 mais il est défectueux, donc rien testé

Cablage :
Mega  =======> Bridge  Driver                 
    35  =======> In1  (Dir pour type LMD18200)
    36  =======> In2
    37  =======> Brake, seulement pour type LMD18200

  Uno  =======> Bridge  Driver                 
    A2  =======> In1  (Dir pour type LMD18200)
    A1  =======> In2
    A0  =======> Brake, seulement pour type LMD18200

Bien à vous.

3
Vos projets / RailCom: Générateur de CutOut
« le: avril 24, 2024, 02:26:08 pm »
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.

// 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
  }
}


4
Vos projets / Décodeur de locomotive multifonctions économique
« le: août 04, 2023, 10:37:08 pm »
Bonjour, cette réalisation s’inspire des travaux de Geoff Bunza .

https://forum.mrhmag.com/post/sma20-low-cost-17-channel-dcc-decoders-ver-6-01-with-soundtriggered-soundstepperdual-motorled-and-12201920

Fabrication :

Sur base d’un Arduino Pro Mini ou Micro :
On lui adjoint dos à dos une « Shield board » comprenant les composant CMS nécessaires pour réaliser un décodeur multifonctions de locomotive économique.

Caractéristiques:
- Dimensions : 33mm x 18mm
- Adresses courtes et longues
- 14, 28 ou 128 pas de vitesses
- 28 Fonctions
- Animations lumineuses.
- Module sonore MP3 externe.
- Servos (max 5)
- 2 Entrées trigger
- RailCom.
- Accélération, décélération.
- Tension de démarrage et maximale.
- Table de vitesse.
- Freinage ABC
- Modification des CV avec centrale ou moniteur série.

 .ino, fichier Gerber, liste des composants, photos etc. sur GitHub

https://github.com/Lebelge2/Loco-Decoder


lebelge2@yahoo.fr

5
Présentez vous ! / Présetation
« le: juin 20, 2023, 09:04:15 pm »
Bonjour.
Electronicien de formation,  mon hobby est le modélisme ferroviaire.
Mon réseau  mesure  +/-  3 mètres sur deux, constitué de 32 cantons entièrement RailCom.
L’électronique du réseau (Booster,  rétro signalisation) est de marque méconnue en France,  c’est du matériel allemand OpenDCC.
La signalisation BAL  3 feux est gérée par un automate Arduino Uno,.
Grâce au RailCom, les locomotives peuvent déclencher des évènements aux entrées ou sorties des cantons, par ex. allumage des phares à l’entrée des tunnels, ralentissement de vitesse au passage dans les gares, positionnement des aiguillages suivant son itinéraire programmé etc.
Ce qui m’intéresse le plus dans modélisme ferroviaire, c’est la partie électronique.
Bien à vous.

Pages: [1]