Leçons de niveau 15

Kidule Ascenseur/Faire le programme Ascenseur

Une page de Wikiversité.
Aller à la navigation Aller à la recherche
Début de la boite de navigation du chapitre
Faire le programme Ascenseur
Icône de la faculté
Chapitre no 3
Leçon : Kidule Ascenseur
Chap. préc. :Tester le hardware
fin de la boite de navigation du chapitre
Icon falscher Titel.svg
En raison de limitations techniques, la typographie souhaitable du titre, « Kidule Ascenseur : Faire le programme Ascenseur
Kidule Ascenseur/Faire le programme Ascenseur
 », n'a pu être restituée correctement ci-dessus.

Programme Ascenseur[modifier | modifier le wikicode]

C'est le moment de s'attaquer au programme proprement dit pour faire bouger notre ascenseur.

Mais avant de programmer, il faut réfléchir à ce que l’on veut faire. Première chose à remarquer, c’est que l’on devra faire plusieurs choses à la fois: lire des boutons, actionner le moteur, allumer et éteindre les Leds et se rappeler ce que l'ascenseur doit faire (monter au 1er étage par exemple).

Lorsque l’on a ce genre de problème (ce qui est très fréquent dans une machine ou dans un robot), la solution est souvent de dessiner un graphe d'états. Un graphe d'état est un dessin où on met une bulle par état possible de la machine. par exemple ici AuRez pour dire que l’on est au rez à attendre, ou encore Monte2eme pour dire que l’on va au 2eme.

Kidule ascenseur2 Graphe etat sans transitions.png

Puis on trace avec des flèches tout ce qui est possible de faire en termes de changement d'état et à côté de la flèche on marque sous quelle condition on va changer d'état. Par exemple, on peut passer de AuRez à Monter1er si on a Bouton1er==Presse.

Exercice[modifier | modifier le wikicode]

Essaie de tracer toutes les transitions qui sont possibles dans le cas de notre ascenseur. Pour cet exercice, on va imaginer que notre ascenseur est très simple:

  • On ne peut lui donner qu'un ordre à la fois.

Traduction d'un graphe d'états en C[modifier | modifier le wikicode]

Pour traduire un graphe d'états en C, il nous faut:

  1. déclarer tous les états possibles
  2. déclarer une variable qui contient l'état
  3. avoir une instruction qui nous permet de faire un bout de programme différent pour chaque état

Pour le 1er point, il existe en C une instruction pour déclarer un type énuméré (qui énumère toutes les possibilités d'une variable de ce type)


pour le 2eme point, comme on vient de déclarer ce nouveau type, on peut juste après déclarer la variable Etat et lui donner sa valeur initiale.

Etat = DescendRez;

pour le 3eme point, il existe une instruction un peu compliquée, mais qui fait exactement ce qu’il nous faut:


Pour traduire notre graphe d'états en code, nous allons écrire un état par case du switch. Dans la première partie de l'état, on va mettre ce que l’on doit faire dans cet état comme par exemple Monter=..., Descendre=..., allumer des leds etc. Puis nous allons regarder s'il a a une transition possible avec un if(...) { Etat = nouvel_etat}. De cette manière, à chaque fois que la fonction GererAscenseur() est appelée, on va effectuer les actions de cet état, puis regarder si la prochaine fois on doit exécuter un autre état.

Exercice[modifier | modifier le wikicode]

Il faut maintenant coder notre programme. Pour pas trop se fatiguer, On peut copier le squelette de programme ci dessous, et on remplacera tous les _A_CHANGER par quelque chose d'utile

#include "hardwareAsc.h"

enum {Au2eme    =0b00000100,
      Au1er     =0b00000010,
      AuRez     =0b00000001,
      Monte2eme =0b00000111,
      Monte1er  =0b00000011,
      Descend1er=0b00000110,
      DescendRez=0b00000000} Etat = Monte2eme;

void AfficherEtat()
{
   if (Etat & 0b00000001) Led3=Allume; else Led3=Eteint;
   if (Etat & 0b00000010) Led4=Allume; else Led4=Eteint;
   if (Etat & 0b00000100) Led5=Allume; else Led5=Eteint;
}

void GererAscenseur()
{
   switch (Etat)
   {
      case Au2eme:
         Monter    =  0;
         Descendre =  0;
         Led2eme = Eteint;  //si on est au 2eme, on éteint la LED qui indique qu'on veut aller au 2eme
         if (Bouton1er==Presse) {
            Etat = Descend1er;
         }
         else if (BoutonRez==Presse) {
            Etat = DescendRez;
         }
         break;
      case Au1er:
         Monter    = A_CHANGER;
         Descendre = A_CHANGER;
         Led1er = Eteint;
         if (Bouton2eme==Presse) {
            Etat = A_CHANGER;
         }
         else if (Bouton_A_CHANGER==Presse) {
            Etat = DescendRez;
         }
         break;
      case AuRez:
         Monter    = A_CHANGER;
         Descendre = A_CHANGER;
         LedRez = A_CHANGER;
         if (Bouton2eme==Presse) {
            Etat = A_CHANGER;
         }
         else if (Bouton1er==Presse) {
            Etat = A_CHANGER;
         }
         break;
      case Monte2eme:
         Monter    = A_CHANGER;
         Descendre = A_CHANGER;
         Led2eme   = Allume;
         if (Switch2eme==Presse) {
            Etat = A_CHANGER;
         }
         break;
      case Monte1er:
         Monter    = A_CHANGER;
         Descendre = A_CHANGER;
         Led1er    = Allume;
         if (Bouton_A_CHANGER==Presse) {
            Etat = Au1er;
         }
         break;
      case Descend1er:
         Monter    = 0;
         Descendre = 1;
         Led1er    = Allume;
         if (Switch1er==Presse) {
            Etat = Au1er;
         }
         break;
      case DescendRez:
         Monter    = 0;
         Descendre = 1;
         LedRez    = Allume;
         if (SwitchRez==Presse) {
            Etat = AuRez;
         }
         break;
      default:
         Led6=Allume; // pour montrer que l’on a un gros problème
     }
}
void loop ()
{
   GererAscenseur();
   AfficherEtat();
}