chronometre — Un chronomètre

Un chronomètre commandé par deux boutons :

  • bouton B pour démarrer ; mettre en pause ; relancer ;

  • bouton A pour afficher le temps de tour (afficher le temps, mais continuer mesurer le temps en arrière plan).

L’intérêt de ce programme est double :

  • tester l’API concernant boutons ;

  • mettre en œuvre une machine à états.

Le programme peut se trouver dans un des cinq états suivants :

  • INITIAL : affiche 00, et attend l’action de l’utilisateur ;

  • COURSE : mesure le temps, et affiche le nombre de secondes écoulées ;

  • PAUSE : le temps écoulé est affiché, mais il ne change pas ;

  • TOUR : le temps écoulé est affiché (sans changer), mais le temps continue de s’écouler en arrière-plan (utilisé pendant une course, pour afficher le temps d’un tour sans pour autant mettre le chronomètre en pause) ;

  • DOUBLEPAUSE : comme l’état TOUR, mais en arrière-plan, le chronomètre est en pause.

Les transitions entre les états se font suivant le graphe suivant (où les étiquettes des transitions désignent la pression des boutons).

Figure made with TikZ

  1# Copyright 2019 Louis Paternault
  2#
  3# This file is part of Jouets.
  4#
  5# Jouets is free software: you can redistribute it and/or modify
  6# it under the terms of the GNU General Public License as published by
  7# the Free Software Foundation, either version 3 of the License, or
  8# (at your option) any later version.
  9#
 10# Jouets is distributed in the hope that it will be useful,
 11# but WITHOUT ANY WARRANTY; without even the implied warranty of
 12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13# GNU General Public License for more details.
 14#
 15# You should have received a copy of the GNU General Public License
 16# along with Jouets.  If not, see <http://www.gnu.org/licenses/>.
 17
 18"""Un chronètre, avec pause et temps de tour.
 19
 20Usage :
 21
 22- bouton B pour démarrer ; mettre en pause ; relancer ;
 23- bouton A pour afficher le temps de tour (afficher le temps, mais continuer
 24  mesurer le temps en arrière plan).
 25"""
 26
 27from utime import ticks_ms as maintenant
 28
 29from microbit import *
 30
 31###############################################################################
 32# Création des images
 33
 34GAUCHE = [
 35    Image("""99000:99000:99000:99000:99000"""),
 36    Image("""09000:09000:09000:09000:09000"""),
 37    Image("""99000:09000:99000:90000:99000"""),
 38    Image("""99000:09000:99000:09000:99000"""),
 39    Image("""99000:99000:99000:09000:09000"""),
 40    Image("""99000:90000:99000:09000:99000"""),
 41    Image("""99000:90000:99000:99000:99000"""),
 42    Image("""99000:09000:09000:09000:09000"""),
 43    Image("""99000:99000:00000:99000:99000"""),
 44    Image("""99000:99000:99000:09000:99000"""),
 45]
 46
 47DROITE = [chiffre.shift_right(3) for chiffre in GAUCHE]
 48
 49
 50def affiche_secondes(millisecondes):
 51    """Affiche le nombre de sondes sur la carte."""
 52    secondes = int(millisecondes / 1000)
 53    display.show(DROITE[secondes % 10] + GAUCHE[(secondes % 100) // 10])
 54
 55
 56###############################################################################
 57# Création des états
 58
 59INITIAL, COURSE, TOUR, PAUSE, DOUBLEPAUSE = range(5)
 60
 61###############################################################################
 62# Boucle principale
 63
 64etat = INITIAL
 65temps_debut = maintenant()
 66temps_pause = 0
 67temps_tour = 0
 68
 69while True:
 70    # Changement éventuel d'état
 71    if button_a.was_pressed():
 72        if etat == COURSE:
 73            temps_tour = maintenant() - temps_debut
 74            etat = TOUR
 75        elif etat == TOUR:
 76            etat = COURSE
 77        elif etat == PAUSE:
 78            etat = INITIAL
 79        elif etat == DOUBLEPAUSE:
 80            etat = PAUSE
 81        else:  # etat == INITIAL
 82            pass
 83    elif button_b.was_pressed():
 84        if etat == COURSE:
 85            temps_pause = maintenant() - temps_debut
 86            etat = PAUSE
 87        elif etat == TOUR:
 88            temps_pause = maintenant() - temps_debut
 89            etat = DOUBLEPAUSE
 90        elif etat == PAUSE:
 91            temps_debut = maintenant() - temps_pause
 92            etat = COURSE
 93        elif etat == DOUBLEPAUSE:
 94            temps_debut = maintenant() - temps_pause
 95            etat = TOUR
 96        else:  # etat == INITIAL
 97            temps_debut = maintenant()
 98            etat = COURSE
 99
100    # Affichage
101    if etat == COURSE:
102        affiche_secondes(maintenant() - temps_debut)
103    elif etat == DOUBLEPAUSE:
104        affiche_secondes(temps_tour)
105    elif etat == PAUSE:
106        affiche_secondes(temps_pause)
107    elif etat == INITIAL:
108        affiche_secondes(0)
109    elif etat == TOUR:
110        affiche_secondes(temps_tour)