Commander sa centrale Marklin® MS2 en WiFi à partir de Rocrail®, JMRI®, iTrain® ou autres gestionnaires.

. Par : bobyAndCo. URL : https://www.locoduino.org/spip.php?article361

Aujourd’hui, je vous propose un sujet en 3 rails, ce qui n’est pas très courant sur Locoduino. Et c’est bien dommage car ce système et son environnement regorgent de techniques intéressantes.

Il s’agit de piloter une MS2 de Marklin® à partir de n’importe quel gestionnaire de réseau comme Rocrail®, iTrain® ou encore JMRI®. Je ne parlerai, dans l’article, que de Rocrail®, mais cela vaudra pour tous les autres.

La MS2 est la centrale d’entrée de gamme de Marklin®. Elle est proposée en particulier dans les kits de démarrage à un tarif attractif pour, bien sûr, attirer de nouveau utilisateurs vers la marque.

Pourtant, la MS2 n’a pas à rougir devant ses grandes sœurs, la CS2 et la CS3 ou encore CS3+ car, équipée tel que je vais vous le présenter dans cet article, peut tout à fait disposer des nombreuses fonctionnalités dont on l’a amputée pour des raisons de positionnement marketing.

De quoi est composé le kit MS2 ?

Quand on parle de la MS2, il faut bien avoir à l’esprit qu’il s’agit de deux appareils principaux, une petite centrale

JPEG - 248.7 kio
Figure 1 - La centrale MS2 de Marklin®

et un booster 60114 ou 60116 mais dont nous verrons que ce dernier est (bien) plus que cela.

JPEG - 492.3 kio
Figure 2 - La "boite de voie", un booster mais pas que !

Ce kit est une réponse "commerciale" simple qui correspond aux besoins d’un grand nombre de modélistes. C’est pourquoi, je pense, cet article intéressera un grand nombre de personnes.

A noter que la centrale de TRIX de couleur verte est le même produit.

JPEG - 387.1 kio
Figure 3 - La MS2 de TRIX vendue à l’intérieur d’un coffret "Digital Start"

Que permet le montage proposé dans cet article ?

Comme je le dis en introduction, compte tenu de son prix, ce kit MS2 est bridé pour marquer une différence vis à vis des autres centrales de la marque. Mais comme elle communique en CAN, il est très facile de hacker ce système en DIY, avec des Arduino et des ESP32 en particulier.

Nous chercherons à utiliser différents logiciels de gestion de réseau gratuits comme Rocrail® ou JMRI® ou payants comme iTrain® ou TrainController® ou tous ceux qui exposent le protocole CAN Marklin® affublé d’autant de noms qu’il existe de logiciels ; mbus chez Rocrail® qui est le gestionnaire que j’utiliserai pour cet article.

La liaison entre l’ordinateur qui héberge le gestionnaire et la centrale Marklin® peut être réalisée en série (USB), filaire (Ethernet) ou sans fil (WiFi). Mais je recommande vivement la connexion en WiFi de loin la plus simple et la plus efficiente et celle que je présente dans cet article.

Une version avec liaison série en USB est cependant disponible sur Github

De quoi se compose le montage ?

JPEG - 99.3 kio
Figure 4 - Présentation de l’installation dans son ensemble

J’utilise ici un ESP32 pour ses performances et son CAN en partie intégré mais aussi pour le WiFi présent nativement.

JPEG - 123 kio
Figure 5 : Carte "universelle" ESP32 avec son alimentation 5V/1A et son transceiver CAN MCP2562

Pour rendre l’ensemble plus « propre », j’utilise des petites cartes « universelles » » que j’avais réalisées, qui incorporent un transceiver CAN MCP2562 et dont j’ai souvent parlé sur Locoduino.

Voyons comment sont reliés les composants.

Côté ordinateur :

Il n’y a aucune liaison filaire puisque l’on communique en WiFi. On peut cependant relier l’ESP32 à l’ordinateur par un câble USB (comme sur la photo) pour l’alimention électrique à partir de cette source ou si l’on souhaite disposer du debug qui permet de visualiser sur un moniteur série l’ensemble du traffic TCP -> CAN ou CAN -> TCP.

Sans liaison USB, L’ESP32 devra alors disposer de sa propre alimentation électrique ce qui est prévu sur la carte « universelle ». Il vous faudra aussi disposer d’un réseau sans fil ce qui est le cas dans pratiquement tous les foyers français aujourd’hui.

Compte tenu de l’intérêt très marginal que peut présenter une liaison Ethernet filaire, je ne ferai qu’exposer cette possibilité et répondrai volontiers à ceux qui s’intéressent à cette configuration. J’ai aussi confectionné sur la base de la carte « universelle » ESP32 une version incorporant l’Ethernet. Sachez que le code est le même que pour la version WiFi en intégrant en plus le code pour les drivers du module Ethernet.

Côté MS2 :

JPEG - 132.4 kio
Figure 6 - L’ESP32 à côté de la boite de voie "Gleisbox"

Il faut tout d’abord réaliser un montage « classique » pour ce système. La centrale MS2 est reliée par son cordon à la boite de voie (Gleisbox dans la langue de Goethe), elle-même reliée à la voie et au courant secteur.

Entre l’ESP32 et la Gleisbox :

JPEG - 58.3 kio
Figure 7 - Raccordement de CAN High et CAN Low sur la seconde prise DIN

Le raccordement est une liaison CAN sur la seconde prise DIN restant disponible. Plutôt que d’acheter à prix d’or un cordon que vous allez devoir sectionner, je vous conseille d’utiliser deux câbles avec prises Dupont.

JPEG - 35.6 kio
Figure 8 - Schéma de la prise DIN de la Boite de Voie

On peut voir sur ce schéma qu’il faut relier le CAN Low dans la broche 8 de la prise DIN et le CAN High dans la broche 4. C’est tout. Vous ne risquez rien si vous inversez les branchements, si ce n’est que cela ne fonctionnera pas ! Attention cependant à ne pas vous tromper avec broche 1 qui est le +12 volts.

C’est tout pour le câblage.

Le programme :

Je rappelle que Marklin® utilise principalement le protocole CAN pour la communication entre ses équipements (hormis malheureusement la rétro signalisation qui est en S88) mais aussi le TCP. C’est sous ce mode que l’on va par exemple relier avantageusement une CS2 ou CS3 à Rocrail®. Mais la MS2, pour les questions de positionnement dans la gamme déjà évoquées, n’est pas équipée de cette liaison.

Tout le protocole de communication CAN de Marklin® est public. Vous pouvez le consulter ici : cs2CAN-Protokoll-2_0 Voir également, au sujet de ce document, mon commentaire en bas de l’article (*).

Les ordinateurs « domestiques » en règle générale communiquent en WiFi, en Ethernet et en Série (USB). Mais pas en CAN malheureusement.

Le programme est avant tout une passerelle qui route les messages entrants en TCP vers le bus CAN et inversement.

Il est téléchargeable sur le Github de Locoduino

Dans le programme, vous devrez renseigner le nom de votre réseau WiFi et son mot de passe. Nous verrons cela un peu plus loin.

Si vous utilisez PlateformIO, vous pourrez téléverser alors le programme sans autre modification.

Sur l’IDE Arduino, vous devrez tout d’abord, renommer le fichier main.cpp avec un nom explicite pour vous, « marklin_cs2_can-gateway.ino » par exemple, en pensant bien à ajouter l’extension « .ino » à la place de ".cpp>.

Et si ce n’est pas déjà fait, installez la bibliothèque CAN pour ESP32 de Pierre Molinaro disponible sur Github

La bibliothèque WiFi @ 2.0.0 est disponible d’origine sur les deux IDE PlateformIO et Arduino et n’a donc pas besoin d’installation.

Quelques considérations générales sur le code :

Précision préliminaire importante :
 
Il est de règle sur Locoduino que l’on publie nos programmes (open source) et qu’on les commente pour que d’autres puisse s’en inspirer et/ou les modifier.
 
Mais vous pouvez tout à fait utiliser ce montage sans avoir compris ni même lu ce qui va suivre concernant le code !

Il faut comprendre que le système proposé n’est ni plus ni moins qu’une passerelle entre un réseau utilisant le protocole TCP et un bus CAN.

Il faut saluer l’efficacité de Marklin® dans la simplicité. Les messages sont tous de 13 bytes en entrée et de 13 bytes en sortie, quel que soit le sens de circulation. L’ordre des bits, (13 x 8 = 104 bits par messages) est le même en entrée et en sortie, c’est juste leur segmentation qui diffère entre une trame TCP et une trame CAN

Le travail consiste à lire les messages entrants, organiser leur segmentation et de le renvoyer sur l’autre réseau.

L’enjeu est de ne perdre aucun message !!! D’où la nécessité d’un programme qui travail vite et qui puisse traiter les tâches de réception et d’envoi en parallèle et non de manière séquentielle.

J’ai utilisé pour cela la programmation en tâches (task) disponible avec FreeRTOS, le système d’exploitation de l’ESP32. Nous avons quatre tâches principales qui s’exécutent concurrament :

CANReceiveTask : Réception des messages en provenance du bus CAN
TCPSendTask : Envoi des messages en TCP vers Rocrail®
TCPReceiveTask : Réception des messages TCP
CANSendTask : Envoi des messages sur le bus CAN

Les tâches s’échangent les messages au travers de deux "queues", files d’attente, dont l’objectif est de stocker les messages avant traitement dans le but de n’en perdre aucun. Ces files sont : canToTcpQueue et tcpToCanQueue

Le debug s’exécute également dans une tâche dédiée debugFrameTask avec une queue qui lui est propre debugQueue

Quelques zooms sur le code :

/*
   rocrail_CAN_TCP_GW

    Programme permettant le pilotage de locomotives à partir de Rocrail©
    et la mise a jour de la liste des locomotives en MFX en utilisant une liaison TCP (WiFi ou Ethernet).
*/

#define PROJECT "rocrail_can_tcp_gateway"
#define VERSION "1.0"
#define AUTHOR "Christophe BOBILLE - www.locoduino.org"

//----------------------------------------------------------------------------------------
//  Board Check
//----------------------------------------------------------------------------------------

#ifndef ARDUINO_ARCH_ESP32
#error "Select an ESP32 board"
#endif

//----------------------------------------------------------------------------------------
//   Include files
//----------------------------------------------------------------------------------------

#include <ACAN_ESP32.h> // https://github.com/pierremolinaro/acan-esp32.git
#include <Arduino.h>
#include <WiFi.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/queue.h>

//----------------------------------------------------------------------------------------
//  Debug serial
//----------------------------------------------------------------------------------------

#define debug Serial // (only for TCP connection)

Classiquement, nous trouvons en début de programmes les fichiers inclus, les déclarations et initialisations de variables globales, l’affectations des broches.

On remarquera l’inclusion des fichiers freertos

#define debug Serial signifie que l’on écrit dans le code debug.print("Hello") par exemple mais que la pré-compilation va substituer Serial en lieu et place de debug.

Personnellement, pour l’affichage de message série comme ceux du debug, j’utilise l’excellent utilitaire coolTerm

PNG - 199.4 kio
Figure 9 - Exemple d’informations fournies par le debug dans une fenêtre de l’utilitaire CoolTerm
//----------------------------------------------------------------------------------------
//  CAN Desired Bit Rate
//----------------------------------------------------------------------------------------

static const uint32_t DESIRED_BIT_RATE = 250UL * 1000UL; // Marklin CAN baudrate = 250Kbit/s

La vitesse de communication sur le bus CAN est réglée à 250Kbp/s qui est le standard Marklin®

//----------------------------------------------------------------------------------------
//  Buffers  : Rocrail always send 13 bytes
//----------------------------------------------------------------------------------------

byte cBuffer[13]; // CAN buffer
byte sBuffer[13]; // Serial buffer

Nous déclarons deux tableaux de type byte pour Les buffers de réception, un pour les réceptions tcp, un pour le can.

//----------------------------------------------------------------------------------------
//  Marklin hash
//----------------------------------------------------------------------------------------

uint16_t rrHash; // for Rocrail hash

Nous déclarons également une variable sur 16 bits qui va contenir l’identifiant unique (ID) du logiciel Rocrail® en tant qu’équipement présent sur le bus CAN.

//----------------------------------------------------------------------------------------
//  TCP/WIFI-ETHERNET
//----------------------------------------------------------------------------------------

#include <WiFi.h>
const char *ssid = "*************";
const char *password = "*************";
const uint port = 15731;
const char *ip = "192.168.1.13"; // tcpbin.com's ip

Nous devons inclure la bibliothèque WiFi, renseigner le SSID de notre réseau WiFi domestique ainsi que le mot de passe d’accès à ce réseau.

Ici, j’ai donné une adresse ip « arbitraire » (192.168.1.13) mais cohérente par rapport à la table d’adresse de ma box. Cette adresse doit être la même que celle renseignée dans Rocrail®.

PNG - 186.5 kio
Figure 10 - Paramètres TCP dans Rocrail®

Le port d’écoute du serveur sur l’ESP32 est 15731, port par défaut des CS2/CS3. Il peut être modifié si vous avez déjà des équipements qui l’utilisent.

WiFiServer server(port);
WiFiClient client;

Pour finir avec cette partie instances/déclarations, nous instancions un objet server de la classe WiFiServer pour que notre ESP32 se transforme en un serveur tcp et un objet client de la classe WiFiClient pour la connexion de Rocrail® à l’ESP32. Notez qu’il n’y a qu’une instance possible, n’autorisant ainsi qu’une seule connexion ce qui est à mon sens préférable pour cette utilisation précise.

//----------------------------------------------------------------------------------------
//  Queues
//----------------------------------------------------------------------------------------

QueueHandle_t canToTcpQueue;
QueueHandle_t tcpToCanQueue;
QueueHandle_t debugQueue; // Queue for debug messages

//----------------------------------------------------------------------------------------
//  Tasks
//----------------------------------------------------------------------------------------

void CANReceiveTask(void *pvParameters);
void TCPSendTask(void *pvParameters);
void TCPReceiveTask(void *pvParameters);
void CANSendTask(void *pvParameters);
void debugFrameTask(void *pvParameters); // Debug task

Et ici, nous avons les déclarations correspondant aux cinq tâches et aux queues évoquées plus haut.

Dans le setup(), nous trouvons tout d’abord le begin() du ports série, que nous avons nommé debug pour une meilleure lisibilité

//----------------------------------------------------------------------------------------
//   SETUP
//----------------------------------------------------------------------------------------

void setup()
{
  //--- Start serial
  debug.begin(115200); // For debug

  while (!debug)
  {
    debug.print(".");
    delay(200);
  }
  delay(100);

  debug.println("Start setup");

Nous avons ensuite dans le programme, la configuration du CAN,

ACAN_ESP32_Settings settings(DESIRED_BIT_RATE);
tout d’abord en renseignant le débit souhaité

  settings.mRxPin = GPIO_NUM_22; // Optional, default Rx pin is GPIO_NUM_5
  settings.mTxPin = GPIO_NUM_23; // Optional, default Tx pin is GPIO_NUM_4

... puis les broches utilisées. Attention, ma carte « universelle » utilise les broches 22 et 23 alors que traditionnellement, ce sont les broches 4 et 5 qui sont réservées pour la communication CAN.

const uint32_t errorCode = ACAN_ESP32::can.begin(settings);

et enfin on démarre une connexion.

 WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    debug.print(".");
  }

  debug.println("");
  debug.println("WiFi connected.");
  debug.println("IP address: ");
  debug.println(WiFi.localIP());

  server.begin();

Viennent ensuite l’activation du WiFi et le lancement du serveur...

while (!client)   // listen for incoming clients
    client = server.available();

  // extract the Rocrail hash
  debug.printf("New Client Rocrail : 0x");
  if (client.connected()) {            // loop while the client's connected
    int16_t rb = 0;                    //!\ Do not change type int16_t
    while (rb != 13)
    {
      if (client.available()) // if there's bytes to read from the client,
        rb = client.readBytes(cBuffer, 13);
    }
    RrHash = ((cBuffer[2] << 8) | cBuffer[3]);

    debug.println(RrHash, HEX);

Nous profitons du setup pour lancer une action qui ne sera exécutée qu’une seule fois, à savoir le décodage du hash, identifiant unique de Rocrail® sur le bus CAN.

Le message de reconnaissance est le premier message envoyé par Rocrail® à l’occasion de son démarrage. Aussi, veillez-bien à ce que l’ESP32 soit déjà opérationnel avant d’ouvrir Rocrail®

Dans le protocole de communication CAN de Marklin®, l’ID de l’équipement est « contenu » dans les 16 bits de poids faible de l’identifiant long du message qui compte 29 bits. On obtient sa valeur par la lecture de deux octets avec un décalage de 8 bits pour le premier octet. RrHash = ((cBuffer[2] << 8) | cBuffer[3]);

while (!client) // listen for incoming clients
    client = server.available();

  // extract the Rocrail hash
  debug.printf("New Client Rocrail : 0x");
  if (client.connected())
  {                 // loop while the client's connected
    int16_t rb = 0; //!\ Do not change type int16_t See https://www.arduino.cc/reference/en/language/functions/communication/stream/streamreadbytes/
    while (rb != 13)
    {
      if (client.available()) // if there's bytes to read from the client,
        rb = client.readBytes(cBuffer, 13);
    }
    rrHash = ((cBuffer[2] << 8) | cBuffer[3]);
    debug.println(rrHash, HEX);

Ensuite, nous nous chargeons d’envoyer sans plus attendre ce message sur le bus CAN afin que tous les équipements raccordés aient connaissance de la présence de Rocrail®. C’est en effet l’une des spécificités du bus CAN particulièrement utile sur nos réseaux miniatures : TOUS les équipements CAN peuvent lire TOUS les messages circulants sur le bus et aucun message ne doit avoir de destinataire(s) « attitré(s) ». Mais on peut choisir, sur n’importe quel équipement, de « filtrer » tel(s) ou tel(s) expéditeur(s) ou telle ou telle commande (ou plage de commande).

   // --- register Rocrail on the CAN bus
    CANMessage frame;
    frame.id = (cBuffer[0] << 24) | (cBuffer[1] << 16) | rrHash;
    frame.ext = true;
    frame.len = cBuffer[4];
    for (byte i = 0; i < frame.len; i++)
      frame.data[i] = cBuffer[i + 5];
    const uint32_t ok = ACAN_ESP32::can.tryToSend(frame);

    debugFrame(&frame);

Puis à la fin du setup(), nous lançons l’exécution des tâches avec leurs paramètres spécifiques ainsi que pour les queues :

// Create queues
  canToTcpQueue = xQueueCreate(50, sizeof(CANMessage));
  tcpToCanQueue = xQueueCreate(50, 13 * sizeof(byte));
  debugQueue = xQueueCreate(50, sizeof(CANMessage));

  // Create tasks
  xTaskCreatePinnedToCore(CANReceiveTask, "CANReceiveTask", 2 * 1024, NULL, 3, NULL, 0); // priority 3 on core 0
  xTaskCreatePinnedToCore(TCPSendTask, "TCPSendTask", 2 * 1024, NULL, 5, NULL, 1);       // priority 5 on core 1
  xTaskCreatePinnedToCore(TCPReceiveTask, "TCPReceiveTask", 2 * 1024, NULL, 3, NULL, 1); // priority 3 on core 1
  xTaskCreatePinnedToCore(CANSendTask, "CANSendTask", 2 * 1024, NULL, 5, NULL, 0);       // priority 5 on core 0
  xTaskCreatePinnedToCore(debugFrameTask, "debugFrameTask", 2 * 1024, NULL, 1, NULL, 1); // debug task with priority 1 on core 1

Avec xTaskCreatePinnedToCore, je demande au système d’exécuter une tâche sur l’un ou l’autre cœur de l’ESP32. Je répartis ainsi le travail ce qui a pour conséquence d’améliorer significativement les performances globales. C’est la dernière valeur passée en paramètre de la fonction.

L’avant avant dernier paramètre est la priorité donnée à la tâche par rapport aux autres. Les tâches de réceptions ont une priorité "3" plus élevés que les tâches d’envoi "5". La tâche de debug est moins prioritaire avec un niveau 1.

Il n’y a rien à exécuter dans le loop() "traditionnel" puisque les tâches s’exécutant simultanément, ce sont chacune des loops ! Mais dans le framework Arduino, la présence de void loop() est obligatoire, même s’il n’y a rien à exécuter dedans.

Vous avez bien compris la répartition des tâches et leurs exécutions (quasi) simultanées. Détaillons la première et la plus simple : CANReceiveTask

//----------------------------------------------------------------------------------------
//   CANReceiveTask
//----------------------------------------------------------------------------------------

void CANReceiveTask(void *pvParameters)
{
  CANMessage frameIn;
  while (true)
  {
    if (ACAN_ESP32::can.receive(frameIn))
    {
      xQueueSend(canToTcpQueue, &frameIn, portMAX_DELAY);
      xQueueSend(debugQueue, &frameIn, 10); // send to debug queue
    }
    vTaskDelay(10 / portTICK_PERIOD_MS); // Avoid busy-waiting
  }
}

frameIn est une instance (objet créé) de la classe CANMessage. Cette instance est créée dans une partie de code qui n’est exécutée qu’une seule fois.

En effet, le loop de la fonction est exécuté à l’intérieur de la boucle while(true). En programmation, c’est un des moyens pour créer une boucle répétée sans fin, la condition true est par essence toujours vraie.

if (ACAN_ESP32::can.receive(frameIn)) nous indique que, si un message CAN est reçu, celui-ci sera placé dans la queue canToTcpQueue par la fonction xQueueSend()

La fonction TCPReceiveTask réalise la même opération mais cette fois pour les messages envoyés par le client (Rocrail®) à destination du serveur TCP de l’ESP32 ;

//----------------------------------------------------------------------------------------
//   TCPReceiveTask
//----------------------------------------------------------------------------------------

void TCPReceiveTask(void *pvParameters)
{
  while (true)
  {
    if (client.connected() && client.available())
    {
      if (client.readBytes(cBuffer, 13) == 13)
        xQueueSend(tcpToCanQueue, cBuffer, 10);
    }
    vTaskDelay(10 / portTICK_PERIOD_MS); // Avoid busy-waiting
  }
}

Concernant maintenant les tâches d’envoi, nous examinerons CANSendTask

byte buffer[13];Nous déclarons tout d’abord une fois pour toute un buffer "local" à 13 éléments. Souvenez vous, les trames TCP sont toujours de 13 bytes, une case de tableau donc pour chacun des octets.

Ensuite, au travers de la boucle sans fin, nous examinons s’il y a un (des) message(s) dans la queue. Dans l’affirmative, nous positionnons chacun des octets reçus à sa place dans l’identifiant du messages CAN mais aussi dans les datas par un jeu de ce que l’on appelle en informatique, la manipulation de bits !

En fin, vous l’avez compris, on expédie le message CAN sur le bus : ACAN_ESP32::can.tryToSend(frameOut);

//----------------------------------------------------------------------------------------
//   CANSendTask
//----------------------------------------------------------------------------------------

void CANSendTask(void *pvParameters)
{
  byte buffer[13];
  while (true)
  {
    if (xQueueReceive(tcpToCanQueue, buffer, portMAX_DELAY))
    {
      CANMessage frameOut;
      frameOut.id = (buffer[0] << 24) | (buffer[1] << 16) | rrHash;
      frameOut.ext = true;
      frameOut.len = buffer[4];
      for (byte i = 0; i < frameOut.len; i++)
        frameOut.data[i] = buffer[i + 5];

      const bool ok = ACAN_ESP32::can.tryToSend(frameOut);
      xQueueSend(debugQueue, &frameOut, 10); // send to debug queue
    }
  }
}

Pour TCPSendTask, vous vous en doutez, les choses sont très similaires :

//----------------------------------------------------------------------------------------
//   TCPSendTask
//----------------------------------------------------------------------------------------

void TCPSendTask(void *pvParameters)
{
  CANMessage frameIn;
  while (true)
  {
    if (xQueueReceive(canToTcpQueue, &frameIn, portMAX_DELAY))
    {
      // clear sBuffer
      memset(sBuffer, 0, sizeof(sBuffer));

      // debug.printf("CAN -> TCP\n\n");
      xQueueSend(debugQueue, &frameIn, 10); // send to debug queue

      sBuffer[0] = (frameIn.id & 0xFF000000) >> 24;
      sBuffer[1] = (frameIn.id & 0xFF0000) >> 16;
      sBuffer[2] = (frameIn.id & 0xFF00) >> 8; // hash
      sBuffer[3] = (frameIn.id & 0x00FF);      // hash
      sBuffer[4] = frameIn.len;
      for (byte i = 0; i < frameIn.len; i++)
        sBuffer[i + 5] = frameIn.data[i];

      client.write(sBuffer, 13);
    }
  }
}

Pour completer cette présentation, il nous faut regarder côté Rocrail® les réglages à opérer :

PNG - 267 kio
Figure 11 - Ecran des propriétés de Rocrail® sous l’onglet "centrale"

1° - On crée une nouvelle centrale dans le menu « propriétés de Rocrail® » onglet « centrale » à l’aide du bouton « ajouter » en bas à gauche en ayant pris soin tout d’abord de sélectionner « mbus » dans le menu déroulant à gauche du bouton ajouter.

PNG - 118.4 kio
Figure 12 - Les paramètres pour l’IP du serveur et pour le n0 de port dans Rocrail®

2° - Vous double-cliquez sur la ligne ainsi crée et vous choisissez TCP (si vous voulez communiquer sous ce mode) ou « CC-Schnitte » en communication série.

PNG - 136.5 kio
Figure 14 - Le mode "Maître" ne doit pas être activé.

Notez que Rocrail® ne doit pas être paramétré en "Maître" mais en "Esclave".

PNG - 111.4 kio
Figure 13 : Ne pas oublier d’affecter une centrale à la locomotive. Ici ESP_32_WIFI

Pour la reconnaissance MFX des locomotives sur les rails et l’incrémentation dans Rocrail®, il faut supprimer la locomotive dans la MS2 et poser la locomotive sur les rails. Quand la MS2 aura terminer sa reconnaissance, elle va diffuser par le bus CAN l’ensemble des données et Rocrail® va ainsi pouvoir l’enregistrer à son tour. Veillez bien à affecter une centrale à cet "objet locomotive" dans Rocrail® sinon tout sera perdu à la fermeture de Rocrail® et tout sera à recommencer.

Pour conclure :

Voilà donc un projet qui devrait intéresser la communauté du 3 rails, mais pas que, car cette « petite centrale » reconnait aussi le protocole DCC et donc le 2 rails.

Cela a été pour moi et continue à être un vrai bonheur de travailler sur le protocole CAN de Marklin®, tellement précis et performant.

Je regrette profondément pour la communauté du 3 Rails que Marklin® n’est pas « basculé » également en CAN son protocole S88 de rétro signalisation ce dont les utilisateurs se seraient délecté. Je comprends et respecte le sacro-saint principe de Marklin® de rétro opérabilité qui est tout à son honneur. Mais il y avait des solutions techniques pour combiner anciens et nouveaux système comme l’a démontré notre camarade Jean-Pierre CLAUDE dans ses articles « Une Passerelle entre le bus S88 et le bus CAN pour la rétro signalisation » et « La rétro-signalisation [S88] sur Arduino »

Ce sont des articles très rigoureux que je trouve passionnants et plein d’enseignements que je vous invite à lire ou à relire.

Mais pour Marklin®, la question ne devait pas être que technique !

Comme à l’habitude, n’hésitez pas à me questionner ou apporter des suggestions. Je répondrai volontiers aux deux.

Quelques liens pour aller plus loin si vous voulez approfondir le sujet :

https://wiki.rocrail.net/doku.php?i...
https://streaming.maerklin.de/publi...

Voici enfin les fichiers Gerber pour le PCB de la carte que j’utilise dans l’article :

ESP32_can_v6_38_pins_gerber.zip
ESP32_can_v6_38_pins_gerber.zip
Fichiers Gerber de la carte pour ESP32 38 pins

(*) J’ai entamé une traduction pour les parties qui m’intéressaient, auxquelles j’ai ajouté des commentaires et des extraits de code en c++ pour pouvoir les mettre en œuvre. C’est un travail passionnant et enrichissant tant les choses sont bien faites chez Marklin® mais au combien chronophage au point que je ne terminerai sans doute jamais ce travail.