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 - laurentr

Pages: 1 [2] 3 4 ... 41
16
Vos projets / Re : centrale DCC / analogique modulaire
« le: mai 02, 2024, 08:21:49 pm »
Historiquement le rapport du cout pour  passer de 2 vs 4 couches était d un rapport de 1 à 4

C'est restait plutôt stable, voir même le cout du 4 couches a baissé

A noter que le format 100mmx100mm ( 10x10cm) est moins pénalisant coté cout qu'autrefois.

En revanche les prix du port ont "explosé"!

Pour le montage c est selon... mais il y a quelques astuces pour optimiser:
respecter la taille mini du 70mmx70mm y compris avec des bords "edges" additionnels pour y parvenir.
choix de composants en évitant si possible les "extended"
garder tout ce qui est traversant à implanter soit même.( connecteurs notamment, relais,...)

en cas de petites séries rester sur des couleurs et épaisseurs "ordinaires" type 1.6mm/vert
équiper 2/5 des pcb fabriqués.

garder un oeil entre les multiples de couts des pièces et leur nombre à implanter.
enfin rester sous les 150€ pour ne pas avoir de taxes supplémentaires à devoir acquitter...

Ltr


Ltr

17
Dans l'exemple donné vous remarquerez qu'il n'est pas nécessaire de déclarer en INPUT et OUTPUT les broches.

La librairie du framework va s'en occuper tt seule comme une grande.  8)

Il peut en être différemment lorsque l'on combine des éléments plus complexes entre eux!

Voir l'exemple de code plus complet donné dans le post: https://forum.locoduino.org/index.php?topic=1707.0 pages 4 et 5.

Ltr

18
On retrouve dans ces framworks des librairies qui vont piloter des couches hardware de ces processeurs.

On peut naturellement se passer de leur apport mais il faudra dans ce cas re écrire une bonne partie de code pour piloter ces éléments hardware.

Autant bénéficier des solutions "universelles" déjà testées et approuvées par une large communauté.
Ces framework étant à présent "matures" et continue d'évoluer pour prendre en comptes des correctifs ou de nouveaux CPU.

Nous avons évoqué précédemment des composants additionnel sur ces nouvelles puces.

Nous allons en traiter 3 ici:
le "GLU LOGIC"
le "COMPARATOR"
l "EVENT"

Chacun dispose de sa bibliothèque et pour l utiliser nous ajouterons  en tête de programme:
#include "nom_de_la_librairie;h"
Maintenant de quoi retourne t il:
GLU LOGIC:
C est en fait un ensemble de portes logiques configurables à la demande.
On peut disposer sur chaque bloc logique appelé LUT de 3 entrées et d'une sortie.
Ces entrées et sorties peuvent être de différentes natures: entrée de pins, event, état d'un composant interne,...
De nombreuses combinaisons sont offertes et il est même possible dans certaines conditions de chainer ces portes logiques.

L intérêt de cette logique programmée est qu'elle est INDEPENDANTE des ressources du coeur du CPU. = elles n'utilisent pas de ressources du cœur du CPU pour fonctionner.
C est l'équivalant de composants externes placés dans la puce comme "bonus" en étant en plus très rapides, moins encombrant et donc globalement plus performant.

A titre d exemple voici un paramétrage du 3eme LUT ( 3eme bloc logique):

sur un ATTINY1626: (MEGATINY1626)

  //LOGIC LUT3:
    Logic3.enable;                                //ENABLE LUT3
    Logic3.input0 = logic::in::ac;           //AC0 level OUT : sortie du comparateur
    Logic3.input1 = logic::in::input;       //PC1 input : correspond ici à la broche PC1
    Logic3.input2 = logic::in::event_a;   //evenement_a
    Logic3.output = logic::out::enable;  //output on PIN PA5
    Logic3.truth = 0x0a;                       //table de vérité de combinaison des 3 entrées input0, 1 ,2: =10 = 0x0a ==> la sortie est a 1 quand uniquement l'entrée input2 est à 1. sinon 0

    Logic3.init();
    Logic3.start();


Cette exemple, non le plus simple, montre surtout la diversité des éléments combinables et il sera surement plus simple dans vos premières mises en œuvre de test de réaliser les exemples fournis par ces frameworks. ( NAND, AND, NOR, XOR, OR,...)

N'hésitez pas à commenter ces premiers éléments de présentation pour que nous l'enrichissions collectivement.

Ltr

19
    Bonjour

    Souvent le terme ARDUINO englobe de nombreux anspects aux frontières parfois mal connues.

    L IDE Arduino (interface de programmation)  est une interface simplifiant la réalisation du code puis son injection dans des microprocesseurs.
    Il utilise le langage C++.

    Il a permis de développer la communauté de pratiquants de l'électronique en passant de l'électronique discrète (à composants "standards"  à l'électronique programmable.

    A LOCODUINO comme ailleurs les domaine d'application sont nombreux.

    ARDUINO doit une part de son succès à la réalisation de cartes mues par un CPU microcontrôleur offrant des performances redoutables pour un prix très compétitif.

    Parmi les plus connus et souvent utilisés ici on retrouve dans la famille AVR:

    les ARDUINO UNO et MICRO équipés de la puce ATMEGA328P
    les AVR MEGA à base de CPU ATMEGA2560
    les TINY à base  de CPU ATTINYx5 comme les ATTINY85, 45, 25.[/li]


On voit ici que des chiffres apparaissent et il vont avoir un rôle pour identifier les générations de processeurs et ou leur ressources.
Sur le ATTINY85 on retrouve 8K de mémoire contre 4K seulement pour le 45 et seulement 2 pour le 25.
Le chiffre 5 étant l'indice de la série de ces processeurs.

Apparus il y a plus de 10 ans ces processeurs ont vu leur descendance s'étendre en apportant leur lot d'innovations et d'apports.

A titre d exemple de nouveaux processeurs sont aussi devenus "compatibles ARDUINO", c'est à dire programmables via l'interface IDE ARDUINO.
Les plus connus sont le LESP8266 et l'ESP32 (dans leur différentes déclinaisons)

Dans la lignée de leur ainés chez ATMEL MICROCHIP les AVR on vu la gamme complétée des AVRx:
On distingue 2 groupes de façon générale: (avec qq exceptions):
les TINY dont le nombre de broches est <=24
les "MEGA" qui ont dont un nombre de broches >24

Dans ces 2 groupes plusieurs générations se sont suivies: série 0, série 1, série 2.

On se reportera aux datasheets de chaque item pour leur caractéristiques propres.

Toutefois ces CPU disposent d'organes communs, souvent méconnus dont nous allons présenter quelques éléments utiles:
TIMER
EVENT
GLU LOGIC
COMPARATOR

Pour assurer la portabilité entre le code et le soft on a recours a des frameworks qui vont faire "en sous marin" des opérations complexes avec une mise en œuvre simplifiée.
Pour les AVRx on dispose de 3 framework selon les CPU:

AVRX MEGA série 0 : les célèbres ATMEGAx08 et X09 dont le ATMEGA4809 qui équipe les ARDUINO NANOEVERY ==>framework MEGACOREX
https://github.com/MCUdude/MegaCoreX

AVRX "TINY" pour les "petits CPU" serie 0, 1 et 2: ==>framework MEGATINYCORE
https://github.com/SpenceKonde/megaTinyCore

AVRX "MEGA" serie 0, 1, 2 avec : ==>framework DXCORE
https://github.com/SpenceKonde/DxCore

Ltr



20
Vos projets / Re : RailCom: Générateur de CutOut
« le: mai 02, 2024, 05:09:45 pm »
Hello Marc

Tu as raison la facilitera "l'adoption" et montrera la plus value de ces processeurs sur leur ainés dans le cas présent.

Je vais ouvrir un post dédié car cela sera utile en dehors de ce projet.

Je vais préparer ce qu'il faut pour mieux comprendre de quoi il retourne

J'ai profité de mes essais pour implémenter la commande externe avec gestion ad hoc de la led d'indication.
J ai du pour cela très légèrement revoir le mapping et ajouter quelques variables pour que "cela passe crème" sans voir besoin de ressources supplémentaires.

Ltr

21
Vos projets / Re : RailCom: Générateur de CutOut
« le: mai 02, 2024, 06:02:49 am »
CODE PART 4:


void setup()
{
  INIT_PINS(); //init first PINS

  //SIMPLE_AMPLIFICATOR = digitalRead(SIMPLE_AMPLIFICATOR_MODE_INPUT_PIN);
  AMPLIFICATOR_MODE = PORTC.IN & PIN4_bm; //faster

  if(AMPLIFICATOR_MODE == false)
  {   
    LED_SIMPLE_AMPLIFICATOR_MODE_PIN_OFF;

    INIT_TCB();

    INIT_ADDITIONNAL_PINS();

    //RAILCOM = digitalRead(RAILCOM_MODE_SELECTOR_INPUT_PIN);
    RAILCOM = PORTC.IN & PIN3_bm; //faster

    INIT_SYSTEM_WITH_RAILCOM();

    if (RAILCOM == false) //NO RAILCOM
    {
      //force these states out:
      LOGIC_ENABLE_OUT_PIN_ON;
      LOGIC_CUTOUT_OUT_PIN_ON;

      LED_RAILCOM_ENABLE_PIN_OFF;
    }
    else
    {
      LED_RAILCOM_ENABLE_PIN_ON;
    }
  }
  else
  {
    LED_RAILCOM_ENABLE_PIN_OFF;
    RAILCOM = false;
    LED_SIMPLE_AMPLIFICATOR_MODE_PIN_ON;
   
    INIT_SYSTEM_SIMPLE_AMPLIFICATOR();
  }

}


void loop(){

  //NOTHING TO DO! ALL IS AUTOMATIC :)

}





Plus qu'a se pencher sur un dessin de PCB pour donner vie à ce dispositif!

Ltr

22
Vos projets / Re : RailCom: Générateur de CutOut
« le: mai 02, 2024, 06:01:40 am »
CODE PART2:

void INIT_SYSTEM_WITH_RAILCOM(){

  //COMPARATOR:

  //when inverting > non inverting ==> AC OUT = high
  //measured current will be connected to inverting input (L6203 SENSE PIN trough a 10K resistor)
   
    Comparator.input_p = comparator::in_p::in1; //inverting PIN_PB5
    Comparator.input_n = comparator::in_n::in1; //non inverting PIN_PB4
    Comparator.reference = comparator::ref::disable;
    Comparator.hysteresis = comparator::hyst::disable;
    Comparator.output = comparator::out::disable; // No output pin, signal not inverted internally

    Comparator.init();
   
    Comparator.start(); // Start comparator
 
  //DEFINE CCL LUT3:
    //NEED EVENT CHANNEL FIRST TO ROUTE INSIDE LUT3: USE EVENT CHANNEL 3

    Event3.assign_generator_pin(gen3::pin_pa6);   //PIN_PA6 AS EVENT CH3 SOURCE
    Event3.set_user(user::ccl3_event_a);          //EVENT A OF LUT3

    Event3.start();

    Logic3.enable;                       //ENABLE LUT3
    Logic3.input0 = logic::in::ac;       //AC0 level OUT
    Logic3.input1 = logic::in::event_a;  //EVENT_A from EVENT CH3
    Logic3.input2 = logic::in::masked;   //not used
    Logic3.output = logic::out::disable; //NOT USED, use EVENT CH2 instead
    Logic3.truth = 0x04;     

    Logic3.init();


    Event2.assign_generator(gen::ccl3_out);
    Event2.set_user(user::evouta_pin_pa7);

    Event2.start();   
 
  //DEFINE CCL LUT0: 
    Logic0.enable;                       //ENABLE LUT0
    Logic0.input0 = logic::in::masked;   //UDPI NOT USED
    Logic0.input1 = logic::in::pin;      //PIN_PA1
    Logic0.input2 = logic::in::pin;      //PIN_PA2
    Logic0.output = logic::out::disable; //NOT USED, use EVENT CH5 instead
    Logic0.truth = 0x04;                 // Set truth table

    Logic0.init();

    Event5.assign_generator(gen::ccl0_out); //source LUT0 OUT
    Event5.set_user(user::tcb0_capt);       //route to TCB0
    Event5.set_user(user::ccl1_event_a);    //event A CCL1
    Event5.set_user(user::ccl2_event_a);    //event A CCL2

    Event5.start();

    Event1.assign_generator_pin(gen1::pin_pa3); //PA3 INPUT
    Event1.set_user(user::ccl1_event_b);        //event B CCL1
    Event1.set_user(user::ccl2_event_b);        //event B CCL2

    Event1.start();

    Logic1.enable;                        //ENABLE LUT1
    Logic1.input0 = logic::in::event_a;   //logic1 in0 event A
    Logic1.input1 = logic::in::event_b;   //logic1 in1 event B
    Logic1.input2 = logic::in::masked;    //not used
    Logic1.output = logic::out::disable;  //OUTPUT NOT USED, OUT STATE will go to EVENT CH0
    Logic1.truth = 0x01;                  // Set truth table

    Logic1.init();

    Event0.assign_generator(gen::ccl1_out);
    Event0.set_user(user::evoutb_pin_pb2);

    Event0.start();

    Logic2.enable;                        //ENABLE LUT2
    Logic2.input0 = logic::in::event_a;   //logic2 in0 event A
    Logic2.input1 = logic::in::event_b;   //logic2 in1 event B
    Logic2.input2 = logic::in::masked;    //not used
    Logic2.output = logic::out::enable;   //PIN_PB3 OUTPUT TO DRIVE L6203 IN
    Logic2.truth = 0x02;                  // Set truth table

    Logic2.init();

    Event4.set_generator(gen::ac0_out);    //source AC0 out
    Event4.set_user(user::evoutc_pin_pc2); //manage LED_SHORCUT_OVERLOAD

    Event4.start();
   
    Logic0.start();
    Logic1.start();
    Logic2.start();
    Logic3.start();

}

void INIT_SYSTEM_SIMPLE_AMPLIFICATOR(){

  //COMPARATOR:
   
    Comparator.input_p = comparator::in_p::in1;
    Comparator.input_n = comparator::in_n::in1;
    Comparator.reference = comparator::ref::disable;
    Comparator.hysteresis = comparator::hyst::disable;
    Comparator.output = comparator::out::disable_invert; // No output pin, signal inverted internally

    Comparator.init();
   
    Comparator.start(); // Start comparator

  //EVENT CH1:
    Event1.assign_generator_pin(gen1::pin_pa1);   //PIN_PA1 AS EVENT CH1 SOURCE
    Event1.set_user(user::ccl1_event_a);          //EVENT A OF LUT0
    Event1.set_user(user::ccl2_event_a);          //EVENT B OF LUT2

    Event1.start();

  //EVENT CH2:
    Event2.assign_generator_pin(gen2::pin_pa2);   //PIN_PA2 AS EVENT CH2 SOURCE
    Event2.set_user(user::ccl1_event_b);          //EVENT A OF LUT0
    Event2.set_user(user::ccl2_event_b);          //EVENT B OF LUT2

    Event2.start();

  //LOGIC LUT1:
    Logic1.enable;                       //ENABLE LUT3
    Logic1.input0 = logic::in::event_a;  //AC0 level OUT
    Logic1.input1 = logic::in::event_b;  //EVENT_A from EVENT CH3
    Logic1.input2 = logic::in::masked;   //not used
    Logic1.output = logic::out::disable; //NOT USED, use EVENT CH0 instead
    Logic1.truth = 0x04;   

    Logic1.init();

  //EVENT CH0:
    Event0.assign_generator(gen::ccl1_out);
    Event0.set_user(user::evoutb_pin_pb2);

    Event0.start();

  //LOGIC LUT2:
    Logic2.enable;                        //ENABLE LUT2
    Logic2.input0 = logic::in::event_a;   //logic1 in0 event A
    Logic2.input1 = logic::in::event_b;   //logic1 in1 event B
    Logic2.input2 = logic::in::masked;    //not used
    Logic2.output = logic::out::enable;   //OUTPUT PIN_PB3
    Logic2.truth = 0x02;                  // Set truth table

    Logic2.init();

  //LOGIC LUT3:
    Logic3.enable;                       //ENABLE LUT3
    Logic3.input0 = logic::in::ac;       //AC0 level OUT
    Logic3.input1 = logic::in::masked;   //not used
    Logic3.input2 = logic::in::masked;   //not used
    Logic3.output = logic::out::disable; //NOT USED, use EVENT CH2 instead
    Logic3.truth = 0x02;     

    Logic3.init();

  //EVENT CH3:
    Event3.assign_generator(gen::ccl3_out);
    Event3.set_user(user::evouta_pin_pa7); //L6203_ENABLE_PIN

    Event3.start();

  //EVENT CH4:
    Event4.assign_generator(gen::ac0_out);
    Event4.set_user(user::evoutc_pin_pc2);

    Event4.start();

  //START LOGIC NODES:
    Logic1.start();
    Logic2.start();
    Logic3.start();


}



CODE PART3:


void CUTOUT(bool RAILCOM_ACTIV_OR_NOT){
 
  if(RAILCOM_ACTIV_OR_NOT == false) //NO RAILCOM CUTOUT TO INSERT
  {
    //BY PASS CUTOUT: FORCE SOME PINS STATE ON:
    LOGIC_ENABLE_OUT_PIN_ON;
    LOGIC_CUTOUT_OUT_PIN_ON;

    return;
  }

  //RAILCOM ACTIV: NEED TO INSERT CUTOUT
 
  //TIMER B IS ALREADY STARTED AND CNT GO UP     
  if(TCB0.CNT < ENABLE_STOP_TIME) //< 26us
  {
    //ENABLE ON
    LOGIC_ENABLE_OUT_PIN_ON;
    while(TCB0.CNT < ENABLE_STOP_TIME) {;}; //WAIT TILL IS OVER
  }
  else if((TCB0.CNT < CUTOUT_START_TIME) && (TCB0.CNT >= ENABLE_STOP_TIME)) // >=26us & <30us
  {
    //ENABLE OFF
    LOGIC_ENABLE_OUT_PIN_OFF;
    while(TCB0.CNT < CUTOUT_START_TIME) {;}; //WAIT TILL IS OVER
  }
  else if((TCB0.CNT < CUTOUT_STOP_TIME) && (TCB0.CNT >= CUTOUT_START_TIME)) // >=30us & <484us
  {
    //MAKE CUTOUT:
    LOGIC_CUTOUT_OUT_PIN_ON;
    while(TCB0.CNT < CUTOUT_STOP_TIME) {;}; //WAIT TILL IS OVER
  }
  else if((TCB0.CNT < ENABLE_START_TIME) && (TCB0.CNT >= CUTOUT_STOP_TIME)) // >=484 us & < 488us
  {
    //STOP CUTOUT
    LOGIC_CUTOUT_OUT_PIN_OFF;
    while(TCB0.CNT < ENABLE_START_TIME) {;}; //WAIT TILL IS OVER
  }
  else if ((TCB0.CNT >= ENABLE_START_TIME)) // >=488us
  {
    //ENABLE PIN ON:
    LOGIC_ENABLE_OUT_PIN_ON;

    //CUTOUT IS OVER

  }
}


//------------------------------------------ DCC Interrupt -------------------------------------------


//------------------------------------------- ISR Timers ----------------------------------------------------
ISR(TCB0_INT_vect) {

  TCB0.EVCTRL ^= TCB_EDGE_bm;                          // Change the event edge at which we trigger
  uint16_t  delta = TCB0.CCMP;                        // Delta holds the time since the previous interrupt
  uint8_t DccBitVal;

  if ((delta >= ONE_BIT_MIN) && (delta <= ONE_BIT_MAX)) {
    if (dccHalfBit & EXPECT_ONE) {                     // This is the second part of the 1 bit
      dccHalfBit = EXPECT_ANYTHING;
      DccBitVal = 1;
    }
    else if (dccHalfBit & EXPECT_ANYTHING) {           // This is the first part of the 1 bit
      dccHalfBit = EXPECT_ONE;
      return;
    }
    else {                                             // We expected a 1, but received 0 => abort
      TCB0.EVCTRL ^= TCB_EDGE_bm;                     // Likely J/K should be changed
      dccHalfBit = EXPECT_ANYTHING;
      dccrecState = WAIT_PREAMBLE;
      dccrec.bitCount = 0;
      return;
    }
  }
  else if ((delta >= ZERO_BIT_MIN) && (delta <= ZERO_BIT_MAX)) {
    if (dccHalfBit & EXPECT_ZERO) {                    // This is the second part of the 0 bit
      dccHalfBit = EXPECT_ANYTHING;
      DccBitVal = 0;
      }
    else if (dccHalfBit & EXPECT_ANYTHING) {           // This is the first part of the 0 bit
      dccHalfBit = EXPECT_ZERO;
      return;
    }
    else {                                             // We expected a 0, but received 1 => abort
      dccHalfBit = EXPECT_ANYTHING;
      dccrecState = WAIT_PREAMBLE;
      dccrec.bitCount = 0;
      return;
    }
  }
  else {
    // We ignore other halfbits, to avoid interference with orther protocols.
    // In case railcom would be implemented, here we could detect the cutout start (26..32us)
    return;
  } 


  dccrec.bitCount++;

  switch( dccrecState )
  {
  // According to NMRA standard S9.2, a packet consists of:
  // - Preamble
  // - Packet Start Bit
  // - Address Data Byte:
  // - Data Byte Start Bit + Data Byte [0 or more times]
  // - Packet End Bit


  case WAIT_PREAMBLE:
      // The preamble to a packet consists of a sequence of "1" bits.
      // A digital decoder must not accept as a valid, any preamble
      // that has less then 10 complete one bits
      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:
    // The packet start bit is the first bit with a value of "0"
    // that follows a valid preamble. The packet start bit terminates the preamble
    // and indicates that the next bits are an address data byte
    if( !DccBitVal )                                  // a "0" bit is received
    {
      dccrecState = WAIT_DATA;
      dccrec.tempMessageSize = 0;
      // Initialise all fields
      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:
    // The next bit is either a Data Byte Start Bit or a Packet End Bit
    // Data Byte Start Bit: precedes a data byte and has the value of "0"
    // Packet End Bit: marks the termination of the packet and has a value of "1"
 
    if(DccBitVal) // End of packet?
    {
      // Complete packet received and no errors
      // we are in a CUTOUT AREA NOW
      noInterrupts(); //no new external event change the sequence actions queue above till queue is over, just add ~500ms latency on AC0 notifications
     
      CUTOUT(RAILCOM); //proceed cutout till end of it
     
      //cutout is over now, continue

      dccrecState = WAIT_PREAMBLE; //next step will be at this state

      interrupts();   
   
    }
    else  // Get next Byte   
    {
      dccrecState = WAIT_DATA;
      dccrec.bitCount = 0;                              // prepare for the next byte 
    }   
 
  break;
  }
}

ISR(AC0_AC_vect) {
 
    AC0.INTCTRL = 0; 

}




Ltr

23
Vos projets / Re : RailCom: Générateur de CutOut
« le: mai 02, 2024, 06:00:50 am »
Bonjour


J'ai comme prévu passe un peu de temps sur une implémentation "qui va bien" avec un cœur AVRx.

J ai retenu les TINY x6 de la serie 2: ATTINY426, 826 1626, 3226.
Le code est également 100% compatible avec leur dérivés x7 ATTINY 427,827,1627,3227.

Bien que désignés par le terme ATTINY il s agit de "MEGATINY" dont le cœur et les mécanismes sont plus proches des AVR Dx et ATMEGA serie 0 ( x08,x09) que des TINY historiques.

Ici on met à contribution la hard natif du chip :) ( TIMER B, LOGIC, COMPARATEUR pour la protection, EVENT pour lier le tout.)

Au final la boucle principale est ... vide de code!
 
Tout se gère via des mécanismes internes et il n'y a plus qu'à "profiter" du résultat pour piloter le pont H L6203 par ses broches ENABLE, IN1 et IN2.

Le MAPPING retenu est en commentaire dans le code ci joint avec un brochage SOIC20.

Le code va permettre de traiter 3 cas de figure:

SIMPLE BOOSTER: amplifie les signaux reçus sur les entrées PIN_PA1 et PIN_PA2, assure une protection contre les CC et surcharges.(avec sortie LED temoin,...)
Rm: Ce signal peut déjà comporter un CUTOUT RAILCOM, il sera alors reproduit.
BOOSTER GERANT LES TIMINGS SANS CUTOUT RAILCOM: on laisse ici le hard redécouper les trames pilotant le pont en H par les inputs sur PIN_PA1 et PIN_PA2.
BOOSTER AVEC CUTOUT RAILCOM: on insère le CUTOUT dans un signal en entrée sans CUTOUT sur PIN_PA1 et PIN_PA2.

A tester sans modération! :)

CODE PART1:
#include <Arduino.h>

/*
  author: LTR Laurent ROEKENS
  version v0.0.1
  last update date: 01/05/2024
*/


/*
  CUTOUT GENERATOR:

  Select mode:

  Simple BOOSTER (H bridge driven by input signals)
  BOOSTER without RAILCOM (H bridge drive by this CPU timings)
  BOOSTER WITH RAILCOM (H bridge drive by this CPU timings)

  In all modes CURRENT LIMITOR is activated (by measure on COMPARATOR AC0)

*/

/*
  HOW IS IT?:
  FROM DCC SIGNAL INPUTS IN PINS PA_PA2 & PIN_PA3:
  analyses DCC messages
  if required introduce CUTOUT at end of DCC messages with security GAP to drive L6203 H BRIDGE PINS

  use of EVENT software
  use of LOGIC hardware
  use of COMPARATOR for protection (overload/shorcut)
  use TCB0 counter in capture frequency mode
  L6203 IN1 and IN2 are driven by logic outputs 
  L6203_ENABLE_PIN is driven by logic output


// Connect the Attinyx26 as follows in SOIC20 SUPPORT:

//
//                            --------U--------
//     VCC (+5V)             -| 1 VCC   GND 20|- GND
//     LOGIC_CUTOUT_OUT_PIN  -| 2 PA4   PA3 19|- LOGIC_CUTOUT_IN_PIN
//     LOGIC_ENABLE_OUT_PIN  -| 3 PA5   PA2 18|- DCC_PIN_L
//     LOGIC_ENABLE_IN_PIN   -| 4 PA6   PA1 17|- DCC_PIN_R
//     L6203_ENABLE_PIN      -| 5 PA7   PA0 16|- UDPI
//     COMP_IN+              -| 6 PB5   PC3 15|- RAILCOM_MODE_SELECTOR_INPUT_PIN
//     COMP_IN-              -| 7 PB4   PC2 14|- LED_SHORCUT_OVERLOAD
//     L6203_IN2             -| 8 PB3   PC1 13|- LED_RAILCOM_ENABLE
//     L6203_IN1             -| 9 PB2   PC0 12|- LED_SIMPLE_AMPLIFICATOR_MODE
//     EXT_START_STOP_PIN    -|10 PB1   PB0 11|- SIMPLE_AMPLIFICATOR_MODE_INPUT_PIN
//                            -----------------

// CODE & PIN MAPPING FULY COMPATIBLE WITH ATTINYx27

*/

#include "Logic.h"
#include "Event.h"
#include "Comparator.h"

//RM: MILLIS_USES_TIMERB1

#define MaxDccSize 6                         // DCC messages can have a length upto this value

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


#define dccrecState       GPIOR0              // fast: saves 3 clock cycli, but requires a free GPIOR
#define dccHalfBit        GPIOR1              // fast
#define RAILCOM           GPIOR2              // fast
#define AMPLIFICATOR_MODE GPIOR3              // fast


//******************************************************************************************************
// Defines, definitions and instantiation of local types and variables
//******************************************************************************************************
// Values for half bits from RCN 210, section 5: http://normen.railcommunity.de/RCN-210.pdf
#define ONE_BIT_MIN                             F_CPU / 1000000 * 52
#define ONE_BIT_MAX                             F_CPU / 1000000 * 64
#define ZERO_BIT_MIN                            F_CPU / 1000000 * 90
#define ZERO_BIT_MAX                            F_CPU / 1000000 * 119


// Possible values for dccrecState
#define WAIT_PREAMBLE                           (1<<0) //WAIT_PREAMBLE = 0;
#define WAIT_START_BIT                          (1<<1) //WAIT_START_BIT = 1;
#define WAIT_DATA                               (1<<2) //WAIT_DATA = 2;
#define WAIT_END_BIT                            (1<<3) //WAIT_END_BIT = 3;

// Possible values for dccHalfBit
#define EXPECT_ZERO                             (1<<0) //EXPECT_ZERO = 0;
#define EXPECT_ONE                              (1<<1) //EXPECT_ONE = 1;
#define EXPECT_ANYTHING                         (1<<2) //EXPECT_ANYTHING = 2;

// Values for half bits from RCN 217,
#define ENABLE_STOP_TIME                        F_CPU / 1000000 * 26    // CUTOUT MIN START VALUE
#define ENABLE_START_TIME                       F_CPU / 1000000 * 488  // CUTPOUT MAX STP¨VALUE

// Value according OPEN DCC best pracitces:
#define CUTOUT_START_TIME                       F_CPU / 1000000 * 30   //4us security gap cutout at start
#define CUTOUT_STOP_TIME                        F_CPU / 1000000 * 484   //4us secutity gap cutout at stop


#define DCC_TIMER                               TCB0

#define DCC_PIN_R                               PIN_PA1  //DCC FROM R INPUT SIGNAL DRIVEN BY LUT0 IN1
#define DCC_PIN_L                               PIN_PA2  //DCC FROM L INPUT SIGNAL DRIVEN BY LUT0 IN2

//PIN_PA3:
#define CUTOUT_LOGIC_IN_PIN                     PIN_PA3 //EVENT CHANNEL 1 IN

//PIN_PA4:

#define LOGIC_CUTOUT_OUT_PIN                    PIN_PA4
#define LOGIC_CUTOUT_OUT_PIN_ON                 PORTA.OUTSET = PIN4_bm
#define LOGIC_CUTOUT_OUT_PIN_OFF                PORTA.OUTCLR = PIN4_bm

//
//RM: HARDWARE SHOULD LINK PIN_PA3 WITH PIN_PA4
//

//PIN_PA5:

#define LOGIC_ENABLE_OUT_PIN                    PIN_PA5
#define LOGIC_ENABLE_OUT_PIN_ON                 PORTA.OUTSET = PIN5_bm
#define LOGIC_ENABLE_OUT_PIN_OFF                PORTA.OUTCLR = PIN5_bm

//PIN_PA6:

#define LOGIC_ENABLE_IN_PIN                     PIN_PA6

//
//RM: HARDWARE SHOULD LINK PIN_PA5 WITH PIN_PA6
//

//PIN_PA7:
#define L6203_ENABLE_OUT_PIN                    PIN_PA7 //L6203_ENABLE_PIN

//PIN_PB2:
#define L6203_IN1                               PIN_PB2 //DRIVEN BY EVOUTB

//PIN_PB3:
#define L6203_IN2                               PIN_PB3 //DRIVEN BY LUT2 OUTPUT

#define RAILCOM_MODE_SELECTOR_INPUT_PIN         PIN_PC3 //RAILCOM SWITCH ENABLE/DISABLE

#define LED_SHORCUT_OVERLOAD_PIN                PIN_PC2 //LED INDICATOR FOR OVERLOAD OR SHORCIRCUIT

#define LED_RAILCOM_ENABLE_PIN                  PIN_PC1
#define LED_RAILCOM_ENABLE_PIN_ON               PORTC.OUTSET = PIN1_bm
#define LED_RAILCOM_ENABLE_PIN_OFF              PORTC.OUTCLR = PIN1_bm

#define LED_SIMPLE_AMPLIFICATOR_MODE_PIN        PIN_PC0
#define LED_SIMPLE_AMPLIFICATOR_MODE_PIN_ON     PORTC.OUTSET = PIN0_bm
#define LED_SIMPLE_AMPLIFICATOR_MODE_PIN_OFF    PORTC.OUTCLR = PIN0_bm

#define EXT_STOP_START_INPUT_PIN                PIN_PB1 //STOP_START_INPUT_PIN: DRIVE EXTERNAL STOP /START

#define SIMPLE_AMPLIFICATOR_MODE_INPUT_PIN      PIN_PB0 //AMPLIFICATOR MODE: SIMPLE APLIFICATOR OR TIMINGS MANAGE BY THIS HARDWARE DRIVING L6203
             

void INIT_PINS(){

  //RAILCOM_MODE_SELECTOR_PIN:
  //pinMode(RAILCOM_MODE_SELECTOR_INPUT_PIN,INPUT); //INPUT slow
  PORTC.DIRCLR = PIN3_bm; //INTPUT fast
  //PORTC.PIN3CTRL |= PORT_PULLUPEN_bm; /// use the internal pullup resistor on PC3
  PORTC.PIN3CTRL &= ~PORT_PULLUPEN_bm;  // don't use the internal pullup resistor on PC3
 

  //AMPLIFICATOR_MODE_MODE_SELECTOR_INPUT_PIN:
  //pinMode(SIMPLE_AMPLIFICATOR_MODE_INPUT_PIN,INPUT); //INPUT slow
  PORTB.DIRCLR = PIN0_bm; //INTPUT fast
  //PORTC.PIN0CTRL |= PORT_PULLUPEN_bm; /// use the internal pullup resistor on PB0
  PORTC.PIN0CTRL &= ~PORT_PULLUPEN_bm;  // don't use the internal pullup resistor on PB0

  //STOP_START_PIN:
  //pinMode(EXT_STOP_START_INPUT_PIN,INPUT); //INPUT slow
  PORTB.DIRCLR = PIN1_bm;
  //PORTB.PIN1CTRL |= PORT_PULLUPEN_bm; /// use the internal pullup resistor on PC2
  PORTB.PIN1CTRL &= ~PORT_PULLUPEN_bm;  // don't use the internal pullup resistor on PC2

  //LED_RAILCOM_ENABLE
  //pinMode(LED_RAILCOM_ENABLE_PIN,OUTPUT); //OUTPUT slow
  PORTC.DIRSET = PIN1_bm; //OUTPUT fast
  PORTC.DIRCLR = PIN1_bm; //INIT STATE OFF

  //LED_SIMPLE_AMPLIFICATOR_MODE
  //pinMode(LED_SIMPLE_AMPLIFICATOR_MODE_PIN,OUTPUT); //OUTPUT slow
  PORTC.DIRSET = PIN0_bm; //OUTPUT fast
  PORTC.DIRCLR = PIN0_bm; //INIT STATE OFF

  //LED_SHORCUT_OVERLOAD_PIN PIN_PC2
  //pinMode(LED_SHORCUT_OVERLOAD_PIN,OUTPUT); //OUTPUT slow
  PORTC.DIRSET = PIN2_bm; //OUTPUT fast
  PORTC.DIRCLR = PIN2_bm; //INIT OFF

}

void INIT_ADDITIONNAL_PINS(){
  //INIT PINS DONT MANAGED BY LUT OR YET SET:

  //LOGIC_CUTOUT_OUT_PIN:
  //pinMode(LOGIC_CUTOUT_OUT_PIN,OUTPUT); //slow
  PORTA.DIRSET = PIN4_bm; //OUTPUT fast
  PORTA.OUTCLR = PIN4_bm; //INIT STATE OFF

  //LOGIC_CUTOUT_IN_PIN:
  //pinMode(CUTOUT_LOGIC_IN_PIN,INPUT); //slow
  PORTA.DIRCLR = PIN3_bm; //INPUT fast
  //PORTA.PIN3CTRL |= PORT_PULLUPEN_bm; // use the internal pullup resistor on PA3
  PORTA.PIN3CTRL &= ~PORT_PULLUPEN_bm;  // don't use the internal pullup resistor on PA3

  //LOGIC_ENABLE_OUT_PIN
  //pinMode(LOGIC_ENABLE_OUT_PIN,OUTPUT); //slow
  PORTA.DIRSET = PIN5_bm; //OUTPUT fast
  PORTA.OUTCLR = PIN5_bm; //INIT STATE OFF

  //LOGIC_ENABLE_IN_PIN:
  //pinMode(LOGIC_ENABLE_IN_PIN,INPUT); //slow
  PORTA.DIRCLR = PIN6_bm; //INPUT FAST
  //PORTA.PIN6CTRL |= PORT_PULLUPEN_bm; /// use the internal pullup resistor on PA6
  PORTA.PIN6CTRL &= ~PORT_PULLUPEN_bm;  // don't use the internal pullup resistor on PA6

  //L6203_IN1: PB2
  //pinMode(L6203_IN1,OUTPUT); //slow
  PORTB.DIRSET = PIN2_bm; //OUTPUT fast
  PORTB.OUTCLR = PIN2_bm; //INIT STATE OFF

  //L6203_IN2:PB3: already done by LOGIC block init
  //pinMode(L6203_IN2,OUTPUT);

  //L6203_ENABLE_PIN
  //pinMode(L6203_ENABLE_OUT_PIN,OUTPUT); //OUTPUT slow
  PORTA.DIRSET = PIN7_bm; //OUTPUT fast
  PORTA.OUTCLR = PIN7_bm; //INIT STATE OFF

}

void INIT_TCB(){
  // Reset registers. See the data sheets for details
    noInterrupts();
  // Clear the main timer control registers. Needed since the Arduino core creates some presets
      DCC_TIMER.CTRLA = 0;
      DCC_TIMER.CTRLB = 0;
      DCC_TIMER.EVCTRL = 0;
      DCC_TIMER.INTCTRL = 0;
      DCC_TIMER.CCMP = 0;
      DCC_TIMER.CNT = 0;
      DCC_TIMER.INTFLAGS = 0;

  // Set values:
      DCC_TIMER.CTRLA = TCB_ENABLE_bm;
      DCC_TIMER.CTRLB = TCB_CNTMODE_FRQ_gc;
      DCC_TIMER.EVCTRL = TCB_CAPTEI_bm | TCB_FILTER_bm;
      DCC_TIMER.INTCTRL |= TCB_CAPT_bm;

    interrupts();
}





24
Vos projets / Re : centrale DCC / analogique modulaire
« le: mai 01, 2024, 07:39:46 pm »
Hello Marc

C est beau!
Y a du travail derrière!!Belle œuvre appréciable

Rm sur les utilisations: avec le retour d'expérience des satellites autonomes qui font appel à des détecteurs "ponctuels" placés aux extrémités de zone(s) via des capteurs optiques ( sortie 0-1) sur comparateur , est ce que cela  n'arrangerait il pas tes usages ? La zone pilotée par le PONT H serait alors composée d' un seul segment ("canton") et si besoin des capteurs aux extrémités viennent informer de l'occupation "locale" selon les zones ou le tain se situe en plus de la détection globale par conso au niveau "canton"?

Pour ce qui est du calcul des couts avec les NE556 ( x2)/555(x1) et les coils selon, leur nombre (5 à priori)  le cout est assez faible mais c est plus une question d encombrement qui sera probablement supérieur à ton dispositif actuel à base de diodes. et avec des montages externes pour les capteur locaux.

la SS34 est une Schottky à faible chute (mais rapide)  aussi tu risques d'avoir quelques surprises avec cette faible chute qui sera plus franche avec une diode "classique" avec un Vdrop plus haut.
.

Ltr

25
Vos projets / Re : RailCom: Générateur de CutOut
« le: avril 30, 2024, 05:46:08 pm »
Y a bien une petit ligne qui le dit:

#ifdef __AVR_ATmega328P__                    // --- Arduino AVR --
Donc oui pour le TINY pas de sujet mais si 328P /MEGA ou autre le mapping brochage est à revoir pour être sur INT0 ( PD2) comme PB2 l'est sur le TINYx5

Ltr

26
Vos projets / Re : centrale DCC / analogique modulaire
« le: avril 30, 2024, 05:43:15 pm »
Hello

Si je me souviens bien des hypothèses de départ l' idée  était de réduire le nombre de composants "externes" au delà du CPU .

Si on peut en ajouter pourquoi alors ne pas partir sur un montage externe qui dans tous les cas donnera la "vérité" sur l'occupation 0/1 de la zone en question? ( montage à diodes + opto? montage  à base de COIL, COIL +NE555/556..?)

Si on désire avoir toutes les mesures de conso local alors on acceptera de poser de petit TINY et remonter cela d une façon ou d une autre...

Pour la détection en analogique une solution peut consister à envoyer un bref temps un courant qui indiquera en retour l'état...

Ltr

27
Vos projets / Re : RailCom: Générateur de CutOut
« le: avril 30, 2024, 04:28:46 pm »
Bonjour

@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?)

Je regarde de mon cote pour porter cela sur AVRx ( MAGTINY AVRx série 0 ou 1 (Atmegax08 x09, NANOEVERY et AVR Dx ( DA DB DD)...)
Je pense cependant plus à un hardware disposant de 2 timer B dans ce lots de candidats...

Ltr

28
Vos projets / Re : RailCom: Générateur de CutOut avec booster
« le: avril 29, 2024, 05:29:11 pm »
Voici a quoi va ressembler la partie d initialisation des I/O utilisés par la circuiterie interne avec la confiuration ad hoc pour piloter le BOOSTER.

On va inclure ceci:


#include <Event.h>
#include <Logic.h>
#include <Comparator.h>


Puis en exploiter les éléments

noInterrupts();

  //define COMPARATOR IN/OUT
  #if defined(__AVR_DA__) || defined(__AVR_DB__)      //use COMPARATOR 0 (AC0)
    Comparator0.input_p = comparator::in_p::in3;      // Use positive input 3 PIN_PD6
    Comparator0.input_n = comparator::in_n::in2;      // Use negative input 2 PIN_PD7
    Comparator0.hysteresis = comparator::hyst::disable;
    Comparator0.reference = comparator::ref::disable;
    Comparator0.output = comparator::out::disable_invert; // No output pin, signal inverted internally;

    // Initialize comparator
    Comparator0.init();

    // Start comparator
    Comparator0.start();
 
  #endif

  #if defined(__AVR__DD__) //default comparator value = AC0

    Comparator.input_p = comparator::in_p::in3;      // Use positive input 3 PIN_PD6
    Comparator.input_n = comparator::in_n::in2;      // Use negative input 2 PIN_PD7
    Comparator.hysteresis = comparator::hyst::disable;
    Comparator.reference = comparator::ref::disable;
    Comparator.output = comparator::out::disable_invert; // No output pin, signal inverted internally;

    // Initialize comparator
    Comparator.init();

    // Start comparator
    Comparator.start();

  #endif

  #if defined(__AVR_ATmegax08__) || defined(__AVR_ATmegax09__) //default comparator value = AC0
    Comparator.input_p = comparator::in_p::in2;      // Use positive input 2 PIN_PD6
    Comparator.input_n = comparator::in_n::in2;      // Use negative input 2 PIN_PD7 
    Comparator.hysteresis = comparator::hyst::disable;
    Comparator.reference = comparator::ref::disable;
    Comparator.output = comparator::out::disable_invert; // No output pin, signal inverted internally;

    // Initialize comparator
    Comparator.init();

    // Start comparator
    Comparator.start();

  #endif 
 
 
  //DEFINE CCL LUT0: 
  Logic0.enable;                       //ACTIV LUT0
  Logic0.input0 = logic::in::ac;       //AC0 OUT
  Logic0.input1 = logic::in::pin;      //PIN_PA1
  Logic0.input2 = logic::in::masked;   //NOT USED
  Logic0.output = logic::out::enable;  //PIN_PA3
  Logic0.truth = 0x04;                 // Set truth table

  Logic0.init();


  Event1.assign_generator_pin(gen1::pin_pa7); //PIN_PA7 as input
  Event1.set_user(user::ccl1_event_b);        //user
  Event1.set_user(user::ccl3_event_b);        //user too
  Event1.start();                             //start event channel1

  //DEFINE CCL LUT1:
  Logic1.enable;                      //ACTIV LUT1
  Logic1.input0 = logic::in::ac;      //AC0 OUT
  Logic1.input1 = logic::in::event_a; //event_a
  Logic1.input2 = logic::in::event_b; //event_b
  Logic1.output = logic::out::enable; //PIN_PC3
  Logic1.truth = 0xc1;                // Set truth table

  Logic1.init();

  //DEFINE CCL LUT2:
  Logic2.enable = true;                 //ACTIV LUT2
  Logic2.input0 = logic::in::ac;        //AC0 OUT
  Logic2.input1 = logic::in::pin;       //PIN_PD1
  Logic2.input2 = logic::in::pin;       //PIN_PD2
  Logic2.output = logic::out::disable;  //NO OUTPUT DIRECTLY SO USE EVENT CHANNEL 0 INSTEAD
  Logic2.truth = 0x04;                  //Set truth table

  Logic2.init();

  Event0.assign_generator(gen::ccl2_out);

  #if defined(DCC_USES_TIMERB0)
    Event0.set_user(user::tcb0_capt); //route to TCB0
  #elif defined(DCC_USES_TIMERB1)
    Event0.set_user(user::tcb1_capt); //route to TCB1
  #elif defined(DCC_USES_TIMERB2)
    Event0.set_user(user::tcb2_capt); //route to TCB2
  #elif defined(DCC_USES_TIMERB3)
    Event0.set_user(user::tcb3_capt); //route to TCB3
  #else
    Event0.set_user(user::tcb0_capt); //route to TCB0 by default
  #endif


  Logic3.enable = true;                //ACTIV LUT2
  Logic3.input0 = logic::in::ac;       //AC0 OUT
  Logic3.input1 = logic::in::event_a;  //event_a
  Logic3.input2 = logic::in::event_b;  //event_b
  Logic3.output = logic::out::disable; ///NO OUTPUT DIRECTLY SO USE EVENT CHANNEL 2 INSTEAD TO ROUTE TO PIN_PF2
  Logic3.truth = 0xc4;                 //Set truth table

  Logic3.init();

  Event2.assign_generator(gen::ccl3_out);
  Event2.set_generator(event::user::evoutc_pin_pc2);

  Event3.assign_generator(event::gen::ac0_out);
  Event3.set_user(event::user::evoutf_pin_pf2);
  Event3.start();

  Logic::start(); //start all logic bloc activated


  interrupts();


Pour memo

1 TIMER B est utilisé pour la gestion du décodage des trames DCC en entrée
1 TIMER B est utilise pour un compteur interne avec les timings utilisés pour les opérations de CUTOUT
1 Comparateur (AC0)
4 LUT ( Logique programmable) pour combiner et traiter le pilotage des broches du pont H ( et des leds autours)
4 Events pour liaisonner le tout.

La partie CUTOUT va être celle ci dessous

CUTOUT_PIN et ENABLE_PIN, présentes ici  vont en fait être des pins de SORTIES LOGIQUES.
Elles ne pilotent pas directement  la broche ENABLE ou une broche CUTOUT
Elles sont utilisées en les liant à des pins d entrée des CCL LIUT: elle agiront comme signaux dans la circuiterie qui va auto réagir vers les broches de pilotage des composants  les broches réelles qui drive le L6203: ENABLE PIN, IN1 IN2 et les leds diverses.

Toute la partie CCL est hardware et ne dépend pas des cycles du CPU.
La réaction est donc (quasi) immédiate (qq nano secondes suffisent!)

Les valeurs de références sont calculées selon la vitesse du CPU ( F_CPU) ( pour les timings suivant en us: 26, 30,484,488):

#define ENABLE_STOP F_CPU / 1000000 * 26    // CUTOUT MIN START VALUE
#define ENABLE_START F_CPU / 1000000 * 488  // CUTPOUT MAX STP¨VALUE
#define CUTOUT_START F_CPU / 1000000 * 30   //4us security gap cutout at start
#define CUTOUT_STOP F_CPU / 1000000 * 484   //4us secutity gap cutout at stop



void CUTOUT(void)
  {   
    //TIMER B IS ALREADY STARTED AND CNT GO UP     
    if(TICK_TIMER.CNT < ENABLE_STOP) //< 26us
    {
      //L6203_ENABLE_PIN ON
      ENABLE_PIN_ON;
    }
    else if((TICK_TIMER.CNT < CUTOUT_START) && (TICK_TIMER.CNT >= ENABLE_STOP)) // >=26us & <30us
    {
      //L6203_ENABLE_PIN OFF
      ENABLE_PIN_OFF;
    }
    else if((TICK_TIMER.CNT < CUTOUT_STOP) && (TICK_TIMER.CNT >= CUTOUT_START)) //>=30us & <484us
    {
      //MAKE CUTOUT
      CUTOUT_PIN_ON;
    }
    else if((TICK_TIMER.CNT < ENABLE_START) && (TICK_TIMER.CNT >= CUTOUT_STOP)) // >=484 us & < 488us
    {
      //STOP CUTOUT
      CUTOUT_PIN_OFF;
    }
    else if ((TICK_TIMER.CNT >= ENABLE_START)) // >=488us
    {
      //ENABLE PIN ON:
      ENABLE_PIN_ON;

      //CUTOUT IS OVER => STOP TICK COINTER
      STOP_TICK_TIMER();
    }
  }




Le pilotage des broches IN1 et IN2 L6203_ENABLE_PIN ne passent pas par le cœur du CPU mais par les portes logique (CCL LUT) qui vont les commander selon les valeurs des tables.

Astucieux?



29
Vos projets / Re : RailCom: Générateur de CutOut
« le: avril 28, 2024, 09:12:00 pm »
De ma compréhension le SECURITY GAP intervient lorsqu'un véhicule est à cheval entre sur 2 boosters. Ceux ci pilotant des électroniques qui peuvent avoir un temps de réaction "élastique" l'un vis à vis de l'autre pour être certain de ne pas être dans un cas où l'un a déjà fini et pas l'autre, on ajoute cette temporisation ce qui pourrait avoir des effets de bords sur les décodeurs mobiles.
C est donc un temps mort de sécurité mis à chaque bout du cutout.

(on pourrait aussi avoir en tête les fameux 4us de précision de delta des AVR avec micro?)

On pourra surement voir avec un L18200 et les ponts similaires comment traiter cela.

Ltr

30
Vos projets / Re : RailCom: Générateur de CutOut
« le: avril 28, 2024, 05:17:13 pm »
Bonjour

J ai une question qui va aider la recherche d éventuels autres pont H.

D après OPEN DCC il faut insérer un "SECURITY GAP" de 4us  sur le L6203 entre son activation/désactivation ( broche ENABLE) et la commande de mise en "CC" ( via IN 1 et IN2)
Ceci est (fortement) recommandé notamment dans le cas de la présence de plusieurs boosters.

Comment gérer cela au niveau du L298 ( que je ne connais pas) ou d'autres ponts H qui ne reposent pas sur la présence de broche ENABLE? ( et donc intégrer cela au dispositif en cours de mise au point pour LABOX)

Ltr

Pages: 1 [2] 3 4 ... 41