Auteur Sujet: Question mise en place CAN dans la centrale DCC  (Lu 15645 fois)

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 3041
  • 100% Arduino et N
    • Voir le profil
Re : Question mise en place CAN dans la centrale DCC
« Réponse #15 le: janvier 08, 2024, 11:52:42 pm »
@ becbunsen, votre projet correspond bien à ce que peut apporter la solution de Christophe qui est très motivé et vous aidera.
Ce réseau étagère sera une belle réussite.  ;D
Cordialement,
Dominique

becbunsen

  • Newbie
  • *
  • Messages: 46
    • Voir le profil
Re : Re : Question mise en place CAN dans la centrale DCC
« Réponse #16 le: février 05, 2024, 12:10:55 pm »
N'hésite surtout pas à revenir vers moi pour plus d'explications comme par exemple la mise en œuvre concrète. Par ailleurs pour la gestion du petit réseau que tu envisages, je t'invite à suivre ce que je publie sur les satellites autonomes sur le forum et sans doute bientôt sous forme d'articles.

Bon courage

Christophe

Bonjour,
Je me permet donc de revenir vers toi, Je réitère d'ailleurs mon admiration devant tout le travail effectué quand je parcours le code....
Pour la partie message CAN, j'ai bien parcouru les fichiers .cpp et .h , assez compliqué de s'y retrouver.
Un peu plus abordable en regardant le code qui envoie automatiquement des ordres à la centrale mais je ne comprend pas tout quand même:
Par contre, jai passé un peu de temps avec la bibliotheque ACAN et je visualise assez bien la structure d'un message.
Pourrais tu m'indiquer quelle structure de données a tu choisis pour commander Labox?

Par exemple, pour controler une loco,  tu ecris

CanMsg::sendMsg(0, cmde, resp, loco->address & 0xFF00, loco->address & 0x00FF, loco->speed, loco->direction);

Pourrais tu expliquer un peu en détail?
-0

-cmde : adresse d'envoi qui défini le type de message et sa priorité? ( controle loco, fonction loco, arret d'urgence,....) 

-resp : reponse mais pas bien compris

- je n'ai pas compris les adresse locos et pourquoi 2 datas

-speed/direction OK

Ou tout simplement si je veux controler la loco 5 à vitesse 25 en avant sans passer par la programmation objet comme dans la box: que dois-je ecrire :

ACANSettings settings (125 * 1000) ; // 125 kbit/s
CANMessage message ;
message.id = 0x...    correspond à cmde?
message.data[?] ???

Merci beaucoup de votre aide.
J'admire le travail logiciel dans la box mais je n'ai pas le niveau pour l'assimiler. j'aimerai juste pouvoir programmer mes "satellites" à mon niveau et controler la box.
L'une de mes premieres idées était de placer un arduino à coté de Labox, qui reçoit des messages CAN et qui les aurait traduit en commande série. mais c'est un peu dommage alors que le CAN est intégré à Labox

bobyAndCo

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1083
  • HO avec DCC++
    • Voir le profil
Re : Re : Re : Question mise en place CAN dans la centrale DCC
« Réponse #17 le: février 05, 2024, 04:12:10 pm »
Pour la partie message CAN, j'ai bien parcouru les fichiers .cpp et .h , assez compliqué de s'y retrouver.
Un peu plus abordable en regardant le code qui envoie automatiquement des ordres à la centrale mais je ne comprend pas tout quand même:
Par contre, jai passé un peu de temps avec la bibliotheque ACAN et je visualise assez bien la structure d'un message.
Pourrais tu m'indiquer quelle structure de données a tu choisis pour commander Labox?

Par exemple, pour controler une loco,  tu ecris
CanMsg::sendMsg(0, cmde, resp, loco->address & 0xFF00, loco->address & 0x00FF, loco->speed, loco->direction);
Pourrais tu expliquer un peu en détail?
-0
-cmde : adresse d'envoi qui défini le type de message et sa priorité? ( controle loco, fonction loco, arret d'urgence,....) 
-resp : reponse mais pas bien compris
- je n'ai pas compris les adresse locos et pourquoi 2 datas
-speed/direction OK

Bonjour becbunsen,

Je te remercie de poser ces questions car je suis certain que d’autres sont comme toi mais n’osent pas poser ces questions. C’est dommage, le CAN n’est pas aussi compliqué qu’il n’y parait à condition de passer le temps nécessaire à le comprendre.

Le CAN, c’est une partie matérielle et surtout, ce qui va vous intéresser ici, une messagerie. Je vais me risquer à prendre l’analogie d’une phrase dans le langage courant. Phrase qui doit respecter une certaine structuration pour être comprise par celui ou ceux à qui elle est destinée.

La trame CAN est en quelque sorte à la communication CAN ce que la phrase est au langage avec un sujet, un verbe un complément d’objet direct…

Fondamentalement la trame CAN se divise en un identifiant (sur 11 ou 29 bits) et un champ de données dont la taille totale peut atteindre 64 bits (ou 8 octets) et que l’on divise souvent en 8 champs de 8 bits : data[0], data[1], data[n]

On est libre du nombre de champ data que l’on envoie selon nos besoins, dans certains cas on peut même n’envoyer aucune data ou jusqu’à 8 champs de 8 bits.

Le champ d’identification du message sur 11 ou 29 bits est totalement libre dans sa construction et c’est ce qui le rend parfois difficile à comprendre.

La principale règle est que, pour des questions de priorité de distribution sur le bus et de gestion des conflits entre messages qui arrivent en même temps sur le bus, ce sont les messages qui ont les identifiants les plus faibles qui sont prioritaire sur les autres.

Ainsi, le message qui aurait pour identifiant 1 est prioritaire sur l’identifiant 536 870 912 (29 bits à 1).

Si je reprends mon analogie avec le langage, il va falloir passer un peu de temps pour structurer intelligemment les informations que l’on va placer dans l’identifiant et l’ordre dans lequel on va placer ces informations.

Dans le code que j’ai proposé, on trouve cela illustré ici :

  uint16_t hash = 0x1801;

  frame.id |= prio << 25;  // Priorite
  frame.id |= cmde << 17;  // Commande
  frame.id |= resp << 16;  // Reponse : Commande = 0 / Reponse = 1
  frame.id |= hash;        // Hash
  frame.ext = true;

frame.id, dans la bibliothèque ACAN_ESP32 correspond à l’identifiant

J’ai choisi que la priorité des messages tiendrait sur 4 bits et aurait pour valeur 0 (car pour moi les messages à la centrale sont plus prioritaires que les autres sur le bus) et je place cette valeur à la position 25 sur les 29 bits de l’identifiant (que j’ai choisi long).

frame.id |= prio << 25;  // Priorite
Position 25 plus longueur de priorité 4 bits remplissent bien les bits 25 à 29 de l’identifiant

J’ai ensuite décidé que les bits qui seront lu comme des bits pour identifier quelles commandes de locomotives allaient être exécutés viendraient se positionner à partir du bit 17 de l’identifiant et tiendraient sur 8 bits.

Concernant l’information de réponse dont tu parles, j’ai jugé que cette information était très intéressante pour savoir s’il s’agissait d’une commande envoyée bit 16 à 0) ou si c’était une réponse de la centrale qui confirme qu’elle a bien reçue la commande (bit 16 à 1). Dans ce cas, la centrale confirme la réception en revoyant un message en tout point identique à celui reçu mais en changeant seulement la valeur du bit 16. Une sorte d’accusé de réception.

Nous verrons cela en détail un peu plus loin.

Enfin, les 16 derniers bits de poids faible de l’identifiant, j’ai choisi de les remplir avec une valeur choisie arbitrairement mais qui souvent est l’ID du nœud CAN qui expédie le message. Ici, j’ai choisi uint16_t hash = 0x1801;

Enfin, deux derniers points, avec la bibliothèque ACAN_ESP32, c’est au programmeur d’indiquer si l’identifiant est sur 29 (frame.ext = true;) ou sur 11 bits (frame.ext = false;). Ext pour extended frame format.

Le programmeur doit aussi renseigner la longueur du champ de données frame.len (en octets).

Si l’on se place maintenant dans la position du récepteur du message, c’est ce que l’on trouve dans le fichier CommandStation-EX-LaBox2/CanMsg.cpp

On voit tout d’abord que l’on « décode » l’identifiant :

if (ACAN_ESP32::can.receive(frameIn))
  {
    const uint8_t cmde = (frameIn.id & 0x1FE0000) >> 17; // Commande
    const uint8_t resp = (frameIn.id & 0x10000) >> 16;   // Commande = 0 / Reponse = 1
    const uint16_t hash = (frameIn.id & 0xFFFF);         // Hash

ensuite, sans entrer dans les détails, on voit que selon la commande envoyée (switch(cmde)), on execute l’une ou l’autre des fonctions internes à la box :

switch (cmde) // Fonction appelée
      {
      case 0xF0:
        DCC::setThrottle(loco, frameIn.data[2], frameIn.data[3]);
        xQueueSendToBack(xQueue, &frameIn, 0);
        break;
      case 0xF1:
        DCC::setFn(loco, frameIn.data[2], frameIn.data[3]); // frame.data[2] = fonction, frame.data[3] : 'on' ou 'off'
        break;
      case 0xF7:
        // WRITE CV on MAIN <w CAB CV VALUE>
        DCC::writeCVByteMain(loco, frameIn.data[2], frameIn.data[3]);
        break;
      case 0xFE:
        TrackManager::setMainPower(frameIn.data[0] ? POWERMODE::ON : POWERMODE::OFF);
        xQueueSendToBack(xQueue, &frameIn, 0);
        break;
      case 0xFF:
        DCC::setThrottle(0, 1, 1); // emergency stop
        xQueueSendToBack(xQueue, &frameIn, 0);
        break;
      }

setThrottle, commande de traction ou de e-stop dans le cas où les paramètres sont :

DCC::setThrottle(0, 1, 1); // emergency stop
Commande de mise sous tension ou d’extinction de la box :

case 0xFE:
        TrackManager::setMainPower(frameIn.data[0] ? POWERMODE::ON : POWERMODE::OFF);

La fonction  xQueueSendToBack(xQueue, &frameIn, 0); est la réponse que la commande à bien été reçue.

Voilà pour ne pas faire trop long.

Deux réponse complémentaire cependant, pourquoi ceci :

loco->address & 0xFF00, loco->address & 0x00FF, simplement pour diviser l’adresse qui peut être en 16 bits sous forme de de deux valeurs en 8 bits.

Je vois d’ailleurs qu’il y a une erreur ici puisque cela devrait être : (loco->address & 0xFF00) >> 8, loco->address & 0x00FF
Attention, ceci n'a rien à voir : Ou tout simplement si je veux controler la loco 5 à vitesse 25 en avant sans passer par la programmation objet comme dans la box: que dois-je ecrire :

ACANSettings settings (125 * 1000) ; // 125 kbit/s est la vitesse de transmission des messages sur le bus CAN.

Comme tu me sembles vouloir comprendre le CAN je te conseille de continuer à expérimenter et poser des questions et de bien lire les articles de base en particulier celui de Jean-Luc : https://www.locoduino.org/spip.php?article268

Je te conseille vraiment de réaliser (pas simplement lire) ce que présente Jean-Luc et tu auras acquis 80% de ce qu'il faut savoir.

Christophe
« Modifié: février 05, 2024, 04:44:49 pm par bobyAndCo »

becbunsen

  • Newbie
  • *
  • Messages: 46
    • Voir le profil
Re : Question mise en place CAN dans la centrale DCC
« Réponse #18 le: février 05, 2024, 06:01:01 pm »
Merci de tous ces éléments, c'est déja plus clair au niveau de la structure du message. je ne savais pas que c'etait en mode étendu. il y'a au final beaucoup d'informations dans l'identifiant.
La longueur du message est donc fixé selon les besoins (pas toujours 8 octets de 8 bits)

Excusez moi, je reformule:
Cette partie est la constitution de mon identifiant, je peux quasi l'utiliser tel quelle:


uint16_t hash = 0x1801;   //identifiant choisi pour mon noeud

  frame.id |= prio << 25;  // Priorite         Je dois declarer une priorité =0000 pour le plus prioritaire
  frame.id |= cmde << 17;  // Commande sur 8 bits à renseigner selon un "catalogue" à recuperer dans les switch/case coté reception
  frame.id |= resp << 16;  // Reponse : Commande = 0 / Reponse = 1   
  frame.id |= hash;        // Hash  = N° de mon noeud
  frame.ext = true;                          // Je declare le message en mode etendu

//selon le type de message défini par cmde je défini le nbe d'octets necessaire et je le renseigne par

 frame.len = //entre 0 et 7 octets


Reste à récupérer les différents "cmde" à envoyer


je vais pouvoir expérimenter tout ça...
« Modifié: février 05, 2024, 07:15:10 pm par becbunsen »

bobyAndCo

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1083
  • HO avec DCC++
    • Voir le profil
Re : Question mise en place CAN dans la centrale DCC
« Réponse #19 le: février 05, 2024, 06:48:57 pm »
Dans le fichier :
Test_CommCan_LaBox_2/Test_CommCan_LaBox_2.ino

tu as tous les exemples pour les envois de commande. Tu peux recopier tous les fichiers sur un ESP32 équipé du CAN pour envoyer ces messages et relier avec un autre ESP32 (en CAN) pour la Box:

Les principales fonctions pour commander des locomotives dans le loop :

void loop() {
  /*------------------------------------------------------------------
   Serie de commandes envoyées a LaBox pour tests
  --------------------------------------------------------------------*/

  // Power on
  laBox.setPower(on);
  delay(100);

  // Test des differentes fonctions du decodeur
  for (byte i = 0; i <= 28; i++) {
    // Activation
    loco->fn[i] = on;
    laBox.setFunction(loco, i);
    delay(1000);

    // Desactivation
    loco->fn[i] = off;
    laBox.setFunction(loco, i);
    delay(100);
  }

  // Active les feux et le bruit de la locomotive
  laBox.toggleFunction(loco, 0);
  laBox.toggleFunction(loco, 1);
  delay(1000);

  // Programmation de CV POM
  // WRITE CV on MAIN   <CAB CV VALUE>
  laBox.writeCVByteMain(loco, 63, 75);
  delay(100);

  // Avant 25
  loco->speed = 25;
  loco->direction = 1;
  laBox.setThrottle(loco);
  delay(15000);

  // Arret de la locomotive
  loco->speed = 0;
  laBox.setThrottle(loco);
  delay(5000);

  // Avant 50
  loco->speed = 50;
  laBox.setThrottle(loco);
  delay(15000);

  // Arriere 50
  laBox.toggleThrottleDir(loco);
  delay(15000);

  // Arriere 75
  loco->speed = 75;
  laBox.setThrottle(loco);
  delay(15000);

  // emergency stop
  laBox.emergency();
  delay(1000);

  // power off
  laBox.setPower(off);
  delay(5000);
}

Petit réglage auparavant dans le setup :

void setup() {
  Serial.begin(115200);
  CanMsg::setup();

  loco->address = 65;

  xTaskCreatePinnedToCore(&recepCan, "recepCan", 2 * 1024, NULL, 5, NULL, 0);
}

On dit ici que la loco a l'adresse 65, il faut mettre une adresse qui correspond à la loco testée

Christophe


bobyAndCo

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1083
  • HO avec DCC++
    • Voir le profil
Re : Question mise en place CAN dans la centrale DCC
« Réponse #20 le: février 05, 2024, 11:27:42 pm »
@becbunsen

Attention, dans le fichier CommandStation-EX-LaBox2/CanMsg.cpp Michel (msport) à apriori rencontré un problème avec le filtre CAN (lignes 74 à 81). Il vaut mieux désactiver le filtre actuel, cela n'a pas d'importance pour les tests.

Il faut donc écrire ceci à la place :

  // with filter
  //const ACAN_ESP32_Filter filter = ACAN_ESP32_Filter::singleExtendedFilter(
  //    ACAN_ESP32_Filter::data, 0xF << 17, 0x1F87FFFF);
  //errorCode = ACAN_ESP32::can.begin(settings, filter);

  // without filter
  errorCode = ACAN_ESP32::can.begin(settings);
  Serial.printf("[CanConfig %d] : config without filter\n", __LINE__);

laurentr

  • Hero Member
  • *****
  • Messages: 648
    • Voir le profil
Re : Question mise en place CAN dans la centrale DCC
« Réponse #21 le: mars 08, 2024, 04:40:15 pm »
Bonjour

Je me plonge dans cette rubrique qui mériterait plus de visibilité pour ceux qui comme moi plongent dans le CAN de "0".

Une première question qui me vient est que l ensemble des messages transitant d une source vers une destination ( possiblement multiple) y aurait il un intérêt à définir un bus montant et un autre bus descendant pour favoriser l écoulement des flux?
Cela peut paraitre luxueux mais après tout cela spécialise chacun des bus à un usage déterminé: émission ou réception, ce qui peut dans certain cas en passant par un "centralisateur" décorréler les actions en favorisant les vitesses de transmission en regard des temps de traitement qui peuvent requérir plus de cycles surtout si les destinataires d un même message sont nombreux et doivent être différenciés.
Ltr

bobyAndCo

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1083
  • HO avec DCC++
    • Voir le profil
Re : Question mise en place CAN dans la centrale DCC
« Réponse #22 le: mars 08, 2024, 04:48:04 pm »
Mon cher Laurent,

ll est absolument contraire à l'esprit du CAN que l'on parle d'émetteur et de récepteur ! Ni d'ailleurs de maitre et d'esclaves. Le can est un bus "broadcast" et sans hiérarchie entre les nœuds.

Pourquoi veux-tu favoriser l'écoulement des flux alors même que sur un réseau de modélisme ferroviaire il est fort probable que tu n'arrives même pas à utiliser 20% du potentiel du bus ?

Pour différencier les messages à la réception, il y a plusieurs dispositifs mis à ta disposition, des filtres "hard" programmables, et des méthodes à la réception d'autant plus efficaces que la messagerie est bien conçue.

Christophe

laurentr

  • Hero Member
  • *****
  • Messages: 648
    • Voir le profil
Re : Question mise en place CAN dans la centrale DCC
« Réponse #23 le: mars 14, 2024, 12:36:58 pm »
Merci Christophe pour ces info.

Débutant avec ce hardware encore mal connu pour moi et ayant quelques idées de la façon de l'intégrer à différents montages, à la lecture également du modèle de messagerie que tu as récemment proposé, j essaye de voir comment articuler le tout pour par exemple disposer de décodeurs locaux sous le réseau avec une fonctionnalité propre ex un décodeur d aiguillage CAN intégrant le pilotage d un servo, la commande d un relais pour une polarisation de pointe de cœur et message d acquittement en retour.

Idem pour un décodeur de signal.

Je note bien que les filtres vont jouer un rôle majeur mais la notion de priorité me pose question car si il y a une pile de messages prioritaires qui ne désemplie pas ( ex le cas de tes satellites qui pilotent les info servant aux instructions les vitesses des trains) comment s assure t on de disposer d assez de bande passante pour les messages moins prioritaires? ( enfin qu'ils soient émis et reçus car si toujours relayes ils finissent par ne pas être transmis?)

Il doit bien y avoir des "trucs" pour tout cela... je dois encore les appréhender.

Ltr

bobyAndCo

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1083
  • HO avec DCC++
    • Voir le profil
Re : Question mise en place CAN dans la centrale DCC
« Réponse #24 le: mars 14, 2024, 04:45:39 pm »
Laurent,

Tout d'abord, je pense qu'il faut que tu crées un nouveau fil pour un sujet qui n'a pas à voir avec la mise en place CAN dans la centrale DCC. Car si je comprends bien, tu veux faire des mini satellites. Je pense que les versions v1 correspondent tout à fait à ce que tu souhaites faire.

Très franchement, tu es loin de la préoccupation de messages qui ne seraient pas émis faute de bande passante ou par saturation des buffers mais on en reparlera sur le nouveau fil.

Christophe
« Modifié: mars 14, 2024, 06:50:07 pm par bobyAndCo »