Discussions Générales > Bus DCC

Arduino + LMD18200

(1/3) > >>

jpjcb66:
Bonjour à tous,
J'ai une loco Roco achetée début des années 2000 équipée d'un décodeur Roco.
Elle fonctionne normalement, lumière et moteur avec le système Roco Transfo 15V 40VA+ centrale 10761 + maus2.
J'ai  en bon curieux appliqué "locoduino.org/spip.php?article14 et suivants" en lieu et place du matériel Roco.
Mon décodeur est paramétré en 01.
J'ai donc modifié les deux lignes 36 :  dps.setFunctions0to4(1,DCC_SHORT_ADDRESS,F0);  et  55 : dps.setSpeed128(1,DCC_SHORT_ADDRESS,speed_byte);
Le moniteur série fait bien ressortir une plage de fonctionnement entre -128 et 128 en actionnant le potar.
Mais ça doit être plus sioux que ça car il n'y a que l'éclairage de la machine qui répond au BP.
J'ai tout relu, ce n'est pas forcément évident.
Quelque chose qui vous semblera certainement évident depuis le temps que vous planchez sur le DCC m’échappe.
Si une idée passe par là.....  Je continue à chercher et vais essayer avec le nouveau décodeur reçu ce matin.
Merci

Dominique:
Bonjour,

Désolé pour le retard (considérable) !!!

Pour diagnostiquer, il faudrait un peu plus de code. Mais une première expérience à faire consiste à répéter les commandes 2, 3, ou 4 fois par seconde.

Si le code marche pour l'éclairage, ça prouve que l'adresse est bonne.
Pour la vitesse, il est certain que certains décodeurs (peut-être tous) ne réagissent que si la commande est répétée.

Dites-moi si ça change, sinon, envoyez moi votre code.

Bon courage

jpjcb66:
Bonsoir Dominique,
En effet ma question date un peu. J'ai du mettre ça en stand by et passer à autre chose, dont mon aiguillage 3 voies.
Je reviendrai la semaine prochaine sur ce problème Dcc.
Merci pour la reponse même tardive, vieux motard.......
Bonne soirée.

jpjcb66:

--- Citation de: Dominique le avril 29, 2016, 09:28:42 pm ---Bonjour,

Désolé pour le retard (considérable) !!!

Pour diagnostiquer, il faudrait un peu plus de code. Mais une première expérience à faire consiste à répéter les commandes 2, 3, ou 4 fois par seconde.

Si le code marche pour l'éclairage, ça prouve que l'adresse est bonne.
Pour la vitesse, il est certain que certains décodeurs (peut-être tous) ne réagissent que si la commande est répétée.

Dites-moi si ça change, sinon, envoyez moi votre code.

Bon courage

--- Fin de citation ---

Voici le code très simple que j'ai voulu tester :

Le bouton active la lumière de la machine mais aucune réaction au potar.

Demain si j'ai le temps de câbler un pupitre j'essaierai ton code bien plus complet.

Bonne soirée et merci pour le coup d’œil.


--- Code: ---/********************
     * Centrale DCC minimum avec un potentiomètre de vitesse connecté
     * sur le port analogique 0,
     * un bouton poussoir connecté entre le 0V et l'entrée digitale 4
     * Le signal DCC est délivré sur la Pin 9, et est capable de piloter
     * un booster à base de LMD18200 directement.
     ********************/
     
    #include <DCCPacket.h>
    #include <DCCPacketQueue.h>
    #include <DCCPacketScheduler.h>
     
    DCCPacketScheduler dps;
    unsigned int analog_value;
    char speed_byte, old_speed = 0;
    byte count = 0;
    byte prev_state = 1;
    byte F0 = 0;
     
    void setup() {
      Serial.begin(9600);
      dps.setup();  // initialisation de la librairie
     
      // Bouton sur la pin 4
      pinMode(4, INPUT_PULLUP);
    }
     
    void loop() {
      // Lecture de l'état du bouton pour la commande de lumière F0
      byte button_state = digitalRead(4); //high == relaché; low == appuyé
      if(button_state && (button_state != prev_state))
      {
        // inversion de l'état
        F0 ^= 1;
        Serial.println(F0,BIN);
        dps.setFunctions0to4(1,DCC_SHORT_ADDRESS,F0);  // adresse DCC  1
      }
      prev_state = button_state;
     
      // Potentiomètre de vitesse
      analog_value = analogRead(0);
      speed_byte = (analog_value >> 2)-127 ;
      // Ramène la gamme 0-1023 à +126-126, l'arrêt étant le point milieu du potentiomètre
      if(speed_byte != old_speed)
      {
        if(speed_byte == 0) // On évite l'arrêt brutal (e_stop) en remplaçant le 0 par 1
        {
          if(old_speed > 0) speed_byte = 1; 
          else speed_byte = -1;
        }
        Serial.print("analog = ");
        Serial.println(analog_value, DEC);
        Serial.print("digital = ");
        Serial.println(speed_byte, DEC);
        dps.setSpeed128(1,DCC_SHORT_ADDRESS,speed_byte);
        old_speed = speed_byte;
      }
      // Cet appel est impératif pour permettre à la librairie de faire son travail
      dps.update();
    }
--- Fin du code ---

Dominique:
J'aurais tendance à penser qu'il faut ajouter dans le SetUp:

--- Code: ---pinMode(A0,  INPUT);
--- Fin du code ---

Et bien désigner la pin analogique par A0 (plutôt que "0")

Si ça peut vous aider, j'ai écrit une classe Loco en C++ qui contient tout ce qu'on a besoin :


--- Code: ---class Loco
{
  private:
    byte index;                     // 0..MaxLOCO
    byte manette;
    bool etat;                      // arrêt (false) ou roule (true)
    int  adresseDCC;                //
    int  vitesse;                   // cran en cours
    byte prev_vitesse;              //
    bool dirloco;                   // direction avant ou arriere
    bool inverse;                   // inversion ou non de la direction
    byte maxSpeed;
    byte minSpeed;
    byte cran30;
    byte cran60;   
    bool change;                    // true : changement vitesse, direction, et/ou F0
    int  potarPin;
    int  potarLu;
    int  potarPrev;
    int  pot[16];                   // 16 lectures du potentiometre
    int  indexpot;
    int  clePin;
    int  cleDir;
    int  clePrev;
    int  boutonPin;
    Bounce bloco;
    int  ledPin;
    int  ledAcc;
    byte lumiere;
   
     
  public:
  // ----------- constructeur complet ------------
  Loco(byte a_index, int a_adresseDCC, int a_potarPin, int a_clePin, int a_boutonPin, int a_ledPin, bool a_inverse);

  void Setup();
  int  adrDCC();
  void SetadrDCC(byte a_adresseDCC);
  void SetmaxSpeed(byte a_maxSpeed);
  void SetminSpeed(byte a_minSpeed);
  void Setcran30(byte a_cran30);
  void Setcran60(byte a_cran60);
  void Rafraichir();
  void Repeter();
  void Nommer();
  void AllerAvant();
  void AllerArriere();
  void SetVitesse(int a_vitesse);
  void Stopper();
  void SetVitesse30();
  void SetVitesse60();
  void ResetVitesse();
  void Ralentir();
  byte Lumiere();
  void SetLumiere(bool a_F0);
  byte Direction();
  void SetDirection(bool a_Dir);
  void EtatLoco();
};

  // ------------ definition des methodes -----------

  Loco::Loco(byte a_index, int a_adresseDCC, int a_potarPin, int a_clePin, int a_boutonPin, int a_ledPin, bool a_inverse)
  {
    this->index = a_index;
    this->manette = this->index;
    this->potarPin = a_potarPin;
    this->clePin = a_clePin;
    this->boutonPin = a_boutonPin;
    this->bloco = Bounce();
    this->ledPin = a_ledPin;
    this->adresseDCC = a_adresseDCC;
    this->inverse = a_inverse;
    this->vitesse = 0;
    this->prev_vitesse = 0;
    this->dirloco = true;
    this->etat = false;
    this->change = false;
    this->ledAcc = 0;
    this->lumiere = false;
    this->maxSpeed = 125;
    this->minSpeed = 2;
    this->cran30 = 25;
    this->cran60 = 50;
    this->indexpot = 0;
  }

  void Loco::Setup()
  {
    pinMode(this->ledPin, OUTPUT);
    digitalWrite(this->ledPin, HIGH);         // Led ON
    delay (500);
    digitalWrite(this->ledPin, LOW);          // Led OFF
   
    pinMode(this->boutonPin,  INPUT_PULLUP);  // bouton
    this->bloco.attach(this->boutonPin);      // input pin associée
    this->bloco.interval(50);                 // debouce time en millisecondes
   
    pinMode(this->clePin,  INPUT_PULLUP);     // direction
    this->cleDir = digitalRead(this->clePin);
    this->dirloco = this->cleDir;
   
    pinMode(this->potarPin,  INPUT);          // speed pot
    this->potarLu = 0;
    this->indexpot = 0;
    for (int z=0; z<16; z++)  {
      this->pot[z] = analogRead(this->potarPin) >> 3;
      this->potarLu = this->potarLu + this->pot[z];
    }
    this->potarLu = this->potarLu >> 4;
    this->potarPrev = this->potarLu;
    this->vitesse = 00;
    if (this->dirloco == 0) {               // avant = 1  arriere = 0
      this->vitesse = -this->vitesse;
    }
    digitalWrite(this->ledPin, this->ledAcc);
                                      // chargement des parametres depuis le record en RAM
    this->adresseDCC = EEPConfig[this->index].dccAddress;
    this->maxSpeed = EEPConfig[this->index].MaxSpeed;
    this->minSpeed = EEPConfig[this->index].MinSpeed;
    this->cran30 = EEPConfig[this->index].cran30;
    this->cran60 = EEPConfig[this->index].cran60;
    this->inverse = EEPConfig[this->index].inverse;
   
  }

  int Loco::adrDCC()
  {
    return(this->adresseDCC);
  }


  void Loco::SetadrDCC(byte a_adresseDCC)
  {
    this->adresseDCC = a_adresseDCC;   
  }
 
 
  void Loco::SetmaxSpeed(byte a_maxSpeed)
  {
    this->maxSpeed = a_maxSpeed;   
  }
 
 
  void Loco::SetminSpeed(byte a_minSpeed)
  {
    this->minSpeed = a_minSpeed;   
  }
 
 
  void Loco::Setcran30(byte a_cran30)
  {
    this->cran30 = a_cran30;   
  }
 
 
  void Loco::Setcran60(byte a_cran60)
  {
    this->cran60 = a_cran60;   
  }
 
 
  void Loco::Rafraichir()
  {
    this->pot[indexpot++] = analogRead(this->potarPin) >> 3; // divide by 8 to take a 0-1023 range number and make it 0-127 range.
    if (indexpot > 15)  {indexpot = 0;}
    this->potarLu = 0;
    for (int z=0; z<16; z++)  {
      this->potarLu = this->potarLu + this->pot[z];
    }
    this->potarLu = this->potarLu >> 4;
    if ((this->potarLu < this->potarPrev -1)||(this->potarLu > this->potarPrev +1)) {
      this->potarPrev = this->potarLu;
      if (this->potarLu < this->maxSpeed) {
        this->vitesse = this->potarLu;
      } else {
        this->vitesse = this->maxSpeed;     
      }
      if (this->vitesse == 1) {
        this->vitesse = 0;                    // pour eviter l'arrêt d'urgence par potar
      }                               
      this->change = true;           
    }
    this->cleDir = digitalRead(this->clePin);
    if (this->cleDir != this->clePrev && this->vitesse == 0)  {
      this->clePrev = this->cleDir;
      this->dirloco = this->cleDir ^ this->inverse;  // av1 ^ inv1 = 0, ar0 ^ inv1 = 1
      this->change = true;
    }
    if (this->change) {
      this->prev_vitesse =  this->vitesse;        // version sans signe vs direction
      if (this->dirloco == 0) {                   // avant = 1  arriere = 0
        this->vitesse = -this->vitesse;
      }
      dps.setSpeed128(this->adresseDCC,DCC_SHORT_ADDRESS,this->vitesse);
      this->change = false;
      bufS[0] = this->index;
      if (this->lumiere) {
        bitSet(bufS[0], 7);                   // bit 7 = lumière
      }
      bufS[1] = this->prev_vitesse;           // vitesse sans signe, bit 7 = 0
      if (this->dirloco) {
        bitSet(bufS[1], 7);
      }
      CAN.sendMsgBuf(TId_LOCO, 0, 2, bufS);   // envoi paramêtres de conduite (Index, Vit, Dir, F0)
      if (_debug) {
        Serial.print(this->vitesse);
        Serial.print(" V loco @ ");
        Serial.println(this->adresseDCC);
      }
    } 
    if (this->bloco.update()) {
      if (this->bloco.rose()) {              // appui = 1  relaché = 0 : inversion lumiere
        if (this->lumiere) {
          this->lumiere = 0;
        } else  {
          this->lumiere = 1;
        }
        dps.setFunctions0to4(this->adresseDCC,DCC_SHORT_ADDRESS,this->lumiere);
        digitalWrite(this->ledPin, this->lumiere);
        bufS[0] = this->index;
        if (this->lumiere) {
          bitSet(bufS[0], 7);                   // bit 7 = lumière
        }
        CAN.sendMsgBuf(TId_F0, 0, 1, bufS);   // envoi paramêtres index et F0
        if (_debug) {
          Serial.print(this->lumiere);
          Serial.print(" F0 loco @ ");
          Serial.println(this->adresseDCC);
        }
      }
    }
  }


  void Loco::Repeter()
  {
    dps.setSpeed128(this->adresseDCC,DCC_SHORT_ADDRESS,this->vitesse);
    dps.setFunctions0to4(this->adresseDCC,DCC_SHORT_ADDRESS,this->lumiere);   
  }
 

  void Loco::SetVitesse(int a_vitesse)            // definit la vitesse maxi
  {
    this->maxSpeed = a_vitesse;
    if (this->prev_vitesse > a_vitesse)  {        // réduire la vitesse seulement si la vitesse maxi est inférieure
      this->vitesse = a_vitesse;
      this->prev_vitesse =  a_vitesse;            // version sans signe vs direction   
      if (this->dirloco == 0) {                   // avant = 1  arriere = 0
        this->vitesse = -this->vitesse;
      }
      dps.setSpeed128(this->adresseDCC,DCC_SHORT_ADDRESS,this->vitesse);
      bufS[0] = this->index;
      if (this->lumiere) {
        bitSet(bufS[0], 7);                   // bit 7 = lumière
      }
      bufS[1] = this->prev_vitesse;           // vitesse sans signe, bit 7 = 0
      if (this->dirloco) {
        bitSet(bufS[1], 7);
      }
      CAN.sendMsgBuf(TId_LOCO, 0, 2, bufS);   // envoi paramêtres de conduite (Index, Vit, Dir, F0)
      if (_debug) {
        Serial.print(this->vitesse);
        Serial.print(" V loco @ ");
        Serial.println(this->adresseDCC);
      }
    }                                         // sinon pas de changement de vitesse
  }


  void Loco::Stopper()
  {
    SetVitesse(0);     
  }
 

  void Loco::SetVitesse30()
  {
    SetVitesse(this->cran30);
   
  }


  void Loco::SetVitesse60()
  {
    SetVitesse(this->cran60);
   
  }
 
  void Loco::ResetVitesse()                   // remonte la vitesse maxi à maxSpeed
  {
    SetVitesse(this->maxSpeed);
   
  }
 
  void Loco::SetLumiere(bool a_F0)
  {
    this->lumiere = a_F0;
    dps.setFunctions0to4(this->adresseDCC,DCC_SHORT_ADDRESS,this->lumiere);
    digitalWrite(this->ledPin, this->lumiere);
    bufS[0] = this->index;
    if (this->lumiere) {
      bitSet(bufS[0], 7);                   // bit 7 = lumière
    }
    CAN.sendMsgBuf(TId_F0, 0, 1, bufS);     // envoi paramêtres index et F0
    if (_debug) {
      Serial.print(this->lumiere);
      Serial.print(" F0 loco @ ");
      Serial.println(this->adresseDCC);
    }
  }

 
  byte Loco::Lumiere()
  {
    return(this->lumiere);
  }
 

  void Loco::SetDirection(bool a_Dir)
  {
    this->dirloco = a_Dir;   
  }

 
  byte Loco::Direction()
  {
    return(this->dirloco);
  }
 
--- Fin du code ---

Je n'aime pas les potentiomètres de vitesse à point milieu (on ne trouve jamais le milieu !!!), donc j'ai une clé pour la direction. D'ailleurs j'interdis le changement de sens sans passer par l'arrêt.

Tenez moi au courant !
Cordialement

Navigation

[0] Index des messages

[#] Page suivante

Utiliser la version classique