Bonjour à tous,
Je vais être peu disponible encore pendant une quinzaine de jours, mais je vais essayer de vous donner régulièrement des informations et répondre aux questions.
Je pense que la question des liaisons entre le module CAN de l’Arduino et la Gleisbox est maintenant comprise.
L’étape suivante que je propose est d’écouter les communications en CAN. Pour l’instant, pour la seule Gleisbox. Mais vous verrez qu’il circule pas mal de messages.
Le programme ci-dessous ne fait donc que d’afficher ce que la Gleisbox envoie sur le bus. C’est en quelque sorte un sniffer.
Si vos branchements sont bons ainsi que vos paramètres, le moniteur série de l’IDE Arduino doit afficher ceci
Configure ACAN2515
Configuration can ok
Fin du setup
-----------------------------------
Nouveau message
-----------------------------------
Received ID frame (BIN): 1100001000101100100011
Received ID frame (Decimal): 3181347
Received ID frame (HEX): 0x308B23
Received hash (HEX): 0x8B23
Received commande (HEX): 0x18
Received : Demande
-----------------------------------
Ping : Interrogation de tous les participants du bus
Tout d’abord que la configuration c’est (normalement) bien passée Configuration can ok
Ensuite, le moniteur nous indique que l’on vient de recevoir un nouveau message et nous indique l’identifiant sur 29 bits de ce message en binaire, décimal et hexadécimal. Il nous donne également le code de la commande envoyé, ici 0x18 qui est une commande de ping. La Gleisbox envoie toutes les 12 secondes environ, une interrogation pour que tous les participants du bus se fassent connaitre.
Si maintenant vous activez la MS2 en désactivant la touche STOP, vous allez avoir ce message
-----------------------------------
Nouveau message
-----------------------------------
Received ID frame (BIN): 10011001101100011
Received ID frame (Decimal): 78691
Received ID frame (HEX): 0x13363
Received hash (HEX): 0x3363
Received commande (HEX): 0x0
Received : Reponse
-----------------------------------
Commande systeme
data32[0] : 0
data[4] : 1
long : 5
Vous avez cette fois encore les informations sur l’identifiant de 29 bits. Le code de la commande est 0x00, ce sont les commandes système et data[4] est égal à 1 c’est la commande d’activation.
Si vous désactivez, vous aurez le même message mais data[4] sera à 0.
Si vous cherchez à faire rouler une locomotive, vous allez voir ce type de message
-----------------------------------
Nouveau message
-----------------------------------
Received ID frame (BIN): 10010011001101100011
Received ID frame (Decimal): 602979
Received ID frame (HEX): 0x93363
Received hash (HEX): 0x3363
Received commande (HEX): 0x4
Received : Reponse
-----------------------------------
autre commande : 0x4
-----------------------------------
Les commandes qui ont le code 0x04 sont les commande de traction.
Enfin, dernier exemple, ici une commande pour activer les lumières d’une locomotives. Les commandes de fonctions ont pour code 0x06.
-----------------------------------
Nouveau message
-----------------------------------
Received ID frame (BIN): 11001000101100100011
Received ID frame (Decimal): 822051
Received ID frame (HEX): 0xC8B23
Received hash (HEX): 0x8B23
Received commande (HEX): 0x6
Received : Demande
-----------------------------------
autre commande : 0x6
-----------------------------------
Pour connaitre la signification des commandes, reportez-vous au document du protocole Marklin plusieurs fois publié.
Si vous le souhaitez, vous pouvez chercher à avoir plus d’informations en écrivant par exemple des Serial.print() pour les data : Serial.println(frame.data[4]); Serial.println(frame.data[5]); Serial.println(frame.data[6]); Serial.println(frame.data[7]);
ce qui vous permettra de connaitre l’adresse de la locomotive dans Serial.println(frame.data[3]); des commandes de traction et de fonction.
#include <ACAN2515.h>
static const byte MCP2515_CS = 10; // CS input of MCP2515 (adapt to your design)
static const byte MCP2515_INT = 2; // INT output of MCP2515 (adapt to your design)
//——————————————————————————————————————————————————————————————————————————————
// MCP2515 Driver object
//——————————————————————————————————————————————————————————————————————————————
ACAN2515 can(MCP2515_CS, SPI, MCP2515_INT);
//——————————————————————————————————————————————————————————————————————————————
// MCP2515 Quartz: adapt to your design
//——————————————————————————————————————————————————————————————————————————————
static const uint32_t QUARTZ_FREQUENCY = 16UL * 1000UL * 1000UL; // 16 MHz
CANMessage frame;
uint16_t thisHash = 0x2f39;
void setup() {
//--- Start serial
Serial.begin(115200);
//--- Begin SPI
SPI.begin();
//--- Configure ACAN2515
Serial.println("Configure ACAN2515");
ACAN2515Settings settings(QUARTZ_FREQUENCY, 250UL * 1000UL); // CAN bit rate 250 kb/s
//settings.mRequestedMode = ACAN2515Settings::LoopBackMode; // Select loopback mode
const uint16_t errorCode = can.begin(settings, [] {
can.isr();
});
if (errorCode == 0) {
Serial.println("Configuration can ok");
} else {
Serial.print("Configuration error 0x");
Serial.println(errorCode, HEX);
}
Serial.println("Fin du setup");
}
void loop() {
memset(frame.data, 0x00, 8); // On efface les datas
if (can.available()) {
Serial.println("-----------------------------------");
Serial.println("Nouveau message");
Serial.println("-----------------------------------");
can.receive(frame);
Serial.print("Received ID frame (BIN): ");
Serial.println(frame.id, BIN); // Affichage sous forme binaire de l'identifiant
Serial.print("Received ID frame (Decimal): ");
Serial.println(frame.id); // Affichage sous forme decimale de l'identifiant
Serial.print("Received ID frame (HEX): 0x");
Serial.println(frame.id, HEX); // Affichage sous forme hexadecimale de l'identifiant
uint32_t hash = frame.id & 0xFFFF;
Serial.print("Received hash (HEX): 0x");
Serial.println(hash, HEX); // Affichage sous forme hexadecimale de l'identifiant
uint32_t commande = (frame.id & 0x1FE0000) >> 17;
Serial.print("Received commande (HEX): 0x");
Serial.println(commande, HEX); // Affichage sous forme hexadecimale de l'identifiant
uint32_t reponse = (frame.id & 0x10000) >> 16;
Serial.print("Received : ");
//Serial.println(reponse); // Affichage sous forme hexadecimale de l'identifiant
Serial.println(reponse ? "Reponse" : "Demande"); // Affichage sous forme hexadecimale de l'identifiant
Serial.println("-----------------------------------");
switch (commande) {
case 0x18:
if (frame.len == 0) { // Ping : Interrogation de tous les participants du bus
Serial.println("Ping : Interrogation de tous les participants du bus");
CANMessage frameOut;
frameOut.id |= 0x18 << 17;
frameOut.id |= 1 << 16; // Reponse
frameOut.id |= thisHash;
frameOut.len = 4;
frameOut.data32[0] = thisHash;
if (can.tryToSend(frameOut)) {
Serial.println("\nReponse envoyee");
} else {
Serial.println("\nEchec de l'envoi");
}
} else if (frame.len == 8) {
Serial.println("Ping :");
uint32_t expediteur = frame.data32[0];
Serial.print("ID expediteur : 0x");
Serial.println(expediteur, HEX);
uint16_t versLogiciel = frame.data16[4];
Serial.print("Num version logiciel : 0x");
Serial.println(versLogiciel, HEX);
uint16_t typeAppareil = frame.data16[6];
Serial.print("Type de l'appareil : 0x");
Serial.println(typeAppareil, HEX);
}
break;
case 0x00: // Commande systeme
Serial.println("Commande systeme");
Serial.print("data32[0] : ");
Serial.println(frame.data32[0]);
Serial.print("data[4] : ");
Serial.println(frame.data[4]);
Serial.print("long : ");
Serial.println(frame.len);
break;
default:
Serial.print("autre commande : 0x");
Serial.println(commande);
}
Serial.println("-----------------------------------\n");
}
}