2101
Les réseaux / Re : Projet Dominique
« le: décembre 21, 2017, 07:16:10 pm »
Le logiciel du module de traction
Je ne vais pas recopier tout le logiciel d'un coup, 1700 lignes, ce serait imbuvable !
Mais je vais distiller des morceaux que vous pourrez récupérer et re-utiliser dans vos projets.
D'abord un numéro et une date de version : ça permet d'éviter de se mélanger les pinceaux quand le projet s'étale dans le temps :
Les bibliothèques utilisées :
Pour utiliser la bibliothèque DCCpp de Therry, rien de plus simple :
Je redéfini dans mon programme les valeurs qui sont dans config.h et dans DCCpp.h et il ne me reste plus qu'à démarrer DCCpp dans le Setup :
Recherche des adresses des terminaux I2C
J'installe le sketch I2C_Scanner et j'obtient les adresses (je recopie le résultat dans mon programme, mais en commentaire :
Cela me permet de déclarer l'écran LCD et le clavier tactile (qui fonctionne en 3,3V, attention, il ne faut pas oublier d'ajouter un circuit convertisseur de niveau)
Puis on installe ces périphériques dans le setup :
Le bus CAN
Je fais carrément un copier-coller depuis mes autres programmes (ceux des autres modules) :
- Constructeur de l'objet CAN
- Définitions et variables de la memoire tampon circulaire pour y stocker immédiatement tout message reçu
- routine d'interruption du CAN, qui ne fait que monter un flag
- liste des identifiants utilisés dans mon réseau, qui concernent ce module de traction
Et puis la routine appelée chaque fois que le Flag_Recv est monté :
On remarque que cette routine assure la gestion des débordements (overflow) éventuels de cette mémoire tampon, ce qui ne m'est jamais arrivé.
On trouvera plus d'explications sur le CAN dans l'article ici : http://www.locoduino.org/spip.php?article148 et un peu plus loin dans ce sujet.
Petite pause pour se détendre, ensuite on verra un certain nombre de routines utilitaires écrites pour décharger la loop et la rendre plus lisible.
A suivre ...
Je ne vais pas recopier tout le logiciel d'un coup, 1700 lignes, ce serait imbuvable !
Mais je vais distiller des morceaux que vous pourrez récupérer et re-utiliser dans vos projets.
D'abord un numéro et une date de version : ça permet d'éviter de se mélanger les pinceaux quand le projet s'étale dans le temps :
Code: [Sélectionner]
const char VersTRACTION[20] = "DCCppTract08 141217"; // 19 caractères + \0
Les bibliothèques utilisées :
Code: [Sélectionner]
#include "DCCpp.h" // La bibliothèque de Thierry
#include <Wire.h> // bus I2C
#include <Streaming.h> // http://arduiniana.org/libraries/streaming/
#include <LiquidCrystal_I2C.h> // I2C adresse 0x27
#include <SPI.h> // bus SPI
#include <mcp_can.h> // bus CAN
#include "Adafruit_MPR121.h" // I2C adresse 0x5A
#include <Encoder.h> // encodeur
#include <Bounce2.h> // boutons poussoir
#include <EEPROM.h> // Eeprom integree
#include "Classes.h" // Ma classe CmdLoco pour commander les locos
Pour utiliser la bibliothèque DCCpp de Therry, rien de plus simple :
Code: [Sélectionner]
#define MOTOR_SHIELD_TYPE 0 // LMD18200
#define COMM_INTERFACE 0
#define LMD_DIR 12 // DCC_MAIN = Arduino Mega - uses OC1B - DIR LMD18200
#define DCC_MAIN 12
#define LMD_PWM 3 // DCC_ENABLE = PWM LMD18200
#define DCC_ENABLE 3
#define Max471 A0 // current sensor
Je redéfini dans mon programme les valeurs qui sont dans config.h et dans DCCpp.h et il ne me reste plus qu'à démarrer DCCpp dans le Setup :
Code: [Sélectionner]
DCCpp::begin();
DCCpp::beginMain(UNDEFINED_PIN, LMD_DIR, LMD_PWM, Max471); // Dc: Dir, Pwm, current sensor
Recherche des adresses des terminaux I2C
J'installe le sketch I2C_Scanner et j'obtient les adresses (je recopie le résultat dans mon programme, mais en commentaire :
Code: [Sélectionner]
//////////// I2C ///////////
// I2C device found at address 0x23 = NRF24L01
// I2C device found at address 0x27 = lcd
// I2C device found at address 0x5A = clavier tactile
Cela me permet de déclarer l'écran LCD et le clavier tactile (qui fonctionne en 3,3V, attention, il ne faut pas oublier d'ajouter un circuit convertisseur de niveau)
Code: [Sélectionner]
///////////// LCD a l'adresse I2C = 0x27 ////////////
LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 20 chars and 4 line display
///////////// RETRO-ECLAIRAGE LCD ///////////////////
#define eclairage 180000 // extinction auto du retro-eclairage au bout de 3 minutes
unsigned long retrotime;
unsigned long lblinktime;
///////////// Touchpad à l'adresse I2C = 0x5A ///////
Adafruit_MPR121 cap = Adafruit_MPR121();
uint16_t lasttouched = 0;
uint16_t currtouched = 0;
int Key;
// Attach the MPR121's IRQ pin to digital pin 4
const int PIN_TOUCH_IRQ = 4;
Puis on installe ces périphériques dans le setup :
Code: [Sélectionner]
//--- init Serial et LCD
pinMode(PIN_TOUCH_IRQ, INPUT);// pour l'interruption du clavier tactile
Serial.begin(115200);
Serial.flush();
Serial.println(VersTRACTION); // affichage du N° de version sur le Terminal
lcd.init(); // initialize the lcd
lcd.clear();
lcd .backlight();
lcd.noBlink();
Le bus CAN
Je fais carrément un copier-coller depuis mes autres programmes (ceux des autres modules) :
- Constructeur de l'objet CAN
- Définitions et variables de la memoire tampon circulaire pour y stocker immédiatement tout message reçu
- routine d'interruption du CAN, qui ne fait que monter un flag
- liste des identifiants utilisés dans mon réseau, qui concernent ce module de traction
Code: [Sélectionner]
///////////// CAN BUS //////////////
MCP_CAN CAN(53); // Set CS to pin 53 (MEGA)
volatile byte Flag_Recv = 0; // flag pour l'interruption IRQ
//--- Message recu
byte IdR; // Id pour la routine CAN_recup()
unsigned char lenR = 0; // Longueur " " "
unsigned char bufR[8]; // buffer reception "
//--- Message emis
unsigned char bufS[8]; // buffer emission
//--- Memoire circulaire pour le stockage rapide des messages recus
unsigned char _Circule[512]; // recepteur circulaire des messages CAN sous IT
unsigned int _indexW, _indexR, _Ncan; // index d'ecriture et lecture, nb d'octets a lire
byte _CANoverflow = 0; // flag overflow (buffer _Circule plein)
int curIndex; // loco désignée dans un message CAN
bool DCC_OK_Central = false;
//--- Interruption (ISR) CAN
void MCP2515_ISR()
{
Flag_Recv = 1;
}
//--- Ids des messages
#define RId_LOCO 0x30 // commande central pour un train (Index, Vit, Dir, F0)
#define RId_F0 0x31 // commande central F0
#define RId_URGENT 0x32 // arrêt urgence (0x8F) et reprise (0x0F)
#define RId_PARAM 0x33 // configuration (index, @dcc, Vmin, Vmax, cran30, cran60)
#define RId_POSTE 0x38 // affichage sur poste de conduite (0x00..0x3F)
#define TId_LOCO 0x13 // envoi des paramêtres de conduite (Index, Vit, Dir, F0)
#define TId_F0 0x14 // envoi F0 d'une loco (index, F0)
#define TId_DCC 0x15 // envoi état DCC (0x80 = on; 0x00 = off)
#define TId_ICC 0X16 // envoi intensité (mA/16) et alarme CC (bit 7)
#define TId_VV 0x17 // envoi consignes V&V (vitesses aller et retour)
#define TId_VITESSE 0x18 // envoi mesure de vitesse d'un train
#define TId_TRACT_CAN 0x1E // envoi alarme CAN overflow
Et puis la routine appelée chaque fois que le Flag_Recv est monté :
Code: [Sélectionner]
//--- Routine de récuperation des messages CAN dans la memoire circulaire _Circule
//--- appelee par LOOP lorsque Flag_Recv = 1;
void CAN_recup()
{
unsigned char len = 0; // nombre d'octets du message
unsigned char buf[8]; // message
unsigned char Id; // Id
while (CAN_MSGAVAIL == CAN.checkReceive()) {
CAN.readMsgBuf(&len, buf); // read data, len: data length, buf: data buf
Id = CAN.getCanId();
if ((_Ncan+len+2) < sizeof(_Circule)) { // il reste de la place dans _Circule
_Circule[_indexW] = Id; // enregistrement de Id
_indexW++;
_Ncan++;
if (_indexW == sizeof(_Circule)) {_indexW = 0;}
_Circule[_indexW] = len; // enregistrement de len
_indexW++;
_Ncan++;
if (_indexW == sizeof(_Circule)) {_indexW = 0;}
for (byte z = 0; z<len; z++) {
_Circule[_indexW] = buf[z]; // enregistrement du message
_indexW++;
_Ncan++;
if (_indexW == sizeof(_Circule)) {_indexW = 0;}
}
} else {
_CANoverflow = 1; // depassement de la capacite de Circule
}
}
}
On remarque que cette routine assure la gestion des débordements (overflow) éventuels de cette mémoire tampon, ce qui ne m'est jamais arrivé.
On trouvera plus d'explications sur le CAN dans l'article ici : http://www.locoduino.org/spip.php?article148 et un peu plus loin dans ce sujet.
Petite pause pour se détendre, ensuite on verra un certain nombre de routines utilitaires écrites pour décharger la loop et la rendre plus lisible.
A suivre ...