P2E-CHIMES

De MCHobby - Wiki
Sauter à la navigation Sauter à la recherche
Page-under-construction.pngPage(s) en cours de traduction/élaboration.

Page(s) under translation/construction

Carillon

Le carillon est un instrument de musique composé de cloches ou diapasons accordés sur des fréquences différentes.

Ils sont généralement couplés à des horloges mécaniques et sonne les heures, demi-heures et parfois précédé -ou pas- d'une petite mélodies.

Certain d'entre-vous reconnaîtront cette horloge de cheminée équipée d'un carillon.

P2E-CHIMES-clock.jpg

Brancher

Sur le Pico-2-Explorer, le piezo buzzer est branché directement sur GP13 par l'intermédiaire d'une électronique d'amplification.

Pour utiliser le Piezo Buzzer, il est donc nécessaire que le cavalier soit en place (voir au dessus du bouton "Reset").

P2E-Buzzer-PWM-20.png

Vérifier l'Horloge

Votre Raspberry-Pi Pico est équipé d'une horloge RTC (Real Time Clock pour Horloge Temps Réel).

Cependant, celle-ci ne reste pas à l'heure lorsque le Pico est mis hors tension.

Par chance, lorsque vous utilisez Thonny IDE avec votre Raspberry-Pi Pico, celui-ci met l'horloge RTC aussi tôt qu'une session REPL est établie (ou réinitialisée).

Thonny utilise l'heure de votre PC pour initialiser la RTC du Pico.

Vous pouvez vérifier la date et l'heure de votre Pico en utilisant les instructions suivantes dans une session REPL:

>>> from machine import RTC
>>> rtc=RTC()
>>> rtc.datetime()
(2025, 3, 19, 2, 19, 32, 23, 0)

Le tuple retourné (2025, 3, 19, 2, 19, 32, 23, 0) contient les informations suivantes:

  • Année
  • Mois
  • Jour
  • Jour de la semaine (0=Lundi)
  • Heure
  • Minute
  • Secondes
  • millisecondes (lorsque disponible

Il est bien entendu possible possible de modifier l'heure d'une horloge RTC en fournissant un tuple avec les informations de la nouvelle date.

A noter que le jour de le semaine et les millisecondes peuvent être remplacés par 0.

>>> from machine import RTC
>>> rtc=RTC()
>>> rtc.datetime( (2025, 2, 10, 0, 03, 55, 27, 0) )

Code

Le script chimes.py est disponible dans le dépôt dédié au Pico-2-Explorer.

 1 from micropython import const
 2 from machine import RTC
 3 from rtplay import *
 4 import time
 5 
 6 HOUR_CHIME = const( 1 )
 7 HALF_HOUR_CHIME = const( 2 )
 8 
 9 rtc = RTC()
10 buzzer = RingTonePlayer( Pin.board.GP13 )
11 
12 def next_chime( _now ):
13     """  Calculate Next 1/2 H and Next Hour chimes time
14 
15      Parameters:
16         _now : rtc datetime  (Y,M,D,wD,h,m,s,ms)
17      
18      returns:
19         Time in seconds (since Jan 1, 2000), chime_type, related_hour
20     """
21     # mktime datetime (Y,M,D,h,m,s,wD,yD)
22     if _now[5]<30: # Minutes < 30 => Chimes at next 30 mins
23         mktime_data = ( _now[0], _now[1], _now[2], _now[4], 30, 0, _now[3], 0 )
24         chime_type = HALF_HOUR_CHIME
25         hour = _now[4]
26     else: # Shime next Hour
27         chime_type = HOUR_CHIME
28         if _now[4]+1 > 23: # > 23H
29             # Next day at 00:00
30             # Transform in seconds
31             mktime_data = ( _now[0], _now[1], _now[2], _now[4], _now[5], _now[6], _now[3], 0 )
32             secs = time.mktime( mktime_data )
33             # Add a day
34             next_day_secs = secs + 24*60+60 + 30
35             # Decode this new date
36             mktime_data = time.localtime( next_day_secs )
37             # Zeroing the Hours, Minutes (shime the at first second)
38             mktime_data = ( mktime_data[0], mktime_data[1], mktime_data[2], 0, 0, 1, 0, 0 )
39             hour = 0
40         else:
41             # Next Hour & Zeroing minutes, seconds
42             mktime_data = ( _now[0], _now[1], _now[2], _now[4]+1, 0, 0, 0, 0 )
43             hour = _now[4]+1
44     
45     # Return seconds, Half or full Hour chime, related Hour
46     return time.mktime( mktime_data ), chime_type, hour
47 
48 
49 _now = rtc.datetime()
50 _next_chime_secs, _chime_type, _hour = next_chime( _now )
51 
52 in_day_time = lambda hour : 7 <= hour <= 21
53 
54 while True:
55     # rtc datetime (Y,M,D,wD,h,m,s,ms)
56     _now = rtc.datetime()
57     # mktime datetime (Y,M,D,h,m,s,wD,yD)
58     _mktime_data = ( _now[0], _now[1], _now[2], _now[4], _now[5], _now[6], _now[3], 0 )
59     _now_secs = time.mktime( _mktime_data ) # Secs since Jan 1, 2000
60     
61     print( "Now = %r (%i secs)" % ( _now, _now_secs ) )
62     print( "Chime at %i secs" % _next_chime_secs )
63     print( "Chime time = %r " % ( time.localtime( _next_chime_secs ), ) )
64     print( "-" * 40 )
65     
66     # It is time to play a Chime 
67     if _now_secs > _next_chime_secs:
68         if in_day_time( _hour ):
69             if _chime_type == HOUR_CHIME:
70                 buzzer.play_str( "We'reRea:d=4,o=6,b=140:8d,8d,8e,8e,f,e,2p,2e,8d,8d,8e,8e,f,e,8d,8d,8e,8f,2p,8d5,16p,8d5,16p,16d5,32d5,32d5,8f,8p,8d,8p,8d5,16p,8d5,16p,16d5,32d5,32d5,8f,8d,8d,8a,8d5,16p,8d5,16p,16d5,16d5,8f,8p,8d" )
71                 time.sleep( 2 )
72                 for i in range( _hour if _hour < 13 else _hour-12 ):
73                     buzzer.play_tone( 1500, 200 )
74                     time.sleep_ms( 800 )
75             else: # Half-Hour
76                 buzzer.play_str( "SexyEyes:d=16,o=6,b=125:b5,8p,32b5,32p,b5,p,32b5,p,32p,f#,8p,32f#,32p,f#,p,f#,p,e,8p,32e,32p,e,p,32e,p,32p,g#,8p,32g#,32p,g#,p,g#,p,f#6,8p,32f#,32p,f#,p,32f#,p,32p,a#,8p,32a#,32p,a#6,p,32a#,p,32p,b,8p,32b" )
77         # Calculate time of the next chime 
78         _next_chime_secs, _chime_type, _hour = next_chime( _now )
79           
80     time.sleep( 5 )

Une fois le script lancé, celui-ci joue une mélodie toutes les heures et toutes les demi-heures. Il faut donc être patient pour le voir fonctionner.

Après la mélodie horaire, le buzzer effectue un nombre de "beep" correspondant à l'heure signalée.

Retour REPL

Outre les sonneries, les activités du script affiche des messages toutes les 5 secondes dans la session REPL:

----------------------------------------
Now = (2025, 3, 20, 3, 17, 2, 22, 0) (1742490142 secs)
Chime at 1742491800 secs
Chime time = (2025, 3, 20, 17, 30, 0, 3, 79) 
----------------------------------------
...
...
----------------------------------------
Now = (2025, 3, 20, 3, 17, 8, 37, 0) (1742490517 secs)
Chime at 1742491800 secs
Chime time = (2025, 3, 20, 17, 30, 0, 3, 79) 
----------------------------------------
Now = (2025, 3, 20, 3, 17, 8, 42, 0) (1742490522 secs)
Chime at 1742491800 secs
Chime time = (2025, 3, 20, 17, 30, 0, 3, 79) 
----------------------------------------

La valeur Now présente la date et heure en provenance de l'horloge RTC. Cette information est affichée sous deux formes:

  1. Tuple ( Année, Mois, Jour, Jour_de_la_semaine, Heure, Minutes, Secondes, 0 ) produit par rtc.datetime() puis le nombre de secondes écoulées depuis 1ier Janvier 2000 (produit par time.mktime().
  2. Chime at est l'heure en secondes (depuis le 1ier Jan 2000) à laquelle le carillon doit jouer la prochaine fois
  3. Chime Time est la représentation, sous forme de tuple, de l'information Chime at. Le format est, cette fois, sensiblement différent avec (Année, Jour, Mois, Heures, Minutes, Secondes, Jour_de_la_semaine, Jour_de_l_annee) puisqu'il provient de la fonction time.localtime()

Le corps du script

Commençons par analyser le corps du programme du s'étend des lignes 49 à 80.

  • Ligne 49 : obtention de la date et l'heure tel que connu par l'horloge RTC. _now contient un tuple au format (Y,M,D,wD,h,m,s,ms), autrement dit (Année, Mois, Jour, jour_de_la_semaine, Heure, Minute, Seconde, 0) avec Lundi=0.
  • Ligne 50 : l'appel next_chime( _now ) détermine l'heure du prochain carillon (Heure ou Heure-et-demi) à jouer. La fonction next_chime() retourne 3 informations :
    • _next_chime_secs : Date et heure à laquelle il faut jouer le prochain carillon (soit l'heure fixe, soit la demie-heure). Ce temps s'exprime en secondes (depuis 1ier Jan 2000).
    • _chime_type : Indique s'il faut jouer le carillon pour l'heure fixe (HOUR_CHIME=1) ou pour la demie-heure (HALF_HOUR_CHIME=2).
    • _hour : L'heure concernée par le carillon (entre 0 et 23).
  • Ligne 52 : définition d'une fonction lambda in_day_time() permettant de savoir si l'argument est dans la "plage horaire d'heures ouvrables". Ainsi in_day_time(10) retourne True là ou in_day_time(22) retourne False. Cela permettra d'éviter un jeu de carillon en pleine nuit.
  • Ligne 54 : début de la boucle principale du programme. A ce stade, nous savons que _next_chime_secs contient le moment où il faudra jouer le carillon ET que cela sera dans le futur par rapport à maintenant. Le bloc des lignes 55 à 80 s'exécute encore et encore.
  • Ligne 56 : obtention de la date et heure actuels stockés dans la variable _now . Pour rappel, le format du tuple est (Y,M,D,wD,h,m,s,ms) .
  • Lignes 58 et 59 : _now_secs contient l'équivalent de _now exprimé en secondes depuis le 1ier janvier 2000. Cette valeur en secondes est obtenir à l'aide de la fonction mktime() à partir d'un tuple décrivant la date.
Attention:
Le tuple requis par mktime() à un format sensiblement différent de celui retourné par le RTC! C'est la raison pour laquelle la variable _mktime_data est créée pour contenir le Tuple correctement formaté en vue de l'appel mktime().
  • Lignes 61 à 64 : Affichage des diverses informations temporelles (déjà décris dans la section code).
  • Ligne 67 : L'heure actuelle _now_secs et l'heure du prochain carillon _next_chime_secs étant tous deux exprimés en secondes (depuis le 1ier Janvier 2000), une simple comparaison d'entiers permet de savoir si l'heure actuelle a dépassée _next_chime_secs (l'heure où il faut jouer un carillon). Dès le carillon joué, il suffit de calculer la valeur suivante de _next_chime_secs pour que le carillon ne soit déclenché qu'une seule fois.
  • Ligne 68 : Bien qu'il faille normalement jouer le carillon, le script ne produira du son qu'entre 7h et 21h (inclus). C'est la raison de l'appel à la fonction in_day_time().
  • Lignes 69 à 74 : la variable _chime_type retournée par next_chime( _now ) permet de savoir qu'il faut jouer un carillon pour une heure fixe. Ce carillon étant suivit du nombre de "beep" correspondant à l'heure. A noter qu'a partir de 13H, il convient de soustraire 12 unité pour revenir à un seul "beep" (puis 2, puis 3 et ainsi de suite).
  • Lignes 75 à 76 : dans cette section else, la variable _chime_type contient forcement la valeur HALF_HOUR_CHIME (2). C'est donc un carillon de "demi-heure" qui sera joué.
  • Ligne 78 : Que du son ait été produit ou non (cfg. if in_day_time( _hour ): en ligne 69), il est nécessaire de calculer l'heure du prochain carillon. C'est la raison de cet appel à next_chime( _now ) .
  • Ligne 80 : Une pause de 5 secondes est insérée à chaque itération de la boucle while.

La fonction next_chime()

Pour rappel, en voici la définition de la fonction next_chime().

Elle est moins compliquée qu'il n'y parait! Elle reçoit une heure en paramètre et calcule (1) l'heure du prochain carillon, (2) s'il s'agit d'un carillon d'heure ou de demi-heure et (3) l'heure concernée (0 à 23).

12 def next_chime( _now ):
13     """  Calculate Next 1/2 H and Next Hour chimes time
14 
15      Parameters:
16         _now : rtc datetime  (Y,M,D,wD,h,m,s,ms)
17      
18      returns:
19         Time in seconds (since Jan 1, 2000), chime_type, related_hour
20     """
21     # mktime datetime (Y,M,D,h,m,s,wD,yD)
22     if _now[5]<30: # Minutes < 30 => Chimes at next 30 mins
23         mktime_data = ( _now[0], _now[1], _now[2], _now[4], 30, 0, _now[3], 0 )
24         chime_type = HALF_HOUR_CHIME
25         hour = _now[4]
26     else: # Shime next Hour
27         chime_type = HOUR_CHIME
28         if _now[4]+1 > 23: # > 23H
29             # Next day at 00:00
30             # Transform in seconds
31             mktime_data = ( _now[0], _now[1], _now[2], _now[4], _now[5], _now[6], _now[3], 0 )
32             secs = time.mktime( mktime_data )
33             # Add a day
34             next_day_secs = secs + 24*60+60 + 30
35             # Decode this new date
36             mktime_data = time.localtime( next_day_secs )
37             # Zeroing the Hours, Minutes (shime the at first second)
38             mktime_data = ( mktime_data[0], mktime_data[1], mktime_data[2], 0, 0, 1, 0, 0 )
39             hour = 0
40         else:
41             # Next Hour & Zeroing minutes, seconds
42             mktime_data = ( _now[0], _now[1], _now[2], _now[4]+1, 0, 0, 0, 0 )
43             hour = _now[4]+1
44     
45     # Return seconds, Half or full Hour chime, related Hour
46     return time.mktime( mktime_data ), chime_type, hour

Voici comment fonctionne cette fonction.

  • Ligne 12 : la paramètre _now est un Tuple contenant une information de date et heure produit par l'horloge temps réel (Y,M,D,wD,h,m,s,ms).
  • Ligne 22 : _now[5] contient le nombre de minutes de l'heure. Si nous sommes en dessous de 30 minutes alors il faut calculer l'heure du carillon à la toute prochaine demi-heure (lignes 22 à 25) sinon calculer l'heure du carillon à la prochaine heure (lignes 27 à 43).
  • Ligne 25 : Cette dernière ligne retourne les 3 parametres:
    • Position 1: La prochaine heure de carillon, exprimé en secondes depuis le 1 janvier 2000.
    • Position 2: Le type de carillon avec HOUR_CHIME=1 pour un carillon d'heure et HALF_HOUR_CHIME=2 pour un carillon de demi-heure.
    • Position 3: L'heure concernée par le carillon. Valeur de 0 à 23.

Prochaine DEMI-HEURE:

  • Ligne 23 : préparation d'un tuple mktim_data pour la fonction time.mktime(). Il doit avoir le format (Y,M,D,h,m,s,wD,yD) à partir de l'information contenue dans _now, en préservant l'heure mais en imposant 30 min, 0 sec. Nous serons donc dans le futur à la prochaine demi-heure.
  • Ligne 24 : identification du type de carillon chime_type comme un carillon de demi-heure (HALF_HOUR_CHIME = 2).
  • Ligne 25 : identification de l'heure de référence.

Prochaine HEURE:

Cette section est plus étendue car il faut tenir compte d'un cas particulier. En effet, lorsque _now contient une heure supérieure à 23h30 alors l'heure suivante est au jour suivant à 0h00m01s!
  • Ligne 27 : identification du type de carillon chime_type comme un carillon d'heure (HOUR_CHIME = 1).
  • Ligne 28 : Si la prochaine heure a sonner est au-delà de 23H (donc 24H00 et quelques minutes)... alors la carillon doit être déclenché le jour suivant à 00h00m01s (1 seconde pour lever toute ambiguïté possible). C'est ce que font les lignes 29 à 39.
  • Lignes 31 et 32 : conversion de l'heure actuelle en secondes.
  • Ligne 34 : ajout de 24H (en seconde) pour se retrouver assurément le jour suivant à la même heure. Ajout de 30 secondes pour s'éloigner un peu plus de la demi-heure (en effet, le coude pourraît être exécuté à pile 23h30m00s).



Traduction augmentée réalisée par Meurisse. D pour shop.MCHobby.be - Licence CC-BY-SA.


MCHobby investit du temps et de l'argent dans la réalisation de traduction et/ou documentation. C'est un travail long et fastidieux réalisé dans l'esprit Open-Source... donc gratuit et librement accessible.
SI vous aimez nos traductions et documentations ALORS aidez nous à en produire plus en achetant vos produits chez MCHobby.