Auteur Sujet: Projet Dominique  (Lu 9782 fois)

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1524
  • 100% Arduino et N
    • Voir le profil
Re: Projet Dominique
« Réponse #30 le: novembre 25, 2017, 11:25:47 am »
je dois maintenant refaire le module de traction
« Modifié: novembre 25, 2017, 01:16:29 pm par Dominique »

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1524
  • 100% Arduino et N
    • Voir le profil
Re: Projet Dominique
« Réponse #31 le: novembre 26, 2017, 01:44:34 pm »
  • L'afficheur 4x20 I2C
  • Le clavier tactile 12 touches I2C
  • L'encodeur en quadrature
  • Le LMD18200 pour fournir la puissance en DCC
  • L'interface CAN en SPI
  • Une interface radio NRF24L01
« Modifié: novembre 26, 2017, 05:05:26 pm par Dominique »

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1524
  • 100% Arduino et N
    • Voir le profil
Re: Projet Dominique
« Réponse #32 le: novembre 26, 2017, 05:45:37 pm »
.

A gauche les fonctions DCC :
Ajout
« Modifié: décembre 21, 2017, 09:17:23 pm par Dominique »

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1524
  • 100% Arduino et N
    • Voir le profil
Re: Projet Dominique
« Réponse #33 le: novembre 26, 2017, 07:51:37 pm »


C'est bidouille mais c'est solide, modifiable et fait pour durer.

A suivre...
« Modifié: décembre 21, 2017, 09:20:41 pm par Dominique »

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1524
  • 100% Arduino et N
    • Voir le profil
Re: Projet Dominique
« Réponse #34 le: décembre 01, 2017, 12:51:28 pm »
« Modifié: décembre 31, 2017, 10:15:00 am par Dominique »

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1524
  • 100% Arduino et N
    • Voir le profil
Re: Projet Dominique
« Réponse #35 le: décembre 09, 2017, 04:54:28 pm »
« Modifié: décembre 31, 2017, 10:21:39 am par Dominique »

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1524
  • 100% Arduino et N
    • Voir le profil
Re: Projet Dominique
« Réponse #36 le: décembre 15, 2017, 11:26:42 pm »
« Modifié: décembre 15, 2017, 11:38:05 pm par Dominique »

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1524
  • 100% Arduino et N
    • Voir le profil
Re: Projet Dominique
« Réponse #37 le: décembre 21, 2017, 07:16:10 pm »
Le logiciel du module de tractionconst char VersTRACTION[20] =  "DCCppTract08 141217"; // 19 caractres + \0


#include "DCCpp.h"              // La bibliothque 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

, rien de plus simple :

#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
Setup :

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//////////// I2C ///////////
// I2C device found at address 0x23  = NRF24L01
// I2C device found at address 0x27  = lcd
// I2C device found at address 0x5A  = clavier tactile
///////////// 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;
setup :

  //--- 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///////////// 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 dsigne 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        // arrt 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 paramtres 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
Flag_Recv//--- Routine de rcuperation 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
    }
  }
}
http://www.locoduino.org/spip.php?article148loop et la rendre plus lisible.

A suivre ...
« Modifié: décembre 31, 2017, 10:23:22 am par Dominique »

bricoleau

  • Jr. Member
  • **
  • Messages: 51
    • Voir le profil
Re: Projet Dominique
« Réponse #38 le: décembre 21, 2017, 10:14:38 pm »
  • adresse 0x27 + premier demi-octet
  • adresse 0x27 + premier demi-octet avec activation de la commande "enable"
ce qui va durer 6 ms
« Modifié: décembre 21, 2017, 10:30:04 pm par bricoleau »

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1524
  • 100% Arduino et N
    • Voir le profil
Re: Projet Dominique
« Réponse #39 le: décembre 21, 2017, 11:32:17 pm »
« Modifié: décembre 21, 2017, 11:38:58 pm par Dominique »

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1524
  • 100% Arduino et N
    • Voir le profil
Re: Projet Dominique
« Réponse #40 le: décembre 30, 2017, 07:32:35 pm »
D'abord un petit rappel de ce que j'ai compris du CAN :

Le bus CAN est fiable :-11Les performances

Et les filtres alors ?setup

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1524
  • 100% Arduino et N
    • Voir le profil
Re: Projet Dominique
« Réponse #41 le: décembre 30, 2017, 07:54:29 pm »
Gestionnaire : 00..1FTCO, occupations de zones : 20..2FSignalisation : 50..5FAutres capteurs : 60..6FAutres actionneurs : 70..7F

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1524
  • 100% Arduino et N
    • Voir le profil
Re: Projet Dominique
« Réponse #42 le: décembre 31, 2017, 10:57:01 am »
  while (_Ncan > 2)  {                // messages dans _Circule : au moins 3 bytes
    _Ncan--;
    RId = _Circule[_indexR];          // recuperation de l' Identifiant
    _indexR++;
    if (_indexR == sizeof(_Circule))  {_indexR = 0;}
    _Ncan--;
    Rlen = _Circule[_indexR];         // recup longueur
    _indexR++;
    if (_indexR == sizeof(_Circule))  {_indexR = 0;}
    for (int k = 0; k < Rlen; k++)  {
      _Ncan--;
      Rbuf[k] = _Circule[_indexR];    // recuperation des octets du message
      _indexR++;
      if (_indexR == sizeof(_Circule))  {_indexR = 0;}
    } // le message est dans les globales RId, Rlen et Rbuf[..]

    //-- Traitement des messages CAN (commandes du gestionnaire)

  } // fin traitement messages CAN
    //-- Traitement des messages CAN (commandes du gestionnaire)
 
    curIndex = Rbuf[0] & 0x3F;       // ne garder que les bits 0..5 = index loco
    if (curIndex < MaxLocos) {
    switch (RId)  {
      case RId_LOCO:                 // 0x30 commande central pour un train (vitesse et direction)
      CanSpeed = Rbuf[1] & 0x7F;
      switch (CanSpeed) {
        case 30:
        gLocoSpeed[curIndex] = gConfigLocos[curIndex].cran30;
        break;
        case 60:
        gLocoSpeed[curIndex] = gConfigLocos[curIndex].cran60;
        break;
        case 90:
        gLocoSpeed[curIndex] = gConfigLocos[curIndex].cran90;
        break;
        default:
        gLocoSpeed[curIndex] = CanSpeed;
        break;
      }
      DccDirection = bitRead(Rbuf[1], 7);
      gLocoDirection[curIndex] = DccDirection;
      if (gConfigLocos[curIndex].inverse) {DccDirection = !DccDirection;}
      DCCpp::setSpeedMain(gConfigLocos[curIndex].registre, gConfigLocos[curIndex].dccAddress, gLocoStepsNumber, gLocoSpeed[curIndex], DccDirection);
      gChange = true;
      break;
     
      case RId_F0:                  // 0x31 commande central F0
      if (bitRead(Rbuf[0], 7)) {gLocoFunctions[curIndex].activate(0);} else {gLocoFunctions[curIndex].inactivate(0);}
      DCCpp::setFunctionsMain(gConfigLocos[curIndex].registre, gConfigLocos[curIndex].dccAddress, gLocoFunctions[curIndex]);
      gChange = true;
      break;
     
      case RId_URGENT:              // 0x32 arrt urgence et reprise
      if (Rbuf[0] == 0x8F) {                  // arret immediat
        stop_DCC();
        DCC_OK_Central = false;
      }
      if (Rbuf[0] == 0x0F) {                  // reprise
        start_DCC();
        DCC_OK_Central = true;
      }
      break;
     
      case RId_PARAM:                 // 0x33 configuration
      //curManette = Rbuf[0] >> 4;    // manette = quartet poids fort,
      break;
     
      case RId_POSTE:                 // 0x38 affichage du central vers poste de conduite (ligne 1)
      // afficher l'adresse DCC sur la manette, l'indication F0, ...
      break; 
      } 
    } 
curIndexgLocoSpeed[curIndex]gConfigLocos[curIndex]struct LocoCONFIG {
  byte registre;                      // numero de registre = pot+1
  byte active;                        // loco active (1=oui)
  int  dccAddress;                    // adresse DCC loco courte ou longue
  byte cran30;                        // cran DCC pour 30 km/h
  byte cran60;                        // cran DCC pour 60 km/h
  byte cran90;                        // cran DCC pour 90 km/h
  byte inverse;                       // inversion avant (0) /arriere (1=oui)
  byte lumiere;                       // lumiere FL (1=oui)
  byte MaxSpeed;                      // vitesse maxi souhaitable en cran DCC
  byte MinSpeed;                      // vitesse mini possible
};

L'analyse de la valeur de vitesse transmise dans le message CAN par un autre switchDccDirectioninverseDCCpp::setSpeedMain(gConfigLocos[curIndex].registre, gConfigLocos[curIndex].dccAddress, gLocoStepsNumber, gLocoSpeed[curIndex], DccDirection);

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1524
  • 100% Arduino et N
    • Voir le profil
Re: Projet Dominique
« Réponse #43 le: décembre 31, 2017, 11:20:19 am »
class CmdLoco {
private :
  int pinLedVerte; // et bouton
  int pinLedRouge;
  int pinPotar;
  unsigned long previousTime ;
  unsigned int intervalTime;
  int etat; // 0 : attente, 1 : 1er changement, 2 : confirmation
  bool buttonVState;
  bool marcheAvant;
  int potValue;
 
public :
  CmdLoco(int pLV, int pLR, int pPot, int pIt) {           // constructeur
    pinLedVerte = pLV;
    pinLedRouge = pLR;
    pinPotar = pPot;
    intervalTime = pIt;
  }

  void CmdInit() {
    marcheAvant=true;
    pinMode(pinLedVerte, OUTPUT);
    pinMode(pinLedRouge, OUTPUT);
    digitalWrite(pinLedVerte, !marcheAvant);        // allume si false
    digitalWrite(pinLedRouge, marcheAvant);         // eteinte
    previousTime = millis();
    this->etat = 0;
    buttonVState = true;   
  }

  void MajLed(bool d) {
    digitalWrite(pinLedRouge, d);
    digitalWrite(pinLedVerte, !d);      // allume si false
  }

  bool CmdMaj( bool d) {
    bool dir = d;
    bool change = false;
    bool buttonValue;
    if (millis()-previousTime >= intervalTime) {   
      previousTime = millis();   
      pinMode(pinLedVerte, INPUT);
      buttonValue = digitalRead(pinLedVerte);
      if (buttonValue != buttonVState) {    // changement d'etat de la pin
        switch (this->etat) {
          case 0:
          if (!buttonValue) {               // 1er appui
          this->etat = 1;                   // attente confirmation
          }
          break;
          case 1:
          if (!buttonValue) {               // confirmation d'appui
            buttonVState = buttonValue;     // nouvel ancien etat de la pin
            dir = !dir;                     // inversion sens de marche
            this->etat = 2;                 // appui en cours, do nothing
            change = true;                  // job done !
          }
          break;
          case 2:
          if (buttonValue) {                // relach
            this->etat = 3;                 // attente confirmation
          }
          break;
          case 3:
          if (buttonValue) {                // relach
            buttonVState = buttonValue;     // nouvel etat
            this->etat = 0;                 // fin process
          }
        }
      }
      pinMode(pinLedVerte, OUTPUT);
      digitalWrite(pinLedRouge, dir);
      digitalWrite(pinLedVerte, !dir);      // allume si false
    }
    return (change);
  }
 
}; // fin classe CmdLoco
CmdInit() qui doit initialiser chaque objet dans le setup();
- la fonction MajLed(bool d) qui allume l'une des 2 leds verte et rouge;
- la fonction CmdMaj( bool d)//--- TABLE DES LOCOS
CmdLoco * gTableCloco[MaxLocos];          // Table des locos

et l'initialiser dans le setup() :

  //--- creation des objets Cloco et de la table
  for (int L=0; L<MaxLocos; L++) {
    gTableCloco[L] = new CmdLoco(ledVerte[L],ledRouge[L],gPotPin[L], 25); // ledVerte, ledRouge, pot, intervalTime)
  }
  //--- initialisation des objets Cloco
  for (int L=0;L<MaxLocos;L++) {
    gTableCloco[L]->CmdInit();   
  }
int gSensorValue = 0;           // value read from the pot
int gOutputValue;
int gPot[MaxLocos];
bool gPotChange = false;

Enfin, la gestion de toute cette interface, dans la loop()  // potentiometres

  for (int i = 0; i < 12; i++) {
    gSensorValue = analogRead(gPotPin[i]);
    gOutputValue = map(gSensorValue, 0, 1023, 0, gConfigLocos[i].MaxSpeed);
    if (gOutputValue != gPot[i]) {
      gPot[i] = gOutputValue;
      gLocoSpeed[i] = gPot[i];
      gPotChange = true;
      DccDirection = gLocoDirection[i];
      if (gConfigLocos[i].inverse) {DccDirection = !DccDirection;}
      DCCpp::setSpeedMain(gConfigLocos[i].registre, gConfigLocos[i].dccAddress, gLocoStepsNumber, gLocoSpeed[i], DccDirection);     
    }
  }
 
  // boutons et leds de direction

  for (int u=0;u<MaxLocos;u++) {
    if (gLocoSpeed[u] == 0) {
      if (gTableCloco[u]->CmdMaj(gLocoDirection[u])) {     
        gLocoDirection[u] = !gLocoDirection[u];
      }
    }     
  }

« Modifié: décembre 31, 2017, 11:25:08 am par Dominique »

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1524
  • 100% Arduino et N
    • Voir le profil
Re: Projet Dominique
« Réponse #44 le: décembre 31, 2017, 11:34:58 am »
  • Un pilotage par le bus CAN


Amicalement

Dominique