Bonjour à tous,
Voila j’ai terminé le programme qui permet d’activer la reconnaissance MFX pour Rocrail avec CC-Schnitte sans avoir besoin de la MS2.
Comme il n’est pas possible de télécharger un fichier .ino, j’ai copié le code ci-dessous.
J’ai écrit le code pour un ESP32 qui tourne sur une petite carte que j’ai réalisée avec un transceiver CAN MCP2562. Mais cela peut aussi fonctionner sur n’importe quel Arduino avec un module CAN MCP2515 en modifiant également la bibliothèque CAN dans le programme.
Pour ceux qui seraient intéressés, n’hésitez pas à poser toutes vos questions aux quelles j’essayerai de répondre. Je peux aussi fournir les fichiers Gerber de la carte (voir des cartes complètes).
/*
rocrail_mfx_discovery
Pogramme permettant la reconnaissance MFX
et la mise a jour de la liste des locomotives dans Rocrail©
*/
#ifndef ARDUINO_ARCH_ESP32
#error "Select an ESP32 board"
#endif
#define PROJECT "rocrail_mfx_discovery"
#define VERSION "0.1"
#define AUTHOR "Christophe BOBILLE : [email protected]"
#include <ACAN_ESP32.h> // https://github.com/pierremolinaro/acan-esp32.git
CANMessage frameIn;
CANMessage frameOut;
/* ----- CAN ----------------------*/
#define CAN_RX GPIO_NUM_22
#define CAN_TX GPIO_NUM_23
#define CAN_BITRATE 250UL * 1000UL // Marklin CAN baudrate = 250Kbit/s
uint32_t CAN_Id;
uint8_t CAN_Len;
uint8_t CAN_Command;
uint16_t CAN_Hash = 0x2f39;
String decToHex(uint8_t dec)
{
auto convert = [](uint8_t x) ->char
{
char ch;
if (x >= 10)
return (char)(x + 55);
else
return (char)(x + 48);
};
String hex = "";
hex += convert(dec / 16);
hex += convert(dec % 16);
return hex;
}
const byte nbLocos = 40;
class Loco
{
private:
public:
Loco();
uint8_t index;
uint8_t locID[2];
uint8_t UID[4];
static uint8_t comptLoco;
};
uint8_t Loco::comptLoco = 4;
Loco::Loco() : index(255) {};
Loco* loco = new Loco[nbLocos];
uint8_t canSendDta[8];
bool err;
bool sendMsgCan(uint8_t CAN_Command, uint8_t length, uint8_t *canSendDta)
{
CAN_Id = CAN_Command << 17 | CAN_Hash;
frameOut.id = CAN_Id;
frameOut.ext = 1;
frameOut.len = length;
frameOut.data[0] = canSendDta[0];
frameOut.data[1] = canSendDta[1];
frameOut.data[2] = canSendDta[2];
frameOut.data[3] = canSendDta[3];
frameOut.data[4] = canSendDta[4];
frameOut.data[5] = canSendDta[5];
frameOut.data[6] = canSendDta[6];
frameOut.data[7] = canSendDta[7];
err = ACAN_ESP32::can.tryToSend (frameOut);
Serial.print("[ ]=> command 0x");
Serial.println(decToHex(CAN_Command));
}
void setup()
{
Serial.begin(115200);
delay(1000);
Serial.printf("\nProject : %s", PROJECT);
Serial.printf("\nVersion : %s", VERSION);
Serial.printf("\nAuteur : %s", AUTHOR);
Serial.printf("\nFichier : %s", __FILE__);
Serial.printf("\nCompiled : %s", __DATE__);
Serial.printf(" - %s\n\n", __TIME__);
//--- Configure ESP32 CAN
Serial.println("Configure ESP32 CAN");
ACAN_ESP32_Settings settings(CAN_BITRATE);
settings.mRxPin = CAN_RX;
settings.mTxPin = CAN_TX;
const uint32_t errorCode = ACAN_ESP32::can.begin(settings);
if (errorCode == 0)
Serial.println("Can configuration OK !\n");
else
{
Serial.printf("Can configuration error 0x%x\n", errorCode);
delay(1000);
return;
}
//2.1 Commande : Système Arrêt
delay(10);
for (byte i = 0; i < 8; i++)
canSendDta[i] = 0x00;
err = sendMsgCan(0x00, 4, canSendDta);
// Bootloader CAN
delay(10);
for (byte i = 0; i < 8; i++)
canSendDta[i] = 0x00;
canSendDta[4] = 0x11;
err = sendMsgCan(0x1B, 5, canSendDta);
//2.10 commande : Système MFX Définir le compteur de nouvelles inscriptions
delay(10);
for (byte i = 0; i < 8; i++)
canSendDta[i] = 0x00;
canSendDta[4] = 0x09; //Sous-CMD MFX
canSendDta[5] = Loco::comptLoco & 0xFF00;
canSendDta[6] = Loco::comptLoco & 0x00FF;
err = sendMsgCan(0x00, 7, canSendDta);
// 3.3 commande : MFX Verify (pour provoquer un UnBIND)
/*
Si un décodeur MFX lié recoit une combinaison erronee d'UID MFX et de SID MFX,
un UnBIND est déclenche dans le decodeur de locomotive avec le SID MFX correspondant
*/
delay(10);
for (byte i = 0; i < 8; i++)
canSendDta[i] = 0x00;
err = sendMsgCan(0x03, 6, canSendDta);
// 2.2 Commande : Système Go
delay(10);
for (byte i = 0; i < 8; i++)
canSendDta[i] = 0x00;
canSendDta[4] = 0x01; // Go a tous
err = sendMsgCan(0x00, 5, canSendDta);
//3.1 Ordre de mission : Locomotive Discovery
delay(10);
for (byte i = 0; i < 8; i++)
canSendDta[i] = 0x00;
canSendDta[0] = 0x20; // MFX protocole
err = sendMsgCan(0x00, 1, canSendDta);
}
void loop()
{
if (ACAN_ESP32::can.receive (frameIn))
{
if (frameIn.id >> 16 == 0x03 && frameIn.len == 5)
{
Serial.printf("Frame ID 0x");
Serial.println(frameIn.id, HEX);
Serial.printf("Frame length %d\n", frameIn.len);
for (byte i = 0; i < frameIn.len; i++)
{
Serial.printf(" Data [");
Serial.print(i);
Serial.print("] = 0x");
Serial.print(frameIn.data[i], HEX);
}
Serial.printf("\n");
byte i;
bool stop = false;
for (i = 0; i < nbLocos; i++)
{
if (loco[i].UID[0] == frameIn.data[0]
&& loco[i].UID[1] == frameIn.data[1]
&& loco[i].UID[2] == frameIn.data[2]
&& loco[i].UID[3] == frameIn.data[3])
{
byte address0 = loco[i].locID[0];
byte address1 = loco[i].locID[1];
// MFX Bind
delay(10);
for (byte i = 0; i < 8; i++)
canSendDta[i] = 0x00;
canSendDta[0] = loco[i].UID[0];
canSendDta[1] = loco[i].UID[1];
canSendDta[2] = loco[i].UID[2];
canSendDta[3] = loco[i].UID[3];
canSendDta[4] = loco[i].locID[0];
canSendDta[5] = loco[i].locID[1];
err = sendMsgCan(0x02, 6, canSendDta);
delay(10);
stop = true;
}
if (stop)
break;
}
if (i == nbLocos) // Pas de locos trouve
{
for (i = 0; i < nbLocos; i++)
{
if (loco[i].index == 255)
{
Loco::comptLoco++;
loco[i].index = i;
loco[i].UID[0] = frameIn.data[0];
loco[i].UID[1] = frameIn.data[1];
loco[i].UID[2] = frameIn.data[2];
loco[i].UID[3] = frameIn.data[3];
loco[i].locID[0] = Loco::comptLoco & 0xFF00;
loco[i].locID[1] = Loco::comptLoco & 0x00FF;
Serial.printf("Creation dans la liste Loc-ID = %d\n", Loco::comptLoco);
// MFX Bind
delay(10);
for (byte i = 0; i < 8; i++)
canSendDta[i] = 0x00;
canSendDta[0] = loco[i].UID[0];
canSendDta[1] = loco[i].UID[1];
canSendDta[2] = loco[i].UID[2];
canSendDta[3] = loco[i].UID[3];
canSendDta[4] = loco[i].locID[0];
canSendDta[5] = loco[i].locID[1];
err = sendMsgCan(0x02, 6, canSendDta);
// MFX Verify
delay(10);
err = sendMsgCan(0x03, 6, canSendDta);
goto end;
}
}
end:
Serial.println("Exit");
}
}
}
}