LOCODUINO

Parlons Arduino => Bibliothèques => Discussion démarrée par: Juan le mai 25, 2021, 12:46:58 pm

Titre: Analog pushes avec Commanders
Posté par: Juan le mai 25, 2021, 12:46:58 pm
Bonjour.
Pour construire une TOC, je dois utiliser 16 boutons poussoirs pour activer et désactiver 16 mécanismes. Pour simplifier, nous pouvons dire que je dois allumer et éteindre 16 LEDs.
Pour éviter un câblage excessif, le plus intéressant serait de connecter les boutons-poussoirs en série, en utilisant ButtonsCommanderAnalogPushes de la bibliothèque Commanders.
Une fois l'installation de test effectuée, et les différentes tensions calibrées, en principe tout semble fonctionner : lorsqu'on appuie sur un bouton, la LED correspondante s'allume. Mais, que faire pour l'éteindre en appuyant à nouveau dessus ? J'aurais besoin de quelque chose comme AddEvent, mais cette commande n'est pas valable pour les boutons-poussoirs en série.
Une aide ?
Merci beaucoup,

Juan.
Titre: Re : Analog pushes avec Commanders
Posté par: Dominique le mai 25, 2021, 03:29:42 pm
Si vous associez à chaque lampe une variable d’état « allumée »  ou « éteinte », et commandez la lampe en fonction de son état, alors chaque appui sur un bouton doit simplement changer l’état : CQFD !

C’est un cas qui existe un peu partout en cherchant avec le mot « toggle »  8)
Titre: Re : Analog pushes avec Commanders
Posté par: Juan le mai 25, 2021, 05:24:55 pm
Merci beaucoup pour votre réponse Dominique, mais pourriez-vous être un peu plus précis ? Je ne le vois pas clairement.
Titre: Re : Analog pushes avec Commanders
Posté par: Dominique le mai 25, 2021, 07:04:37 pm
Si l’état de la lampe se nomme « etatLampe » de type booléen, vous faites :
etatLampe = !etatLampe;
Regardez cet exemple (que je vous ai suggéré):

 https://www.arduino.cc/en/tutorial/switch (https://www.arduino.cc/en/tutorial/switch)
Titre: Re : Analog pushes avec Commanders
Posté par: Juan le mai 25, 2021, 07:26:53 pm
C'est bon, je connaissais déjà le truc, je vais m'y mettre.
Merci beaucoup.
Titre: Re : Analog pushes avec Commanders
Posté par: Juan le mai 28, 2021, 08:20:20 pm
Bonsoir,
Le problème est que j'ai essayé tout l'après-midi d'appliquer la méthode précédente à mon croquis, et je n'y arrive pas. Je ne parviens pas à intégrer la méthode dans les Commanders, en utilisant les ButtonsCommanderAnalogPushes.
La vérité est que ma connaissance de la programmation en Arduino est très limitée.
Une aide ?
Merci beaucoup,
Juan.
Titre: Re : Analog pushes avec Commanders
Posté par: Dominique le mai 28, 2021, 11:18:16 pm
En quoi consiste votre projet ?
Pouvez-vous présenter votre croquis et ce qui coince ?
Titre: Re : Analog pushes avec Commanders
Posté par: Juan le mai 29, 2021, 06:50:42 pm
Bon après-midi,
Et bien après de nombreuses tentatives je peux annoncer que le décodeur fonctionne ... à demi-chemin.
Bref, demain j'essaierai de résumer mon projet, et je m'expliquerai avec cette demi-œuvre.
Meilleures salutations,
Juan.
Titre: Re : Analog pushes avec Commanders
Posté par: Dominique le mai 29, 2021, 07:19:32 pm
Comme quoi, quand on s’acharne ... ;D

Bravo et vivement votre présentation !
Titre: Re : Analog pushes avec Commanders
Posté par: Juan le mai 30, 2021, 12:54:58 pm
Bonjour, Dominique, et tous les autres.
Je vais essayer de résumer mon projet actuel, qui consiste à construire des décodeurs accessoires pour compléter un central DCC (soit DCC++, DCCpp, ou simplement DCC, comme le Lenz XpressNet, ce n'est pas le moment de parler des centraux).

Après plusieurs essais, j'ai décidé de classifier les accessoires de mon modèle en trois catégories : les aiguillages (solénoïdes dans mon cas), les sémaphores, et un troisième groupe avec le reste des effets "décoratifs" : lumières, sons, moteurs, relais, (même servos). Le deuxième groupe, les feux de signalisation, nous l'oublions pour le moment, puisque je n'ai pas encore commencé avec lui.
Pour chacun des groupes, je construis une carte avec un Nano, deux ou plusieurs multiplexeurs (MCP23017) pour avoir un nombre suffisant de contacts, et deux ULN2803 pour chaque multiplexeur, pour avoir assez de tension et de puissance pour déplacer les différents accessoires.

En principe, c'est tout à fait normal, et il existe de nombreux exemples déjà réalisés, mais mon projet présente deux difficultés supplémentaires, à savoir :
1.- Les multiplexeurs. Cela ne devrait pas être un problème majeur, mais comme je l'ai dit, je ne suis pas un expert en programmation de l'arduino. Quoi qu'il en soit, je pense avoir surmonté cette difficulté.
2.- L'inclusion d'un TOC. Voici le problème : je veux que tous les accessoires, en plus d'être gérés par des commandes DCC, puissent également être actionnés par des interrupteurs (boutons-poussoirs ou switches), en ajoutant également des LEDs qui indiquent l'état de chaque accessoire.

Eh bien, c'est mon projet. Qu'est-ce que j'ai accompli jusqu'à présent ? Bon, aussi étrange que cela puisse paraître, la partie la plus difficile, les aiguillages, fonctionne parfaitement. (J'inclus quelques photos illustratives du tableau et de la COT). J'ai basé le sketch correspondant sur le "Décodeur pour aiguillage à solénoïdes sur Arduino" de JPClaude, pour le DCCpp, et la bibliothèque "Commanders" de Thierrry pour gérer les boutons poussoirs. Comme je l'ai dit, cela fonctionne parfaitement, mais après de nombreuses tentatives.

Cependant, je n'arrive pas à faire fonctionner le troisième groupe, disons les lumières, pour simplifier. Et ça semble plus facile, mais je n'arrive pas à le faire fonctionner. Je m'explique : je peux gérer les lumières par des commandes DCCpp, sans aucun problème. Et je peux allumer et éteindre ces lumières avec des boutons poussoirs (grâce à la bibliothèque du Commandant). Mais je n'arrive pas à faire fonctionner les deux méthodes en même temps. Dès que j'active (sans commentaire) la commande ret = Commanders::loop() ; la partie TOC fonctionne, mais la partie DCCpp échoue, montrant un comportement erratique.

Bref, je suis désolé d'avoir été si long. J'espère que je ne vous ai pas trop ennuyé.
Dans l'attente de vos commentaires, meilleures salutations de
Juan

Traduit avec www.DeepL.com/Translator (version gratuite)
Titre: Re : Analog pushes avec Commanders
Posté par: Dominique le mai 30, 2021, 01:36:18 pm
Bonjour,

Pour mieux comprendre où est le problème, le mieux est de joindre un schéma et les éléments de croquis concernés, avec vos hypothèses sur le diagnostic.

Les photos que vous avez annoncées ne sont pas là !
Attention à la taille et la qualité des pièces jointes.
Titre: Re : Analog pushes avec Commanders
Posté par: Juan le mai 30, 2021, 01:45:55 pm
J'ai oublié les photos. Et dire aussi qu'évidemment, tout le code correspondant est à votre disposition, si cela intéresse quelqu'un.
Titre: Re : Analog pushes avec Commanders
Posté par: Juan le mai 30, 2021, 01:49:26 pm
Bien sûr Dominique, pour comprendre le problème il faudra que j'envoie un résumé du code, je ne l'ai pas fait dans le message précédent pour ne pas trop l'étendre.
Je suis en train de préparer un tel résumé explicatif, dès que je l'aurai, je l'enverrai.
Titre: Re : Analog pushes avec Commanders
Posté par: Juan le mai 30, 2021, 06:07:45 pm
Eh bien, comme je l'ai annoncé ce matin, voici le résumé du code. C'est la première fois que je le fais, j'espère que c'est compris.
Nous commençons par l'introduction des variables et ainsi de suite :
Ceci concerne les multiplexeurs, MCP23017, trois sont définis, MCP0, MCP1 et MCP2.
//***************************************************
//   Se define el valor ID para identificar origen:
//       ID <  FIRST_ID_MCP                          => arduino
//       ID >= FIRST_ID_MCP and <FIRST_ID_MCP+16     => MCP0
//       ID >= FIRST_ID_MCP+16 and <FIRST_ID_MCP+32  => MCP1
//       ID >= FIRST_ID_MCP+32                       => MCP2
//***************************************************
//////////////////////MCP23017///////////
#include <Wire.h>
#include <Adafruit_MCP23017.h>

Adafruit_MCP23017 mcp0;
Adafruit_MCP23017 mcp1;
Adafruit_MCP23017 mcp2;
 #define addr0 0
 #define addr1 1
 #define addr2 2
 
const byte maxaccessories = 32;
#define FIRST_DCC_MCP 16  // primera dirección para los MCP (central Lenz)
#define FIRST_ID_MCP  10  // primer número de orden de los MCP
///////////////////////////////////////////////////////////////////////////////
Il continue avec les termes de la bibliothèque Commanders, pour gérer 16 boutons poussoirs en série, et avec la structure de chaque accessoire :
////__________ COMMANDERS ________________________________________________
#include <Commanders.h>
// Analog push buttons
ButtonsCommanderAnalogPushes pushes;
#define NUMBER_OF_ANALOG_PUSHES  16
int pushes_values[NUMBER_OF_ANALOG_PUSHES] =
        { 58,114,174,233,290,348,404,463,519,578,638,698,760,824,889,955 }; 
unsigned long pushes_ids[NUMBER_OF_ANALOG_PUSHES] =
        {101,102,103,104,105,106,107,108,109,110,111,112,123,114,115,116};
////_______________________________________________________________________
//////////////////////////////////////
// Estructura de cada accesorio //////

typedef struct {
  int     address;       // User Configurable. DCC address to respond to
  int     ID;            // User Configurable. para identificar MCP0 ó MCP1
  byte    outputPin;     // User Configurable. Arduino pin where accessory is connected to
  byte    onoff;         // User Configurable. Initial state of accessory output: 1=on, 0=off (ON = pin LOW)
  byte    onoffmcp;      // User Configurable. Initial state of accessory mcp: 1=on, 0=off (ON = pin LOW)
  byte    previous;      // User Configurable. The previous reading from the input pin
  byte    dccstate;      // Internal use. DCC state of accessory: 1=on, 0=off
}
DCCAccessoryAddress;
DCCAccessoryAddress accessory[maxaccessories];

void ConfigureDecoderFunctions()
{
  for (int k = 0; k <16; k++)
  {
    accessory[FIRST_ID_MCP+k].address = FIRST_DCC_MCP+k; // DCC address empezando en FIRST_DCC_MCP
    accessory[FIRST_ID_MCP+k].outputPin = k;
    accessory[FIRST_ID_MCP+k].ID = FIRST_ID_MCP+k;
  }
  for (int k = 16; k <32; k++)
  {
    accessory[FIRST_ID_MCP+k].address = FIRST_DCC_MCP+k; // DCC address empezando en FIRST_DCC_MCP
    accessory[FIRST_ID_MCP+k].outputPin = k-16;
    accessory[FIRST_ID_MCP+k].ID = FIRST_ID_MCP+k;
  }
}  // END ConfigureDecoderFunctions
//____________________________
Le setup:
void setup()
{
  Serial.begin(115200); 
  Commanders::begin();
  DccCommander.begin(0x00, 0x00, digitalPinToInterrupt(2)); 
  pushes.begin(A1, NUMBER_OF_ANALOG_PUSHES, pushes_ids, pushes_values, 20);

  ConfigureDecoderFunctions();
  DCC.SetBasicAccessoryDecoderPacketHandler(BasicAccDecoderPacket_Handler, true);
 
  mcp0.begin(addr0);
  mcp1.begin(addr1);
  mcp2.begin(addr2);
 
  for(int k=0; k<16; k++)
  {
    mcp0.pinMode(accessory[FIRST_ID_MCP+k].outputPin, OUTPUT);
    mcp0.digitalWrite(accessory[FIRST_ID_MCP+k].outputPin, LOW);
    accessory[FIRST_ID_MCP+k].previous = LOW;
  }
 for(int k=16; k<32; k++)
  {
    mcp1.pinMode(accessory[FIRST_ID_MCP+k].outputPin, OUTPUT);
    mcp1.digitalWrite(accessory[FIRST_ID_MCP+k].outputPin, LOW);
    accessory[FIRST_ID_MCP+k].previous = LOW;
  }
} // END setup
Le loop (uniquement pour les cinq premiers boutons-poussoirs):
void loop()

  DCC.loop(); // Loop DCC library
  activation();
    unsigned long ret;
    ret = Commanders::loop();   
    switch(ret)
  {
//******** Guardavias  ************
case 101:  // Orden = 28       
       pulsadoresmcp1(28);
       break; 
//******** Estación  ************
    case 102:   // Orden = 11
       pulsadoresmcp0(11);
       break;
    case 103:  // Orden = 12
       pulsadoresmcp0(12);
       break;
    case 104:    // Orden = 10
       pulsadoresmcp0(10);
       break;
//******** Farolas  (Doble circuito, 14 y 15)************
    case 105: // Orden = 14 y 15
       pulsadoresmcp0(14);
       pulsadoresmcp0(15);
       break;                       
  }          /////////////  // End switch ret
} //END loop
Enfin, les différentes fonctions définies : l'activation des accessoires :
void activation()
{
  static int addr = 0;
  if( ++addr >= maxaccessories ) addr = 0; // Next address to test

  if (accessory[addr].dccstate)  accessory[addr].onoff = 1;
  else  accessory[addr].onoff = 0; 
      if ((accessory[addr].onoff==1) && (!accessory[addr].onoffmcp))
      {
        if (accessory[addr].ID < FIRST_ID_MCP+16) {
          mcp0.digitalWrite(accessory[addr].outputPin, HIGH);
        }
        if (accessory[addr].ID > FIRST_ID_MCP+15) {
          mcp1.digitalWrite(accessory[addr].outputPin, HIGH);
        }
        accessory[addr].onoffmcp = true;
      }
      if ((accessory[addr].onoff==0) && (accessory[addr].onoffmcp))
      {
        if (accessory[addr].ID < FIRST_ID_MCP+16) {
          mcp0.digitalWrite(accessory[addr].outputPin, LOW);
        }
        if (accessory[addr].ID > FIRST_ID_MCP+15) {
          mcp1.digitalWrite(accessory[addr].outputPin, LOW);
        }
        accessory[addr].onoffmcp = false;
      }
}///// FIN ACTIVACION //////////////////////
Celles relatives aux boutons poussoirs de Commanders
  //////////////////
  // Pulsadores MCP0
  /////////////////
  void pulsadoresmcp0(int orden)
  {
     if (accessory[orden].previous == HIGH) {
          if (accessory[orden].onoffmcp == HIGH) accessory[orden].onoffmcp = LOW;
          else accessory[orden].onoffmcp = HIGH;
       }             
       mcp0.digitalWrite(accessory[orden].outputPin, !accessory[orden].onoffmcp);
       accessory[orden].previous = !accessory[orden].onoffmcp;
  } //END Pulsadores MCP0
  //------------------------------------------------------
  //////////////////
  // Pulsadores MCP1
  //////////////////
  void pulsadoresmcp1(int orden)
  {
      if (accessory[orden].previous == HIGH) {
          if (accessory[orden].onoffmcp == HIGH) accessory[orden].onoffmcp = LOW;
          else accessory[orden].onoffmcp = HIGH;
       }             
       mcp1.digitalWrite(accessory[orden].outputPin, !accessory[orden].onoffmcp);
       accessory[orden].previous = !accessory[orden].onoffmcp;   
  } //END Pulsadores MCP1
Et la gestion des paquets DCC
  ///////////////////////////////
  // DCC accessory packet handler
  ///////////////////////////////
  void BasicAccDecoderPacket_Handler(int address, boolean activate, byte data)
  {
    // Convert NMRA packet address format to human address
    address -= 1;
    address *= 4;
    address += 1;
    address += (data & 0x06) >> 1;
    boolean enable = (data & 0x01) ? 1 : 0;
    for (int i=0; i<maxaccessories; i++)
    {
      if (address == accessory[i].address)
      {
        if (enable) accessory[i].dccstate = 1;
        else accessory[i].dccstate = 0;
      }
    }
  } //END BasicAccDecoderPacket_Handler

Et avec tout ça, que se passe-t-il ? Eh bien, il se trouve que, tel que le code est, les boutons poussoirs fonctionnent parfaitement, allumant et éteignant les lumières correspondantes, mais la partie DCC ne fonctionne pas (les lumières s'allument et s'éteignent de manière erratique).
Cependant, si j'annule (commente) la sentence
//   ret = Commanders::loop();ensuite les boutons poussoirs cessent de fonctionner (évident), mais la partie DCC fonctionne parfaitement ! !!

Quelqu'un peut-il m'expliquer ? ! !!!!
Muchas gracias a todos ppor vuestro interés.
Un saludo,
Juan.

Titre: Re : Analog pushes avec Commanders
Posté par: Dominique le juin 02, 2021, 05:44:12 pm
Juan,

Un peu de patience, j’ai quelques jours de vacances en ce moment  8)
Titre: Re : Analog pushes avec Commanders
Posté par: Juan le juin 03, 2021, 09:13:05 am
Pas de problème, profitez de vos vacances.