Auteur Sujet: Arduino + LMD18200  (Lu 18569 fois)

jpjcb66

  • Jr. Member
  • **
  • Messages: 62
    • Voir le profil
Arduino + LMD18200
« le: février 17, 2016, 01:34:44 pm »
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

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2889
  • 100% Arduino et N
    • Voir le profil
Re : Arduino + LMD18200
« Réponse #1 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
« Modifié: avril 29, 2016, 10:41:49 pm par Dominique »
Cordialement,
Dominique

jpjcb66

  • Jr. Member
  • **
  • Messages: 62
    • Voir le profil
Re : Arduino + LMD18200
« Réponse #2 le: avril 29, 2016, 10:34:48 pm »
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

  • Jr. Member
  • **
  • Messages: 62
    • Voir le profil
Re : Arduino + LMD18200
« Réponse #3 le: avril 30, 2016, 09:03:24 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

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.

/********************
     * 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();
    }

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2889
  • 100% Arduino et N
    • Voir le profil
Re : Arduino + LMD18200
« Réponse #4 le: avril 30, 2016, 10:23:36 pm »
J'aurais tendance à penser qu'il faut ajouter dans le SetUp:
pinMode(A0,  INPUT);
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 :

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);
  }
 

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
Cordialement,
Dominique

jpjcb66

  • Jr. Member
  • **
  • Messages: 62
    • Voir le profil
Re : Arduino + LMD18200
« Réponse #5 le: mai 01, 2016, 10:38:28 am »
OK merci Dominique pour votre réponse.
Je vais essayer ça ainsi que l'application du très bel article "Comment piloter trains et accessoires en DCC avec un Arduino". Bravo pour ce travail.

Cdlt JP

jpjcb66

  • Jr. Member
  • **
  • Messages: 62
    • Voir le profil
Re : Arduino + LMD18200
« Réponse #6 le: mai 01, 2016, 02:28:54 pm »
En fait le court sketch du 30/04 un peu plus haut fonctionne avec un décodeur ESU54400 sur le canal 2
Par contre pour l'instant le décodeur du début des années 2000 ne fonctionne qu'au niveau éclairage avec ce sketch.
Les deux fonctionnent ou fonctionnaient plus exactement avec le kit Roco 10761 et la Lok Maus 2. car une maladresse a mis un terme à la vie des étages de puissance de la digitalbox 10761 : voir les flèches.
Sur la Maus 2 le potar de commande comporte un encliquetage qui permet de sentir le point 0.
Je reconnais qu'avec un potentiomètre normal "ça ne le fait pas".
Je vais donc m'orienter vers la solution d'un switch inverseur en étudiant votre travail.

L'idéal serait de remplacer cette digitalbox en logique câblée (74HCxxx) et autres nands et trigger de scmitt) par une box à base d'arduino avec les mêmes fonctions. Il y a plus de 15 ans entre ces deux technologies.
Je ne doute pas que Roco a évolué depuis. Ses prix aussi....



« Modifié: mai 01, 2016, 03:39:49 pm par jpjcb66 »

DDEFF

  • Hero Member
  • *****
  • Messages: 738
    • Voir le profil
Re : Arduino + LMD18200
« Réponse #7 le: mai 01, 2016, 06:44:44 pm »
Comme quoi, avant d'accuser le code ... ;D ;D ;D
"Ce n'est pas le puits qui est trop profond, c'est ta corde qui est trop courte" (proverbe chinois)

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2889
  • 100% Arduino et N
    • Voir le profil
Re : Arduino + LMD18200
« Réponse #8 le: mai 01, 2016, 07:23:11 pm »
L'idéal serait de remplacer cette digitalbox en logique câblée (74HCxxx) et autres nands et trigger de scmitt) par une box à base d'arduino avec les mêmes fonctions. Il y a plus de 15 ans entre ces deux technologies.

Avec tout ce que vous allez encore découvrir sur Locoduino, sur le thème de la génération DCC, je ne doute pas que vous allez la faire vous-même, cette box  ;)

Il y a des choses dans les cartons ou un coin de tête. Il faut juste qu'on trouve le temps...
Cordialement,
Dominique

jpjcb66

  • Jr. Member
  • **
  • Messages: 62
    • Voir le profil
Re : Re : Arduino + LMD18200
« Réponse #9 le: mai 01, 2016, 09:06:06 pm »
Comme quoi, avant d'accuser le code ... ;D ;D ;D

Je te soupçonne de m'avoir lu en digonale Denis !  :D  ;)
Le code n'y est pour rien dans le décès accidentel de mon booster Roco.
C'est juste mon bordelisme qui est en cause. Durant les essais de mon aiguillage triple un malicieux Bout de fil dénudé m'a permis de goûter le délicat fumet du composant qui grille ! :o  :-[
C'est après que je suis revenu contraint et forcé à l'arduino.

Et au passionnant article de Dominique qui en effet m'a motivé pour piloter mes locos via l'arduino.
Mais il y a du travail, la bibliothèque DCC m'est a ce stade d'un abord assaz mystérieux.

Bonne soirée.

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2889
  • 100% Arduino et N
    • Voir le profil
Re : Arduino + LMD18200
« Réponse #10 le: mai 01, 2016, 09:22:08 pm »
D'ailleurs il ne faut surtout pas oublier la détection de court-circuit, merci d'avoir pointé cette questions !
Cordialement,
Dominique

jpjcb66

  • Jr. Member
  • **
  • Messages: 62
    • Voir le profil
Re : Arduino + LMD18200
« Réponse #11 le: mai 02, 2016, 08:44:44 am »
D'ailleurs il ne faut surtout pas oublier la détection de court-circuit, merci d'avoir pointé cette questions !
Oh !J e ne l'ai pas pointée à dessin, j'ai juste avoué une belle négligence. D'ailleurs je crois que la dernière version Roco Centrale Ampli 10764 a anticipé mes distractions.
Malheureusement j'avais la génération 10761.
Il me semble que ce problème est décrit et résolu dans "Comment piloter trains et accessoires en DCC avec un Arduino (3)" à propos des sorties C/S et T/S du LMD18200 et amélioré avec le petit module Max471.

J'y retourne...  J'aimerais utiliser F1....F4   :D

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2889
  • 100% Arduino et N
    • Voir le profil
Re : Arduino + LMD18200
« Réponse #12 le: août 20, 2016, 01:49:16 pm »
Je crois que c'est le moins cher que j'ai trouvé (7,92€) !

http://www.ebay.fr/ulk/itm/252503593836
« Modifié: août 20, 2016, 01:51:54 pm par Dominique »
Cordialement,
Dominique