Buzzons du Mario avec un Arduino
Les montage des tutos sur l’Arduino incluent souvent des buzzers. C’était le cas de la première boite Robobox. Sur leurs forums, nombreux sont ceux qui ont ajouté un peu de fun en jouant un thème comme Mario.
Vous pouvez trouver assez facilement des exemples de code de buzzers qui jouent un thème, que ce soit du Mario ou un autre. Dans cet article, je vais vous montrer comment bien programmer ce buzzer.
Matériel
Si ce billet est illustré avec les boites Robobox, vous pouvez évidemment utiliser n’importe quel kit Arduino comme le Starter Kit officiel ou d’autres moins officiels et moins cher. Si vous avez déjà un Arduino, vous pouvez évidemment vous procurer des buzzers seuls qui peuvent être vendus en pack à pas trop cher.
Jouer un son
La bibliothèque de l’Arduino propose une fonction tone qui permet de jouer facilement un son. Cette fonction prend deux ou trois paramètres, le connecteur (pin), la fréquence et de manière optionnelle la durée (en millisecondes).
Jouer une note consiste donc à appeler la fonction tone() avec une certaine fréquence et une certaine durée. Mais pour entendre une note, il convient de la faire suivre par une pause. Cette pause est un appel à la fonction delay. Jouer une note consiste donc, pou être complet, à appeler la fonction tone() avec une certaine fréquence et une certaine durée puis la fonction delay() avec une certaine durée.
Ces trois paramètres (fréquence, durée du son et durée de la pause) peuvent évidemment tous être différent pour chaque note (pas uniquement la fréquence). L’idée sera alors d’écrire une fonction qui prend ces 3 paramètres et appelle les deux fonctions.
void play_note(int note, int note_duration, int delay_duration) {
tone(speakerPin, note, note_duration);
delay(delay_duration);
}
Évidemment, si on accompagne chaque note d’un clignotement de LED, ajoutez ces appels à la fonction.
Maintenant, il faut appeler cette fonction pour chaque note. Attention, la solution de facilité est de répéter les appels de la manière suivante :
play_note(2637, 100, 150)
play_note(2637, 100, 300)
play_note(2637, 100, 300)
play_note(2093, 100, 100)
Et on a un code kilométrique d’appel de fonctions. Rendons ça plus lisible, et plus évolutif.
Définir les données
Pour commencer, une note a une fréquence spécifique. Nous pouvons commencer par définir des constantes pour chaque note, constantes qui auront pour valeur la fréquence de chaque note. L’exemple ci-dessous est un extrait.
const int NOTE_A6 = 1760;
const int NOTE_AS6 = 1865;
const int NOTE_B6 = 1976;
const int NOTE_E6 = 1319;
const int NOTE_G6 = 1568;
Ensuite, nous pouvons définir notre thème. Un thème sera une collection de notes jouées. Une note jouée est une collection de 3 valeurs (la fréquence, la durée et la durée de pause).
Et bien voilà, nous avons tout, un thème n’est rien d’autre qu’une collection de collections de 3 entiers. Le code ci-dessous déclare le début du thème Mario :
const int mario_tunes [][3] = {{NOTE_E7, 100, 150},
{NOTE_E7, 100, 300},
{NOTE_E7, 100, 300},
{NOTE_C7, 100, 100},
{NOTE_E7, 100, 300}};
Et pour le jouer, il suffit maintenant d’itérer sur cette collection.
for (int i = 0; i < 5; i++) {
play_note(mario_tunes[i][0], mario_tunes[i][1], mario_tunes[i][2]); }
Et je vais vous surprendre, mais on n’y est pas tout à fait… 🙂
Être indépendant de la taille du thème
Le code d’itération est dépendant de notre liste mario_tunes. Vous ajoutez ou supprimez une note et bim, ça ne marche plus. Ceci vient du fait que nous avons spécifié le nombre d’itérations. Évidemment, le mieux serait que le programme détermine le nombre d’itérations à faire. Pour cela, il y a la fonction sizeof. Mais attention, sizeof(liste) retourne le nombre d’éléments contenus dans la liste, pas la taille de la liste… en d’autres termes, pour notre mélodie Mario précédente qui contient 5 notes contenant chacune 3 informations, sizeof(mario_tunes) retournera 15. Pas bon.
L’astuce, vous vous doutez, est de diviser cette taille par la taille des éléments. Au final, notre itération va s’écrire ainsi :
for (int i = 0; i < sizeof(mario_tunes) / sizeof(mario_tunes[0]); i++) {
play_note(mario_tunes[i][0], mario_tunes[i][1], mario_tunes[i][2]); }
La dernière petite astuce : à la première ligne, sizeof(mario_tunes[0]) ne divise pas par 3 mais par la taille du premier élément de la liste. Oui, c’est 3 dans notre cas, mais cette valeur n’étant pas fixée, si la taille de la sous-liste change, la taille de la liste sera toujours bonne.
Un code indépendant du thème joué
Vous n’êtes pas fan de Mario ? Et bien ce n’est pas grave car ce code est ainsi indépendant du thème. Vous préférez Zelda, K-2000, Joyeux Anniversaire ? Créez la liste des notes à jouer et utilisez cette liste, vous n’avez que le nom de la variable à changer. D’ailleurs, l’idéal serait, au lieu de nommer la variable contenant le thème mario_tunes, d’utiliser un nom plus générique. Vous pourrez ainsi remplacer le thème dans vos programme.
Ou mieux, nous pourrions créer une bibliothèque de thèmes à importer dans nos programmes… Mais ceci sera un autre post 😉
À propos de... Darko Stankovski
iT guy, photographe et papa 3.0, je vous fais partager mon expérience et découvertes dans ces domaines. Vous pouvez me suivre sur les liens ci-dessous.