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.


Messages - bobyAndCo

Pages: [1] 2 3 ... 59
1
Vos projets / Re : Re : RailCom: Générateur de CutOut
« le: avril 30, 2024, 04:32:55 pm »
@Christophe, l'adaptation pour le 328P ne devrait elle pas plutôt avoir PD2 comme entrée (INT0) pour le signal DCC ? et passer les broches de pilotage sur le PORTB ? ( PB2 ne gère pas des interruptions externes me semble t il?)

Eheuuuu, excuse moi Laurent mais je ne vois pas du tout de quoi tu parles ! Je ne crois pas que l'on ait parler de 328 ici. Ce qui est amusant c'est l'ATTiny. Je trouve ce petit montage simple et ludique, c'est tout

2
Vos projets / Re : RailCom: Générateur de CutOut
« le: avril 30, 2024, 04:25:54 pm »
Super ce petit montage. Oui ce serait sympa d'avoir les Gerber !

Est-ce que tu ne peux pas en profiter pour exposer les pins nécessaires à sa programmation ?

Merci par avance

Christophe

3
Vos projets / Re : RailCom: Générateur de CutOut
« le: avril 30, 2024, 08:27:17 am »
@lebelge : Effectivement, avec cette modification ça fonctionne avec un ATTiny45 à 8Mhz.

Sur 3 locos testées, j'en ai juste une qui, à l'arret, ne se laisse pas lire 1/3 du temps environ. Bon ça veut dire que les 2/3 du temps, ça fonctionne. En roulage, la lecture est bonne. C'est un décodeur LENZ.

Les deux autres locos, ESU et Zimo envoient sans problème leur adresse en roulage et à l'arrêt.

Du coup, je publie le code ci-dessous dans lequel j'ai ajouté les modifications et le brochage sur l'ATTiny45.

J'ai ajouté un #define pour que le code soit compatible avec les autres versions d'µC. #define ATTiny45
   Cablage :

   MEGA 6 -------> ATTiny PB2
   MEGA 7 -------> L298 EN
   ATTiny PB3 ---> L298 IN1
   ATTiny PB4 ---> L298 IN2

// RailCom: Programme pour insérer un CutOut dans les trames DCC.  Arduino Uno, Nano, Micro.  Attiny85.(Betâ)
//
// V.1.0.   24-04-24  Testé avec Bridge Driver L6203 et L298N
// V.1.1.   27-04-24  Upgrade pour Attiny85 et polarité inverse.
//
// lebelge2@yahoo.fr
//--------------------------------- Sélectionné votre  Hardware Bridge Driver------------------------------------
#define L298N           // L6203
//#define LMD18200
//----------------------------------------------------------------------------------------------

/*
   Modifié 30/04/24 par christophe bobille

   Adapté pour ATTiny45 à 8Mhz (#define ATTiny45 ligne 27)
   DCC-Ex sur Arduino MEGA / booster LN298

   Cablage :

   MEGA 6 -------> ATTiny PB2
   MEGA 7 -------> L298 EN
   ATTiny PB3 ---> L298 IN1
   ATTiny PB4 ---> L298 IN2

*/

#define ATTiny45

volatile uint8_t dccrecState;
volatile uint8_t tempByte;
bool PolariteDcc = true;
bool Brake;
unsigned long currentTime = 0;
unsigned long previousTime = 0;
unsigned long Temps;
#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 value

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;
//---------------------------------------------- SetUp -------------------------------------------------------
void setup() {
#ifdef LMD18200
  Brake = true;
#endif
#ifdef __AVR_ATmega328P__                    // --- Arduino AVR ---
#define PORTx PORTD                          // PORTD
  Serial.begin(250000);
  init_timer2();                             // Timer 2
#elif ARDUINO_AVR_ATTINYX5                   // --- ATTINY CORE ATTINY85 ---  (Micronucleus DigiSpark)
#define PORTx PORTB                          // PORTB
  init_timer1();                             // Timer 1
#else
#error "Unsupported CPU, you need to add another configuration section for your CPU"
#endif
#define PinIn PB2                               // Entrée trames Dcc sans CutOut
#define PinOut1 PB3                             // Sortie trames DCC avec CutOut           (LMD18200: Dir (sans CutOut))
#define PinOut2 PB4                             // Sortie trames DCC inversées avec CutOut (LMD18200: Brake (uniquement CutOut))
  pinMode(PinIn, INPUT);
  pinMode(PinOut1, OUTPUT);
  pinMode(PinOut2, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(PinIn), Dcc_Interrupt, CHANGE );
  dccIn.port = digitalPinToPort(PinIn);
  dccIn.bit = digitalPinToBitMask(PinIn);
  dccIn.portRegister = portInputRegister(dccIn.port);
}
//--------------------------------------------- Loop --------------------------------------------------------
void loop() {}
//------------------------------------------- Attiny 85 -----------------------------------------------------------
#ifdef ARDUINO_AVR_ATTINYX5
void init_timer1(void) {
  noInterrupts();              // disable all interrupts
  TCCR1 = 0;                   // B0 à B3: diviseur par 1, 2, 4, 8
#ifdef ATTiny45
  TCNT1 = 102;                 // preload the timer for ATTiny45 (8 Mhz)
#else
  TCNT1 = 112;                 // preload the timer
#endif
  TIMSK = 4;                   // the timer is used in overflow interrupt mode
  interrupts();                // enable all interrupts
}
//--------------------------------------------- AVR ---------------------------------------------------------
#elif __AVR_ATmega328P__
void init_timer2(void) {
  noInterrupts();              // disable all interrupts
  TCCR2A = 0;                  // should be zero for our purpose
  TCCR2B = 0;                  // 0 => timer is stopped
  TCNT2 = 102;                 // preload the timer
  TIMSK2 |= 1;                 // the timer is used in overflow interrupt mode
  interrupts();                // enable all interrupts
}
#endif
//----------------------------------------------------------------------------
void CutOut() {
  if (PolariteDcc == false) {        // Si DCC inversé,
    delayMicroseconds(38);           // retarder CutOut d'un demis-bit
    PORTx = PORTx | B00001000;
    PORTx = PORTx &= ~ B00010000;
    delayMicroseconds(20);
  }
  delayMicroseconds(8);
  PORTx = PORTx | B00010000;
  PORTx = PORTx | B00001000;
  delayMicroseconds(430);
  PORTx = PORTx &= ~ B00001000;
  PORTx = PORTx &= ~ B00010000;
}

//------------------------------------------ DCC Interrupt -------------------------------------------
void Dcc_Interrupt() {
#ifdef __AVR_ATmega328P__
  if ((bitRead(PIND, PinIn)) == 1) {                // bitRead en 3µs,    digitalRead en 7µs
    TCCR2B |= 2;                                    // Start Timer 2
#elif ARDUINO_AVR_ATTINYX5
  if ((bitRead(PINB, PinIn)) == 1) {
#ifdef ATTiny45
    TCCR1 |= 3;                                     // Start Timer 1
#else
    TCCR1 |= 4;                                     // Start Timer 1
#endif
#endif
    if (Brake == false)
      PORTx = PORTx &= ~ B00010000;                 // Temps d'exécution de ces instructions:
    PORTx = PORTx | B00001000;                      // 0,125µs en ASM,    0,170µs en C,      6µs en C++
  }
  else {
    if (Brake == false)
      PORTx = PORTx | B00010000;
    PORTx = PORTx &= ~ B00001000;
  }
  if (dccrecState == WAIT_START_BIT)  {           // L'intervalle de temps après le préambule est évalué,
    Temps = micros();
    previousTime = Temps - currentTime;
    currentTime = Temps;                          // si l'écart entre le dernier et le premier zéro est de 116 µs,
    if (previousTime > 90)                        // alors le signal est reconnu dans la bonne phase.
      PolariteDcc = true;                         // Polarité correcte
    else
      PolariteDcc = false;                        // Polarité inversée
  }
}

//------------------------------------------- ISR Timers ----------------------------------------------------
#ifdef __AVR_ATmega328P__
ISR(TIMER2_OVF_vect) {
  TCCR2B = 0;                                    // 0 => timer is stopped
  TCNT2 = 102;                                   // preload the timer. Fr. 16Mhz
#elif ARDUINO_AVR_ATTINYX5
ISR(TIMER1_OVF_vect) {
  TCCR1 = 0;                                     // 0 => timer is stopped
  #ifdef ATTiny45
  TCNT1 = 102;                 // preload the timer for ATTiny45 (8 Mhz)
#else
  TCNT1 = 112;                                   // preload the timer.  Fr. 16,5Mhz
#endif
#endif
  uint8_t DccBitVal;
  DccBitVal = !(*dccIn.portRegister & dccIn.bit);
  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 / Re : Re : RailCom: Générateur de CutOut
« le: avril 29, 2024, 08:59:32 am »
Bonjour à tous,

Retour d’expérience :

Avec l’Arduino Nano comme dit dans mes précédents messages, lecture parfaite des adresses de locomotives.

Configuration : Centrale DCC-Ex sur MEGA – Montage « leBelge » sur Nano – L298N

Malgré tout, de nombreuses trames sont hors des normes NMRA, 1/3 environ mais ça fonctionne. Voir copie d'écran en PJ.

Avec l’ATTiny45, je n’ai aucun résultat ! Les décodeurs refusent d’envoyer leur adresse. J’ai modifié les délais comme suggéré par lebelge mais les locos ne se laissent plus piloter ou refusent de bouger !!!

j’ai ajusté les tempos.
Dans la void CutOut()
Remplacer le delayMicroseconds(38) par 36 et le delayMicroseconds(20)  par 24

J’ai essayé d’autres valeurs mais cela ne change rien.

Je ne pense pas avoir de problème de câblage (lebelge ne m’a pas répondu sur ce point)

MEGA 6 -------> ATTiny PB2
MEGA 7 -------> L298 EN
ATTiny PB3 ---> L298 IN1
ATTiny PB4 ---> L298 IN2

J’ai réglé l’horloge à 8Mhz (internal), c'est normalement cela non ?

Quelqu’un a une idée du problème, ou mieux, de la solution ?

Christophe

5
Discussions ouvertes / Re : La Cockerill au travail
« le: avril 29, 2024, 08:43:23 am »
Oui c'est vraiment du beau travail. Est-ce que tu partageras le moyen de réaliser cette grue ?

6
Vos projets / Re : RailCom: Générateur de CutOut
« le: avril 28, 2024, 02:48:19 pm »
@lebelge : J'ai moins de succès avec l'ATTiny !!!

Toutes les commandes DCC fonctionnent mais je n'ai aucune réponse du décodeur.

Configuration : MEGA avec DCC-Ex / L298 / ATTiny45

Peut-être un problème de câblage ?

MEGA 6 -------> ATTiny PB2
MEGA 7 -------> L298 EN
ATTiny PB3 ---> L298 IN1
ATTiny PB4 ---> L298 IN2

Une idée de solution ???

Christophe

7
Vos projets / Re : Re : RailCom: Générateur de CutOut
« le: avril 28, 2024, 07:49:35 am »
J'arrive un peu après la bataille... désolé

Toutefois je vous présente le "petit dernier".

Bonjour Laurent, bonjour à tous.

Tout d’abord bravo à toi aussi Laurent pour cette réalisation. Je trouve que Locoduino est un sacré incubateur de propositions très sympatiques.

Il est important de préciser que ta proposition et celle du belge, bien qu’ayant toutes les deux le même objectif, ont des applications différentes.

Pour le belge, le montage se place entre la partie logicielle, par exemple un MEGA avec DCC-Ex et un booster

Dans ton cas, ton montage se place à la sortie d’une centrale avec booster (cas d’une centrale du commerce par exemple), génère un nouveau signal DCC avec cutout et l’envoie dans un nouveau booster, ici un L6203.

Ce qui fait que dans le premier cas nous n'avons besoin que d'un Nano/Uno voire même un ATTiny85 alors que dans le second, on reconstruit une centrale au moins pour la partie HardWare.

L'un et l'autre montages répondent à des contraintes différentes.

Il est probable pour éviter toute confusion que je séparerai les deux sujets dont les domaines d’application ne sont pas les mêmes.

Christophe

8
Vos projets / Re : Re : RailCom: Générateur de CutOut
« le: avril 28, 2024, 07:30:30 am »
Attention que dans cette version (V.1.1)
Entrée Dcc      Pin 2  (Sur Uno)
Out1              Pin 3
Out2              Pin 4

Le cablage:
MEGA 5 ou 6 -------> UNO 2
MEGA 7 ------------> L298 EN1
UNO 3 -------------> L298 IN2
UNO 4 -------------> L298 IN1

Oups, je m'ai gouré en effet. J'avais pris une photo et avec l'erreur de parallaxe j'ai décallé les broches. Du coup, j'ai modifié dans mon post au dessus

9
Vos projets / Re : RailCom: Générateur de CutOut
« le: avril 27, 2024, 10:35:23 pm »
Bonsoir à tous,

@lebelge : Bravo, je viens de tester la version 1.1 sur un MEGA avec DCC-EX et un L298 La détection Railcom fonctionne nickel !

Dans mon cas il a cependant fallu que je mette IN1 du L298 sur la pin 6 du Uno.

Je n'ai pas eu besoin de modifier le nombre de bits du préambule qui est donc resté à 16 (réglage par défaut de DCC-Ex)

Les réglages pour la carte L298 dans DCC-Ex sont les suivants :

#define MY_MOTOR_SHIELD F("L298"),\
  new MotorDriver(7, 6, 5, UNUSED_PIN, A0, 2.99, 2000, UNUSED_PIN), \
  new MotorDriver(2, 4, 3, UNUSED_PIN, A1, 2.99, 2000, UNUSED_PIN)

Le câblage dans mon cas est donc celui-ci.

MEGA 6 -------> NANO 2
MEGA 7 -------> L298 EN1
NANO 3 -------> L298 IN2
NANO 4 -------> L298 IN1

Demain je vais tester le même montage mais en remplaçant le MEGA par un ESP32 pour me mettre dans les conditions les plus proches de laBox.

Je crois que j’ai des ATTiny85 dans mon bazar, je ferai aussi alors le test.

Et enfin, comme j’ai aussi des L6203 et si j’ai le temps je remplacerai le L298.

Voilà un chantier important qui a sans doute trouvé sa solution.

Restera cependant la question des centrales sur lesquelles on ne peut pas s’intercaler entre le µC et le booster !!!

Christophe





10
Vos projets / Re : RailCom: Générateur de CutOut
« le: avril 27, 2024, 12:57:37 pm »
Ok. Pour le LMD18200, tu as peut-êtr vu que j'ai effectivement ajouté la broche BRAKE. Ca fonctionne nickel !

11
Vos projets / Re : RailCom: Générateur de CutOut
« le: avril 27, 2024, 12:51:41 pm »
Merci vraiment une nouvelle fois.


Evolution du soft , maintenant accepte les deux polarités.
Fonctionne aussi avec un  Attiny85


Est-elle disponible cette évolution ???

12
Vos projets / Re : Re : RailCom: Générateur de CutOut
« le: avril 27, 2024, 09:28:47 am »
Bonjour Marc, bonjour à tous,

Je te rejoins totalement sur l’ensemble des points que tu soulignes.

- ne pas toucher au code DCC-EX , dès qu'il a assez de bits pour le préamble

Tu as montré où il était possible de modifier le nombre de bits de préambule dans DCC-Ex, il faudra si nécessaire faire une petite entorse  au principe de ne pas modifier le programme original ou trouver une astuce pour contourner.

- choisir un attiny412 (8 broches , récent) , prévoir le téléversement par l'ESP32 , mais aussi et d'abord par un connecteur externe , sur lequel on pourra brancher un convertisseur USB <-> série , que tout le monde a ; l'un ou l'autre composant supplémentaire nécessaire (résistance , diode) étant aussi à ajouter sur la carte

C’est aussi à mon avis la meilleure solution. A tester, je vais essayer de m’y coller dans la semaine ou les 15 jours à venir.

utiliser le code de lebelge2 , vu qu'il existe et qu'il fonctionne (le code) ; je n'ai pas non plus compris le problème de l'inversion du signal (l'opposé de l'inverse étant identique à la même chose)

J’espère que le belge va nous apporter une réponse sur ce point, sinon je vais essayer au cours du WE de trouver le problème (s’il y en a un) et la solution concernant DCC-Ex.

Par ailleurs, je suis très intéressé par ce que tu appelles le point n°3 pour un autre sujet :

3) décoder , à la manière d'un sniffer , le DCC issu de l'ESP32 , puis le reproduire

C’est un sujet sur lequel nous travaillons à quelques-uns. Si tu as déjà des choses réalisées, cela est très intéressant. L’objectif est de capter l’ensemble des trames DCC qui circulent sur le bus et, au travers d’une passerelle, envoyer ces trames sur un bus CAN pour par exemple permettre à un gestionnaire mais aussi tout autres appareils de connaitre « au plus près » l’état du réseau.

Je m’explique avec un exemple concret. La Box (basée sur DCC-Ex) sait retourner une confirmation de réception de commande, soit en CAN (les méthodes CAN revoyant un accusé de réception pour chaque commande) soit en TCP (WiFi, Ethernet) à l’appareil qui a envoyé cette commande. Mais dans ce dernier cas, seul l’appareil à l’origine de la commande reçoit la confirmation. Par exemple smartphone avec une appli Z21. Mais pas le gestionnaire de réseau par exemple. En cherchant à faire une diffusion CAN des commandes du bus DCC, on rend les informations accessibles à tous.

Donc si tu as déjà des solutions, je suis bien évidement très intéressé. Je vais créer un fil à part pour ne pas interférer avec celui-ci.

Bon week-end  tous

Christophe

13
Vos projets / Re : RailCom: Générateur de CutOut
« le: avril 26, 2024, 10:43:06 am »
Merci Marc pour les perspectives que tu apportes.

Dans le cas de laBox qui s’adresse à un public sans compétences particulières, je pense qu’il ne faut pas modifier DCC-Ex. Je pense principalement aux MAJ, car on oublie vite que l’on avait changé tel ou tel paramètre, modifié telle ou telle configuration.

Par ailleurs, les trames générées par DCC-Ex sont parfaites !

L’idée de téléverser le soft à partir de l’ESP32 est vraiment intéressante. Pas certain qu’il faille utiliser la même broche pour le téléversement et la liaison série. Il faudra il est vrai ajouter du code dans DCC-Ex pour cela (avec les précautions de MAJ dont je parlais). Je vois bien une commande en synthaxe DCC++, <xx> qui lancerait le processus !!!

Je parle ATTiny ou AVR car c’est ce qui est le plus compatible avec l’environnement Arduino en programmation. Et celui dont je connais le mieux la manipulation des ports  ;D

Il reste à adapter le programme du belge à l’ESP32 et surtout à DCC-Ex, j’avoue ne pas avoir bien compris l’histoire des trames inversées.

Il y a aussi une demande d’adaptation pour placer ce montage, non plus derrière une centrale sans booster, mais derrière un booster.

14
J'ai construis mon réseau sur Rocrail et je suis arrivé à le faire fonctionner avec sa centrale virtuelle. Le step suivant pour moi était de connecter la centrale DCC++ en Port série. J'y suis arrivé mais là tout se complique.

Ok, ça se complique mais qu'est-ce qui ce complique à part tout ??? Pas évident de t'aider si tu es si peu précis sur les problèmes que tu rencontres.

RocRail est pourtant simple à configurer avec DCC++ : https://wiki.rocrail.net/doku.php?id=dccpp:dccpp-fr

Je l'utilise également en 3R avec CC-Schnitte relié à l’un des ports USB et à une Geiltsbox de Marklin : https://forum.3rails.fr/t/homemade-marklin-creation-dun-circuit-intelligent/13574/25

Et ça fonctionne très bien.

Est-ce que tu as lu l'article de Michel ? : https://www.locoduino.org/spip.php?article306

Merci d'envoyer précisions et copies d'écrans où il y a des problèmes

Christophe

15
Vos projets / Re : RailCom: Générateur de CutOut
« le: avril 26, 2024, 09:17:26 am »
Bonjour Marcel,

Je n'ai pas beaucoup de temps disponible aujourd'hui mais les équivalence de broche sont dans le commentaire en début du code modifié ci-dessous. Normalement tu vas t'y retrouver sans problème.

Le code ci-dessous est à copier sur un Nano par exemple. Sur le MEGA qui sert de centrale, j'ai copié le code original de DCC++ qui a 22 bits de préambule : https://github.com/DccPlusPlus/BaseStation

Je n'ai pas le temps de faire les tests avec moins de bits dans le préambule, à voir par la suite.

Je précise bien, mais ça ce voit dans le cablage, que le UNO est directement derrière le MEGA et avant le LMD. Cette solution ne convient pas derrière un booster. A voir par la suite.


// RailCom: Programme pour insérer un CutOut dans les trames DCC.  Arduino Uno, Nano, Micro.

// V.1.0.   24-04-24
// lebelge2@yahoo.fr

/*
Modifié pour LMD18200 le 26/04/24

Testé à partir de DCC++ version originale téléchargé sur Arduino MEGA : https://github.com/DccPlusPlus/BaseStation
Ce code téléchargé sur un Arduino Nano.

Cablage :

  MEGA 3 ------> LMD18200 PWM
  MEGA 12 -----> NANO 3
  NANO 4 ------> LMD18200 DIR
  NANO 6 ------> LMD18200 BRAKE
  MEGA GND ----> NANO GND
  MEGA GND ----> LMD18200 GND

*/

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
#define PinBrake 6                           // Sortie signal brake

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(115200);

  DDRD = DDRD | B01110000;  // pin 3 -> input, pin 4 à 6 -> output
  init_timer2();
  attachInterrupt(digitalPinToInterrupt(PinIn1), Dcc_Interrupt, CHANGE );
  Serial.println ("SetUp OK");
}

void loop() {}

void CutOut(void) {
  delayMicroseconds(8);
  PORTD = PORTD | B01010000;
  PORTD = PORTD &= ~ B00100000;
  //
  delayMicroseconds(425);
  PORTD = PORTD | B00100000;
  PORTD = PORTD &= ~ B01010000;
}
//----------------------------------------------------------------------------------------------------------
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 ((PIND & 0x04) >> 2) {
    PORTD = PORTD | B00010000;
    TCCR2B |= (T2_PRESCALER_BITS);  // Start Timer 2
  }
  else {
    PORTD = PORTD &= ~ B00010000;
  }
}
//-----------------------------------------------------------------------------------
ISR(TIMER2_OVF_vect) {
  uint8_t DccBitVal = !(PORTD & (1 << 4));
  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
  }
}

Pages: [1] 2 3 ... 59