Programmation arduino

Bonjour au forum Arduino,

Je suis actuellement en école d’ingénieur et nous avons un projet à réaliser. Notre sujet est “changement de batterie automatisé” appliqué à une station de bus.

Pour ceci, nous avons réalisé une maquette. La maquette comprend :

  • le stockage des batteries (un rack linéaire)
  • un convoyeur permettant de chercher/ranger la batterie
  • un élévateur permettant d’insérer/retirer la batterie du bus
    Tous les mouvements sont réalisés par des moteurs dont j’ai déjà programmé le fonctionnement.

J’ai réalisé le grafcet mais je ne vois pas comment le programmer sous arduino, si quelqu’un peut m’aider …
Merci par avance.

(Nota 1 : n’hésitez pas à me demander s’il manque des infos)
(Nota 2 : le grafcet est en pièce jointe .pdf et un schéma maquette en .jpeg)

Grafcet - projetBUS.pdf (362 KB)

Pour un Arduino, "tempo" sera réalisé par la fonction delay. Le reste de ton programme sera une suite d'appels à des fonctions "unitaires" qui font ce qui se trouve dans les rectangles de ton graphe.

Si ton problème est plus sur la compréhension et la programmation en C/C++, tu devrais commencer par lire des tutos : Eskimon, OpenClassRooms dans un premier temps (mais il y en a d'autres), et faire quelques uns des montages proposés en exemples.

Sans indiscrétion : quelle école d'ingénieur ?

Merci lesept pour cette réponse rapide ! ce que tu appelles “fonctions unitaires” sont des suites “if - then - else”, c’est bien ça ?
Si c’est le cas, puis-je déposer mon programme ici une fois réalisé pour que quelqu’un y jette un œil ?

Je maîtrise le fondamental d’arduino, là c’est surtout un problème “d’architecture” de programme :frowning:

Mon école d’ingénieur est HEI

Bonsoir
Le Grafcet (graphe étapes transitions)e st une variante d’automate à états finis.

le codage Arduino sous forme de machine d’états parait içi tout à fait adapté.

Voir par exemple le tutoriel de J-M-L

(dans le Grafcet joint on a la forme la plus simple d’automate à états finis (‘machine de Moore’) avec ,à chaque étape des actions ne dépendant que de l’état courant, les entrées ne servant qu’à réaliser les transitions entre étapes.
En plus il n’y a a pas de divergence, chaque état à un prédécesseur unique et un successeur unique.)

La transposition ne devrait pas poser de problèmes : énumérer les 19 états (étapes) , associer les actions aux états (étapes), décrire les conditions d’évolution d’une étape à la suivante

(tu peux aussi utiliser diverses librairies pour programmer ce genre modélisation, arduino-fsm en est une)

The62:
ce que tu appelles "fonctions unitaires" sont des suites "if - then - else", c'est bien ça ?

Pas forcément, je pensais à des fonctions comme

void function (paramètres) {
  instructions;
  instructions;
}

qui seraient appelées aux bons moments.

Ça donnerait une loop comme :

void loop () {
  fonction_1 ();
  delay(durée_1);
  fonction_2 ();
  delay(durée_2);
    ...
  fonction_n ();
}

Mais la solution de la machine à états proposée par al1fch est plus élégante.

The62:
Si c'est le cas, puis-je déposer mon programme ici une fois réalisé pour que quelqu'un y jette un œil ?

Oui, c'est un peu le but du forum...

Bonsoir,
J’ai eu peu de temps pour travailler sur le programme. Ici je ne traite le cas que d’un moteur en exemple afin de savoir si j’ai bien compris le principe ! La gestion du moteur se fait directement par un shield qui modifie le PWM, voilà pourquoi ça peut paraître bizarre comme prog !

// moteur_A
int enA = 10;
int in1 = 9;
int in2 = 8;
// moteur_B
int enB = 5;
int in3 = 7;
int in4 = 6;


void setup()
{
// déclare les pins "controle moteur" en tant que sorties
pinMode(enA, OUTPUT);
pinMode(enB, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
pinMode(in3, OUTPUT);
pinMode(in4, OUTPUT);
}


void moteurA_Horaire()
{
// Rotation horaire moteurA
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
analogWrite(enA, 200); // réglage vitesse (200) du moteurA sur la plage 0~255
}

void moteurA_Antihoraire()
{
// Rotation antihoraire moteurA
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
analogWrite(enA, 200); // réglage vitesse (200) du moteurA sur la plage 0~255
}

void moteurA_Stop()
{
// Arret moteur A
digitalWrite(in1, LOW);
digitalWrite(in2, LOW);
}

void moteurB_Horaire()
{
// Rotation horaire moteurB
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
analogWrite(enB, 200); // réglage vitesse (200) du moteurB sur la plage 0~255
}

void moteurB_Antihoraire()
{
// Rotation antihoraire moteurB
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);
analogWrite(enB, 200); // réglage vitesse (200) du moteur_B sur la plage 0~255
}

void moteurB_Stop()
{
// Arret moteurB
digitalWrite(in3, LOW);
digitalWrite(in4, LOW);
}


void loop()
{
moteurA_Horaire();
moteurB_Horaire();
delay(1000);
moteurA_Stop();
moteurB_Stop();
delay(1000);
moteurA_Antihoraire();
moteurB_Antihoraire();
delay(1000);
moteurA_Stop();
moteurB_Stop();
delay(1000);
}

Ça a l'air bien : ton robot doit tourner dans un sens, s'arrêter puis tourner dans l'autre sens.

Tu peux améliorer ton code en passant les valeurs de vitesse en arguments :

void moteurB_Horaire(byte vitesse)
{
// Rotation horaire moteurB
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
analogWrite(enB, vitesse); // réglage vitesse du moteurB sur la plage 0~255
}

et faire par exemple :

moteurB_Horaire(200);

ou déclarer en début de loop

byte vitesse = 200;

et appeler

moteurB_Horaire(vitesse);

Bonjour, voici mon code ! je ne pense pas qu'il soit fonctionnel mais il correspond au fonctionnement de mon grafcet ! par exemple si je commande le moteur en sens horaire dans un "if", en sortant du "if", arrête-t-il de tourner ?
en vous souhaitant un bon après-midi :slight_smile:

//Elevateur batterie
EB_b = ;
EB_bState = 1;
//Trappe
int To = ;
int Tf = ;
int ToState = 0;
int TfState = 1;
//Détection_Bus
int Bp1 = ;
int Bp2 = ;
int Bp1State =0;
int Bp2State =0;
// Moteur trappe (carte1)
int enA = 2;
int in1 = 3;
int in2 = 4;
// Moteur élévateur (carte1)
int enB = 5;
int in3 = 6;
int in4 = 7;
// Moteur convoyeur (carte2)
int enC = 8;
int in5 = 9;
int in6 = 10;
// Moteur stock batterie (carte2)
int enD = 11;
int in7 = 12;
int in8 = 13;
// Electroaiamant stock batterie
int EA_SB = ;
// Electroaiamant bus
int EA_B = ;

void setup()
{
// déclare les PB "présence bus" en tant qu'entrées
pinMode(PB1, INPUT);
pinMode(PB2, INPUT);
// déclare le capteur "élévateur batterie position basse" en tant qu'entrée
pinMode(EB_b, INPUT);
// déclare les capteurs de trappe "ouverte et/ou fermée" en tant qu'entrées
pinMode(To, INPUT);
pinMode(Tf, INPUT);
// déclare les capteurs "présence bus" en tant qu'entrées
pinMode(Bp1, INPUT);
pinMode(Bp2, INPUT);
// déclare les pins "controle moteur" en tant que sorties
// Moteur trappe (carte1)
pinMode(enA, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
// Moteur élévateur (carte1)
pinMode(enB, OUTPUT);
pinMode(in3, OUTPUT);
pinMode(in4, OUTPUT);
// Moteur convoyeur (carte2)
pinMode(enC, OUTPUT);
pinMode(in5, OUTPUT);
pinMode(in6, OUTPUT);
// Moteur stock batterie (carte2)
pinMode(enD, OUTPUT);
pinMode(in7, OUTPUT);
pinMode(in8, OUTPUT);
// Electroaiamant stock batterie
pinMode(EA_SB, OUTPUT);
// Electroaiamant bus
pinMode(EA_B, OUTPUT);
}

void loop()
{
//ETAPE 0 DU GRAFCET
Bp1State = digitalRead(Bp1); //lecture état Bp1
Bp2State = digitalRead(Bp2); //Lecture état Bp2
TfState = digitalRead(Tf); //Lecture état trappe (=1 si fermée)
EB_bState = digitalRead(EB_b); // Lecture état élévateur batterie (=1 si position basse)

if (Bp1State == HIGH)&&(Bp2State == HIGH)&&(TfState = HIGH)&&(EB_bState = HIGH)
{ //ETAPE 1 DU GRAFCET
  while (ToState == LOW)
  {
    // Moteur trappe sens horaire
    digitalWrite(in1, HIGH);
    digitalWrite(in2, LOW);
    analogWrite(enA, 180); // plage vitesse 0~255
    digitalWrite(EA_B, HIGH);
  }
}

ToState = digitalRead(To); //Lecture état trappe (=1 si ouvert)
if (ToState == HIGH)
{ //ETAPE 2 DU GRAFCET
    digitalWrite(EA_B, HIGH);
    // Moteur élévateur sens horaire
    digitalWrite(in3, HIGH);
    digitalWrite(in4, LOW);
    analogWrite(enB, 180); // plage vitesse 0~255
    delay(5000)
}
//ETAPE 3 DU GRAFCET
digitalWrite(EA_B, LOW);
delay(2000);

//ETAPE 4 DU GRAFCET
EB_bState = digitalRead(EB_b)
while (EB_bState == LOW)
{
// Moteur élévateur sens antihoraire
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);
analogWrite(enB, 180); // plage vitesse 0~255
}

EB_bState = digitalRead(EB_b)
if (EB_bState == HIGH)
{//ETAPE 5 & 6 DU GRAFCET
  // Moteur convoyeur sens horaire
  digitalWrite(in5, HIGH);
  digitalWrite(in6, LOW);
  analogWrite(enC, 180); // plage vitesse 0~255
  delay (3000);
}
//ETAPE 7 DU GRAFCET
// Moteur stock batterie sens horaire
digitalWrite(in7, HIGH);
digitalWrite(in8, LOW);
analogWrite(enD, 180); // plage vitesse 0~255
delay(1000);

//ETAPE 8 DU GRAFCET
// Moteur stock batterie sens antihoraire
digitalWrite(in7, LOW);
digitalWrite(in8, HIGH);
analogWrite(enD, 180); // plage vitesse 0~255
delay(1000);

//ETAPE 9 DU GRAFCET
// Moteur convoyeur sens antihoraire
digitalWrite(in5, LOW);
digitalWrite(in6, HIGH);
analogWrite(enC, 180); // plage vitesse 0~255
delay(1500);

//ETAPE 10 DU GRAFCET
// Moteur stock batterie sens horaire
digitalWrite(in7, HIGH);
digitalWrite(in8, LOW);
analogWrite(enD, 180); // plage vitesse 0~255
delay (1000);

//ETAPE 11 DU GRAFCET
digitalWrite(EA_SB, HIGH);
delay (1000);

//ETAPE 12 DU GRAFCET
digitalWrite(EA_SB, HIGH);
// Moteur stock batterie sens antihoraire
digitalWrite(in7, LOW);
digitalWrite(in8, HIGH);
analogWrite(enD, 180); // plage vitesse 0~255
delay (1000);

//ETAPE 13 DU GRAFCET
digitalWrite(EA_SB, LOW);
delay (2000);

//ETAPE 14 DU GRAFCET
// Moteur convoyeur sens antihoraire
digitalWrite(in5, LOW);
digitalWrite(in6, HIGH);
analogWrite(enC, 180); // plage vitesse 0~255
delay(3000);

//ETAPE 15 DU GRAFCET
// Moteur élévateur sens horaire
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
analogWrite(enB, 180); // plage vitesse 0~255
delay (10000);

//ETAPE 16 DU GRAFCET
delay(5000);

//ETAPE 17 DU GRAFCET
digitalRead (EB_b);
while (EB_b == LOW)
{
  // Moteur élévateur sens antihoraire
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
  analogWrite(enB, 180); // plage vitesse 0~255
}

//ETAPE 18 DU GRAFCET
digitalRead (TfState);
while (TfState == LOW)&&(Bp1 == HIGH)&&(Bp2 == HIGH)
{
  // Moteur élévateur sens antihoraire
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
  analogWrite(enB, 180); // plage vitesse 0~255
}
}

Sincèrement, je n’ai pas tout lu, mais on voit que tu as bien bossé.

Il reste quelques choses à changer ou vérifier.

Il est toujours bon d’initialiser des variables dans un programme, sinon on ne maîtrise pas forcément leur valeur. Mais il faut leur donner une valeur : cette instruction (et les autres similaires) ne passera pas à la compilation

EB_b = ;

Donc fais plutôt :

EB_b = 0;

Un test c’est

if (condition) 
{
  suite d'instructions;
}

Donc, cette ligne n’est pas bonne :

if (Bp1State == HIGH)&&(Bp2State == HIGH)&&(TfState = HIGH)&&(EB_bState = HIGH)

La condition en entier doit être entre parenthèses :

if ((Bp1State == HIGH)&&(Bp2State == HIGH)&&(TfState = HIGH)&&(EB_bState = HIGH))

ou bien

if (Bp1State == HIGH && Bp2State == HIGH && TfState = HIGH && EB_bState = HIGH)

Vérifie si les autres tests sont bons…

Enfin, lorsque tu fais un while, il faut prévoir de sortir de la boucle. Dans celui-ci :

  while (ToState == LOW)
  {
    // Moteur trappe sens horaire
    digitalWrite(in1, HIGH);
    digitalWrite(in2, LOW);
    analogWrite(enA, 180); // plage vitesse 0~255
    digitalWrite(EA_B, HIGH);
  }

Comme tu ne modifies pas la valeur de ToState, s’il entre dans la boucle il n’en sortira jamais. Il faut que tu relises la valeur de ToState à la fin :

  while (ToState == LOW)
  {
    // Moteur trappe sens horaire
    digitalWrite(in1, HIGH);
    digitalWrite(in2, LOW);
    analogWrite(enA, 180); // plage vitesse 0~255
    digitalWrite(EA_B, HIGH);
    ToState = digitalRead(To); // <-- mise à jour de ToState pour voir si on sort du while
  }

Du coup tu n’as plus besoin de le lire après le while, ni de le tester à HIGH puisqu’il y est déjà (condition de sortie du while)

Même chose à l’étape 4 :

//ETAPE 4 DU GRAFCET
EB_bState = digitalRead(EB_b)
while (EB_bState == LOW)
{
// Moteur élévateur sens antihoraire
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);
analogWrite(enB, 180); // plage vitesse 0~255
}

EB_bState = digitalRead(EB_b); // <-- passer cette ligne avant l'accolade fermante

D’ailleurs, il manque un point virgule ici:

//ETAPE 4 DU GRAFCET
EB_bState = digitalRead(EB_b)

et le même quelques lignes plus bas : vérifie que les points-virgules sont tous là où il le faut.

Enfin, étapes 17 et 18, vérifie ces lignes :

//ETAPE 17 DU GRAFCET
digitalRead (EB_b);

et

//ETAPE 18 DU GRAFCET
digitalRead (TfState);

Ca doit être

EB_bState = digitalRead(EB_b);

et

TfState = digitalRead (TfState);

Bonne continuation !

Je vous remercie beaucoup pour le temps que vous m'accordez !
voici le programme corrigé, sans erreur :slight_smile:
Passez une bonne journée :smiley:

//Elevateur batterie
int EB_b = 16;
int EB_bState;
//Trappe
int To = 17;
int Tf = 18;
int ToState;
int TfState;
//Détection_Bus
int Bp1 = 19;
int Bp2 = 20;
int Bp1State;
int Bp2State;
// Moteur trappe (carte1)
int enA = 2;
int in1 = 3;
int in2 = 4;
// Moteur élévateur (carte1)
int enB = 5;
int in3 = 6;
int in4 = 7;
// Moteur convoyeur (carte2)
int enC = 8;
int in5 = 9;
int in6 = 10;
// Moteur stock batterie (carte2)
int enD = 11;
int in7 = 12;
int in8 = 13;
// Electroaiamant stock batterie
int EA_SB = 14;
// Electroaiamant bus
int EA_B = 15;

void setup()
{
// déclare les PB "présence bus" en tant qu'entrées
pinMode(PB1, INPUT);
pinMode(PB2, INPUT);
// déclare le capteur "élévateur batterie position basse" en tant qu'entrée
pinMode(EB_b, INPUT);
// déclare les capteurs de trappe "ouverte et/ou fermée" en tant qu'entrées
pinMode(To, INPUT);
pinMode(Tf, INPUT);
// déclare les capteurs "présence bus" en tant qu'entrées
pinMode(Bp1, INPUT);
pinMode(Bp2, INPUT);
// déclare les pins "controle moteur" en tant que sorties
// Moteur trappe (carte1)
pinMode(enA, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
// Moteur élévateur (carte1)
pinMode(enB, OUTPUT);
pinMode(in3, OUTPUT);
pinMode(in4, OUTPUT);
// Moteur convoyeur (carte2)
pinMode(enC, OUTPUT);
pinMode(in5, OUTPUT);
pinMode(in6, OUTPUT);
// Moteur stock batterie (carte2)
pinMode(enD, OUTPUT);
pinMode(in7, OUTPUT);
pinMode(in8, OUTPUT);
// Electroaimant stock batterie
pinMode(EA_SB, OUTPUT);
// Electroaimant bus
pinMode(EA_B, OUTPUT);
}

void loop()
{
//ETAPE 0 DU GRAFCET
Bp1State = digitalRead(Bp1); //lecture état Bp1
Bp2State = digitalRead(Bp2); //Lecture état Bp2
TfState = digitalRead(Tf); //Lecture état trappe (=1 si fermée)
EB_bState = digitalRead(EB_b); // Lecture état élévateur batterie (=1 si position basse)
if (Bp1State == HIGH && Bp2State == HIGH && TfState == HIGH && EB_bState == HIGH)
{ //ETAPE 1 DU GRAFCET
  while (ToState == LOW)
  {
    // Moteur trappe sens horaire
    digitalWrite(in1, HIGH);
    digitalWrite(in2, LOW);
    analogWrite(enA, 180); // plage vitesse 0~255
    digitalWrite(EA_B, HIGH); //Activation electroaiamant bus
    ToState = digitalRead(To);
  }
}

//ETAPE 2 DU GRAFCET
digitalWrite(EA_B, HIGH); //Activation electroaiamant bus
// Moteur élévateur sens horaire
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
analogWrite(enB, 180); // plage vitesse 0~255
delay(5000);

//ETAPE 3 DU GRAFCET
digitalWrite(EA_B, LOW); //Désactivation electroaiamant bus
delay(2000);

//ETAPE 4 DU GRAFCET
EB_bState = digitalRead(EB_b);
while (EB_bState == LOW)
{
// Moteur élévateur sens antihoraire
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);
analogWrite(enB, 180); // plage vitesse 0~255
EB_bState = digitalRead(EB_b);
}

//ETAPE 5 & 6 DU GRAFCET
// Moteur convoyeur sens horaire
digitalWrite(in5, HIGH);
digitalWrite(in6, LOW);
analogWrite(enC, 180); // plage vitesse 0~255
delay (3000);
 
//ETAPE 7 DU GRAFCET
// Moteur stock batterie sens horaire
digitalWrite(in7, HIGH);
digitalWrite(in8, LOW);
analogWrite(enD, 180); // plage vitesse 0~255
delay(1000);

//ETAPE 8 DU GRAFCET
// Moteur stock batterie sens antihoraire
digitalWrite(in7, LOW);
digitalWrite(in8, HIGH);
analogWrite(enD, 180); // plage vitesse 0~255
delay(1000);

//ETAPE 9 DU GRAFCET
// Moteur convoyeur sens antihoraire
digitalWrite(in5, LOW);
digitalWrite(in6, HIGH);
analogWrite(enC, 180); // plage vitesse 0~255
delay(1500);

//ETAPE 10 DU GRAFCET
// Moteur stock batterie sens horaire
digitalWrite(in7, HIGH);
digitalWrite(in8, LOW);
analogWrite(enD, 180); // plage vitesse 0~255
delay (1000);

//ETAPE 11 DU GRAFCET
digitalWrite(EA_SB, HIGH); //Activation electroaimant stock batterie
delay (1000);

//ETAPE 12 DU GRAFCET
digitalWrite(EA_SB, HIGH); //Activation electroaimant stock batterie
// Moteur stock batterie sens antihoraire
digitalWrite(in7, LOW);
digitalWrite(in8, HIGH);
analogWrite(enD, 180); // plage vitesse 0~255
delay (1000);

//ETAPE 13 DU GRAFCET
digitalWrite(EA_SB, LOW); //Désactivation electroaimant stock batterie
delay (2000);

//ETAPE 14 DU GRAFCET
// Moteur convoyeur sens antihoraire
digitalWrite(in5, LOW);
digitalWrite(in6, HIGH);
analogWrite(enC, 180); // plage vitesse 0~255
delay(3000);

//ETAPE 15 DU GRAFCET
// Moteur élévateur sens horaire
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
analogWrite(enB, 180); // plage vitesse 0~255
delay (10000);

//ETAPE 16 DU GRAFCET
delay(5000);

//ETAPE 17 DU GRAFCET
EB_bState = digitalRead (EB_b);
while (EB_bState == LOW)
{
  // Moteur élévateur sens antihoraire
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
  analogWrite(enB, 180); // plage vitesse 0~255
  EB_bState = digitalRead(EB_b);
}

//ETAPE 18 DU GRAFCET
TfState = digitalRead(Tf);
Bp1State = digitalRead(Bp1);
Bp2State = digitalRead(Bp2);
while (TfState == LOW && Bp1State == HIGH && Bp2State == HIGH)
{
  // Moteur élévateur sens antihoraire
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
  analogWrite(enB, 180); // plage vitesse 0~255
  TfState = digitalRead(Tf);
  Bp1State = digitalRead(Bp1);
  Bp2State = digitalRead(Bp2);
}
}

Oui, pas de problème : tu ne fais qu'initialiser une variable (EB_bstate), elle changera dans le cours du programme selon ses diverses affectations.

Dans l'IDE, fais CTRL T, tu verras mieux les indentations et les blocs entre accolade.
Est-ce que ça compile ? Et ça marche ?

Merci pour l'astuce du "CTRL+T" !
Je vous le dirai demain dans l'après-midi, je n'ai pas la maquette sous la main malheureusement ...
Bonne journée :slight_smile:

Bonjour à tous,

Le concours est passé, tout à fonctionner.
Je tiens à remercier le forum et tout particulièrement lesept ! :slight_smile:

Bonne continuation.