LOCODUINO

Parlons Arduino => Vos projets => Discussion démarrée par: peyo le juin 24, 2018, 12:11:07 pm

Titre: Automate embarqué
Posté par: peyo le juin 24, 2018, 12:11:07 pm
Bonjour à tous,
Voila quelques années que je construis des trains de jardin à l'échelle 1/13.5ème (7/8n2) pour mon fils mais aussi un peu pour moi je l'avoue :-)
J'ai réalisé un circuit de 50m dans mon jardin et toute une serie de locos mais je bloque sur la prog Arduino..
J'ai bien avancé et progressé en code et compréhension de l'engin mais je suis bloqué à l'heure ou je vous tape ces lettres..
Je maîtrise le module RFID et sa programmation (lecture et envoi d'ordres) ainsi que le module L298 (accélération et sens moteur)

Le projet :
Un circuit de 50m linéaire avec un badge RFID à chaque extremité (butée fin de voie) et également 1 badge RFID en entrée ET sortie de gare (Gare 1 et Gare 2).
Sous ma loco j'ai un arduino nano, un bouton poussoir BP1, un lecteur RFID et également un module L298 pour gérer l'accélération progressive de la loco et le sens du moteur.

Mon objectif :
    1 : La loco se met en marche avant  (progressive) lorsque j'appui sur un bouton poussoir BP1.
    2 : Si la loco badge sur une puce RFID Fin de voie 1 ou Fin de voie 2, la loco s'arrête progressivement pour repartir dans l'autre sens suivant une tempo définie.
    3 : Si la loco passe sur un Badge Gare 1 ou Gare 2, la loco décélère, s'arrête, puis repart progressivement (dans le même sens) après une tempo définie.
    4 : enfin, si je rappuis sur BP1, la loco s'arrête.

Je peux ainsi déplacer les badges sur la voie pour faire évoluer le parcours...

Matos :
- Arduino nano
- Bouton poussoir BP1
- RFID RC522
- Module L298N
- Badge RFID Gare 1
- Badge RFID Gare 2
- Badge RFID Fin de voie 1
- Badge RFID Fin de voie 2

 :o Voila le bazard, J'arrive à faire quelques bout de code mais rien qui tienne le rail, j'y ai déjà passé une bonne vingtaine d'heure mais la... je vois pas d'issue possible avec mon niveau débutant..

Merci infiniment à toutes les personnes qui seraient de bon conseil et je vénérerai quiconque me proposerais un bout de code!

 Au plaisir  :)
peyo
Titre: Re : Automate embarqué
Posté par: msport le juin 24, 2018, 03:27:07 pm
Bonjour,

est-ce que le programme de va-et-vient de Dominique ne pourrait pas servir de trame au votre ?

http://www.locoduino.org/spip.php?article232

et sur le forum :

http://forum.locoduino.org/index.php?topic=479.msg4837#msg4837

Dominique l'a bien structuré et c'est un exemple en particulier pour la méthode.
Titre: Re : Automate embarqué
Posté par: peyo le juin 24, 2018, 09:07:01 pm
Merci pour votre réponse,
Oui effectivement ce programme pourrait m’être bien utile,
Cependant je le garde en plan B car je voudrais vraiment garder l'option RFID avec les badges déplacables suivant mes besoins.
L'affichage ne me sert à rien non plus, puisque tout est embarqué dans la loco.

En tous les cas je vais prendre le temps de comprendre ce programme car il pour moi,
comprendre un programme est relativement simple, le modifier et enlever des éléments...

MERCI en tous les cas.
Peyo
Titre: Re : Automate embarqué
Posté par: msport le juin 24, 2018, 09:42:21 pm
Dans le programme de Dominique, l'arrivée dans un canton est donnée par un signal logique fourni par un détecteur d'occupation.
Détecteur d'occupation qui peut fonctionner sur plusieurs principes (comme discuté). Le tout étant d'avoir un signal logique comme peut le fournir un lecteur de badge. Il suffit d'inclure sa gestion sous la forme d'une fonction.
Bien sur, l'afficheur ne sert à rien en exploitation normale, mais peut être bien utile dans la phase de mise au point, surtout pour avoir quelques points de repère et savoir où votre programme en est.
Titre: Re : Automate embarqué
Posté par: savignyexpress le juin 25, 2018, 07:43:02 am
Bonjour Peyo,

Je pense que ton système peut se modéliser par une machine d'états. L'article de Locoduino sur la gestion d'un PN illustre parfaitement ce concept: http://www.locoduino.org/spip.php?article25 (http://www.locoduino.org/spip.php?article25).

Dans ton cas, les transitions seront déclenchées par les passages sur les différents types de badge, les timeouts et le bouton poussoir. Pour les accélérations / décélérations, il faudra changer les consignes de vitesse toutes les N millisecondes jusqu'à ce que la consigne = 0 ou la valeur max. Ensuite la loco passera à l'état arrêté ou vitesse de croisière.

Bonne réalisation et bon début de semaine.

Titre: Re : Automate embarqué
Posté par: Dominique le juin 25, 2018, 09:49:35 am
Mais quel est le problème ?

Un problème de capteurs RFID ? Es-tu certain de les détecter tous à tous les coups ?

Ou un problème de logique d’automate ?

Peux-tu mettre ton programme en pièce jointe ?

Bonne journée.

Dominique
Titre: Re : Automate embarqué
Posté par: peyo le juin 25, 2018, 12:06:14 pm
Merci pour vos réponses,
J'ai pas encore grand chose comme code hormis le code du RFID de base qui voit passer la loco pour déclencher une action et celui de la carte L298N avec un code pour une fonction accélération et Deceleration. (j'ai testé les deux et ils fonctionnent bien)

Voici mon Grafcet :
(http://forum.locoduino.org/index.php?action=dlattach;topic=575.0;attach=1734)

Pour la machine d'état, c'est bien la solution selon moi, mais j'aimerai trouver un programme sur lequel me baser pour démarrer..
Mon problème c'est que je suis un débutant en code et je maîtrise chaque élément mais les mélanger.. je bugg!

Belle journée à vous.
Peyo


Titre: Re : Automate embarqué
Posté par: Dominique le juin 25, 2018, 12:56:38 pm
Mais justement, l’article de Jean-Luc cité par Marc-Henri est exactement ce qu’il te faut : à moins d’un coup de chance extraordinaire, tu ne trouveras pas ton programme tout fait, il faut passer par une phase de réflexion pour faire la modélisation, c’est à dire imaginer ton système en fonctionnement et faire la liste de tous les événements (les passages devant les capteurs, les fins de temporisation), les actions déclenchées par ces événements (des sous-programmes pour garder ton programme principal le plus clair possible, en choisissant des noms explicites), et surtout les états possibles qui seront représentés par une ou plusieurs variables d’état.

Par exemple, les différentes phases du parcours sont représentées par une variable d’état et le sens de déplacement par une autre. Quand une condition se réalise (capteur, tempo) il faut tester toutes les variables concernées.

Autre exemple, une variable doit indiquer si le train entre où sort de la gare : cela éliminera la problème que tu évoques.

Pour gérer les temporisations en tache de fond il faut évidemment utiliser la fonction millis()  :
if ((millis() - dateDernierChangement) > tempo)
{
  action en fin de tempo
}

C’est difficile de te donner des exemples, il y en plein dans Locoduino !

Dans tous les cas une bonne réflexion avant de programmer est nécessaire.

Bon courage.
Titre: Re : Automate embarqué
Posté par: peyo le juin 29, 2018, 10:11:59 pm
Bonsoir à tous,
Bon je n'ai pas encore fini mais j'ai essayé de faire un programme...
Vous en pensez quoi? je vais dans le mur ou je peux poursuivre??

C'est surement bourré de fautes mais j'y travail..

D'avance merci pour vos réponses..

// Gestion d'un train automatique par badges RFID posés sur la voie

#include <SPI.h>
#include <RFID.h>
RFID RFID(10,9);


/*
 * Décommentez la ligne ci-dessous pour avoir l'affichage
 * de l'état courant de l'automate sur les broches 8 à 12
 */
// #define AVEC_AFFICHAGE_ETAT
//répertoir des gadges :
int UID[5]={};
int Gare1[5]={34,199,71,115,209};  // badge gare 1
int Gare2[5]={60,111,82,115,114};  //badge gare 2
int Fin1[5]={17,17,76,115,63};     //badge Fin de voie 1
int Fin2[5]={176,247,96,131,164};  //badge Fin de voie 2


//gestion du pont en H
int IN1 = 6; // commande pont en H "1"
int IN2 = 7; // commande pont en H "2"
 
int a; //rapport cyclique entre 0 et 255

/*-------------------------------------------------------------------*/
/* Les états possible pour le PN */
enum { LOCO_ARRET, LOCO_SENS1, LOCO_SENS2, LOCO_ACC_SENS1GARE, LOCO_DEC_SENS1GARE, LOCO_ACC_SENS2GARE, LOCO_DEC_SENS2GARE, LOCO_ACC_SENS1FIN, LOCO_DEC_SENS1FIN, LOCO_ACC_SENS2FIN, LOCO_DEC_SENS2FIN, TEMPO_FIN_SENS1, TEMPO_GARE_SENS1, TEMPO_FIN_SENS2, TEMPO_GARE_SENS2 } etat_loco;
//adressage à des pin en vu d'un affichage
const byte Badge_Gare1 = 2;
const byte Badge_Gare2 = 3;
const byte Badge_FinDeVoie1 = 4;
const byte Badge_FinDeVoie2 = 5;

/* Feux de la loco */

const byte feu_sens_1Pin = 8;
const byte feu_sens_2Pin = 9;


/*-------------------------------------------------------------------*/
// La temporisation en gare en ms

const unsigned long temporisationEnGare = 60000;
const unsigned long temporisationEnFinDeVoie = 2000;

/*-------------------------------------------------------------------*/
/* Intialisations */
void setup()
{
 
  Serial.begin(9600);
  SPI.begin();
  RFID.init();
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  //sortie moteur sens 1 et sens 2 à 0
  digitalWrite(IN2, 0);
  digitalWrite(IN1, 0);
  // Rapport cyclique à 0
a=0;
 
}

/*-------------------------------------------------------------------*/
/* Recherche des Badges RFID */
void loop()
{
  if (RFID.isCard()) { 

          /* Lecture du tag */
          if (RFID.readCardSerial())
          {       
          /*Serial.print("L'UID est: ");*/ 
            for(int i=0;i<=4;i++)
            {
              UID[i]=RFID.serNum[i];
             /* Serial.print(UID[i],DEC);
              Serial.print(".");*/
            }
            /*Serial.println("");*/
          }
          /* fin de  Lecture du tag */
         
          if (UID[0] == Gare1[0]   
           && UID[1] == Gare1[1]   
           && UID[2] == Gare1[2]   
           && UID[3] == Gare1[3]   
           && UID[4] == Gare1[4]) 
            {
              Badge_Gare1 = HIGH;
              else
              Badge_Gare1 = LOW;
            }
           
          if (UID[0] == Gare2[0]   
           && UID[1] == Gare2[1]   
           && UID[2] == Gare2[2]   
           && UID[3] == Gare2[3]   
           && UID[4] == Gare2[4]) 
            {
              Badge_Gare2 = HIGH;
              else
              Badge_Gare2 = LOW;
            }
           
          if (UID[0] == Fin1[0]   
           && UID[1] == Fin1[1] 
           && UID[2] == Fin1[2]   
           && UID[3] == Fin1[3]   
           && UID[4] == Fin1[4]) 
            {
              Badge_FinDeVoie1 = HIGH;
              else
              Badge_FinDeVoie1 = LOW;
            }
           
          if (UID[0] == Fin2[0]   
           && UID[1] == Fin2[1]   
           && UID[2] == Fin2[2]   
           && UID[3] == Fin2[3]   
           && UID[4] == Fin2[4]) 
            {
             Badge_FinDeVoie1 = HIGH;
              else
              Badge_FinDeVoie1 = LOW;
            }
           
          RFID.halt();
 
    delay(100);   
}
  switch (etat_loco)
  {
    case LOCO_SENS1:
    analogWrite(IN1, 255);
      /* lecture du badge détecter un train */
      if (digitalRead(Badge_Gare1) = HIGH) {
        /* train en gare 1 */
        /* On décélère */
       analogWrite(IN1, a);
   a = a - 1;
   delay(20);

        etat_loco = LOCO_DEC_SENS1GARE;
      }
      if (digitalRead(Badge_FinDeVoie1) = HIGH) {
        /* train en fin de voie 1 */
        /* On décélère */
      analogWrite(IN1, a);
   a = a - 1;
   delay(20);

        etat_loco = LOCO_DEC_SENS1FIN;
      }
      break;

    case LOCO_SENS2:
    analogWrite(IN2, 255);
      /* lecture du badge détecter un train */
      if (digitalRead(Badge_Gare2) = HIGH) {
        /* train en gare 1 */
        /* On décélère */
       analogWrite(IN2, a);
   a = a - 1;
   delay(20);
        etat_loco = LOCO_DEC_SENS2GARE;
      }
      if (digitalRead(Badge_FinDeVoie2) = HIGH) {
        /* train en fin de voie 1 */
        /* On décélère */
      analogWrite(IN2, a);
   a = a - 1;
   delay(20);

        etat_loco = LOCO_DEC_SENS2FIN;
      }
      break;

    case LOCO_DEC_SENS1GARE:
      /* On attend que a = 0 puis on lance la tempo */
     if (a = 0) {
        etat_loco = TEMPO_GARE_SENS1;
      }
      break;
      case LOCO_DEC_SENS2GARE:
      /* On attend que a = 0 puis on lance la tempo */
     if (a = 0) {
       tempsArret = millis() + temporisationEnGare;
        etat_loco = TEMPO_GARE_SENS2;
      }
      break;
      case LOCO_DEC_SENS1FIN:
      /* On attend que a = 0 puis on lance la tempo */
     if (a = 0) {
        etat_loco = TEMPO_FIN_SENS1;
      }
      break;
      case LOCO_DEC_SENS2FIN:
      /* On attend que a = 0 puis on lance la tempo */
     if (a = 0) {
        etat_loco = TEMPO_FIN_SENS2;
      }
      break;

    case TEMPO_GARE_SENS1:
      /* Un train est en gare on attends 60secondes */
       if (millis() >= temporisationEnGare) {
          /* On redémare progressivement */
          etat_loco = LOCO_ACC_SENS1GARE ;
      }
      break;
      case TEMPO_GARE_SENS2:
      /* Un train est en gare on attends 60secondes */
       if (millis() >= temporisationEnGare) {
          /* On redémare progressivement */
          etat_loco = LOCO_ACC_SENS2GARE ;
      }
      break;
      case TEMPO_FIN_SENS1:
      /* Un train est en gare on attends 60secondes */
       if (millis() >= temporisationEnFinDeVoie) {
          /* On redémare progressivement */
          etat_loco = LOCO_ACC_SENS2FIN ;
      }
      break;
     
      case TEMPO_FIN_SENS2:
      /* Un train est en gare on attends 60secondes */
       if (millis() >= temporisationEnFinDeVoie) {
          /* On redémare progressivement */
          etat_loco = LOCO_ACC_SENS1FIN ;
      }
      break;
     
case LOCO_ACC_SENS1FIN:
      /* On attend que a = 0 puis on lance la tempo */
     analogWrite(IN1, a);
   a = a + 1;
   delay(20);
        etat_loco = LOCO_SENS1;
      }
      break;
     
      case LOCO_ACC_SENS2FIN:
      /* On attend que a = 0 puis on lance la tempo */
     analogWrite(IN2, a);
   a = a + 1;
   delay(20);
        etat_loco = LOCO_SENS2;
     
      break;
     
      case LOCO_ACC_SENS1GARE:
      /* On attend que a = 0 puis on lance la tempo */
     analogWrite(IN1, a);
   a = a + 1;
   delay(20);
        etat_loco = LOCO_SENS1;
     
      break;
     
      case LOCO_ACC_SENS2GARE:
      /* On attend que a = 0 puis on lance la tempo */
     analogWrite(IN2, a);
   a = a + 1;
   delay(20);
        etat_loco = LOCO_SENS2;
     
      break;
     
    case LOCO_ARRET:
    /* La loco est arrté ou qu'elle soit */
    analogWrite(IN1, 0)
    analogWrite(IN2, 0)
     
      break;

  }
}
Titre: Re : Automate embarqué
Posté par: Dominique le juin 30, 2018, 12:27:37 pm
Peux-tu m'indiquer quelle bibliothèque RFID tu utilises ?
Est-elle dans le gestionnaire de bibliothèque de l'IDE ?
Sinon où sur GitHub ?

Merci d'avance.

Il y a des erreurs dans ton sketch, notamment, tu définis des pins d'affichage (pour des leds ?) en constante et tu affectes ensuite des valeurs différentes :

const byte Badge_Gare1 = 2;
const byte Badge_Gare2 = 3;
const byte Badge_FinDeVoie1 = 4;
const byte Badge_FinDeVoie2 = 5;

---

{
  Badge_Gare1 = HIGH;
else
  Badge_Gare1 = LOW;
}

Je penses que tu voulais écrire
{
  digitalWrite(Badge_Gare1, HIGH);
else
  digitalWrite(Badge_Gare1, LOW;
}

D'une manière générale évite de mélanger les valeurs HIGH et LOW des booléens avec des valeurs numériques (même si LOW = 0 et HIGH > 0) : cela conduit très vite à des erreurs.

Ton sketch ne peut pas marcher car tu n'as qu'une seule variable d'état et ton système à besoin de plusieurs variables d'état :
- une pour la position de la loco
- une pour le sens
- une pour la vitesse courante
- une pour la tempo d'acceleration ou deceleration
- une pour la tempo d'arrêt en gare

De plus, comme ton programme doit pouvoir faire plusieurs choses à la fois, tu NE DOIS PAS utiliser delay() !!

Peux-tu lire mon article sur le va et vient qui traite à peu près le même problème que toi :
http://www.locoduino.org/spip.php?article232 (http://www.locoduino.org/spip.php?article232)

Tu y trouveras à coup sur les réponses dont tu as besoin.

Titre: Re : Automate embarqué
Posté par: peyo le juillet 01, 2018, 09:53:38 pm
Dominique,
Merci pour ta réponse,

J'ai trouvé ma biblio ici : http://idehack.com/dl/rfid_lib.rar (http://idehack.com/dl/rfid_lib.rar)
Je viens de finir de lire ton article sur le module Navette, il est vrai que ça m'à également l'air d'être une bonne base pour mon projet.
Je vais tout recommencer à partir de ton code, mais je t'avoue que quand je vois le nombre de lignes... je crois que je ne suis pas prêt d'y arriver !!

Je vais essayer, ça coûte rien. Merci encore pour tes conseils.


Peyo
Titre: Re : Automate embarqué
Posté par: Dominique le juillet 01, 2018, 10:07:08 pm
Peyo,

Mon code est un peu gros parce qu’il fait des tas de choses dont tu n’as pas besoin comme la recherche automatique d’adresse DCC, la gestion complète de l’afficheur et les asservissements de vitesse et de ralentissement.

Je te conseille d’essayer d’elaguer tout ce qui ne te semble pas indispensable et, tu verras que ce sera une bonne base.

On essayera d’en faire profiter tout le monde.

Bon courage et bonnes vacances !
Dominique

Titre: Re : Automate embarqué
Posté par: peyo le juillet 07, 2018, 04:15:41 pm
J'ai enfin un programme fonctionnel,
Dominique va surement bondir de son siège car je n'est pas (encore) suivi ces précieux conseils (mais je vais le faire! )

Prochaine étape : fonction MILLIS, et non Delay..

Voici le programme (vous en pensez quoi, des conseils pour une amélioration ?)
D'avance merci !
//Automate pour navette train plus arret en gare.
// commande automatismes par lecture de gadges RFID sur la voie
#include <SPI.h>
#include <RFID.h>
RFID RFID(10,9);
int UID[5]={};
int Gare1[5]={34,199,71,115,209};  // badge gare 1
int Gare2[5]={60,111,82,115,114};  //badge gare 2
int Fin1[5]={17,17,76,115,63};     //badge Fin de voie 1
int Fin2[5]={176,247,96,131,164};  //badge Fin de voie 2
int pinBouton;
int pinLedsens1, pinLedsens2;
//gestion du pont en H
int IN1 = 5; // commande pont en H "1"
int IN2 = 6; // commande pont en H "2"
 
int a; //rapport cyclique entre 0 et 255
 // tableau des machines à états
 enum {sens1, sens2 } etatloco ;
 enum {Marche, Stop  } etatmoteur ;
void setup() {
 
  Serial.begin(9600);
  SPI.begin();
  RFID.init();
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
 
  //leds avant arrière sur pin 3 et 4 :
  pinLedsens1 = 3;
  pinLedsens2 = 4;
 
  pinMode(pinBouton, INPUT); //mode lecture pour le bouton
  pinMode(pinLedsens1, OUTPUT);//sens 1 = led avant blanche et arrière rouge
  pinMode(pinLedsens2, OUTPUT); //sens 2 = led avant rouge et arrière blanche
 
  //bouton marche arret sur sortie 2:
   pinBouton = 2;
   
  // initialisation du moteur vitesse à 0
  digitalWrite(IN2, 0);
  digitalWrite(IN1, 0);
 
 // Initialisation des états
 etatloco = sens1 ;
 etatmoteur = Stop ;
 // initialisation du facteur d'incrémentation moteur
 a=0;
 
 // Initialisation des leds (feux du train en sens 1)
  digitalWrite(pinLedsens1,HIGH);
  digitalWrite(pinLedsens2,LOW);
}

void loop()

    //lecture de l'état du bouton et stockage dans etatBouton
  boolean etatBouton = digitalRead(pinBouton);
 
if (etatBouton == HIGH && etatmoteur == Stop ) //marche
{
  a=0;
ACCELERATION_SENS1();
a=255;
etatmoteur = Marche;
etatloco = sens1 ;
etatBouton == LOW ;
}


else if (etatBouton == HIGH && etatmoteur == Marche)// Arret
{
  a=255;
  STOP_moteur();
  etatmoteur = Stop;
  etatBouton == LOW ;
 }
 
// Recherche de badges RFID sur la voir
   if (RFID.isCard() && etatmoteur == Marche) { 

          /* Lecture du tag */
          if (RFID.readCardSerial())
          {       
          /*Serial.print("L'UID est: ");*/ 
            for(int i=0;i<=4;i++)
            {
              UID[i]=RFID.serNum[i];
             /* Serial.print(UID[i],DEC);
              Serial.print(".");*/
            }
            /*Serial.println("");*/
          }
          /* fin de  Lecture du tag */
         
          if (UID[0] == Gare1[0]// si lecture du badge Gare 1
           && UID[1] == Gare1[1]   
           && UID[2] == Gare1[2]   
           && UID[3] == Gare1[3]   
           && UID[4] == Gare1[4]
           && etatloco == sens1)
            {
              a=255 ;
             DECCELERATION_SENS1();
          delay (2000);
          a=0;
          ACCELERATION_SENS1() ;
          etatloco = sens1 ;
           
            }
           
          if (UID[0] == Gare2[0] // si lecture du badge Gare 2
           && UID[1] == Gare2[1]   
           && UID[2] == Gare2[2]   
           && UID[3] == Gare2[3]   
           && UID[4] == Gare2[4]
           && etatloco == sens2) 
            {
              a=255 ;
          DECCELERATION_SENS2();
          delay (2000);
          a=0;
          ACCELERATION_SENS2() ;
          etatloco = sens2 ;
            }
           
          if (UID[0] == Fin1[0] // si lecture du badge fin de voie 1 
           && UID[1] == Fin1[1] 
           && UID[2] == Fin1[2]   
           && UID[3] == Fin1[3]   
           && UID[4] == Fin1[4]
           && etatloco == sens1) 
            {
             a=255 ;
             DECCELERATION_SENS1();
          delay (2000);
          digitalWrite(pinLedsens2,HIGH); //inversement des feux rouge en blanc
          digitalWrite(pinLedsens1,LOW);
          delay (1000) ;
          a=0;
          ACCELERATION_SENS2() ;
          etatloco = sens2 ;
            }
           
          if (UID[0] == Fin2[0] // si lecture du badge fin de voie 2 
           && UID[1] == Fin2[1]   
           && UID[2] == Fin2[2]   
           && UID[3] == Fin2[3]   
           && UID[4] == Fin2[4]
           && etatloco == sens2)   
            {
              a=255 ;
             
             DECCELERATION_SENS2();
          delay (2000);
          digitalWrite(pinLedsens1,HIGH);
          digitalWrite(pinLedsens2,LOW);
          delay (1000) ;
          a=0;
          ACCELERATION_SENS1() ;
          etatloco = sens1 ;
            }
           
          RFID.halt();
    }
    delay(100);   
}

void STOP_moteur()//en cas de problème ou pour éteindre l'automate
{
 analogWrite(IN1, 0) ;
 analogWrite(IN2, 0) ;

}
void ACCELERATION_SENS1()
{
  while (a <=255)
  { // phase d'accélération.
   analogWrite(IN1, a);
   a = a + 1;
   delay(20);
 }
}

void DECCELERATION_SENS1()
{
  while (a >=0) { // phase de décélération
   analogWrite(IN1, a);

   a = a - 1;
   delay(20);
  }
}
void ACCELERATION_SENS2()
{
 while (a <=255)
  { // phase d'accélération.
   analogWrite(IN2, a);
   a = a + 1;
   delay(20);
 }
}

void DECCELERATION_SENS2()
{
  while (a >=0)
  { // phase d'accélération.
   analogWrite(IN2, a);
   a = a - 1;
   delay(20);
 }
}


Je n'ai pas encore installé le montage dans la loco mais tout est fonctionnel, le seul problème que je rencontre est que le bouton STOP est fonctionnel uniquement en plage constante de fonctionnent . (je souhaiterais que le programme s'arrête est que le mode stop soit prioritaire..)
Titre: Re : Automate embarqué
Posté par: Dominique le juillet 07, 2018, 08:40:32 pm
Bravo Peyo, il y a de gros progrès  ;D

Citer
le seul problème que je rencontre est que le bouton STOP est fonctionnel uniquement en plage constante de fonctionnent

A première vue (je rentre de voyage à l'instant), tu testes l'état du bouton (qui peut fluctuer énormément car il y a des rebonds (voir la 2ème partie de l'article http://www.locoduino.org/spip.php?article74 (http://www.locoduino.org/spip.php?article74)), alors qu'il faudrait tester plutôt l'enfoncement du bouton (après élimination des rebonds, avec la bibliothèque Bounce2).

Après il faut que je regarde de plus près quelles conditions empêchent le bouton STOP d'être fonctionnel tout le temps (demain).
Titre: Re : Automate embarqué
Posté par: msport le juillet 08, 2018, 12:00:04 am
ligne 71 le else n'est pas logique.
Titre: Re : Automate embarqué
Posté par: peyo le juillet 08, 2018, 09:46:52 am
Citer
ligne 71 le else n'est pas logique.

J'ai trouvé cette bidouille dans un exemple sur le net, et sans ce ELSE IF, le moteur démarre à l'appuis sur le bouton puis s'arrête d'un coup..

Je ne comprends pas pourquoi d'ailleurs mais avec le else ça fonctionne !
Titre: Re : Automate embarqué
Posté par: peyo le juillet 08, 2018, 09:58:21 am
Citer
tu testes l'état du bouton (qui peut fluctuer énormément car il y a des rebonds
Dominique, J'ai monté mon bouton un pull up, (à ce qu'il parait) c'est moins pire?

J'ai essayé d’insérer bounce 2 mais rien ne fonctionne, je ne comprends pas..
(j'ai même cramé une UNO en modifiant le câblage après un C-C sur l'alim stabilisé 12v :-( ..)


//Automate pour navette train plus arret en gare.
// commande automatismes par lecture de gadges RFID sur la voie
#include <Bounce2.h>
#include <SPI.h>
#include <RFID.h>

RFID RFID(10,9);
int UID[5]={};
int Gare1[5]={34,199,71,115,209};  // badge gare 1
int Gare2[5]={60,111,82,115,114};  //badge gare 2
int Fin1[5]={17,17,76,115,63};     //badge Fin de voie 1
int Fin2[5]={176,247,96,131,164};  //badge Fin de voie 2
int pinLedsens1, pinLedsens2;
//gestion du pont en H
int IN1 = 5; // commande pont en H "1"
int IN2 = 6; // commande pont en H "2"

// Création d'un objet Bounce que j'appelle bouton
Bounce bouton;
const byte bp = 2;
 
int a; //rapport cyclique entre 0 et 255
 // tableau des machines à états
 enum {sens1, sens2 } etatloco ;
 enum {Marche, Stop  } etatmoteur ;
 
 //////////////////////////////////////////////////////////////
void setup() {
 
  Serial.begin(9600);
  SPI.begin();
  RFID.init();
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
 
  //leds avant arrière sur pin 3 et 4 :
  pinLedsens1 = 3;
  pinLedsens2 = 4;
 
  pinMode(bp,INPUT_PULLUP);
 
  // definition des paramètres de l'objet Bounce
  bouton.attach(bp);   // la broche du bouton poussoir
  bouton.interval(10); // l'intervalle de temps en ms
 
  pinMode(pinLedsens1, OUTPUT);//sens 1 = led avant blanche et arrière rouge
  pinMode(pinLedsens2, OUTPUT); //sens 2 = led avant rouge et arrière blanche
 
   
  // initialisation du moteur vitesse à 0
  digitalWrite(IN2, 0);
  digitalWrite(IN1, 0);
 
 // Initialisation des états
 etatloco = sens1 ;
 etatmoteur = Stop ;
 // initialisation du facteur d'incrémentation moteur
 a=0;
 
 // Initialisation des leds (feux du train en sens 1)
  digitalWrite(pinLedsens1,HIGH);
  digitalWrite(pinLedsens2,LOW);
}

void loop()

   // l'objet Bounce doit exécuter son code interne à chaque loop :
  bouton.update();
   // Lire la valeur du bp filtré :
  int value = bouton.read();
 
if (value == LOW && etatmoteur == Stop ) //marche
{
  a=0;
 
ACCELERATION_SENS1();
a=255;
etatmoteur = Marche;
etatloco = sens1 ;
value = HIGH;
delay (100) ;
}


else if (value == LOW && etatmoteur == Marche)// Arret
{
  a=255;
  STOP_moteur();
  etatmoteur = Stop;
  value = HIGH;
   delay (100) ;
 }
 
// Recherche de badges RFID sur la voir
   if (RFID.isCard() && etatmoteur == Marche) { 

          /* Lecture du tag */
          if (RFID.readCardSerial())
          {       
          /*Serial.print("L'UID est: ");*/ 
            for(int i=0;i<=4;i++)
            {
              UID[i]=RFID.serNum[i];
             /* Serial.print(UID[i],DEC);
              Serial.print(".");*/
            }
            /*Serial.println("");*/
          }
          /* fin de  Lecture du tag */
         
          if (UID[0] == Gare1[0]// si lecture du badge Gare 1
           && UID[1] == Gare1[1]   
           && UID[2] == Gare1[2]   
           && UID[3] == Gare1[3]   
           && UID[4] == Gare1[4]
           && etatloco == sens1)
            {
              a=255 ;
             DECCELERATION_SENS1();
          delay (2000);
          a=0;
          ACCELERATION_SENS1() ;
          etatloco = sens1 ;
           
            }
           
          if (UID[0] == Gare2[0] // si lecture du badge Gare 2
           && UID[1] == Gare2[1]   
           && UID[2] == Gare2[2]   
           && UID[3] == Gare2[3]   
           && UID[4] == Gare2[4]
           && etatloco == sens2) 
            {
              a=255 ;
          DECCELERATION_SENS2();
          delay (2000);
          a=0;
          ACCELERATION_SENS2() ;
          etatloco = sens2 ;
            }
           
          if (UID[0] == Fin1[0] // si lecture du badge fin de voie 1 
           && UID[1] == Fin1[1] 
           && UID[2] == Fin1[2]   
           && UID[3] == Fin1[3]   
           && UID[4] == Fin1[4]
           && etatloco == sens1) 
            {
             a=255 ;
             DECCELERATION_SENS1();
          delay (2000);
          digitalWrite(pinLedsens2,HIGH); //inversement des feux rouge en blanc
          digitalWrite(pinLedsens1,LOW);
          delay (1000) ;
          a=0;
          ACCELERATION_SENS2() ;
          etatloco = sens2 ;
            }
           
          if (UID[0] == Fin2[0] // si lecture du badge fin de voie 2 
           && UID[1] == Fin2[1]   
           && UID[2] == Fin2[2]   
           && UID[3] == Fin2[3]   
           && UID[4] == Fin2[4]
           && etatloco == sens2)   
            {
              a=255 ;
             
             DECCELERATION_SENS2();
          delay (2000);
          digitalWrite(pinLedsens1,HIGH);
          digitalWrite(pinLedsens2,LOW);
          delay (1000) ;
          a=0;
          ACCELERATION_SENS1() ;
          etatloco = sens1 ;
            }
           
          RFID.halt();
    }
    delay(100);   
}

void STOP_moteur()//en cas de problème ou pour éteindre l'automate
{
 analogWrite(IN1, 0) ;
 analogWrite(IN2, 0) ;

}
void ACCELERATION_SENS1()
{
  while (a <=255)
  { // phase d'accélération.
   analogWrite(IN1, a);
   a = a + 1;
   delay(20);
 }
}

void DECCELERATION_SENS1()
{
  while (a >=0) { // phase de décélération
   analogWrite(IN1, a);

   a = a - 1;
   delay(20);
  }
}
void ACCELERATION_SENS2()
{
 while (a <=255)
  { // phase d'accélération.
   analogWrite(IN2, a);
   a = a + 1;
   delay(20);
 }
}

void DECCELERATION_SENS2()
{
  while (a >=0)
  { // phase d'accélération.
   analogWrite(IN2, a);
   a = a - 1;
   delay(20);
 }
}
Titre: Re : Automate embarqué
Posté par: msport le juillet 08, 2018, 10:07:58 am
le else élimine le cas Etat bouton == HIGH

pour voir où on passe dans le programme, il faut y placer des mouchards avec des Serial.print avec les variables concernées.
Titre: Re : Re : Automate embarqué
Posté par: msport le juillet 08, 2018, 10:10:50 am
j'ai même cramé une UNO en modifiant le câblage après un C-C sur l'alim stabilisé 12v :-( ..)

cause de décès prématuré bien connue. RIP.
Titre: Re : Automate embarqué
Posté par: Dominique le juillet 08, 2018, 07:46:42 pm
Bonsoir peyo,

Voici une version améliorée de ton sketch :
//Automate pour navette train plus arret en gare.
// commande automatismes par lecture de gadges RFID sur la voie
#include <Bounce2.h>
#include <SPI.h>
#include <RFID.h>

RFID RFID(10,9);
int UID[5]={};
int Gare1[5]={34,199,71,115,209};  // badge gare 1
int Gare2[5]={60,111,82,115,114};  //badge gare 2
int Fin1[5]={17,17,76,115,63};     //badge Fin de voie 1
int Fin2[5]={176,247,96,131,164};  //badge Fin de voie 2

// Création d'un objet Bounce que j'appelle bouton
const int pinBp = 2;
Bounce bouton = Bounce();

// leds de sens
const int pinLedsens1 = 3;
const int pinLedsens2 = 4;

//gestion du pont en H
const int pinIN1 = 5; // commande pont en H "1"
const int pinIN2 = 6; // commande pont en H "2"

//vitesse moteur : rapport cyclique entre 0 et 255
int a = 0;

// tableau des machines à états
enum {sens1, sens2 } etatloco ;
enum {Marche, Stop } etatmoteur ;
enum {nulpart, posGare1, posGare2, posFin1, posFin2} posloco;
 
 //////////////////////////////////////////////////////////////
void setup() {
 
  Serial.begin(9600);
  SPI.begin();
  RFID.init();
  pinMode(pinIN1, OUTPUT);
  pinMode(pinIN2, OUTPUT);

  // initialisation du moteur vitesse à 0
  digitalWrite(pinIN1, 0);
  digitalWrite(pinIN2, 0);

  //leds avant arrière sur pin 3 et 4 :
  pinMode(pinLedsens1, OUTPUT);//sens 1 = led avant blanche et arrière rouge
  pinMode(pinLedsens2, OUTPUT); //sens 2 = led avant rouge et arrière blanche
  // Initialisation des leds (feux du train en sens 1)
  digitalWrite(pinLedsens1,HIGH);
  digitalWrite(pinLedsens2,LOW);
 
 
  // definition des paramètres de l'objet Bounce
  pinMode(pinBp,INPUT_PULLUP);
  bouton.attach(pinBp);   // la broche du bouton poussoir
  bouton.interval(20); // l'intervalle de temps en ms
 
 
  // Initialisation des états
  etatloco = sens1 ;
  etatmoteur = Stop ;
  posloco = nulpart;
 
  // initialisation du facteur d'incrémentation moteur ???
  a=0; // mais c'est déjà fait dans la déclaration
 
}

///////////////// UTILITAIRES ////////////
void STOP_MOTEUR()  //en cas de problème ou pour éteindre l'automate
{
 analogWrite(pinIN1, 0) ;
 analogWrite(pinIN2, 0) ;

}

void ACCELERATION_SENS1()
{
  while (a < 255)
  { // phase d'accélération sens 1
    a++;
    analogWrite(pinIN1, a);
    delay(20);
  }
}

void DECCELERATION_SENS1()
{
  while (a > 0)
  { // phase de décélération sens 1
    a--;
    analogWrite(pinIN1, a);
    delay(20);
  }
}

void ACCELERATION_SENS2()
{
  while (a < 255)
  { // phase d'accélération sens 2
    a++;
    analogWrite(pinIN2, a);
    delay(20);
  }
}

void DECCELERATION_SENS2()
{
  while (a > 0)
  { // phase d'accélération sens 2
   a--;
   analogWrite(pinIN2, a);
   delay(20);
 }
}


void loop()

  // l'objet bouton doit exécuter son code interne à chaque loop :
  bouton.update();
  // lecture du bouton et execution à chaque enfoncement
  if (bouton.fell())
  {
    if (etatmoteur == Stop) // acceleration et marche
    {
      // demarrage depuis la vitesse 0 (stop)
      a = 0;
      ACCELERATION_SENS1();
      etatmoteur = Marche;
      etatloco = sens1 ;
      delay (100) ;
    } else // (etatmoteur == Marche) : stop
    {
      // arrêt immediat du moteur
      STOP_MOTEUR();
      a = 0;
      etatmoteur = Stop;
      delay (100) ;
    }
  }
   
 
  // Recherche de badges RFID sur la voie, uniquement en marche
  if (RFID.isCard() && etatmoteur == Marche)
  { 

    /* Lecture du tag */
    if (RFID.readCardSerial())
    {       
      /*Serial.print("L'UID est: ");*/ 
      for (int i=0;i<=4;i++)
      {
        UID[i]=RFID.serNum[i];
        // Serial.print(UID[i],DEC);Serial.print(".");
      }
      //Serial.println("");
    }/* fin de  Lecture du tag */
    RFID.halt();
  }

  // recherche de la position
  posloco = nulpart;
  for (int i=0;i<=4;i++)
    {     
      if (UID[i] == Gare1[i]) // si lecture du badge Gare 1
      {
        posloco = posGare1;
      } else {
        posloco = nulpart;
        break; // sortie de la boucle for car une des valeurs est fausse
      }
    }
  for (int i=0;i<=4;i++)
    {     
      if (UID[i] == Gare2[i]) // si lecture du badge Gare 2
      {
        posloco = posGare2;
      } else {
        posloco = nulpart;
        break; // sortie de la boucle for car une des valeurs est fausse
      }
    }
  for (int i=0;i<=4;i++)
    {     
      if (UID[i] == Fin1[i]) // si lecture du badge Fin de voie 1
      {
        posloco = posFin1;
      } else {
        posloco = nulpart;
        break; // sortie de la boucle for car une des valeurs est fausse
      }
    }
  for (int i=0;i<=4;i++)
    {     
      if (UID[i] == Fin2[i]) // si lecture du badge Fin de voie 2
      {
        posloco = posFin2;
      } else {
        posloco = nulpart;
        break; // sortie de la boucle for car une des valeurs est fausse
      }
    }
             
  switch (posloco)
  {
    case posGare1 :
      a=255 ;
      DECCELERATION_SENS1();
      delay (2000);
      a=0;
      ACCELERATION_SENS1() ;
      etatloco = sens1 ;
    break;
    case posGare2 :
      a=255 ;
      DECCELERATION_SENS2();
      delay (2000);
      a=0;
      ACCELERATION_SENS2() ;
      etatloco = sens2 ;
    break;
    case posFin1 :
      if (etatloco == sens1) 
      {
        a=255 ;
        DECCELERATION_SENS1();
        delay (2000);
        digitalWrite(pinLedsens2,HIGH); //inversement des feux rouge en blanc
        digitalWrite(pinLedsens1,LOW);
        delay (1000) ;
        a=0;
        ACCELERATION_SENS2() ;
        etatloco = sens2 ;
      }
    break;
    case posFin2 :
      if (etatloco == sens2)   
      {
        a=255 ;
        DECCELERATION_SENS2();
        delay (2000);
        digitalWrite(pinLedsens1,HIGH);
        digitalWrite(pinLedsens2,LOW);
        delay (1000) ;
        a=0;
        ACCELERATION_SENS1() ;
        etatloco = sens1 ;
      }         
    break;     
  }
           
  //delay(100);   
}


Les améliorations sont les suivantes :

- les définitions et déclarations sont mieux classées et les pins de l'Arduino sont déclarées en const int.
- j'ai préfixé chaque pin des lettres "pin".
- l'objet bouton était mal déclaré : Bounce bouton = Bounce();
- j'ai ajouté une variable d'état : enum {nulpart, posGare1, posGare2, posFin1, posFin2} posloco;

Ceci permet de traiter indépendamment les 3 actions de ta loop (la lecture du bouton, la reconnaissance RFID et l'action qui en découle.

- j'ai remonté tes fonctions utilitaires entre le setup() et la loop() car c'est mieux de déclarer quelque chose AVANT de s'en servir (même si le compilateur ne proteste pas, crois moi, il protestera un de ces jours quand ton code va grossir !).
Je les ai modifiées pour les rendre plus claires.

La loop() est composée de 3 parties qui s'exécutent l'une après l'autre :

La lecture du bouton :
Seul l'enfoncement est pris en compte. Un appui, ça démarre, un appui ça s'arrête.
Il faudra que tu regardes ce que tu voulais exactement pour initialiser la variable "a" ou pas selon le résultat attendu

La lecture du RFID : elle donne un résultat qui est TOUJOURS un des cas de l'enum "posloco".
C'est "nulpart" quand une des valeurs est fausse.

Ensuite le traitement de la position : si c'est nulpart, elle ne fait rien (il n'y a pas de "case nulpart").
Donc dès qu'il y a une détection valide, l'un des cas du switch s'éxécute.

Il faudra que tu revoies les exécutions des cas dans le switch et que tu simplifies ou corriges. C'est là que ton programme fait le boulot principal.

Amicalement
Dominique
Titre: Re : Automate embarqué
Posté par: Dominique le juillet 08, 2018, 09:17:41 pm
Bon je n’ai probablement pas pris le temps de tout vérifier, donc il reste sûrement des erreurs.

Par exemple, la recherche de la position doit être dans le « if (RFID.iscard()) » sinon le traitement de la balise précédente va se répéter jusqu’à la suivante.

Bon je te laisse chercher les autres ...
Titre: Re : Automate embarqué
Posté par: peyo le juillet 12, 2018, 10:25:14 pm
Merci Dominique pour ton aide,
Je ne serais pas dispo cet été pour bosser sur ce programme mais dès la rentrée je m'y replonge !!!
Effectivement le bouton fonctionne bien mais les badges ne sont pas détectés.

Bonnes vacances à tous et bon courage pour ceux qui comme moi, bossent dur tout l'été !!