Etape | Commande |
Autentification | status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid)); |
Lecture | status = mfrc522.MIFARE_Read(block, buffer, &size); |
if (status != MFRC522::STATUS_OK) {…}
L'instruction .GetStatusCodeName(status)
donne le message d'erreur// ========================================================
// Lecture Block
// ========================================================
void Read_Block(byte block,int n1, int n2, int mode) {
// Serial.println();
for (byte i = 0; i < MFRC522::MF_KEY_SIZE; ++i) {
key.keyByte[i] = 0xFF;
}
// if (mfrc522.PICC_ReadCardSerial()) {
status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
if (status == MFRC522::STATUS_OK) {
status = mfrc522.MIFARE_Read(block, buffer, &size);
if (status == MFRC522::STATUS_OK) {
if (mode<2) {
Serial.print(F("Data in block ")); Serial.print(block); Serial.print (F(": "));
}
TmpStr="";
for (int p=n1; p<n2; p++) {
if (mode==0) {
Serial.print(buffer[p] < 0x10 ? " 0" : " ");
Serial.print(buffer[p], HEX);
}
else if(mode%2==1) {
if (buffer[p]>20) TmpStr+=(char)buffer[p];
else TmpStr+="-";
}
}
if(mode%2==1) Serial.print(TmpStr);
Serial.println();
}
}
// }
}
Read_Block(Param[0].toInt(),Param[1].toInt(),Param[2].toInt(),0);
mfrc522.PCD_StopCrypto1(); // Stop encryption on PCD
Ecrire dans un RFIDEtape | Commande |
Autentification | status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid)); |
Ecriture | status = mfrc522.MIFARE_Write(block, nbuffer, 16); |
if (status != MFRC522::STATUS_OK) {…}
L'instruction .GetStatusCodeName(status)
donne le message d'erreur// ========================================================
// Configuration RFID
// ========================================================
void ConfigureRFID(byte block, String s, byte v) {
// Vidage du buffer
byte nbuffer[16];
for (int p=0;p<16;p++) {
nbuffer[p]=' ';
}
if (String(s.charAt(0))=="#") { // Configuration du nom
for (int p=1;p<s.length();p++) {
nbuffer[p-1]=s[p];
Serial.print(nbuffer[p-1]);Serial.print(" ");
}
Serial.println("!");
} else { // Configuration du Nr et du type
Read_Block(block,0,16,0); // Recupere les valeurs initiales
for (int p=0;p<16;p++) {
nbuffer[p]=buffer[p];
Serial.print(nbuffer[p]);Serial.print("-");
}
Serial.println("!");
nbuffer[s.toInt()]=v; // Change le CV concerné
}
Serial.println(F("Authenticating using key A..."));
for (int p=0;p<16;p++) {
Serial.print(nbuffer[p]);Serial.print(" ");
}
Serial.println("!");
status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
if (status != MFRC522::STATUS_OK) {
for (int p=0;p<16;p++) {
Serial.print(nbuffer[p]);Serial.print(" ");
}
Serial.println("!");
Serial.print(F("PCD_Authenticate() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
for (int p=0;p<16;p++) {
Serial.print(nbuffer[p]);Serial.print(" ");
}
Serial.println("!");
return;
}
else Serial.println(F("PCD_Authenticate() success: "));
Serial.println();
for (int p=0;p<16;p++) {
Serial.print(nbuffer[p] < 0x10 ? " 0" : " ");
Serial.print(nbuffer[p], HEX);
}
status = mfrc522.MIFARE_Write(block, nbuffer, 16);
if (status != MFRC522::STATUS_OK) {
Serial.print(F("MIFARE_Write() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
else Serial.println(F("MIFARE_Write() success: "));
}
Dans tous les cas, une fois l'écriture effectuée, il faut clore le cryptage du RFID a l'aide de l'instruction .PCD_StopCrypto1() ConfigureRFID(Param[0].toInt(),Param[1], Param[2].toInt());
mfrc522.PCD_StopCrypto1(); // Stop encryption on PCD
# define I2C_SLAVE1_ADDRESS 11
# define I2C_SLAVE2_ADDRESS 12
# define I2C_SLAVE_ADDRESS 11 // 12 pour l'esclave 2 et ainsi de suite
# define I2cMsgLength 60
Maitre# define I2C_SLAVE1_ADDRESS 11
# define I2C_SLAVE2_ADDRESS 12
# define I2C_SLAVE_ADDRESS 11 // 12 pour l'esclave 2 et ainsi de suite
# define I2cMsgLength 60
Dans le Setup Wire.begin();
// ========================================================
// Scan des esclaves I2C pour obtenir les messages
// ========================================================
void I2CGetMessages() {
for (int i=10; i< 15;i++) {
int j=0;
int nr=0;
char Message[I2cMsgLength];
inStr="";
//Serial.println(F(" recieved : "));
Wire.requestFrom(i, I2cMsgLength); // Demande 60 Octets à l'esclave I2C #i
while (Wire.available()>0) { // L'esclave peut envoyer moins d'octets
Message[j] = Wire.read(); // reception d'un octet
if (Message[j]>=0) {
inStr+=Message[j];
}
j++;
}
// Traitement des messages recus
if (inStr!="" && inStr.length()>3) {
Serial.print(F(" recieved ("));
Serial.print(inStr.length());
Serial.print(F(") : "));
Serial.println(inStr);
if (inStr[2]=='P') { // Annonce arrivée des trains
inStr = String(Dcc.getCV(CV_JINGLE)) + "_" + inStr.substring(3); // (ajout du jingle)
Annonce(inStr); // Sequencage de l'annonce
} else if (inStr[2]=='J') { // Autre sons
inStr.replace('_',' ');
} else if (inStr[2]=='-') { // Defaut
inStr.replace('_',' ');
}
}
delay(100);
}
}
Il reste alors a traiter les messages reçus en fonction de ce que l’on souhaite faire.# define I2C_SLAVE1_ADDRESS 11
# define I2C_SLAVE2_ADDRESS 12
# define I2C_SLAVE_ADDRESS 11 // 12 pour l'esclave 2 et ainsi de suite
# define I2cMsgLength 60
Dans le Setup Wire.begin(I2C_SLAVE_ADDRESS);
Wire.onRequest(requestEvents);
Wire.onReceive(receiveEvents);
// ========================================================
// Reception message I2C
// ========================================================
void receiveEvents(int numBytes)
{
Serial.println(F("---> recieved events"));
n = Wire.read();
Serial.print(numBytes);
Serial.println(F("bytes recieved"));
Serial.print(F("recieved value : "));
Serial.println(n);
}
// ========================================================
// Réponse a un message reçu I2C
// ========================================================
void requestEvents()
{
if (Param[0]!="") {
Param[0].toCharArray(Message,60);
Serial.print(F("sending value ("));
Serial.print(String(Message).length());
Serial.print(F(") : "));
Serial.println(String(Message));
Wire.write(Message);
Serial.println();
Param[0]="";
Param[0].toCharArray(Message,60);
} else {
Wire.write("11-");
}
}
Serial.print(F("Message : "));
Serial.println(Param[0]);
Param[0]="11P"+Param[0];
// ========================================================
// Structures DCC
// ========================================================
struct CVPair
{
uint16_t CV;
uint8_t Value;
};
#define CV_VOLUME 15
CVPair FactoryDefaultCVs [] =
{
{CV_VOLUME,5}, // Volume Son MP3
}
int v=Dcc.getCV(i)
Dcc.setCV(Param[0].toInt(),Param[1].toInt());
// ========================================================
// Reset CV
// ========================================================
void ResetCV() {
Serial.print(Msg_ResetCV);
for (int j=0; j < sizeof(FactoryDefaultCVs)/sizeof(CVPair); j++ ) {
Serial.print(FactoryDefaultCVs[j].CV);
Serial.print(F(" = "));
Serial.println(FactoryDefaultCVs[j].Value);
Dcc.setCV( FactoryDefaultCVs[j].CV, FactoryDefaultCVs[j].Value);
}
}
// ========================================================
// Dcc Accessory Turnout message treatment
// ========================================================
void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t Direction, uint8_t OutputPower )
{
DccMsg=Addr;
DccMsg+=",";
DccMsg+=Direction;
DccMsg+=",";
DccMsg+=OutputPower;
if (LastDccMsg!=DccMsg) {
LastDccMsg=DccMsg;
//#ifdef Debug >>>>>>>>>>>>>>>>>>>>>>>>
Serial.print("notifyDccAccTurnoutOutput: ") ;
Serial.print(Addr,DEC) ;
Serial.print(',');
Serial.print(Direction,DEC) ;
Serial.print(',');
Serial.println(OutputPower, HEX) ;
//#endif <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
byte data;
int address=Addr;
boolean enable=(Direction==1) ? 1: 0;
boolean activate=(OutputPower==1) ? 1: 0;
bool Upd=false;
switch (Mode) {
case 0: // Update Turnout state, if in the list
// If address is one of the expected (Aiguillage[])
// update its direction (Trn[])
for (int i=0; i<20; i++) {
if (address=Dcc.getCV(CV_TRN_ADD + i)) {
if (Trn[i]!=enable) {
Trn[i]=enable;
Serial.print(address);
Serial.print(F(" -> "));
Serial.println(Trn[i]);
Upd=true;
}
}
}
if (Upd) ShowTurnOutState(); // Display turnout known states
break;
case 1: // Display received accessory address and state
digitalWrite(DccAckPin,true);
tmpDccAddress=address;
msg = "Detecte Dcc : ";
msg += String(tmpDccAddress);
Serial.println(msg);
msg = "! ou SW2 = Sauve Adresse Dcc "; //Cmd_SaveDcc;
msg += String(tmpDccAddress);
Serial.println(msg);
digitalWrite(DccAckPin,false);
break;
}
}
}
// ========================================================
// Affiche l'etat des aiguillages surveilles
// ainsi que les MP3 de provenance et de destination
// ========================================================
void ShowTurnOutState() {
String tmp="";
Serial.println(F("===="));
for (int i=9;i>=0;i--) {
if (Trn[i]) tmp+="1"; else tmp+="0";
}
Serial.println(tmp);
// Calcul Provenance
Provenance=0; // =tmp[2]+2*(tmp[1]+2*Trn[0]);
for (int i=2;i>=0;i--) {
Provenance=2*Provenance;
if (Trn[i]==true) Provenance+=1;
}
Serial.print(F("Provenance : "));
Serial.print(Provenance);
Serial.print(F(" CV "));
Serial.print(CV_MP3_PROV+Provenance);
Prv=Dcc.getCV(CV_MP3_PROV+Provenance);
Serial.print(F(" = "));
Serial.println(Prv);
// Calcul Destination
Destination=0; //=Trn[6]+2*(Trn[5]+2*(Trn[4]+2*(Trn[3]+2*(Trn[2]+2*(Trn[1]+2*Trn[0])))));
for (int i=9;i>2;i--) {
Destination=2*Destination;
if (Trn[i]==true) Destination+=1;
}
Serial.print(F("Destination : "));
Serial.print(Destination);
Serial.print(F(" CV "));
Serial.print(CV_MP3_DEST+Destination);
Dst=Dcc.getCV(CV_MP3_DEST+Destination);
Serial.print(F(" = "));
Serial.println(Dst);
}
// ========================================================
// Creation de l'annonce en DCC
// ========================================================
void MakeAnnonce(int train, int t) {
String s;
// Calcul Provenance
Provenance=0; // =tmp[2]+2*(tmp[1]+2*Trn[0]);
for (int i=2;i>=0;i--) {
Provenance=2*Provenance;
if (Trn[i]==true) Provenance+=1;
}
Prv=Dcc.getCV(CV_MP3_PROV+Provenance);
// Calcul Destination
Destination=0; //=Trn[6]+2*(Trn[5]+2*(Trn[4]+2*(Trn[3]+2*(Trn[2]+2*(Trn[1]+2*Trn[0])))));
for (int i=9;i>2;i--) {
Destination=2*Destination;
if (Trn[i]==true) Destination+=1;
}
Dst=Dcc.getCV(CV_MP3_DEST+Destination);
if (train!=0) { // Le train est connu
if (t==0) {
Serial.print(F("Le train ")); // Creation de l'annonce en fonction des éléments
Serial.print(train);
Serial.print(F(" En provenance de "));
Serial.print(Prv);
Serial.print(F(" va entrer en gare "));
Serial.print(Dst);
Serial.println(F(" Eloignez vous de la bordure des quais"));
s = "P" + String(Dcc.getCV(CV_LETRAIN)) + "_" + String(train) // Le Train N°
+ "_" + String(Dcc.getCV(CV_PROVENANCE)) + "_" + String(Dcc.getCV(CV_MP3_PROV+Provenance)) // en provenance de
+ "_" + String(Dcc.getCV(CV_VA_ENTRER)) + "_" + String(Dcc.getCV(CV_MP3_DEST+Destination)) // va entrer en gare Voie
+ "_" + String(Dcc.getCV(CV_ELOIGNEZ_VOUS));
} else if (t==1) {
Serial.print(Dst);
Serial.println(F(" attention au passage d'un train"));
s = "P" + String(Dcc.getCV(CV_MP3_DEST+Destination)) // Voie
+ "_" + String(Dcc.getCV(CV_PASSAGE)); // attention au passage d'un train
} else if (t==2) {
Serial.print(F("Attention "));
Serial.print(F(" le train "));
Serial.print(train);
Serial.print(F(" En provenance de "));
Serial.print(Prv);
Serial.println(F(" est annonce avec un retard de 10 minutes"));
s = "P" + String(Dcc.getCV(CV_JINGLE)) // Jingle
+ "_" + String(train) // Le Train N°
+ "_4_" + String(Dcc.getCV(CV_MP3_PROV+Provenance)) // en provenance de
+ "_11_"; // est annonce avec un retard de 10 minutes
} else {
Serial.println(F("Suite a un mouvement de grève ... "));
s = "P37_"; // Suite a un mouvement de grève ...
}
} else { // Le Train est inconnu
long randNumber = random(110,130);
if (randNumber==109){ // Greve
s = "P7"; // Par suite d'un mouvement de Greve
} else { // Train sans arrêt
s = "P7_" + String(Dcc.getCV(CV_MP3_DEST+Destination)) // Attention Voie
+ "_6"; // eloignez vous ...
}
}
Param[0]="11"+s; // mise a disposition de l'annonce pour les requetes I2C
}
Base | Type |
0-39 | (40) Général annonces |
50-69 | (20) Quais |
70-89 | (20) Gares |
90-139 | (50) Trains |
150-179 | (30) Animaux |
170-199 | (20) Véhicules |
200-255 | (55) Ambiance |
Commande | Fonction | Générique MAM |
? | Aide | Liste des commandes disponibles |
& | Liste | Liste des valeurs des paramètres |
@ | Identification Sketch | Identification du sketch chargé ex: MAM-Gare V0 |
{a v | Set CV | Programmation CV :Adresse (0-255) Valeur(0-15) {1 255 permet de réinitialiser les CV |
}a | Get CV | Lecture CV : Adresse (0-255) } affiche toutes les CV via USB |
Vv | Volume | Niveau sonore DfPlayer (0-30) |
Jj | Joue | Joue fichier MP3 identifié par son N°(1-255) |
Z | Stop | Stop le MP3 en cours. |
Commande | Fonction | MAM ReadRfid & MAM GaresMAM |
R | Reset CV | Remet les CV du décodeur à leur valeur initiale. |
Tn v | Turnout | Test le changement de position de l’aiguillage suivi n en position v en absence de DCC |
An t | Annonce | Test une annonce en absence de RFID (on indique le N° du train et son type) |
# | Affiche données RFID | Affiche le contenu du RFID devant le lecteur sous forme hexadécimale. |
G | Get RFID CV | G<Bloc> <N° 1er CV dans le bloc> <Nombre de CV> Affichage des CV du RFID devant le lecteur sous forme hexadécimale. |
S | Set RFID CV | S<Bloc> <N° CV dans le bloc> <Valeur du CV> S<Bloc> #<Valeur de la chaîne> Définit le ou les CV du RFID devant le lecteur Les chaînes ont 16 caractères maximum! |
D | Définit DCC | D<n> <Adresse DCC> Définit l'adresse DCC à suivre en position n |
Le moniteur série indique alors: | Set Turnout x à y |
Position des différents aiguillages surveillés | 10010100 |
N° MP3, CV correspondant = Valeur du CV | Provenance : 4 CV 184 = 255 |
N° MP3, CV correspondant = Valeur du CV | Destination : 18 CV 68 = 50 |
CV | |
Volume | 15 |
Adresse 1er esclave I2C | 16 |
Nombre d'esclaves | 17 |
MP3 Jingle SNCF | 100 |
MP3 | 101 à 104 120 et 121 |
CV | |
Adresse esclave | 16 |
Adresses DCC des appareils de voie surveillés | 30 à 49 |
Numéro MP3 standard annonces | 200 à 260 |
Numéro MP3 de provenance | 180 à 188 |
Numéro MP3 de destination | 50 à 177 |
De plus, initialement prévu pour l'arrivée des trains en gare, il devrait bientôt permettre les annonces pour les départs, les grèves et autres ...