Forums LR PRESSE

Où il est question de trains, petits et grands

  • Advertisement

Arduino et incompatibilité de manoeuvre (enclenchement)

Toutes les discussions sur l'Arduino !

Modérateur: MOD

Re: Arduino et incompatibilité de manoeuvre (enclenchement)

Publié: Mar 18 Fév 2014, 18:25 
Je continue ma présentation de mon programme.

const byte E0 = 12;
const byte S0 = 0;
const byte E1 = 11;
const byte S1 = 1;
const byte E2 = 10;
const byte S2 = 2;
const byte E3 = 9;
const byte S3 = 3;
const byte S6 = 6;
const int nb_levier = 4;
const byte entree[4]= {E0,E1,E2,E3};
const byte sortie[4] = {S0,S1,S2,S3};



Je déclare mes entrées et mes sorties.

void setup()
{
  for (int i=0;i<nb_levier;i++)
  {
    pinMode( entree[i], INPUT );
    digitalWrite( entree[i], HIGH );
    pinMode( sortie[i], OUTPUT );
    digitalWrite(sortie[i], LOW );
  } 



A l'aide des tableaux entree[] et sortie[], j'initialise les ports. Merci à jlb sur ce point

boolean etat_levier[4] = {false,false,false,false};
int verrou_levier[4]={0,0,0,0};
const int table_enclenchement[16]={
0,103,1,0,
103,0,1,0,
0,0,0,0,
0,0,0,0};



Je déclare la position initiale de mes différents leviers dans un tableau etat_levier[]. FALSE pour normal et TRUE pour ouvert (le signal associé sera ouvert (voie libre) / l'aiguille associée sera en position déviée).

Je déclare l'état (verrouillé ou non) de mes différents leviers dans un tableau verrou_levier[].

Je déclare les enclenchements dans un tableau table_enclenchement[].
Les règles :
-1 pour Release (libère, débloque le levier)
1 pour Lock (bloque le levier)
0 pour rien
10x pour Lock When

Image

Cf. viewtopic.php?f=63&t=75470&start=15#p1572403
On notera dans la case 1:2 (ligne 1 : colonne 2) 103 pour LW3R.

A suivre...
Fabrice Fayolle
Avatar de l’utilisateur
ffayolle
Causant
 
Messages: 254
Inscrit le: Mar 09 Mai 2006, 19:55
Localisation: Amiens, Somme, Picardie
Âge: 50

Re: Arduino et incompatibilité de manoeuvre (enclenchement)

Publié: Mar 18 Fév 2014, 18:36 
Je continue la présentation de mon programme.

void message_erreur()
{
  digitalWrite(S6, HIGH );
  delay(500);
  digitalWrite(S6, LOW );
   delay(500);
  digitalWrite(S6, HIGH );
  delay(500);
  digitalWrite(S6, LOW );
}



Si je ne peux pas actionner un levier car il est bloqué, alors j'exécute cette fonction. Elle fait clignoter une LED mais je souhaiterais qu'il déclenche pendant quelques instants un buzzer (je ne cherche pas à jouer la Marseillaise!!!). Si quelqu'un a une solution des plus simplistes, je suis preneur.
Fabrice Fayolle
Avatar de l’utilisateur
ffayolle
Causant
 
Messages: 254
Inscrit le: Mar 09 Mai 2006, 19:55
Localisation: Amiens, Somme, Picardie
Âge: 50

Re: Arduino et incompatibilité de manoeuvre (enclenchement)

Publié: Mar 18 Fév 2014, 18:41 
Hey Fabrice,

je viens de découvrir la question que tu m'as posée vers 16 h 30 sur un autre forum (j'étais en courses) ; super, jlb a répondu (ce que j'aurais d'ailleurs répondu) et comme cela tu pourras consulter son site qui est extrêmement pédagogue (en fait, c'est plutôt lui qui l'est, pas le site, mais ça revient au même :mdr2: )

D'ailleurs, j'ai également orienté Tuture vers ce site sur un autre forum (oui, ben, ça fait beaucoup de forums à surveiller et heureusement qu'on est plusieurs ! :lol: ).

Et pour ceux qui arrivent sur les forums Arduino, j'ai essayé de faire un petit topo sur les différents forums, histoire de s'y retrouver, mais ça évolue vachement vite. D'autres forum (décoration par exemple) ont parfois plus d'une centaine de pages ... :roll: pas facile de trouver comment faire une soudure ou quelle colle utiliser ... :mdr:
Avatar de l’utilisateur
Arduino
Démonstratif
 
Messages: 1596
Inscrit le: Mer 25 Sep 2013, 17:14

Re: Arduino et incompatibilité de manoeuvre (enclenchement)

Publié: Mar 18 Fév 2014, 18:56 
ffayolle a écrit:Je continue la présentation de mon programme.

void message_erreur()
{
  digitalWrite(S6, HIGH );
  delay(500);
  digitalWrite(S6, LOW );
   delay(500);
  digitalWrite(S6, HIGH );
  delay(500);
  digitalWrite(S6, LOW );
}



Si je ne peux pas actionner un levier car il est bloqué, alors j'exécute cette fonction. Elle fait clignoter une LED mais je souhaiterais qu'il déclenche pendant quelques instants un buzzer (je ne cherche pas à jouer la Marseillaise!!!). Si quelqu'un a une solution des plus simplistes, je suis preneur.


va sur le site d'Arduino et regarde la fonction tone. :wink:

De plus, que penses-tu de transformer ta fonction avec une boucle :

void message_erreur()
{
  boolean etat_led = HIGH;
  byte s6 = 13; // cette variable globale serait déclarée ailleurs, c'est juste pour pouvoir vérifier
  for(byte i = 0; i <= 4; i++)
  {
    digitalWrite(s6, etat_led);
    delay (500);
    etat_led = !etat_led;
  }
}




Cela fait clignoter 5 fois (de 0 à 4) :wink:
Avatar de l’utilisateur
Arduino
Démonstratif
 
Messages: 1596
Inscrit le: Mer 25 Sep 2013, 17:14

Re: Arduino et incompatibilité de manoeuvre (enclenchement)

Publié: Mar 18 Fév 2014, 21:39 
Arduino a écrit:
va sur le site d'Arduino et regarde la fonction tone. :wink:

De plus, que penses-tu de transformer ta fonction avec une boucle :

void message_erreur()
{
  boolean etat_led = HIGH;
  byte s6 = 13; // cette variable globale serait déclarée ailleurs, c'est juste pour pouvoir vérifier
  for(byte i = 0; i <= 4; i++)
  {
    digitalWrite(s6, etat_led);
    delay (500);
    etat_led = !etat_led;
  }
}




Cela fait clignoter 5 fois (de 0 à 4) :wink:


Pourquoi n'y ai-je pas pensé!!!
Merci Christian.

La fonction Tone. Oui, je suis allé voir. Je vais simplifier au maximum car je souhaite surtout émettre un bip et seulement un bip.
Fabrice Fayolle
Avatar de l’utilisateur
ffayolle
Causant
 
Messages: 254
Inscrit le: Mar 09 Mai 2006, 19:55
Localisation: Amiens, Somme, Picardie
Âge: 50

Re: Arduino et incompatibilité de manoeuvre (enclenchement)

Publié: Mar 18 Fév 2014, 23:05 
La fonction tone crée une onde carrée, de rapport cyclique 50%, de fréquence au choix (mais pas inférieure à 31 Hz). En conséquence, il s'agit d'un bip, dont tu peux régler la durée dans l'appel de la fonction. En choisissant la fréquence, le bip est plus ou moins aigu.

Va faire un tour dans les exemples du site Arduino ; tu verras comment jouer une mélodie (juste pour le fun) soit une fois si tu places le programme dans la fonction setup (qui ne sert pas qu'au setup), soit indéfiniment si tu le places dans la fonction loop (mais tu en auras vite marre :lol: ). Tu verras aussi comment relier le haut-parleur à Arduino avec une résistance de 100 ohms.
Avatar de l’utilisateur
Arduino
Démonstratif
 
Messages: 1596
Inscrit le: Mer 25 Sep 2013, 17:14

Re: Arduino et incompatibilité de manoeuvre (enclenchement)

Publié: Mer 19 Fév 2014, 00:49 
Attention Fabrice,

juste un rappel pour permettre aux informaticien qui pourront aider a réaliser ton programme ou aux experts pour comprendre ton analyse et ta manière de décrire tes instructions.

Il est de convention en informatique et encore plus en développement de dire qu'une variable est VRAI ou TRUE quand la valeur est 1 et à l'inverse elle est fausse ou FALSE quand elle vaut 0.

SI tu dois utiliser un test de comparaison du style:

si ma variable est vrai alors ce qui donne en informatique :
If( mavariable) // si vrai
ou
If(mavariable is TRUE) si mavariable est vrai

Peu importe l'écriture car tout dépend dans quelle langage tu développes mais le résultat est le même, le test est vrai si mavariable vaut 1.

C'est une convention mais tu fais ce que tu veux, seulement encore une fois indique le en commentaire dans ton programme quand tu le fais pour rappeler que 0 est Vrai et 1 est Faux.
Dans ce cas , tu ne pourras pas utiliser le type Boolean sinon à inverser les tests et générer des non sens.

Cousin Hub
Le train de la vie file.
Avatar de l’utilisateur
HDE5962
Éloquent
 
Messages: 347
Inscrit le: Mar 20 Août 2013, 10:03
Localisation: Malakoff par obligation et Schti par naissance
Âge: 55
Echelle pratiquée: HO et de cordes

Re: Arduino et incompatibilité de manoeuvre (enclenchement)

Publié: Mer 19 Fév 2014, 21:38 
HDE5962 a écrit:Attention Fabrice,

juste un rappel pour permettre aux informaticien qui pourront aider a réaliser ton programme ou aux experts pour comprendre ton analyse et ta manière de décrire tes instructions.

Il est de convention en informatique et encore plus en développement de dire qu'une variable est VRAI ou TRUE quand la valeur est 1 et à l'inverse elle est fausse ou FALSE quand elle vaut 0.

SI tu dois utiliser un test de comparaison du style:

si ma variable est vrai alors ce qui donne en informatique :
If( mavariable) // si vrai
ou
If(mavariable is TRUE) si mavariable est vrai

Peu importe l'écriture car tout dépend dans quelle langage tu développes mais le résultat est le même, le test est vrai si mavariable vaut 1.

C'est une convention mais tu fais ce que tu veux, seulement encore une fois indique le en commentaire dans ton programme quand tu le fais pour rappeler que 0 est Vrai et 1 est Faux.
Dans ce cas , tu ne pourras pas utiliser le type Boolean sinon à inverser les tests et générer des non sens.

Cousin Hub


Hubert,
Tout à fait d'accord mais je ne comprends pas pourquoi cette remarque. Sauf erreur de ma part, je n'ai pas trouvé de "logique inversée" dans le nouveau code que je dévoile au fur et à mesure.
Fabrice
Fabrice Fayolle
Avatar de l’utilisateur
ffayolle
Causant
 
Messages: 254
Inscrit le: Mar 09 Mai 2006, 19:55
Localisation: Amiens, Somme, Picardie
Âge: 50

Re: Arduino et incompatibilité de manoeuvre (enclenchement)

Publié: Mer 19 Fév 2014, 23:35 
c'est ton post en page précédente ou tu dis

"Si la valeur est à zéro, le levier n'est pas bloqué et je renvoie donc la valeur VRAI.
Si la valeur est différente de zéro (1,2,... car le levier pourrait être bloqué par plusieurs autres leviers), je renvoie la valeur FAUX.

J'utilise un tableau pour stocker le verrouillage ou non du levier.
"


c'est tout.
Le train de la vie file.
Avatar de l’utilisateur
HDE5962
Éloquent
 
Messages: 347
Inscrit le: Mar 20 Août 2013, 10:03
Localisation: Malakoff par obligation et Schti par naissance
Âge: 55
Echelle pratiquée: HO et de cordes

Re: Arduino et incompatibilité de manoeuvre (enclenchement)

Publié: Jeu 20 Fév 2014, 16:09 
HDE5962 a écrit:c'est ton post en page précédente ou tu dis

"Si la valeur est à zéro, le levier n'est pas bloqué et je renvoie donc la valeur VRAI.
Si la valeur est différente de zéro (1,2,... car le levier pourrait être bloqué par plusieurs autres leviers), je renvoie la valeur FAUX.

J'utilise un tableau pour stocker le verrouillage ou non du levier.
"


c'est tout.


Hubert,

Je comprends mieux ton commentaire.

Mais comme indiqué précédemment, le levier peut être bloqué plusieurs fois. C'est pourquoi, je n'utilise pas un booléen mais un nombre entier. Ce nombre indique le nombre de fois que le levier est bloqué. J'espère avoir été plus clair dans mes explications.

int verrou_levier[4]={0,0,0,0};

Fabrice Fayolle
Avatar de l’utilisateur
ffayolle
Causant
 
Messages: 254
Inscrit le: Mar 09 Mai 2006, 19:55
Localisation: Amiens, Somme, Picardie
Âge: 50

Re: Arduino et incompatibilité de manoeuvre (enclenchement)

Publié: Sam 22 Fév 2014, 16:00 
Bonjour,

Et merci aux différentes personnes qui ont commentés ce fil de discussion car leurs compétences mais avant tout leur ténacité m'ont permis de revoir le programme que je présentais dans le 1er post de ce fil.

Est-il optimisé ? Permet-il d'utiliser toutes les possibilités offertes par une carte Arduino Uno ?
La réponse est non
Répond-t-il à mes besoins ?
La réponse est oui

Pour rappel, le programme doit permettre de reproduire le fonctionnement d'un poste d'aiguillage mécanique en y intégrant les enclenchements. Attention, je ne cherche pas ici à gérer directement des itinéraires.

Il doit permettre de gérer le plan suivant :

Image

Les principes fondamentaux des enclenchements a été décrit dans le fil suivant : viewtopic.php?f=63&t=75470&start=15#p1572430

Pour ce type de plan de voies, j'avais donc besoin de 10 entrées et de sorties.
Un Arduino Uno permet de répondre à ces besoins.

Côté entrée, en lieu et place du levier d'aiguillage, c'est un bouton poussoir qui sera utilisé (Merci à Pico pour le schéma!!!)

Image

Côté sortie, et suivant le type de sortie, une action sera réalisée. A ce jour, seule l'action du type mise à LOW ou HIGH est possible.

Image

J'ai prévu de piloter les moteurs des signaux et des aiguillages par un étage de puissance extérieur (Cf. http://jurasecondairen.blogspot.ca/p/8- ... on.html#82)

Mais rien n'empêche de programmer une action pour un autre type de sortie comme par exemple le pilotage d'un servo moteur (Cf. http://jurasecondairen.blogspot.ca/p/6- ... ur.html#61).

// Poste d'aiguillage à 9 + 1 leviers incluant une table d'enclenchements
// Fabrice Fayolle, Février 2014
// Version 1.0
// Déclaration des entrées de E0 à E9 (port 19 à port 10)
const byte E0 = 19;
//Déclaration des sorties de S0 à S9 (port 0 à port9) 
const byte S0 = 0;
const byte E1 = 18;
const byte S1 = 1;
const byte E2 = 17;
const byte S2 = 2;
const byte E3 = 16;
const byte S3 = 3;
const byte E4 = 15;
const byte S4 = 4;
const byte E5 = 14;
const byte S5 = 5;
const byte E6 = 13;
const byte S6 = 6;
const byte E7 = 12;
const byte S7 = 7;
const byte E8 = 11;
const byte S8 = 8;
const byte E9 = 10;
const byte S9 = 9;
// Déclaration du nombre de leviers
const int Nb_levier = 10;
// Déclaration dans un tableau des noms des entrées
const byte Entree[Nb_levier]= {E0,E1,E2,E3,E4,E5,E6,E7,E8,E9};
// Déclaration dans un tableau des noms des sorties
const byte Sortie[Nb_levier] = {S0,S1,S2,S3,S4,S5,S6,S7,S8,S9};
// Déclaration dans un tableau du type de sortie
// 1 : Mise à l'état HIGH de la sortie
// 99 : Buzzer signalant une incompatibilité (facultatif)
const int Type_sortie[Nb_levier] = {1,1,1,1,1,1,1,1,1,99};
// Déclaration dans un tableau de la position de chaque levier
// false -> normal (correspond à un signal fermé (arrêt) ou à un aiguillage en position normale)
// La position "normal" est celle par défaut. 
// true -> reverse (correspond à un signal ouvert (voie libre) ou à une aiguillage en position déviée)
boolean etat_levier[Nb_levier] = {false,false,false,false,false,false,false,false,false,false};
// Déclaration dans un tableau de l'état verouillé ou non du levier
// 0 -> non verrouillé
// 1 -> verrouillé 1 fois
// x -> verrouillé x fois
int verrou_levier[Nb_levier]={0,0,0,0,0,0,0,0,0,0};
// Déclaration dans une matrice de la table d'enclenchement
// 0 -> ne verrouille pas le levier
// 1 -> verrouille le levier (Lock)
// -1 -> déverouille le levier (Release)
// 1xx -> verrouille le levier si le levier xx est en position reverse (LW)
const int table_enclenchement[Nb_levier*Nb_levier]={
// Levier 1
0,0,0,0,0,0,0,0,0,0,
// Levier 2
0,0,0,0,0,0,0,0,0,0,
//Levier 3
0,0,0,0,0,0,0,0,0,0,
// Levier 4
0,0,0,0,0,0,0,0,0,0,
// Levier 5
0,0,0,0,0,0,0,0,0,0,
// Levier 6
0,0,0,0,1,0,0,0,0,0,
// Levier 7
0,0,0,0,0,0,0,0,0,0,
// Levier 8
0,0,0,0,0,0,0,0,0,0,
// Levier 9
0,0,0,0,0,0,0,0,0,0,
// Levier 10 (non utilisé si la sortie correspondante est utilisée en type 99 (dans ce cas, laisser toutes les valeurs à 0))
0,0,0,0,0,0,0,0,0,0};

void setup()
{
  // Initialisation des entrées (mise à l'état HIGH de chaque sortie)
  // Initialisation des sorties suivant type
  // (mise à l'état LOW de chaque sortie ce qui correspond à une position normale du levier (signal fermé, aiguille en position normale,...))
  for (int i=0;i<Nb_levier;i++)
  {
    pinMode( Entree[i], INPUT );
    digitalWrite( Entree[i], HIGH );
    pinMode( Sortie[i], OUTPUT );
    sortie_changer(i,Type_sortie[i],etat_levier[i]);
  } 
}

void loop()
{
  // Pour l'ensemble des leviers, si un changement est demandé alors
  // Si le changement est possible
  // le changement est effectué
  // Sinon une incompatibilité est signalée
  
  for (int i=0; i< Nb_levier; ++i)
  {
    if ( demande_changement(i))
    {
      if ( levier_changeable(i))
      {
        levier_changer(i);
      }
      else
      {
         sortie_changer(9,99,true);
      }
    }
  }
}

boolean levier_changeable(int levier)
{
  // Fonction levier_changeable verifiée si le levier n'est pas bloqué
  // Valeur true renvoyée si le levier n'est pas bloqué
  // Valeur false renvoyée si le levier est bloqué
  boolean result;
  result = (verrou_levier[levier] == 0);
  return result;
}

void levier_changer(int levier)
{
  // Fonction levier_changer applique ou désapplique la table d'enclenchement à l'ensemble des leviers
  // Fonction levier_changer change la position du levier
  int decalage = levier * Nb_levier;
  if (!etat_levier[levier])
  {
    for (int i = 0; i <Nb_levier;i++)
    {
      switch (table_enclenchement[decalage+i])
      {
        case -1 :
        verrou_levier[i] += table_enclenchement[decalage+i];
        break;
        case 0 :
        break;
        case 1 :
        verrou_levier[i] += table_enclenchement[decalage+i];
        break;
        default:
        int condition;
        condition = table_enclenchement[decalage+i]-101;
        if (etat_levier[condition])
        {
         verrou_levier[i] += 1;
        } 
      }
    }
    sortie_changer(levier,Type_sortie[levier],true);
  }
  else
  {
    for (int i = 0; i <Nb_levier;i++)
    {
      switch (table_enclenchement[decalage+i])
      {
        case -1 :
        verrou_levier[i] -= table_enclenchement[decalage+i];
        break;
        case 0 :
        break;
        case 1 :
        verrou_levier[i] -= table_enclenchement[decalage+i];
        break;
        default:
        int condition;
        condition = table_enclenchement[decalage+i]-101;
        if (etat_levier[condition])
        {
         verrou_levier[i] -= 1;
        } 
      }
    }
    sortie_changer(levier,Type_sortie[levier],false);
  }
  etat_levier[levier]=!etat_levier[levier];
}

void sortie_changer(int levier, int type, boolean action)
{
  // Fonction sortie_changer modifie l'état de la sortie
  // Type 1 -> mise à l'état HIGH ou LOW de la sortie (permet par exemple d'alimenter un étage de puissance pour alimenter des moteurs de type Tortoise)
  // Type 99 -> type réservé au buzzer (clignotement d'une LED)
  switch (type)
  {
    case 1:
    if (action)
    {
      digitalWrite(Sortie[levier],HIGH);
    }
    else
    {
      digitalWrite(Sortie[levier],LOW);
    }
    break;
    case 99:
    boolean Etat_sortie = HIGH;
    for (int i=0;i<6;i++)
    {
      digitalWrite(Sortie[levier],Etat_sortie);
      delay(250);
      Etat_sortie = !Etat_sortie;
    }
    break;
  } 
}

boolean demande_changement(int levier)
{
  // Fonction demande_changement vérifie si le bouton poussoir est appuyé (mise à LOW de l'entrée)
  // Boucle d'attente permet d'éviter le phénomène de rebond
  // Valeur true si le bouton poussoir a été appuyé
  boolean result = false;
  if (digitalRead(Entree[levier]) == LOW)
  {
    delay( 100 );
    while ( digitalRead(Entree[levier]) == LOW )
    {
      delay( 100 );
    }
    result = true;
  }
  return result;
}



Comme différents points sont paramétrables (le nombre de leviers, la table d'enclenchements,...), ce programme peut répondre à d'autres types de plan de voie. Il n'a que de limite que le nombre de ports nécessaire. Mais sachant qu'une carte Arduino Mega dispose de 70 ports, cela laisse un peu de marge!!!
Fabrice Fayolle
Avatar de l’utilisateur
ffayolle
Causant
 
Messages: 254
Inscrit le: Mar 09 Mai 2006, 19:55
Localisation: Amiens, Somme, Picardie
Âge: 50

Re: Arduino et incompatibilité de manoeuvre (enclenchement)

Publié: Dim 23 Fév 2014, 20:51 
Bonsoir,

J'ai souhaité tester le programme avec un autre plan de voies afin de m'assurer que le système fonctionne.

Voici le nouveau plan de voies :

Image

Ce plan de voies est directement inspiré d'un article paru dans le n° de février 2014 de Railway Modeller.

9 entrées et 9 sorties sont nécessaires pour gérer cette installation. Une carte Arduino Uno répond à ces besoins.

J'ai créé un fichier Excel pour définir ma table d'enclenchement. (en fait, le plus difficile à construire après le programme!!!).
:roll: :roll: :roll:
Si vous souhaitez l'obtenir, n'hésitez pas à me contacter en MP.

Quant au programme, afin de simplifier la gestion des enclenchements conditionnels, j'ai créé une nouvelle fonction.

int condition_enclenchement (int enclenchement)
{
  // Fonction condition_enclenchement applique ou désapplique l'enclenchement si la condition est remplie
  // 1xx -> verrouille le levier si le levier xx est en position normal (LW (Lock When Normal))
  // -1xx -> déverrouille le levier si le levier xx est en position normal (RW (Release When Normal))
  // 2xx -> verrouille le levier si le levier xx est en position reverse (LW (Lock When Reverse))
  // -2xx -> déverrouille le levier si le levier xx est en position reverse (RW (Release When Reverse))
  int centaine = enclenchement / 100;
  int result = 0;
  switch (centaine)
  {
    case 1 :
    if (!etat_levier[enclenchement - 101])
    {
      result = 1;
    }
    break;
    case -1 :
    if (!etat_levier[-enclenchement - 101])
    {
      result = -1;
    }
    break;
    case 2 :
    if (etat_levier[enclenchement - 201])
    {
      result = 1;
    }
    break;
    case -2 :
    if (etat_levier[-enclenchement - 201])
    {
      result = -1;
    }
    break;
  } 
  return result;
}



Et voici le programme complet :

// Poste d'aiguillage à 9 + 1 leviers incluant une table d'enclenchements
// Fabrice Fayolle, Février 2014
// Version 1.1
// Déclaration des entrées de E0 à E9 (port 19 à port 10)
const byte E0 = 19;
//Déclaration des sorties de S0 à S9 (port 0 à port9) 
const byte S0 = 0;
const byte E1 = 18;
const byte S1 = 1;
const byte E2 = 17;
const byte S2 = 2;
const byte E3 = 16;
const byte S3 = 3;
const byte E4 = 15;
const byte S4 = 4;
const byte E5 = 14;
const byte S5 = 5;
const byte E6 = 13;
const byte S6 = 6;
const byte E7 = 12;
const byte S7 = 7;
const byte E8 = 11;
const byte S8 = 8;
const byte E9 = 10;
const byte S9 = 9;
// Déclaration du nombre de leviers
const int Nb_levier = 10;
// Déclaration dans un tableau des noms des entrées
const byte Entree[Nb_levier]= {E0,E1,E2,E3,E4,E5,E6,E7,E8,E9};
// Déclaration dans un tableau des noms des sorties
const byte Sortie[Nb_levier] = {S0,S1,S2,S3,S4,S5,S6,S7,S8,S9};
// Déclaration dans un tableau du type de sortie
// 1 : Mise à l'état HIGH de la sortie
// 99 : Buzzer signalant une incompatibilité (facultatif)
const int Type_sortie[Nb_levier] = {1,1,1,1,1,1,1,1,1,99};
// Déclaration dans un tableau de la position de chaque levier
// false -> normal (correspond à un signal fermé (arrêt) ou à un aiguillage en position normale)
// La position "normal" est celle par défaut. 
// true -> reverse (correspond à un signal ouvert (voie libre) ou à une aiguillage en position déviée)
boolean etat_levier[Nb_levier] = {false,false,false,false,false,false,false,false,false,false};
// Déclaration dans un tableau de l'état verouillé ou non du levier
// 0 -> non verrouillé
// 1 -> verrouillé 1 fois
// x -> verrouillé x fois
int verrou_levier[Nb_levier]={0,1,0,0,0,0,1,0,0,0};
// Déclaration dans une matrice de la table d'enclenchement
// 0 -> ne verrouille pas le levier
// 1 -> verrouille le levier (Lock)
// -1 -> déverouille le levier (Release)
// 1xx -> verrouille le levier si le levier xx est en position normal (LW (Lock When Normal))
// -1xx -> déverrouille le levier si le levier xx est en position normal (RW (Release When Normal))
// 2xx -> verrouille le levier si le levier xx est en position reverse (LW (Lock When Reverse))
// -2xx -> déverrouille le levier si le levier xx est en position reverse (RW (Release When Reverse))
const int table_enclenchement[Nb_levier*Nb_levier]={
// Levier 1
0,0,0,0,0,0,1,0,0,0,
// Levier 2
0,0,1,1,1,1,1,0,1,0,
//Levier 3
0,1,0,1,0,0,0,0,-206,0,
// Levier 4
0,-1,1,0,0,1,1,0,0,0,
// Levier 5
0,1,0,0,0,1,-1,0,0,0,
// Levier 6
0,1,0,1,1,0,1,0,103,0,
// Levier 7
1,1,1,1,1,0,0,0,1,0,
// Levier 8
0,0,0,0,0,1,0,0,0,0,
// Levier 9
0,1,1,0,0,103,1,0,0,0,
// Levier 10 (non utilisé si la sortie correspondante est utilisée en type 99 (dans ce cas, laisser toutes les valeurs à 0))
0,0,0,0,0,0,0,0,0,0};

void setup()
{
  // Initialisation des entrées (mise à l'état HIGH de chaque sortie)
  // Initialisation des sorties suivant type
  // (mise à l'état LOW de chaque sortie ce qui correspond à une position normale du levier (signal fermé, aiguille en position normale,...))
  for (int i=0;i<Nb_levier;i++)
  {
    pinMode( Entree[i], INPUT );
    digitalWrite( Entree[i], HIGH );
    pinMode( Sortie[i], OUTPUT );
    sortie_changer(i,Type_sortie[i],etat_levier[i]);
  } 
}

void loop()
{
  // Pour l'ensemble des leviers, si un changement est demandé alors
  // Si le changement est possible
  // le changement est effectué
  // Sinon une incompatibilité est signalée
  
  for (int i=0; i< Nb_levier; ++i)
  {
    if ( demande_changement(i))
    {
      if ( levier_changeable(i))
      {
        levier_changer(i);
      }
      else
      {
         sortie_changer(9,99,true);
      }
    }
  }
}

boolean levier_changeable(int levier)
{
  // Fonction levier_changeable verifiée si le levier n'est pas bloqué
  // Valeur true renvoyée si le levier n'est pas bloqué
  // Valeur false renvoyée si le levier est bloqué
  boolean result;
  result = (verrou_levier[levier] == 0);
  return result;
}

void levier_changer(int levier)
{
  // Fonction levier_changer applique ou désapplique la table d'enclenchement à l'ensemble des leviers
  // Si un l'enclenchement est conditionnel, utilisation de la focntion condition_enclenchement
  // Fonction levier_changer change la position du levier
  int decalage = levier * Nb_levier;
  if (!etat_levier[levier])
  {
    for (int i = 0; i <Nb_levier;i++)
    {
      switch (table_enclenchement[decalage+i])
      {
        case -1 :
        verrou_levier[i] += table_enclenchement[decalage+i];
        break;
        case 0 :
        break;
        case 1 :
        verrou_levier[i] += table_enclenchement[decalage+i];
        break;
        default :
        verrou_levier[i] += condition_enclenchement(table_enclenchement[decalage+i]);
      }    
    }
    sortie_changer(levier,Type_sortie[levier],true);
  }
  else
  {
    for (int i = 0; i <Nb_levier;i++)
    {
      switch (table_enclenchement[decalage+i])
      {
        case -1 :
        verrou_levier[i] -= table_enclenchement[decalage+i];
        break;
        case 0 :
        break;
        case 1 :
        verrou_levier[i] -= table_enclenchement[decalage+i];
        break;
        default :
        verrou_levier[i] -= condition_enclenchement(table_enclenchement[decalage+i]);
      }
    }
    sortie_changer(levier,Type_sortie[levier],false);
  }
  etat_levier[levier]=!etat_levier[levier];
}

int condition_enclenchement (int enclenchement)
{
  // Fonction condition_enclenchement applique ou désapplique l'enclenchement si la condition est remplie
  // 1xx -> verrouille le levier si le levier xx est en position normal (LW (Lock When Normal))
  // -1xx -> déverrouille le levier si le levier xx est en position normal (RW (Release When Normal))
  // 2xx -> verrouille le levier si le levier xx est en position reverse (LW (Lock When Reverse))
  // -2xx -> déverrouille le levier si le levier xx est en position reverse (RW (Release When Reverse))
  int centaine = enclenchement / 100;
  int result = 0;
  switch (centaine)
  {
    case 1 :
    if (!etat_levier[enclenchement - 101])
    {
      result = 1;
    }
    break;
    case -1 :
    if (!etat_levier[-enclenchement - 101])
    {
      result = -1;
    }
    break;
    case 2 :
    if (etat_levier[enclenchement - 201])
    {
      result = 1;
    }
    break;
    case -2 :
    if (etat_levier[-enclenchement - 201])
    {
      result = -1;
    }
    break;
  } 
  return result;
}


void sortie_changer(int levier, int type, boolean action)
{
  // Fonction sortie_changer modifie l'état de la sortie
  // Type 1 -> mise à l'état HIGH ou LOW de la sortie (permet par exemple d'alimenter un étage de puissance pour alimenter des moteurs de type Tortoise)
  // Type 99 -> type réservé au buzzer (clignotement d'une LED)
  switch (type)
  {
    case 1:
    if (action)
    {
      digitalWrite(Sortie[levier],HIGH);
    }
    else
    {
      digitalWrite(Sortie[levier],LOW);
    }
    break;
    case 99:
    boolean Etat_sortie = HIGH;
    for (int i=0;i<6;i++)
    {
      digitalWrite(Sortie[levier],Etat_sortie);
      delay(250);
      Etat_sortie = !Etat_sortie;
    }
    break;
  } 
}

boolean demande_changement(int levier)
{
  // Fonction demande_changement vérifie si le bouton poussoir est appuyé (mise à LOW de l'entrée)
  // Boucle d'attente permet d'éviter le phénomène de rebond
  // Valeur true si le bouton poussoir a été appuyé
  boolean result = false;
  if (digitalRead(Entree[levier]) == LOW)
  {
    delay( 100 );
    while ( digitalRead(Entree[levier]) == LOW )
    {
      delay( 100 );
    }
    result = true;
  }
  return result;
}

Fabrice Fayolle
Avatar de l’utilisateur
ffayolle
Causant
 
Messages: 254
Inscrit le: Mar 09 Mai 2006, 19:55
Localisation: Amiens, Somme, Picardie
Âge: 50

Re: Arduino et incompatibilité de manoeuvre (enclenchement)

Publié: Mar 25 Fév 2014, 14:16 
Il existe un excellentissime bouquin paru aux éditions "presse pont et chaussée" il y a 25ans au prix de un peu plus de 120 euros qui décrivait tout ceci. Il contenait même les lignes de code.
Je mettrai des photos.
J'étais aux WC :mdr:
Avatar de l’utilisateur
fa57
Zorro est à rivets
 
Messages: 16114
Inscrit le: Sam 20 Août 2005, 15:52
Localisation: ACAL

Re: Arduino et incompatibilité de manoeuvre (enclenchement)

Publié: Mar 25 Fév 2014, 20:07 
pour tout ce qui est logique signalisation ferroviaire il y a ceci:

Image

Image

Image
le matériel était primitif mais la logique reste
J'étais aux WC :mdr:
Avatar de l’utilisateur
fa57
Zorro est à rivets
 
Messages: 16114
Inscrit le: Sam 20 Août 2005, 15:52
Localisation: ACAL

Re: Arduino et incompatibilité de manoeuvre (enclenchement)

Publié: Mar 25 Fév 2014, 20:25 
Plus récent, il y a aussi CE LIVRE mais à 75 euros le tome (il y en a 3), ce n'est hélas pas à la portée de tout le monde :cry:
Avatar de l’utilisateur
Arduino
Démonstratif
 
Messages: 1596
Inscrit le: Mer 25 Sep 2013, 17:14

PrécédentSuivant

Retour vers Arduino

Qui est en ligne ?

Utilisateur(s) parcourant actuellement ce forum : Aucun utilisateur inscrit et 1 invité