Porte de garage
- Par Benoît
- Publié le 5 décembre 2016
- Licence CC BY-SA 4.0
Description
Aujourd'hui, on automatise la porte du garage de votre Ferrari !
Pour cela, on va gérer notre portail avec une télécommande sur laquelle il n'y a qu'un bouton.
La télécommande fonctionne de la façon suivante :
Si la porte est OUVERTE ou FERMÉE, cliquer sur le bouton va faire que la porte
va s'ouvrir (ou se fermer) jusqu'à la fin du cycle ou le reclique sur un
bouton. Pour schématiser : Porte : Fermé -> Bouton appuyé -> Porte : En cours d'ouverture -> Cycle complet -> Porte : Ouverte
.
Si la porte est en cours de fermeture ou d'ouverture, appuyer sur le bouton va
stopper la porte. Ensuite réappuyer sur le bouton va faire repartir la porte
dans l'autre sens. Pour schématiser : Porte : Fermé -> Bouton appuyé -> Porte : En cours d'ouverture -> Bouton appuyé -> Porte : Stop en ouverture -> Bouton appuyé -> Porte : En cours de fermeture
.
Dans notre exercice, on commencera toujours avec une porte fermée.
Entrées et sorties
Les entrées sont une série de commande :
Clique_bouton
Cycle_complet
Clique_bouton
Clique_bouton
Clique_bouton
Clique_bouton
Clique_bouton
Cycle_complet
Les sorties doivent être l'état de la porte après chaque entrée.
Par exemple :
Porte : Fermé
> Clique_bouton
Porte : En cours d'ouverture
> Cycle_complet
Porte : Ouverte
>Clique_bouton
Porte : En cours de fermeture
>Clique_bouton
Porte : Stop en fermeture
>Clique_bouton
Porte : En cours d'ouverture
>Clique_bouton
Porte : Stop en ouverture
>Clique_bouton
Porte : En cours de fermeture
> Cycle_complet
Porte : Fermé
Conseil
Pour cet exercice, il est conseillé d'utiliser une machine à état, pour comprendre le principe je vous dirige vers Wikipédia : Automate fini.
Bonus
En bonus, pour éviter de rayer la Ferrari ou d'écraser le chat, on va ajouter un rayon infrarouge sur la porte. Si quelque chose passe devant la porte alors elle sera bloquée.
Pour cela, on ajoute les règles suivantes sur notre système :
-
Si la porte est en cours de fermeture et qu'un objet coupe le rayon alors la porte va s'ouvrir complétement. Elle restera ensuite bloqué tant que l'entrée INFRAROUGE_OK ne sera pas appelée.
-
Pour tous les autres cas, la porte se bloquera dans sa position tant que INFRAROUGE_OK ne sera pas reçu. Ensuite la porte repartira à son état d'avant le blocage.
Entrée bonus
Clique_bouton
Cycle_complet
Clique_bouton
Infrarouge_rompu
Clique_bouton
Cycle_complet
Clique_bouton
Infrarouge_ok
Clique_bouton
Cycle_complet
Sortie bonus
Porte : Fermé
>Clique_bouton
Porte : En cours d'ouverture
>Cycle_complet
Porte : Ouverte
>Clique_bouton
Porte : En cours de fermeture
>Infrarouge_rompu
Porte : Ouverture d'urgence
>Clique_bouton
Porte : Ouverture d'urgence
>Cycle_complet
Porte : Ouverte et bloqué
>Clique_bouton
Porte : Ouverte et bloqué
>Infrarouge_ok
Porte : Ouverte
>Clique_bouton
Porte : Fermeture
>Cycle_complet
Porte : Fermé
Bonne chance à tous !
Travaux réalisés
- Moi-même : pastebin - Go
Mon code
(non finalisé)
package main
// Importations
import (
"fmt"
"time"
)
// Constantes
var DOpened = 0
var DClosed = 1
var DOpening = 2
var DClosing = 3
var DOpeningStopped = 4
var DClosingStopped = 5
// Variable d'état
var state = DClosed
// État au format chaine
func stateToString(state int) string {
switch state {
case DOpened:
return "Ouvert"
case DClosed:
return "Fermé"
case DOpening:
return "En cours d'ouverture"
case DClosing:
return "En cours de fermeture"
case DOpeningStopped:
return "Ouverture arrêtée"
case DClosingStopped:
return "Fermeture arrêtée"
default:
return "État inconnu"
}
}
// Afficher l'état au format chaine
func displayState(state int) {
fmt.Printf("État : %s\n", stateToString(state))
}
// Appuyer sur le bouton
func pushButton(state *int) {
fmt.Printf("Appui sur le bouton\n")
switch *state {
case DOpened, DOpeningStopped:
*state = DClosing
displayState(*state)
for i := 0 ; i < 5000 ; i++ {
if *state == DClosing {
time.Sleep(1 * time.Millisecond)
} else {
return
}
}
*state = DClosed
displayState(*state)
case DClosed, DClosingStopped:
*state = DOpening
displayState(*state)
for i := 0 ; i < 5000 ; i++ {
if *state == DOpening {
time.Sleep(1 * time.Millisecond)
} else {
return
}
}
*state = DOpened
displayState(*state)
case DOpening:
*state = DOpeningStopped
displayState(*state)
case DClosing:
*state = DClosingStopped
displayState(*state)
}
}
func main() {
var input string
for {
fmt.Scanln(&input)
go pushButton(&state)
}
}