Jouer avec les inputs d’un Arduino peut vite se transformer en casse-tête. Et fabriquer un piano pour le cadeau d’une petite est un parfait exercice pour comprendre comment jouer avec plusieurs inputs à la fois !
Liste d’achats
Pour faire ce piano on aura besoin :
- D’un Arduino Nano
- Des buzzers
- Un assortiment de boutons avec capuchons
- Des leds 3mm
- Un kit de résistances
Optionnel :
- Un variateur de résistance, pour le volume
- Une batterie
- Un module de chargement TP4056 pour la batterie
- Un booster, pour convertir le 3V de la pile en 5V nécessaires pour tout alimenter
Que doit pouvoir faire la boite?
Cette boite doit pouvoir :
- Fonctionner sur batterie. On ne va tout de même pas demander à un enfant de rester raccorder à une prise murale tout de même!
- Jouer des mélodies pour enfant en appuyant à la fois le bouton principal ainsi qu’une note
- Avoir des combinaisons secretes de touches qui vont jouer des mélodies qui sont plus à destination des parents (mario, star wars, tetris, etc).
- Arrêter une mélodie qui joue, aussi à destination des parents!
- Contrôler le volume sonore
1er essai: Input analog
L’avantage de cette méthode est qu’i lest possible d’avoir de nombreux boutons sur un seul pin de l’Arduino. Pratique pour un piano !
Pour y arriver, il faut mettre plusieurs boutons en parallèle sur un seul pin digital relié au 5V. Le truc, c’est d’ajouter à chaque bouton une résistance de valeur différente. A la lecture, chaque résistance va donner une tension différente, ce qui permettra de différencier les boutons pressés.
Malheureusement, pour le nombre de boutons que j’avais à mettre et les combinaisons que je voulais faire, les valeurs en lecture se superposaient. Cela rendait les actions déclenchées à la limite de l’aléatoire, le jeu n’en valait pas la chandelle… Je suis donc passé à la seconde méthode, un peu plus brutale: un pin par bouton!
2e essai concluant: Input digital.
Résistance de rappel / tirage
Une résistance de rappel (pull-down) ou de tirage (pull-up) va permettre de forcer la lecture du signal d’un bouton pressé à 0 pour un pull-down ou à 1 pour un pull-up, et ainsi éviter le bruit électronique.
Lorsqu’un bouton est pressé, le circuit devient fermé et conduit le courant. Ce courant crée une tension sur le pin en lecture de l’Arduino. Cette lecture sera « HIGH » si le seuil de tension en entrée est atteint, et « LOW » dans le cas contraire. Cet état de lecture peut être testé dans le programme de l’Arduino, ce qui permet l’execution de commandes lorsqu’un bouton est pressé, en théorie.
Malheureusement, ce seuil de tension sur un pin en lecture pourrait être atteint par le bruit: chaleur, humidité ou même électricité statique du doigt. Pour éviter ce bruit, on va mettre une résistance très élevée juste à l’entrée de la broche, soit vers le potentiel baas (GND), soit vers le potentiel haut (5V).
Lorsque le bouton n’est pas pressé (le circuit est donc dit « ouvert ») dans une configuration pull-down, une résistance élevée (généralement 10k) est branchée au GND et « tire » donc la tension vers ce potentiel bas. Dans une configuration pull-up, la résistance est branchée au 5V et tire donc la tension vers ce potentiel haut. Cela évite nécessairement le bruit.
Montage
Pour ce montage il n’apparait pas dans le schéma, mais j’ai utilisé un module TP4056 pour pouvoir charger la batterie à l’aide d’une prise micro-usb :
Pins analog : attention à A6 et A7!
Je me suis fait avoir comme un bleu avec ce piège, surtout parce que je n’ai pas pris la peine de tester l’ensemble du montage avant de commencer les soudures.
Les pins analog A6 et A7 sont des pins qui ne savent faire que de l’input. En d’autres termes, impossible avec cela d’allumer une LED comme je comptais le faire. En fait, la seule fonction qu’il est possible d’exécuter sur ces pins est analogRead().
J’aurais du utiliser ces pins pour les boutons, et mettre deux LEDs sur les pins digitaux à la place!
En avant la musique!
Fonction tone()
Pour jouer de la musique sur Arduino, la façon la plus directe est l’utilisation de la fonction tone(). En fait elle va simplement envoyer au buzzer un signal à une certaine fréquence, ce qui va générer une note.
Pour se simplifier la vie, on peut utiliser le fichier pitches.h et suivre le tutoriel présent ici: https://www.arduino.cc/en/Tutorial/toneMelody.
Vous l’aurez compris, je n’ai pas choisi cette méthode mais plutôt celle de la librairie RTTTL (voir plus bas). C’est pourquoi je ne souhaite pas m’étaler plus que ça sur le sujet, je n’ai aucune valeur ajoutée par rapport au tuto d’Arduino sur le sujet.
Librairie RTTTL
Installation
RTTTL signifie « Ring Tone Text Transfer Language ». C’est un langage mis au point par Nokia à la glorieuse époque des 3210. Le détail sur comment interpréter une sonnerie RTTTL ici: https://en.wikipedia.org/wiki/Ring_Tone_Transfer_Language
Concernant son usage avec un Arduino, la première chose que vous voulez faire c’est ajouter cette bibliothèque à votre IDE: https://github.com/cefn/non-blocking-rtttl-arduino
C’est la seule qui permet de jouer des mélodies stockées dans la mémoire PROGMEM, ce qui étant donné la taille que prennent les mélodies est un atout non négligeable (Voir l’article Arduino Nano out of memory: SRAM, Flash et EEPROM).
Utilisation
Jouer une mélodie se passe en deux temps: charger les notes, jouer les notes. Malheureusement, le README du repo n’est pas super bien fourni : il y a plusieurs fonctions ou constructeurs qui ne sont pas détaillées et qui pourtant m’ont été indispensables. En voici quelques unes :
- ProgmemPlayer : construit un player RTTTL qui va chercher ses mélodies dans la mémoire PROGMEM. On lui passe en paramètre le pin# du speaker.
- initSong() : réinitialise le player au début de la dernière mélodie chargée dans le player
- setSong(): Charge une mélodie dans le player
- pollBeep(): Retourne vrai tant qu’une note est en train d’être joué, puis faux le temps de passer à la note suivante.
- silence() : Arrête la mélodie en cours
- pollSong(): C’est expliqué dans le readme, mais pour la forme je reprécise que cette fonction va jouer la mélodie de façon non bloquante. Cela signifie qu’au niveau hardware on va pouvoir détecter des évènements, comme un bouton appuyé par exemple 😉
Code
L’intégralité du code est mise à disposition sur github: patrickroux/boitemusique.
J’ai essayé de commenter de manière à le rendre explicite. Dans l’idée, la loop va permettre de de surveiller les boutons. L’appui sur tel bouton ou telle combinaison va alors charger la musique correspondante dans le player puis appeler showMeWhatYouGot(). Cette fonction va jouer la mélodie tant et aussi longtemps que le bouton d’interruption n’a pas été pressé. A chaque note, on va allumer une led au hasard pour l’effet visuel.
Combinaisons secretes
Les combinaisons (secrètes ou non) ne sont pas compliquées, finalement. Le bébé à qui j’ai offert la boite commence à les comprendre a un an et demi! Il s’agissait simplement de détecter l’appui de plusieurs boutons simultanés, et la bibliothèque button.h fait ça très bien. Lorsqu’une combinaison est détectée, la mélodie correspondante est alors chargée depuis le fichier songs.h dans le player puis jouée.
Montage de la boite
Résultat
bonjour
valeurs des resistances svp pour boite à musique
merci
ap16mp@gmail.com
Bonjour Pira,
Peu importe pour les résistances. Vous pouvez prendre du 220 par exemple, assez classique pour des LED. L’essentiel est d’en avoir une, sachant que plus elle sera grande moins la LED sea lumineuse, et plus elle sera faible pour la luminosité sera grande mais sa durée de vie courte.