Programme pour une gare sur étagère

Toutes les discussions sur l'Arduino !

Modérateur : MOD

Répondre
macsddau
Papotier
Messages : 114
Enregistré le : jeu. 17 oct. 2013, 22:46
Echelle pratiquée : N

Programme pour une gare sur étagère

Message par macsddau » dim. 31 janv. 2016, 16:51

Bonjour à tous,

Je programme la gestion de la gare sur étagère
viewtopic.php?f=3&t=80622&start=0

Je bute sur l'utilisation de tableau (encore et encore...)

Pour le TCO je déclare ceci :

Code : Tout sélectionner

PMIO* buttons[][] = {
    {
        new PMButton(),
        new PMButton(),
        new PMButton(),
        new PMButton(),
        new PMButton(),
        new PMButton(),
        new PMButton(),
        NOT_AN_IO
    }, {
        new PMButton(),
        new PMButton(),
        new PMButton(),
        new PMButton(),
        new PMButton(),
        new PMButton(),
        NOT_AN_IO,
        NOT_AN_IO
    }, {
        new PMButton(),
        new PMButton(),
        new PMButton(),
        new PMButton(),
        new PMButton(),
        new PMButton(),
        new PMButton(),
        NOT_AN_IO
    }
}
puis je passe ce tableau à l'objet matrice :

Code : Tout sélectionner

PMIOMatrix* inputMatrix = new PMInputMatrix(buttons, BUTTON_ROW_COUNT, buttonsPins);
enfin je l'utilise de cette manière :

Code : Tout sélectionner

void PMIOMatrix::doForThis() {
    //send clear
    digitalWrite(this->pins[PIN_CLEAR], LOW);
    digitalWrite(this->pins[PIN_CLEAR], HIGH);
    
    for (unsigned char r = 0; r < this->rowCount; r++) {
        digitalWrite(this->pins[PIN_ROW_DATA], r == 0 ? HIGH : LOW);
        
        digitalWrite(this->pins[PIN_ROW_CLOCK], HIGH);
        digitalWrite(this->pins[PIN_ROW_CLOCK], LOW);
        
        digitalWrite(this->pins[PIN_ROW_STORE], HIGH);
        digitalWrite(this->pins[PIN_ROW_STORE], LOW);
        
        digitalWrite(this->pins[PIN_COL_STORE], HIGH);
        digitalWrite(this->pins[PIN_COL_STORE], LOW);
        
        for (unsigned char c = 0; c < MATRIX_COL_COUNT; c++) {
            if (this->io[r][c] != NOT_AN_IO) {
                digitalWrite(this->pins[PIN_COL_CLOCK], HIGH);
                digitalWrite(this->pins[PIN_COL_CLOCK], LOW);
                
                this->io[r][c]->setValue(digitalRead(this->pins[PIN_COL_DATA]));
            }
        }
    }
}
Le compilateur Arduino renvoi comme erreur

Code : Tout sélectionner

PMInputMatrix.cpp:33: error: no match for 'operator[]' (operand types are 'PMIO' and 'unsigned char')
             if (this->io[r][c] != NOT_AN_IO) {
En théorie this->io == buttons. Je ne comprends donc pas pourquoi je ne peut pas accéder au données du tableau.

Please, help me !
MS2 CC2 S-DEC-4-DC Rocrail

macsddau
Papotier
Messages : 114
Enregistré le : jeu. 17 oct. 2013, 22:46
Echelle pratiquée : N

Re: Programme pour une gare sur étagère

Message par macsddau » dim. 31 janv. 2016, 18:23

Déjà résolu une partie du problème

la déclaration du membre io était :

Code : Tout sélectionner

PMIO*     io;
a été remplacée par

Code : Tout sélectionner

PMIO*    *pio;
son utilisation devient :

Code : Tout sélectionner

if (&(this->pio[r][c]) != NOT_AN_IO)
MS2 CC2 S-DEC-4-DC Rocrail

Avatar du membre
jlb
Fécond
Messages : 692
Enregistré le : jeu. 04 oct. 2012, 16:38
Echelle pratiquée : N
Prénom : Jean-Luc
Site Internet : http://modelleisenbahn.triskell.org

Re: Programme pour une gare sur étagère

Message par jlb » lun. 01 févr. 2016, 09:27

Sans la totalité du code, c'est difficile de répondre. Je n'ai pas la déclaration d'une PMIO ni d'une PMIOMatrix

macsddau
Papotier
Messages : 114
Enregistré le : jeu. 17 oct. 2013, 22:46
Echelle pratiquée : N

Re: Programme pour une gare sur étagère

Message par macsddau » lun. 01 févr. 2016, 18:06

jlb a écrit :Sans la totalité du code, c'est difficile de répondre. Je n'ai pas la déclaration d'une PMIO ni d'une PMIOMatrix
En effet Jean-Luc ce n'est pas très clair.

Je reprends à zéro.

Je souhaite créer un tableau à 2 dimension contenant des objets. Je le déclare comme ceci :

Code : Tout sélectionner

Object1Class* tableObjects1 [][kTaille]={
  {
    new Object1Class(),
    NULL
  },
  {
    new Object1Class(),
    new Object1Class()
  }
};
j'ai besoin de cellules vides dans mon tableau. J'utilise donc NULL.

J'envoi ce tableau à un autre object

Code : Tout sélectionner

Object2Class object2 = new Object2Class(tableObjects1);
Celui ci est défini de la manière suivante :

Code : Tout sélectionner

class Object2Class {
  Object1class* obj;
  Object2class(Object1class*);
};
Je souhaite
1. tester si obj[r][c] == NULL
2. accéder aux membres de obj[r][c]

Je pense avoir glissé beaucoup d'erreur dans ces quelques lignes de code. Ce n'est pas pour tester le savoir de tous mais pour prouver mon ignorance dans le domaine

Pour contourner ce problème j'ai une solution mais elle est très gourmande en temps d'initialisation (Objet Pile : Stack)
MS2 CC2 S-DEC-4-DC Rocrail

Avatar du membre
jlb
Fécond
Messages : 692
Enregistré le : jeu. 04 oct. 2012, 16:38
Echelle pratiquée : N
Prénom : Jean-Luc
Site Internet : http://modelleisenbahn.triskell.org

Re: Programme pour une gare sur étagère

Message par jlb » mar. 02 févr. 2016, 08:08

Pourrais tu attacher le zip de tes fichiers source ?

macsddau
Papotier
Messages : 114
Enregistré le : jeu. 17 oct. 2013, 22:46
Echelle pratiquée : N

Re: Programme pour une gare sur étagère

Message par macsddau » mer. 03 févr. 2016, 09:12

Bonjour Jean-Luc

Je n'ai pas conservé le code d'origine. J'ai donc rapidement construit les quelques lignes ci-dessous :
PanelMaster.ino

Code : Tout sélectionner

#include "PMButton.h"
#include "PMMatrix.h"

PMButton* button1 = new PMButton();
PMButton* button2 = new PMButton();
PMButton* button3 = new PMButton();
PMButton* button4 = new PMButton();
PMButton* button5 = new PMButton();

PMButton* buttons[][2] {
    {
      button1,
      button2
    },
    {
      button3,
      NULL
    },
    {
      button4,
      button5
    }
  };

PMMatrix* matrix= new PMMatrix(*buttons);

void setup() {
  // put your setup code here, to run once:
}

void loop() {
  // put your main code here, to run repeatedly:

}
PMButton.h:

Code : Tout sélectionner

#ifndef PMBUTTON_H
#define PMBUTTON_H  1

class PMButton {
  public:
  inline PMButton() {};
};

#endif
PMMatrix.h :

Code : Tout sélectionner

#ifndef PMMATRIX_H
#define PMMATRIX_H  1

#include "PMButton.h"

class PMMatrix {
  private:
    PMButton**  buttons;
  public:
    PMMatrix(PMButton**);

    void doForThis();
};

#endif
PMMatrix.cpp :

Code : Tout sélectionner

#include "PMMatrix.h"
#include "Arduino.h"

PMMatrix::PMMatrix(PMButton* *someButtons) {
  this->buttons = someButtons;
}

void PMMatrix::doForThis() {
  for (unsigned char r = 0; r < 3; r++) {
    for (unsigned char c = 0; c < 2; c++) {
      if (this->buttons[r][c] != NULL) {
        
      }
    }
  }
}
Le compilateur me retourne ce message :
PMMatrix.cpp:11: error: no match for 'operator!=' (operand types are 'PMButton' and 'int')

if (this->buttons[r][c] != NULL) {

^

exit status 1
no match for 'operator!=' (operand types are 'PMButton' and 'int')

Cela peut-il t'aider pour résoudre mon problème ?
MS2 CC2 S-DEC-4-DC Rocrail

Avatar du membre
jlb
Fécond
Messages : 692
Enregistré le : jeu. 04 oct. 2012, 16:38
Echelle pratiquée : N
Prénom : Jean-Luc
Site Internet : http://modelleisenbahn.triskell.org

Re: Programme pour une gare sur étagère

Message par jlb » mer. 03 févr. 2016, 09:33

A vue de nez, il y a un embrouillamini entre le type d'un tableau bi dimensionnel et un pointeur de pointeur. Ce n'est pas équivalent comme ça peut l'être pour un tableau unidimensionnel.

Voir https://www.eskimo.com/~scs/cclass/int/sx9a.html

Que représentent ces données, as tu réellement besoin d'un tableau bi dimensionnel ?

macsddau
Papotier
Messages : 114
Enregistré le : jeu. 17 oct. 2013, 22:46
Echelle pratiquée : N

Re: Programme pour une gare sur étagère

Message par macsddau » mer. 03 févr. 2016, 09:50

jlb a écrit :Que représentent ces données, as tu réellement besoin d'un tableau bi dimensionnel ?
Pour mon TCO j'ai décidé de matricer les entrées et les sorties (download/file.php?id=411086). Cela me permet d'avoir un grand nombre de bouton et de led avec un Arduino nano. Je représente donc les données d'entrées (ou de sorties) dans une table bi-dimensionelle. Dans la fonction doForThis() (non implémentée entièrement dans le code fourni) je parcours donc les lignes et les colonnes de ma table et active les E/S de l'Arduino en fonction.

Je regarderai le lien ce soir au calme.
MS2 CC2 S-DEC-4-DC Rocrail

macsddau
Papotier
Messages : 114
Enregistré le : jeu. 17 oct. 2013, 22:46
Echelle pratiquée : N

Re: Programme pour une gare sur étagère

Message par macsddau » mer. 03 févr. 2016, 10:57

jlb a écrit :A vue de nez, il y a un embrouillamini entre le type d'un tableau bi dimensionnel et un pointeur de pointeur. Ce n'est pas équivalent comme ça peut l'être pour un tableau unidimensionnel.
Comme je sais travailler avec les tables uni-dimensionnelles, cela m'a donné une idée:
Voici le code qui compile sans erreur (cela ne veut pas dire qu'il fonctionne):

PanelMaster.ino :

Code : Tout sélectionner

#include "PMButton.h"
#include "PMMatrix.h"

PMButton* button1 = new PMButton();
PMButton* button2 = new PMButton();
PMButton* button3 = new PMButton();
PMButton* button4 = new PMButton();
PMButton* button5 = new PMButton();

#define BUTTON_TABLE_COUNT  8

PMButton* buttons[BUTTON_TABLE_COUNT] {
    button1, button2, NULL,
    button3, NULL,
    button4, button5, NULL
  };

PMMatrix* matrix= new PMMatrix(*buttons, BUTTON_TABLE_COUNT);

void setup() {
  // put your setup code here, to run once:
}

void loop() {
  // put your main code here, to run repeatedly:

}
PMButton.h (pas de changement)

PMMatrix.h :

Code : Tout sélectionner

#ifndef PMMATRIX_H
#define PMMATRIX_H  1

#include "PMButton.h"

class PMMatrix {
  private:
    PMButton* buttons;
    unsigned char count;
    
  public:
    PMMatrix(PMButton*&, unsigned char);

    void doForThis();
};

#endif
PMMatrix.cpp :

Code : Tout sélectionner

#include "PMMatrix.h"
#include "Arduino.h"

PMMatrix::PMMatrix(PMButton*& someButtons,
                   unsigned char aCount) {
  this->buttons = someButtons;
  this->count = aCount;
}

void PMMatrix::doForThis() {
  unsigned char r = 0;
//unsigned char c = 0;
  for (unsigned char i = 0; i < this->count; i++) {
      if (&this->buttons[i] == NULL) {
        r++;
      }
  }
}
MS2 CC2 S-DEC-4-DC Rocrail

macsddau
Papotier
Messages : 114
Enregistré le : jeu. 17 oct. 2013, 22:46
Echelle pratiquée : N

Programme pour une gare sur étagère

Message par macsddau » mar. 01 nov. 2016, 07:52

Bonjour à tous

Après quelques mois d'interruption c'est reparti.

Ces jours ci, je me suis attaqué à la gestion des itinéraires avec les enclenchements. Pour ce faire j'ai écris et debug actuellement une petite librairie "Interlocking"

Voici comment cela ce présente dans le programme principal. Ce code est celui qui me sert à la mise au point.

Code : Tout sélectionner

#include <Interlocking.h>

#define LEVER_COUNT 7   //255max
#define ROUTE_COUNT 11  //255max

/* 
 *  Levers diagramm
 *  
 *  |-B---1---------0------A-<->
 *         \       /
 *  |-D-----5--4--3--2-----C-|
 *            /       \
 *  |-G-------   |-F---6---E-|
 * 
*/

const char interlockingTable[ROUTE_COUNT][LEVER_COUNT] = {
// 0          1         2         3         4         5         6         <- Levers
  {STRAIGHT,  STRAIGHT, 0,        0,        0,        0,        0},       // Route 0  : A <-> B
  {DERIVED,   DERIVED,  0,        DERIVED,  STRAIGHT, DERIVED,  0},       // Route 1  : A <-> B
  {DERIVED,   0,        0,        DERIVED,  STRAIGHT, STRAIGHT, 0},       // Route 2  : A <-> D
  {DERIVED,   0,        0,        DERIVED,  DERIVED,  0,        0},       // Route 3  : A <-> G
  {0,         DERIVED,  STRAIGHT, STRAIGHT, STRAIGHT, DERIVED,  0},       // Route 4  : C <-> B
  {0,         0,        STRAIGHT, STRAIGHT, STRAIGHT, STRAIGHT, 0},       // Route 5  : C <-> D
  {0,         0,        STRAIGHT, STRAIGHT, DERIVED,  0,        0},       // Route 6  : C <-> G
  {0,         DERIVED,  DERIVED,  STRAIGHT, STRAIGHT, DERIVED,  DERIVED}, // Route 7  : E <-> B
  {0,         0,        DERIVED,  STRAIGHT, STRAIGHT, STRAIGHT, DERIVED}, // Route 8  : E <-> D
  {0,         0,        DERIVED,  STRAIGHT, DERIVED,  0,        DERIVED}, // Route 9  : E <-> G
  {0,         0,        0,        0,        0,        0,        STRAIGHT} // Route 10 : E <-> F
};

Interlocking* interlocking;

void setup() {
  Serial.begin(9600);

  interlocking = new Interlocking(ROUTE_COUNT, LEVER_COUNT, &interlockingTable[0][0]);
}

void loop() {
  // testing route 0
  Serial.print("l0  = ");Serial.println(interlocking->setLeverState(0, STRAIGHT), DEC);//move levers to good position for route 0
  Serial.print("l1  = ");Serial.println(interlocking->setLeverState(1, STRAIGHT), DEC);
  Serial.print("r0 is ");Serial.println(interlocking->setRouteBusy(0, true) ? "busy" : "free");//route 0 get busy
  Serial.print("l0  = ");Serial.println(interlocking->setLeverState(0, DERIVED), DEC);//try to move lever but they are locked
  Serial.print("l1  = ");Serial.println(interlocking->setLeverState(1, DERIVED), DEC);
  Serial.print("r0 is ");Serial.println(interlocking->setRouteBusy(0, false) ? "busy" : "free");//route 0 is free
  Serial.println("");

  // testing route 1
  Serial.print("l0  = ");Serial.println(interlocking->setLeverState(0, DERIVED), DEC);
  Serial.print("l1  = ");Serial.println(interlocking->setLeverState(1, DERIVED), DEC);
  Serial.print("l3  = ");Serial.println(interlocking->setLeverState(3, DERIVED), DEC);
  Serial.print("l4  = ");Serial.println(interlocking->setLeverState(4, STRAIGHT), DEC);
  Serial.print("l5  = ");Serial.println(interlocking->setLeverState(5, DERIVED), DEC);
  Serial.print("r1 is ");Serial.println(interlocking->setRouteBusy(1, true) ? "busy" : "free");
  Serial.print("l0  = ");Serial.println(interlocking->setLeverState(0, STRAIGHT), DEC);
  Serial.print("l1  = ");Serial.println(interlocking->setLeverState(1, STRAIGHT), DEC);
  Serial.print("l3  = ");Serial.println(interlocking->setLeverState(3, STRAIGHT), DEC);
  Serial.print("l4  = ");Serial.println(interlocking->setLeverState(4, DERIVED), DEC);
  Serial.print("l5  = ");Serial.println(interlocking->setLeverState(5, STRAIGHT), DEC);
  Serial.print("r1 is ");Serial.println(interlocking->setRouteBusy(1, false) ? "busy" : "free");
  Serial.println("");

  delay(1000);
}
Cette solution permet de gérer des tables d'enclenchement de taille variable dont la seul limite est la capacité du micro-contrôleur. :D
MS2 CC2 S-DEC-4-DC Rocrail

macsddau
Papotier
Messages : 114
Enregistré le : jeu. 17 oct. 2013, 22:46
Echelle pratiquée : N

Re: Programme pour une gare sur étagère

Message par macsddau » mar. 01 nov. 2016, 13:58

Ca y est la librairie "Interlocking" est déverminée. Le programme de test a été modifié pour voir un peu tout les cas possible : bouger un levier verrouillé, activer une route qui en traverse une qui est occupée, activer deux itinéraires en parallèle, lire la position de leviers et l'état d'occupation des routes...

Code : Tout sélectionner

#include <Interlocking.h>

#define LEVER_COUNT 7   //255max (unsigned char)
#define ROUTE_COUNT 11  //255max (unsigned char)

/* 
 *  Levers diagramm
 *  
 *  |-B---1---------0------A-<->
 *         \       /
 *  |-D-----5--4--3--2-----C-|
 *            /       \
 *  |-G-------   |-F---6---E-|
 * 
*/

const char interlockingTable[ROUTE_COUNT][LEVER_COUNT] = {
// 0          1         2         3         4         5         6         <- Levers
  {STRAIGHT,  STRAIGHT, 0,        0,        0,        0,        0},       // Route 0  : A <-> B
  {DERIVED,   DERIVED,  0,        DERIVED,  STRAIGHT, DERIVED,  0},       // Route 1  : A <-> B
  {DERIVED,   0,        0,        DERIVED,  STRAIGHT, STRAIGHT, 0},       // Route 2  : A <-> D
  {DERIVED,   0,        0,        DERIVED,  DERIVED,  0,        0},       // Route 3  : A <-> G
  {0,         DERIVED,  STRAIGHT, STRAIGHT, STRAIGHT, DERIVED,  0},       // Route 4  : C <-> B
  {0,         0,        STRAIGHT, STRAIGHT, STRAIGHT, STRAIGHT, 0},       // Route 5  : C <-> D
  {0,         0,        STRAIGHT, STRAIGHT, DERIVED,  0,        0},       // Route 6  : C <-> G
  {0,         DERIVED,  DERIVED,  STRAIGHT, STRAIGHT, DERIVED,  DERIVED}, // Route 7  : E <-> B
  {0,         0,        DERIVED,  STRAIGHT, STRAIGHT, STRAIGHT, DERIVED}, // Route 8  : E <-> D
  {0,         0,        DERIVED,  STRAIGHT, DERIVED,  0,        DERIVED}, // Route 9  : E <-> G
  {0,         0,        0,        0,        0,        0,        STRAIGHT} // Route 10 : E <-> F
};

Interlocking* interlocking;

void setup() {
  Serial.begin(9600);

  interlocking = new Interlocking(ROUTE_COUNT, LEVER_COUNT, &interlockingTable[0][0]);
}

void loop() {
  // testing for changing levers
  Serial.println(interlocking->setLeverState(0, STRAIGHT), DEC);//move levers to good position for route 0
  Serial.println(interlocking->setLeverState(1, STRAIGHT), DEC);
  Serial.println(interlocking->setRouteBusy(0, true) ? "true" : "false");//route 0 get busy
  Serial.println(interlocking->setLeverState(0, DERIVED), DEC);//try to move lever but they are locked
  Serial.println(interlocking->setLeverState(1, DERIVED), DEC);
  Serial.println(interlocking->setLeverState(3, DERIVED), DEC);
  Serial.println(interlocking->setLeverState(4, STRAIGHT), DEC);
  Serial.println(interlocking->setLeverState(5, DERIVED), DEC);
  Serial.println(interlocking->setRouteBusy(0, false) ? "true" : "false");//route 0 is free
  Serial.println("");

  // try to activate an other route
  Serial.println(interlocking->setLeverState(0, DERIVED), DEC);
  Serial.println(interlocking->setLeverState(1, DERIVED), DEC);
  Serial.println(interlocking->setRouteBusy(1, true) ? "true" : "false");
  Serial.println("");

  // testing for activating a route when one of his lever is locked or an other route is busy
  Serial.println(interlocking->setRouteBusy(2, true) ? "true" : "false");
  Serial.println(interlocking->setRouteBusy(10, true) ? "true" : "false");
  Serial.println(interlocking->setRouteBusy(1, false) ? "true" : "false");
  Serial.println(interlocking->setRouteBusy(2, true) ? "true" : "false");
  Serial.println(interlocking->setRouteBusy(10, false) ? "true" : "false");
  Serial.println("");

  // testing getting methodes
  for (unsigned char r = 0; r < ROUTE_COUNT; r++) {
    Serial.println(interlocking->getRouteBusy(r) ? "true" : "flase");
  }
  Serial.println("");

  for (unsigned char l = 0; l < LEVER_COUNT; l++) {
    Serial.println(interlocking->getLeverState(l), DEC);
  }
  Serial.println("");
 
  delay(1000);
}
Cette librairie utilise une sous-librairie appelée "Stack" qui permet le stockage des objets.
Je peux fournir "Interlocking" et "Stack" à qui le demande via MP. Bien évidement sans aucune garantie.
MS2 CC2 S-DEC-4-DC Rocrail

Répondre