Auteur Sujet: Definir le sens de circulation pour un decodeur de fonctions embarquées.  (Lu 17521 fois)

laurentr

  • Hero Member
  • *****
  • Messages: 648
    • Voir le profil
Bonjour

En DCC existe t il un moyen de définir le sens de circulation et de l'exploiter dans l Arduino ( vers l'avant ou l’arriéré en DCC)

Ex dans un décodeur de fonction pour par exemple n éclairer que les leds blanches à l'avant et les rouges à l'arriéré en cas d activation.

Je n'ai rien trouve sur ce sujet.

Avez vous quelques pistes sur cette thématique?

Je vos bien l idée d ajouter une valeur ( CV) pour indiquer actif si AVANT ou ACTIF si ARRIÈRE ou DANS LES DEUX SENS ou INACTIF par exemple.
Mais comment trouver ce sens de circulation!...???


Je suis preneur de vos idées....

Laurent

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 3039
  • 100% Arduino et N
    • Voir le profil
Le bit 0 du CV 29 permet d'inverser ou non le sens de déplacement par rapport aux commandes DCC "avant" et "arrière"
Cordialement,
Dominique

laurentr

  • Hero Member
  • *****
  • Messages: 648
    • Voir le profil
Bonjour Dominique

Merci pour cette info très utile.

Donc pour exploiter cela il faut


1/lire le bit en question du CV 29
2/avoir un bit de sens par fonction
3/comparer les deux valeurs et si identiques on fait telle action si différent on fait telle autre?[/li][/list]


C est bien la trame à suivre?

Aurais tu un modèle de syntaxe à me proposer?

Je voudrais voir dans le code suivant ou pouvoir l'insérer car celui ci est "un rêve" de fonctionnement" à juste finaliser avec cette fonction de sens. (il était utilisé sur les barrettes que j avais présenté à Lille)

Je pense du coup devoir ajouter des CV par groupe de fonction mais cela n est en soit pas gênant des lors que tout est bien documenté.
Par ailleurs je pense qu'il faudra aussi enrichir le contenu du CV 29 tel qu'il est présent actuellement.

Cela reste néanmoins pour moi un peu au delà de mes capacités.

Si certains veulent bien s y pencher un peu....
Merci pour votre aide.

Laurent






laurentr

  • Hero Member
  • *****
  • Messages: 648
    • Voir le profil
Hello

A la réflexion je pense qu'il y a une petite astuce intéressante à exploiter.

Dans les type de fonctions de sortie possibles du programme de Geoff
il y en nativement 5 + 1 sixième qu'a ajouté Vlad. (ON/OFF, SERVO, BLINK, FADE, DBL LED.... +RANDOM)
C est la valeur qui est stockée dans les CV 30 + (i x5)) pour definir le type d usage.

L idée est ici d en définir une nouvelle ( ou une série de nouvelles) qui sera sensible au sens de circulation pour être active ou non.

J identifie les 4 états suivants:
0 OFF  (toujours inactif)
1 AVANT (actif si le véhicule se déplace vers l'avant uniquement)
2 ARRIÈRE (actif si le véhicule se déplace vers l’arrière uniquement)
3 AVANT et ARRIÈRE  (toujours actif quelque soit le sens de circulation)

On ne modifierait alors que la valeur des CV en question pour indiquer l'effet recherché.

Notre objectif étant alors par exemple en affectant à F0 les feux de fin de convoi d un fourgon on ne les active que si le véhicule se déplace vers le sens avant lorsque F0 est active.

Reste donc à créer cette brique capable de déceler le sens de circulation et les modèles complémentaires du type de  sorties.
Je pense aussi que du coup le parametrage de la CV 29 du décodeur devient aussi plus complet que la simple ventilation uniquement entre adresse courte ( CV1 et adresses longue CV17 & CV18 )

Suis je dans la bonne voie?
Cela vous semble t il adéquat?

Laurent

laurentr

  • Hero Member
  • *****
  • Messages: 648
    • Voir le profil
En complément je pense qu une astuce pour déceler le sens effectif est contenu dans les lignes de ce nouvel exemple

https://github.com/mrrwa/NmraDcc/blob/master/examples/NmraDccMultiFunctionMotorDecoder/NmraDccMultiFunctionMotorDecoder.ino


Je pense à la definition de ces éléments

uint8_t newDirection = 0;
uint8_t lastDirection = 0;
avec l extraction des info depuis

// This call-back function is called whenever we receive a DCC Speed packet for our address
void notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, [b]uint8_t Speed, DCC_DIRECTION Dir,[/b] DCC_SPEED_STEPS SpeedSteps )


la fonction d appel de lecture du décodeur de Geoff est celle ci

void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState) 
On peut j imagine la complexifier en y insérant la notion de direction... et l exploiter ensuite...

On trouve également ceci

// Setup the Pins for the Fwd/Rev LED for Function 0 Headlight
  pinMode(LED_PIN_FWD, OUTPUT);
  pinMode(LED_PIN_REV, OUTPUT);


Je vois ensuite dans l exemple cette partie tres interessante

// Handle Direction and Headlight changes
  if((lastDirection != newDirection) || (lastLedState != newLedState))
  {
    lastDirection = newDirection;
    lastLedState = newLedState;

    digitalWrite(MOTOR_DIR_PIN, newDirection);

    if(newLedState)
    {
      #ifdef DEBUG_FUNCTIONS
      Serial.println("LED On");
      #endif
      digitalWrite(LED_PIN_FWD, newDirection ? LOW : HIGH);
      digitalWrite(LED_PIN_REV, newDirection ? HIGH : LOW);
    }
    else
    {
      #ifdef DEBUG_FUNCTIONS
      Serial.println("LED Off");
      #endif
      digitalWrite(LED_PIN_FWD, LOW);
      digitalWrite(LED_PIN_REV, LOW);
    }
  }



Je pense donc que les morceaux sont présents mais pas encore complement bien assembles...

Si vous êtes inspirés pour m y aider...


Par extension on pourrait encore pousser un peu plus loin le modèle!!

J explique une piste:

Si on sait aussi identifier la "vitesse" du nombre de crans on peut alors imaginer pouvoir asservir l'activation de sortie à des paramètres.

Une application directe pourra être par exemple de faire scintiller une led  à un moment précis ( ex freinage) ou par exemple de déclancher un son ( freinage à un certain seuil...)
Les possibilités sont alors... très OPEN! enfin il me semble...

Laurent



« Modifié: mai 15, 2020, 06:03:34 pm par bobyAndCo »

bobyAndCo

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1081
  • HO avec DCC++
    • Voir le profil
Laurent,

Il faut utiliser la balise #code quand on insert du code pour que celui-ci soit plus lisible comme j'ai fait ci-dessus.

Bien à toi

laurentr

  • Hero Member
  • *****
  • Messages: 648
    • Voir le profil
Merci

Cela va améliorer la lisibilité.

On est pas trop loin du but recherché je pense.

Ltr

laurentr

  • Hero Member
  • *****
  • Messages: 648
    • Voir le profil
Hello

L information à exploiter se trouve dans le message DCC via la bibiliotheque NMRA on trouve ceci

notifyDccSpeed( Addr, AddrType, speed, dir, SPEED_STEP_128 )

La notion DIR indique la direction FOWARD (avant) ou REVERSE (arriere)

donc si je "capte tout bien" il nous faut exploiter cette information DIR d




Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 3039
  • 100% Arduino et N
    • Voir le profil
OUI c'est exactement cela   :D

Tu peux partir de l'exemple Loco_Test de cette bibliothèque pour démarrer (dans la bonne direction ;)

Cordialement,
Dominique

laurentr

  • Hero Member
  • *****
  • Messages: 648
    • Voir le profil
Hello

L information à exploiter se trouve dans le message DCC via la bibliothèque NMRA on trouve ceci


Dans NMRADCC.H

notifyDccSpeed() Callback for a multifunction decoder speed command.
 *                   The received speed and direction are unpacked to separate values.
 *
 *  Inputs:
 *    Addr        - Active decoder address.
 *    AddrType    - DCC_ADDR_SHORT or DCC_ADDR_LONG.
 *    Speed       - Decoder speed. 0               = Emergency stop
 *                                 1               = Regular stop
 *                                 2 to SpeedSteps = Speed step 1 to max.
 *    Dir         - DCC_DIR_REV or DCC_DIR_FWD
 *    SpeedSteps  - Highest speed, SPEED_STEP_14   =  15
 *                                 SPEED_STEP_28   =  29
 *                                 SPEED_STEP_128  = 127
 *
 *  Returns:
 *    None
 */
extern void    notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Speed, DCC_DIRECTION Dir, DCC_SPEED_STEPS SpeedSteps ) __attribute__ ((weak));

Et dans
NMRADCC.cpp

notifyDccSpeed( Addr, AddrType, speed, dir, SPEED_STEP_128 )

La notion DIR indique la direction FORWARD (avant) ou REVERSE (arriere)

donc si je "capte tout bien" il nous faut exploiter cette information DIR dans nos usages.

Il est un peu dommage de ne pas pouvoir avoir cette info dans la fonction notifyDccFunc sauf dans ce cas à la modifier si cela est possible. (mais peut etre pas ds le meme "mot" DCC comme source...)

En conséquence on devra croiser les résultats des info des deux fonctions pour les combiner sur l activation des sortie selon le sens de fonctionnements

Le tout dans une boucle pour que cela se balaye sur l'ensemble des N fonctions utilisées (de F0 à Fx)...

Nous progressons... sur une ébauche!.

Reste encore tout cette satanée syntaxe à produire!  :-[

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 3039
  • 100% Arduino et N
    • Voir le profil
Modifier un bibliothèque est interdit ! Sauf accord du propriétaire après proposition faite en bonne et due forme sur Github. Là je pense que ce sera refusé

Donc il vaut mieux oublier la fonction notifyDccFunc !

Mais la fonction notifyDccSpeed convient très bien et il faut s'y adapter, tout simplement
Cordialement,
Dominique

msport

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2217
  • HO avec DCC++ en DIY Réseaux très éphémères
    • Voir le profil
Il y a un temps, j'étais parvenu à extraire l'information "direction" du message DCC destiné à une locomotive avec un ATTiny :
https://forum.locoduino.org/index.php?topic=333.msg3181#msg3181
https://forum.locoduino.org/index.php?topic=556.msg6287#msg6287
Il y a certainement moyen de faire plus propre.
Cordialement

laurentr

  • Hero Member
  • *****
  • Messages: 648
    • Voir le profil
Bonjour


Je chemine toujours sur ce qui est à utiliser

Voici les pistes que je suis

Définition de nouvelles variables

// Some global state variables

//Variables pour les états de sortie des leds

uint8_t newLedStateOut0 = 0;
uint8_t lastLedStateOut0 = 0;
uint8_t newLedStateOut1 = 0;
uint8_t lastLedStateout1 = 0;
uint8_t newLedStateOut2 = 0;
uint8_t lastLedStateout2 = 0;
uint8_t newLedStateOut3 = 0;
uint8_t lastLedStateout3 = 0;
uint8_t newLedStateOut4 = 0;
uint8_t lastLedStateout4 = 0;

// rm: Il faudra autant de variables que de OUTPUTS

//Variable directionnelle

uint8_t newDirection = 0;
uint8_t lastDirection = 0;


Appel de la fonction d identification de la direction et affectation de la valeur à la variable newDirection:

// This call-back function is called whenever we receive a DCC Speed packet for our address
void notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Speed, DCC_DIRECTION Dir, DCC_SPEED_STEPS SpeedSteps )
newDirection = Dir;

Appel des fonctions utilisées sur le decodeur:

// This call-back function is called whenever we receive a DCC Function packet for our address
void notifyDccFunc(uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState)



Premier groupe à traiter:

// pour le premier groupe de fonctions 0_4 incrementation des variables selon les conditions d activation

if(FuncGrp == FN_0_4)
  {
    newLedState0 = (FuncState & FN_BIT_00) ? 1 : 0;
    #ifdef DEBUG_FUNCTIONS
    Serial.print(" FN 0: ");
    Serial.print(newLedState0);
    #endif

    newLedState1 = (FuncState & FN_BIT_01) ? 1 : 0;
    #ifdef DEBUG_FUNCTIONS
    Serial.print(" FN 0: ");
    Serial.print(newLedState1);
    #endif
 
newLedState2 = (FuncState & FN_BIT_02) ? 1 : 0;
    #ifdef DEBUG_FUNCTIONS
    Serial.print(" FN 0: ");
    Serial.print(newLedState2);
    #endif

    newLedState3 = (FuncState & FN_BIT_03) ? 1 : 0;
    #ifdef DEBUG_FUNCTIONS
    Serial.print(" FN 0: ");
    Serial.print(newLedState3);
    #endif
 
    newLedState4 = (FuncState & FN_BIT_04) ? 1 : 0;
    #ifdef DEBUG_FUNCTIONS
    Serial.print(" FN 0: ");
    Serial.print(newLedState4);
    #endif
  }
 


(QUESTION peut on utiliser une syntaxe d incrémentation type i pour ces variables? Si oui selon quelle synthaxe?
 
suite


  switch(FuncGrp)

case FN_0_4:    //Function Group 1 F0 F4 F3 F2 F1
  exec_function( 0, FunctionPin0, newLedState0>>4 ); //call for F0 to handle activating all outputs
  exec_function( 1, FunctionPin1, newLedState1);
  exec_function( 2, FunctionPin2, newLedState2>>1 );
  exec_function( 3, FunctionPin3, newLedState3>>2 );
  exec_function( 4, FunctionPin4, newLedState4>>3 );
    break;

Actualisation

// Actualisation des statuts
// Handle Direction and Headlight changes
  if((lastDirection != newDirection) || (lastLedState0 != newLedState0) || (lastLedState1 != newLedState1|| (lastLedState2 != newLedState2)|| (lastLedState3 != newLedState3)|| (lastLedState4 != newLedState4))
  {
    lastDirection = newDirection;
   
lastLedState0 = newLedState0;
lastLedState1 = newLedState1;
lastLedState2 = newLedState2;
lastLedState3 = newLedState3;
lastLedState4 = newLedState4;

QUESTION Idem ici peut on variabiliser en i ? Si oui selon quelle synthaxe?

Application du changement sur la sortie si on sait variabliser:

 switch ( cv_value ) {
      case 0:   // LED on/off in FWD direction
        ftn_queue[i].inuse = 0;
           digitalWrite(fpins[i], lastLedState[i] ? LOW : HIGH);
break;

sinon à écrire dans le détail comme ceci (ou proche de ceci)

 switch ( cv_value ) {
      case 0:   // LED on/off in FWD direction
        ftn_queue 0.inuse = 0;
           digitalWrite(fpins 0, lastLedState0 ? LOW : HIGH);
        ftn_queue 1.inuse = 0;
           digitalWrite(fpins 1, lastLedState1 ? LOW : HIGH);
        ftn_queue 2.inuse = 0;
           digitalWrite(fpins 2, lastLedState2 ? LOW : HIGH);
        ftn_queue 3.inuse = 0;
           digitalWrite(fpins 3, lastLedState 3 ? LOW : HIGH);
        ftn_queue 4.inuse = 0;
           digitalWrite(fpins 4, lastLedState 4 ? LOW : HIGH);
break;

ou un truc s en approchant...

Je suis ouvert a vos suggestions...

Laurent

bobyAndCo

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1081
  • HO avec DCC++
    • Voir le profil
C’est quand même très compliqué comme code. Je ne connais pas le contexte mais ça ne va pas être facile à débugger s’il y a des erreurs (et il y en aura) et encore moins facile à maintenir.


QUESTION Idem ici peut on variabiliser en i ? Si oui selon quelle synthaxe?

Application du changement sur la sortie si on sait variabliser:

 switch ( cv_value ) {
      case 0:   // LED on/off in FWD direction
        ftn_queue[i].inuse = 0;
           digitalWrite(fpins[i], lastLedState[i] ? LOW : HIGH);
break;


Oui d’une manière générale, il vaut mieux utiliser des tableaux quand il y a un grand nombre de valeurs qui ont la même structure :

Oui cette syntaxe sous forme de tableau est préférable :
        ftn_queue[i].inuse = 0;
        digitalWrite(fpins[i], lastLedState[i] ? LOW : HIGH);

La première ligne est issue d’une structure qui a été instanciée sous forme de tableau, la seconde il s’agit de deux tableaux simples.

Personnellement, je procède de la façon suivante avec un #define:


#define NBRE_SOUHAITE     10

// Tableaux simples :
byte fpins[NBRE_SOUHAITE];
bool lastLedState[NBRE_SOUHAITE];

for(int i = 0; i < NBRE_SOUHAITE; i++) {
  fpins[i] = i;
  lastLedState[NBRE_SOUHAITE] = LOW;
}


Pour une structure :

typedef struct {
  uint8 inuse;
  uint16 xxx;
  bool zzz;
} Ftn_Queue;

//Les instances de Ftn_Queue sont crées sous forme de tableau
Ftn_Queue ftn_queue[NBRE_SOUHAITE];


for(int i = 0; i < NBRE_SOUHAITE; i++) {
  ftn_queue[i].inuse = i;
  ftn_queue[i].xxx = 0;
  ftn_queue[i].zzz = false;
}

Quand cela est opportun, il est grandement préférable de regrouper les variables dans une structure et de faire des instances sous forme de tableaux car comme on peut le voir, le code est plus concis, plus facile à lire et à comprendre et il y aura donc moins d'erreurs potentielles.

 
   


msport

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2217
  • HO avec DCC++ en DIY Réseaux très éphémères
    • Voir le profil
Pour me permettre de suivre le débat, le but final est de faire un TCO avec le sens des trains ou simplement d'inverser des feux ?
Cordialement