1. Introduction

En 1969, dans la fusée Apollo 11 se trouvait le premier AGC (Apollo Guidance computer) : l'ordinateur le plus puissant de son temps, développé par MIT, qui a coûté aux alentours de 10 millions de dollars à produire [1]. Pourtant, il n'était composé que de 12'300 transistors (l'entité de base d'un micro-processeur), alors que l'iPhone 6, en comparaison, en contient environ 1,6 milliards [2]...


Figure 1 : Le DSKY (Display and Keyboard) de l'ordinateur central des fusées Apollo. [3]

Ainsi, le matériel électronique et les ressources informatiques nécessaires à l'utilisation de celui-ci deviennent toujours plus accessibles et performantes. Cela a des conséquences très simples : au lieu d'être seulement utilisées par des scientifiques pour la construction d'outils à la pointe de la technologie, l'électronique et l'informatique sont utilisées par tout un chacun pour réaliser une multitude de projets. Certains sont intéressants, pratiques ou esthétiques, tandis que d'autres, on peut le dire, sont justes saugrenus. Souvent, ces projets nécessitent un micro-contrôleur, qui va s'occuper d'associer des inputs à des outputs et différents périphériques : des LEDs, des moteurs, des ventilateurs, des lasers et/ou tout un panel de capteurs (température, humidité, pression, luminosité, ...), selon les besoins. Une rapide recherche dans un navigateur internet permet de prendre conscience du nombre de projets existants, qui semble croître exponentiellement. Par exemple, rien que pour le type de micro-contôleur Arduino, qui est une plateforme très appréciée car facile à utiliser tant pour faire des prototypes que des produits finis, on peut trouver des pages internet qui listent plusieurs centaines de projets qui l'utilisent [4] [5].

Ce projet s'inscrit dans ce mouvement de créations électroniques réalisées par des personnes sans formation dans ce domaine. Ce que l'on veut développer n'a pas réellement d'intérêt pratique, mais sa fabrication nous permet d'acquérir des connaissances et de s'amuser. Initialement, le projet est né suite à la récupération imprévue d'une vieille valise à codes sur un tas de déchets encombrants. L'objectif était alors le suivant: placer, à l'intérieur de cette valise, du matériel électronique qui permettrait de la faire fonctionner comme un lecteur MP3 autonome. Le projet s'étant nettement précisé depuis le début, voici les objectifs que nous désirons obtenir $$Les expressions afficheur LED, carte perforée et lecteur de cartes sont définies dans le projet hiver que l'on trouve ici$$ :

  • Contrôle du volume.
  • Lorsqu’une carte perforée est introduite dans le lecteur de cartes, le morceau correspondant doit être joué.
  • Lorsqu’on joue un morceau, son titre, le nom du groupe et le temps restant sont affichés sur l’affichage LED, si la place manque, le texte défile de droite à gauche.
  • Possibilité de jouer une trentaine de morceaux différents.
  • Mise en veille du CHIP afin de réduire la consommation énergétique sans devoir débrancher de fils.
  • Un mode "single song" où une carte est insérée, puis le morceau correspondant est joué.
  • Un mode "playlist" : les cartes sont insérées l’une après l’autre et les morceaux sont joués à tour de rôle.

1.1 Technologies et protocole I2C

Lors du projet hiver, la partie hardware a été fortement développée, pour cette partie printemps, ce sera le software qui sera le plus mis en avant.

Ce projet est basé sur deux micro-contrôleurs : un ATmega32U4 (le micro-contrôleur de la majorité des Arduino) et un CHIP, qui est davantage un micro-ordinateur. L'atMega32U4 sert à produire des données qui seront ensuite récupérées par le CHIP: il est l'entité intelligente de cardReader et sert donc à scanner la carte perforée qui y est insérée pour obtenir son identifiant, mesurer la température, mesurer la luminosité et enfin, stocker le mode du bouton 3 positions. Le CHIP, quant à lui, est nécessaire car il permet notamment de jouer des fichiers MP3, d'autres avantages sont sa sortie jack 1/4 de pouce, sa mémoire importante (4Gb) et son Wi-Fi incorporé [6]. Puisqu'il y a deux micro-contrôleurs différents, deux langages de programmation sont utilisés: Arduino et JavaScript.

Une partie majeure du projet est d'établir une connection entre les deux micro-contrôleurs, ainsi que l'afficheur LED, pour permettre de faire circuler des informations entre eux. Pour cela, nous utilisons le protocole de communication I2C (Inter-Integrated Circuit). Ce protocole est standard pour énormément de micro-contrôleurs et de prériphériques et il permet à un master de s'adresser jusqu'à 1008 slaves sur un seul bus. Le protocole utilise deux fils: SDA (fil de données de l'I2C) et SCL (horloge de l'I2C). Aussi, c'est toujours le maître qui s'adresse aux esclaves, il peut ne communiquer qu'avec un seul module à la fois. Les paquets de données I2C sont formés deux parties principales: une adresse (7 bits) et des données (8 bits) [7]. Le détail des paquets est représenté ci-dessous.


Figure 2 : Structure des paquets I2C. [8]

Dans notre projet, nous avons un master, le CHIP, et 17 slaves, l'ATmega32U4 et les 16 PCA9685 qui se trouvent sur les modules de l'afficheur LED. La particularité de cardReader est que nous avons dû en faire un esclave I2C et donc superviser la communication avec ce protocole à un bas niveau. Cela est expliqué dans la partie Méthodes.

1.2 Librairies

Lors de ce projet, deux types de librairies ont été utilisées : des librairies Arduino et les librairies JavaScript. En général, ces librairies ont permis le fonctionnement de modules I2C (comme le PCA9685), l'utilisation de protocoles de communication (serial) et de permettre certaines fonctionalités dans la partie JavaScript du code (comme avoir des délais).

1.2.1 Librairies Arduino

Voici les librairies utilisées dans la partie Arduino du software :

  • pca9685 : contrôle du composant homonyme en I2C.
  • Wire : supervision des communications en I2C.
  • NilRTOS : multithread de l'Arduino.

1.2.2 Librairies Node

Voici les librairies utilisées dans la partie JavaScript du software :

  • debug : messages d'erreur dans le terminal affichés selon les programmes JavaScript pour lesquels c'est demandé.
  • delay : offre la possibilité de mettre des délais dans les programmes JavaScript.
  • mplayer-as-promised : lancement, arrêt, reprise et temps restant d'un morceau de musique.
  • i2c-bus : communication en I2C entre le CHIP et l'ATmega32U4.
  • child_process : exécute des scripts bash depuis un programme JavaScript.
  • spawn-promise : librairie qui adapte child_process.spawn pour utiliser des promise.
  • fs : abbréviation de file system, sert à accéder aux fichiers du disque et à les modifier.

2. Matériel

Ci-dessous est listé tout le matériel nécessaire à l'obtention de la valise lecteur MP3 complète.

Électronique :

  • 16 circuits imprimés ledDisplay soudées
  • 1 circuit imprimé cardReader soudé
  • Autant de cartes perforées que de morceaux de musique désirés, soudées de façon unique
  • 1 C.H.I.P.
  • 1 cable mini USB (pour le CHIP)
  • 1 cable micro USB (pour cardReader)
  • 50cm de fil de cuivre dénudé (diamètre environ 1mm)
  • 1m de fil de cuivre non dénudé (diamètre environ 2mm)
  • 1.5m de fil électrique (diamètre environ 2mm)
  • 1.5m de fil électrique (diamètre environ 1mm)
  • 4 haut-parleurs
  • 1 subwoofer
  • 2 supports pour trois batteries 18650
  • 6 batteries NCR18650B
  • 1 amplificateur (TPA3116D2)
  • 1 régulateur de tension 12V à 5V (MH-MINI-360 [9]
  • Thermocontractible de différents diamètres

Général :

  • 1 vieille valise en cuir (dimensions intérieures : 450x315x100mm)
  • 96 vis M3 par 10 en nylon noir + 96 écrous M3 en nylon noir
  • 4 entretoises de 25 mm de haut
  • 700x500mm de MDF (une sorte de bois composite) de 3mm d'épaisseur
  • 3 plaquettes fines (environ 1mm d'épaisseur) de métal magnétisable
  • 6 aimants néodium cylindriques (1cm de diamètre x 3mm d'épaisseur)
  • 1 cercle de mousse amortissante de 10cm de diamètre et 3cm d'épaisseur
  • Mousse de polystyrène extrudé rigide (max 15x15cm)

Outils :

  • 1 fer à souder
  • Fil d'étain
  • 1 paire de brucelles
  • 1 pince à dénuder
  • 1 multimètre
  • 1 alimentation variable jusqu'à 20V et 2A
  • 1 ordinateur
  • 1 perceuse
  • 1 mèche M4
  • 1 mèche M5
  • 1 mèche M15
  • 1 tournevis cruciforme
  • Colle chaude
  • 1 découpeuse laser qui puisse au moins découper des surfaces de 500 par 400mm

3. Méthode

3.1 Adressage de l'afficheur LED et soudure des cartes perforées

Toutes les plaques de l'afficheur LED ont été soudées entre la fin du projet hiver et le début du projet printemps. Néanmoins, il restait encore une étape pour qu'elles soient entièrement terminées : leur attribuer à chacune une addresse I2C en court-circuitant les quatre jumpers à l'arrière. À cause des spécifications du composant I2C de ces plaques (le PCA9685) , le premier bit de l'adresse est forcément à 1 [10], et nous avons décidé de placer les trois suivantes à 0. Ainsi, toutes nos adresses sont de la forme:

0b1000xxxx

En second lieu, il était encore nécessaire de souder des cartes perforées pour pouvoir les attribuer à des morceaux de musique ou à des playlists. Nous avons fait cela aléatoirement, en prenant toutefois garde à deux aspects : ne pas faire accidentellement deux cartes identique et ne pas relier tous les pins entre eux (la carte ne pourrait alors pas être détectée). Ensuite, nous avons inséré les cartes dans cardReader afin d'obtenir leur code unique (résultat du hash 32 bits élaboré au projet hiver) sous forme de 8 caractères en hexadécimal (le programme utilisé est stea-mp-unk-3/arduino/cardReader/cardToHash). Nous imprimons ce code et le collons au dos des cartes afin de pouvoir les distinguer. Enfin, une liste des codes uniques a été effectuée, avec les morceaux qui leurs sont attribués (on trouve cette liste ici).

Figure 3 : Exemple de cartes perforées soudées.

3.2 Finalisation, assemblage et test du hardware

Au début de ce projet, toutes les parties principales étaient réunies : les circuits électroniques avaient tous été soudés et testés, les haut-parleurs étaient à disposition et le support énergétique aussi. Pourtant, il fallait réaliser le support qui permettrait de soutenir tous ces éléments. Celui-ci est constitué de deux parties: une plaque permet de rassembler les 16 modules de l'afficheur LED, une autre les 5 haut-parleurs, l'amplificateur et le lecteur de cartes. Pour modéliser ces plaques, le programme FreeCAD a été utilisé [11]. Ce programme permet de faire à la fois du design 2 et 3D, est open-source et permet de réaliser des modèles complètement paramètrés, ce qui signifie que les dimensions du modèles peuvent être modifiées très facilement. Les modèles se trouvent dans stea-mp-unk-3/freecad.

Figure 4 : Modèles FreeCAD des planches à découper.

Afin de réaliser les modèles, nous avons procédé de deux façons différentes pour connaître les dimensions exactes des objets à placer sur ceux-ci. Pour les plaques, nous avons exporté leur dimensions directement depuis Eagle. Pour les trous dans lesquels rentrent les haut-parleurs, nous avons réalisé les mesures en utilisant un pied à coulisse, qui a permis une précision suffisante. Néanmoins, les trous pour les fixer ont été réalisés après coup avec une visseuse, une mèche M3 pour les petits haut-parleurs et une mèche M4 pour le grand (subwoofer).Une fois les modèles terminés, ils ont été exportés au format .dxf. En effet, c'est un des formats acceptés par la découpeuse laser que nous avons utilisée pour réaliser les modèles. Ils ont été découpés dans du MDF 3mm, qui est un matériau peu cher (5fr/m²) et suffisemment résistant pour cette application.

mdfSupport.JPG Figure 5 : Planches découpées à la découpeuse laser.

Ensuite, toutes les parties ont été fixées sur les plaques avec les vis en nylon M3 et les écrous, excepté le subwoofer qui a été fixé avec des vis M4 dans un premier temps. Pour terminer l'afficheur LED, les 16 modules ont été connectés entre eux en utilisant les fils de cuivre. Quatre connections devaient être faites : SDA, SCL, GND (terre) et +12V (alimentation). Pour les modules côte à côte, des petits bout (<1cm) de cuivre dénudé ont été utilisés. Pour connecter les lignes entre elles, par contre, ce sont des morceaux plus longs de fil non dénudé (pour éviter les courts-circuits) qui ont été soudés. Pour l'autre plaque, les haut-parleurs les plus petits ont été soudés en parallèle l'un à l'autre avant d'être reliés à l'amplificateur. Le subwoofer, quand à lui, y a été directement connecté. Ces connections consistent en deux fils : une terre et un signal d'excitation.

Une fois ces plaques terminées, elles ont été testées. Pour tester l'afficheur LED en entier, le même système a été utilisé que pour tester les modules séparément : un arduino, ayant une terre commune avec l'afficheur, qui sort les fils SCL et SDA et une alimentation qui procure la terre commune et le +12V. Ces quatre fils ont été connectés à l'afficheur, puis nous avons utilisé le programme de test stea-mp-unk-3/arduino/I2C/i2c-scanner afin de scanner le bus I2C et de vérifier que les seize modules étaient reconnus. Le résultat de ce scan est montré à la Figure 6. Enfin, le programme stea-mp-unk-3/arduino/ledDisplay/segmentsTestAll a été utilisé (il fait clignoter tous les segments de l'afficheur l'un après l'autre). Ce test, accompagné de commentaires sur le projet, est visible à la vidéo au lien suivant: https://youtu.be/d6xZFdfC1cU. Pour tester l'amplificateur, celui-ci a juste été relié à une alimentation 12V standard à l'aide du câble approprié et à un téléphone portable depuis lequel un fichier MP3 était joué (voir Vidéo 1). L'amplificateur fonctionne et les haut-parleurs aussi, néanmoins, le subwoofer émet un son vibrant désagréable. Pour améliorer cela, il a été surélevé au moyen d'entretoises M3 et déposé sur un morceau de mousse.

i2cDisplayScan.jpg Figure 6 : Résultat du scan du bus I2c sur lequel est connecté ledDisplay.

Vidéo 1 : Test des haut-parleurs.

Lorsque toutes les parties ont fonctionné indépendamment les unes des autres, il fallut encore s'occuper de l'alimentation. Celle-ci se fait au moyen de 6 batteries maintenues dans deux porte-batteries qui ont été fixés à l'avant de la plaque qui supporte les haut-parleurs. Chacun d'eux produit une tension de environ 11.4V quand les batteries sont chargées. Un des porte-batterie alimente le CHIP, cardReader et l'afficheur LED alors que l'autre alimente l'amplificateur, et donc les haut-parleurs. Le CHIP devant être alimenté en 5V, nous avons utilisé un régulateur de tension soudé à un câble USB mini pour l'alimenter (voir Figure 8).

Afin de terminer l'assemblage du matériel, il a fallu fixer toutes les parties ensemble, à l'intérieur de la valise. L'afficheur LED a été fixé dans la moitié de la valise la moins épaisse au moyen des aimants néodium. Les aimants ont été placés sur la plaque de l'afficheur avec de la colle chaude. Les plaquettes métalliques magnétisables ont été collées sur la valise elle-même. Pour la partie avec les haut-parleurs, des paralèllipipèdes de polystyrène extrudé rigide ont été collés au dos afin de supporter le poids de la plaque. Ensuite, celle-ci est juste glissée dans la valise et tient car elle est suffisamment bien ajustée.

Figure 7 : Dos de la plaque supportant les haut-parleurs.

Enfin, toutes les connections électriques nécessaires ont été réalisées comme indiqué au Figure 8.

mainScheme2.png Figure 8 : Tous les fils qui connectent les différentes parties du projet.

3.3 Obtention et traitement de la musique

Afin d'obtenir les morceaux de musique désirés au format MP3, une playlist avec tous les morceaux a été réalisée sur YouTube (on la trouve ici). Ensuite, l'outil youtube-dl (plus d'informations ici) a été utilisé afin de la télécharger. En effet, cet outil permet de télécharger n'importe quelle vidéo qui se trouve à un lien donné sur YouTube en différents formats et différentes qualités. Afin d'installer youtube-dl sur Fedora 27.0. nous avons procédé de la façon suivante:

sudo curl -L https://yt-dl.org/downloads/latest/youtube-dl -o /usr/local/bin/youtube-dl
sudo chmod a+rx /usr/local/bin/youtube-dl

Après quoi, la commande terminal ci-dessous a été utilisée, dans laquelle le lien est celui vers la playlist.

youtube-dl -x --audio-format mp3 https://www.youtube.com/playlist?list=PL-AGTXGfTz5ZugN3OLKQ2QQJyzX-eool0

L'option -x précise que seul l'audio doit être extrait. L'option audio-format précise le format des fichiers, ici MP3. Une fois les morceaux téléchargés au bon format, ils ont été renommés d'une manière standardisée. Dans le cas d'une carte perforée qui ne correspond que à un seul morceau, le nom est comme suit:

xxxxxxxx - nom auteur - titre morceau.mp3

Où les x sont des chiffres en hexadécimal qui correspondent au hash d'une des cartes perforées qui a été soudée. Si la carte correspond à une playlist, les morceaux de la playlist sont placés dans un dossier dont le nom est le hash de la carte et ils sont juste nommés comme cela:

 nom auteur - titre morceau.mp3

Cela fait, il restait à transférer toute la musique sur le CHIP. Le protocole scp a été utilisé depuis le CHIP, avec la commande:

scp -r mp3/ root@192.168.1.78:/root/git/opatiny/node-steam-player/mp3

-r indique que la commande est récursive, mp3/ est le dossier sur le CHIP où la copie doit être faite et root@192.168.1.78:/root/git/opatiny/node-steam-player/mp3 le dossier de la machine de départ qui doit être copié.

3.4 Programmation

3.4.1 Partie Arduino

L'ATmega32U4, le micro-contrôleur de cardReader, est aussi celui utilisé dans les Arduinos. Par conséquent, on peut utiliser leur plateforme de programmation, qui est open-source, afin d'écrire le code qu'il doit exécuter (on peut télécharger ce programme ici). Afin que le programme Arduino final (qu'on peut trouver ici) soit compréhensible et réutilisable, il a été divisé en plusieurs fichiers, chacun s'occupant d'une fonction spécifique. La majorité des fichier de base sont les programmes de tests réalisés au projet hiver, récupérés dans ce programme principal. L'un d'eux, cardReaderMT/A_Parameters.ino, permet de définir tous les paramètres qui sont utilisés dans le reste du programme. Pour définir ces paramètres, la syntaxe #define a été utilisée. Celle-ci est pratique, car selon les paramètres définis, on peut exécuter ou non diverses parties du programme.

testDefine.png Programme 1 : Programme Arduino. La fonction hi() est exécutée seulement si PARAMETER est défini.

Il stocke tous ces paramètres dans sa mémoire et les met à jour à une fréquence définie dans le code, qui peut différer selon les paramètres. Lors de cette partie, le problème principal a été que le micro-contrôleur doit effectuer de nombreuses tâches simultanément, c'est ce qu'on appelle du multithread, c'est-à-dire l'exécution simultanée de plusieurs programmes, les threads [12]. Or, ce procédé requière plusieurs cores, mais l'atMega32U4 n'en a qu'un seul. Par conséquent, un procédé un peu différent a dû être différent: le temps d'utilisation du core est réparti selon la priorité des programmes, on nomme alors cela parathread. Pour réussir à faire cela, nous avons récupéré, puis modifié le code arduino d'un projet existant : un spectrophotomètre open-source dont on trouve la page Github ici [13]. Le principe est plutôt simple: une librairie Arduino, NilRTOS [14], permet de définir et de coordonner les threads. Le Programme BASICNIL (stea-mp-unk-3/arduino/multiThread/BasicNil) est un exemple simple de multithread qui permet de faire clignoter deux LEDS à des fréquences sans diviseur commun [15]. Dans notre cas, néanmoins, chaque thread a été placé dans un programme distinct.

Programme 2 : Permet de faire clignoter deux LEDs en utilisant des threads distincts.

Dans notre cas, il y a six threads coordonnés dans le programme arduino/cardReader/cardReaderMT/Z_Start_thread.ino, ils sont définis dans l'ordre de priorité suivant:

  1. ThreadSerial : Communication sérial permettant la programmation de l'ATmega32U4 (récupéré tel quel du projet open-spectro)
  2. ThreadLuminosity : Mesure l'intensité lumineuse captée par la photorésistance
  3. ThreadTemperature : Mesure de la température
  4. ThreadCardReader : Gère le stockage du le hash correspondant à la carte introduite
  5. ThreadButton : Gère l'état du bouton
  6. ThreadMonitoring : Watchdog qui réinitialise le micro-contôleur après 7 secondes

Le sixième thread, le watchdog, consiste en un compteur qui croît en permanance jusqu'à ce qu'il atteigne une certaine valeur. Dans ce cas-là, il exécute une fonction, une réinitialisation par défaut pour l'atMega32U4. L'objectif est de remettre ce compteur régulièrement à zéro dans le programme. Ainsi, s'il y a un problème et que le programme n'est pas exécuté normalement, le compteur atteint sa valeur maximale et le micro-contrôleur est réinitialisé, ce qui permet de rendre de le rendre plus autonome, puisqu'il n'est pas nécessaire de le faire manuellement [16].

En ce qui concerne l'adaptation de cardReader en un esclave I2C, l'adresse 0x08 lui a été attribuée (dans les paramètres). Ainsi, on peut s'y adresser depuis le CHIP. Ensuite, la partie du programme stea-mp-unk-3/arduino/cardReader/cardReaderMT/WireSlave.ino a été écrite (ce programme est basé sur [17]), qui utilise principalement la librairie Arduino Wire. Elle contient trois fonctions, dont la principale, startWireSlave(), permet l'initialisation en soit de l'esclave I2C. Cette fonction en requière deux autres: requestEvent() qui sert à l'Arduino de renvoyer un paramètre qui lui a été demandé par le master et receiveEvent() qui permet à l'arduino de recevoir une commande.

3.4.2 Partie JavaScript

Toute la partie JavaScript du programme se trouve dans son propre projet GitHub (lien ici''. Elle est séparée du reste du projet car tout ce dossier est cloné sur le CHIP. Il faut donc éviter tout fichier inutile puisque la mémoire est limitée. L'autre avantage d'avoir le code dans un projet GitHub est qu'il est possible de travailler dans un vrai éditeur de code sur un ordinateur. Dans notre cas, l'éditeur Visual Studio Code [18] est utilisé car il est open-source et permet d'implémenter des extensions facilement en fonction des besoins.

Sur le CHIP, on ne peut lancer un programme que depuis un terminal. Par conséquent, nous utilisons Node.js [19], qui permet d'exécuter des programmes JavaScript depuis terminal. Afin d'installer Node.js sur le CHIP, il était d'abord nécessaire d'installer NVM (Node Version Manager), qui permet donc de superviser Node.js (tutoriel d'installation ici). D'autre part, NPM (Node Package Manager) permet s'occupe de toutes les librairies que nous utilisons dans le programme JavaScript. Lorsque Node.js est installé, tout programme peut être lancé facilement avec la commande terminal suivante :

node monProgramme.js

La partie JavaScript est le programme qui coordonne toutes les parties du projet: cardReader, ledDisplay et la sortie vers l'amplificateur. Afin de réussir à faire tout fonctionner, il a à nouveau été nécessaire de réaliser de nombreux tests. Tous les tests qui ont été réalisés se trouvent dans node-steam-player/src/util/tests et dans node-steam-player/src/i2c/tests. Ceux-ci nous ont permis de développer de nombreuses fonctions que l'on requière dans le code principal : node-steam-player/src/index.js.

Pour réaliser le programme JavaScript, il a fallu trouver un moyen de partager des paramètres communs entre toutes les parties du code. Pour cela, nous définissons un objet context dans le code principal qui est appelé par toutes les fonctions utilisées (cet objet est montré au Programme **contextObject**). Ces fonctions utilisent alors les valeurs des paramètres dont elles ont besoin et modifient celles qu'elles doivent modifier. Cette méthode est pratique, car on a alors toutes les paramètres à jour en même temps et au même endroit.

Programme 3 : Objet principal du code servant au stockage de tous les paramètres.

Lors de cette partie de la programmation, plusieurs problèmes ont dû être résolus :

  • Requérir les paramètres du slave I2C (cardReader).
  • Lancer un fichier MP3 à partir du CHIP et le temps depuis lequel le morceau est joué.
  • Connaître la durée d'un morceau.
  • Connaître le contenu d'un dossier, afin de savoir tous les morceaux de musique disponibles dans la mémoire.
  • Contrôler les sorties PWM des PCA9685.
  • Afficher des lettres sur l'afficheur LED.
  • Éteindre le CHIP à partir d'un programme JavaScript.
  • Lancer un programme par défaut lors du démarrage du CHIP.

Afin de superviser la communication I2C du côté master, la librairie i2c-bus est utilisée [20]. Celle-ci permet d'ouvrir une connection sur un bus I2C en particulier avec la fonction openSync(bus). Un fois la connection ouverte, on peut lire un paramètre I2C stocké par l'Arduino en utilisant la méthode readWordSync(slaveAddress, parameter)slaveAdress est l'adresse de l'esclave I2C et parameter est le paramètre que l'on veut lire. Le Programme **i2cLibraryTest** montre comment requérir le paramètre luminosity stocké par cardReader. Dans notre cas, tous les paramètres récupérés (luminosity, temperature, switchState et card'') sont stockés dans la propriété cardReaderStatus de l'objet commun context.

Programme 4 : Requière en I2C le paramètre luminosité stocké par cardReader.

Ensuite, on dût trouver un moyen de jouer un fichier audio depuis le CHIP. Heureusement, il existe une librairie qui permet de faire cela plutôt facilement: mplayer-as-promised (informations sur la librairie : [21]). Nous utilisons trois méthodes de cette librairie :

  • openfile(pathToAudioFile) : permet de lancer un fichier audio.
  • stop() : permet de stopper un fichier audio.
  • getCurrentTime() : retourne le nombre de secondes depuis lequel un morceau est en train d'être joué.

Le Programme 5 montre comment lancer un morceau au moyen de cette librairie.

Programme 5 : Requière en I2C le paramètre luminosité stocké par cardReader.

Pour pouvoir afficher le temps restant du morceau qui est en train d'être joué, il nous fallait non seulement le temps actuel du morceau joué, mais aussi sa durée. Or, tout morceau de musique contient des informations sur lui-même dans son fichier et il existe un outil qui permet de les récupérer: mp3info. Néanmoins, cet outil est normalement utilisé au niveu d'un terminal. Il a donc fallut trouver un moyen de l'utiliser depuis notre programme JavaScript. Par chance, une librairie très simple permet de faire cela: pilla-lib-mp3info [22]. C'est ce qui a été utilisé afin de connare la longueur de nos morceaux.

Un autre aspect a été d'être capable de scanner tout le dossier contenant les morceaux copiés sur le CHIP afin de créer une correspondance entre les clés existantes, le nom de l'artiste et le titre du morceau qui sont attribués à un fichier situé à un certain chemin : c'est une sorte de table des matières. Celle-si peut être générée grâce à la librairie fs [23], dont nous utilisons les méthodes suivantes:

  • existsSync(path) : vérifie si le chemin relatif path existe.
  • readdirSync(path) : liste le contenu du dossier indiqué par le chemin relatif path sous forme d'un array.
  • isDirectory(path) : renvoie true si le fichier est un dossier.

Nous stockons cette table des matières en tant qu'une liste d'objets dont les propriétés sont key (code de la carte perforée correspondante), file (chemin relatif vers le fichier audio), author (le nom de l'artiste) et title (le titre du morceau). Cette liste est générée par le programme node-steam-player/src/util/loadTOC.js à chaque fois que index.js est lancé.

Pour contrôler l'afficheur LED, il a fallu être capable de contrôler les PCA9685. Pour ce faire, nous nous sommes basés sur la librairies Johny-Five pca9685 et sur la fiche de données de ce composant. Nous avons ainsi pu définir plusieurs fonctions qui permettent d'allumer à volonté les seize segments contrôlés par chaque PCA9685 en utilisant un masque de 16 bits (node-steam-player/src/i2c/pca9685.js). Dès lors, nous avons pu définir tous les caractères que nous voulions afficher sur l'afficheur LED sous forme d'un nombre binaire de un byte. Tous ces caractères, qui forment notre alphabet, sont contenus dans l'objet contenu dans le fichier node-steam-player/src/i2c/alphabet.js. Le Programme 6 montre une partie de ces caractères.

alphabet.png Programme 6 : Codes binaires correspondant aux lettres A, B et C affichés sur ledDisplay.

Dès lors, en accolant deux des codes de cet objet (qui correspondent à deux lettres qui veulent être affichées), on obtient le masque qui fait office de paramètre aux fonctions dévellopées pour l'afficheur. Les fonctions servant à afficher directement un texte voulu sont contenue dans le programme node-steam-player/src/i2c/display.js, qui requière le fichier pca9685.js qui a été mentionné auparavant.

Puis, nous avons encore dû trouver un moyen d'éteindre le CHIP depuis un programme JavaScript. Ce qui est très simple si on utilise la méthode exec (qui est une partie d'une librairie plus importante, child-process) qui permet d'effectuer n'importe quelle commande terminal depuis un script. Le Progamme 7 (node-steam-player/src/i2c/tests/shutdown-test.js|https://github.com/opatiny/node-steam-player/blob/master/src/i2c/tests/shutdown-test.js]) permet d'éteindre le CHIP après cinq secondes.

Programme 7 : Permet d'éteindre le CHIP depuis un script JavaScript.

Enfin, il faut que index.js soit lancé automatiquement lors du démarrage du CHIP. Il existe un package NPM qui permet cela: PM2. Cet outil permet de rajouter un ou plusieurs programmes qui sont exécutés lors de la procédure de démarrage de la machine (pour voir une procédure détaillée de l'installation et de l'utilisation, cliquer ici). Dans notre cas, cela ne concerne que index.js.

4. Résultats

Puisque une grande partie des résultats obtenus pour les parties individuelles du projet ont été montrés dans la section Méthodes de ce billet, nous ne montrons ici que les résultats d'ensemble qui sont présentés au travers de la marche à suivre d'utilisation ci-dessous.

Utilisation du lecteur MP3

Voici un court protocole expliquant la procédure qui permet d'utiliser le lecteur MP3. L'équivalent vidéo peut être trouvé au lien suivant : https://youtu.be/vln9X8TIJ3k.

Démarrage :

  • Ouvrir la valise en tirant les deux clapets vers l'extérieur après avoir composé le code 197 197.
  • Prendre les six batteries qui se trouvent dans la poche extérieure de la valise et les placer dans les deux portes-batteries en prenant garde au sens.
  • Vérifier que tous les fils sont branchés au bon endroit : le câble jack, l'alimentation USB du CHIP, l'alimentation de cardReader et l'alimentation de l'amplificateur.
  • Vérifier que la LED rouge de cardReader clignote et que la LED verte de l'amplificateur est allumée.
  • Patienter le temps du démarrage du CHIP : la LED blanche doit clignoter.
  • Lorsque le lecteur est prêt à être utilisé, il affiche Waiting sur la ligne du haut. Il afficher huit zéro sur celle du bas. Si une carte est insérée et pas reconnue, il affiche le hash correspondant en hexadécimal.

Utilisation :

  • Balancer le bouton trois positions vers la droite pour mettre en mode 1 (playlist) ou le balancer vers la gauche pour mettre en mode 2 (single song).
  • Prendre la liste des cartes et morceaux correspondants qui se trouve dans la poche extérieure de la valise avec les cartes perforées.
  • Insérer une carte perforée dans le lecteur de cartes (les deux sens sont possibles). Le morceau correspondant devrait être joué. Le titre, le nom de l'auteur et le temps restant du morceau sont affichés sur l'afficheur LED.
  • En mode 1, autant de cartes que désiré peuvent être insérées, les morceaux correspondants s'ajoutent à la fin de la liste de lecture. Le nombre de morceaux en attente est affiché en bas à droite de l'afficheur LED.
  • En mode 2, toute carte insérée interromps la musique jouée et lance le nouveau morceau.

Arrêt :

  • Placer le bouton trois position en mode 1 et appuyer sur le bouton rouge. La procédure d'arrêt devrait être enclanchée. L'afficheur doit indiquer Shutting down.
  • L'appareil est éteint lorsque les LEDs du CHIP sont éteintes.
  • Enlever les batteries et les ranger dans la poche extérieure de la valise ainsi que les cartes perforées.
  • Refermer la valise en prenant garde à ne pas coincer les quatre fils connectés à l'afficheur LED.

5. Discussion

Le projet en entier fonctionne comme désiré initialement pour la majorité des points. Tout d'abord, les PCA968 des seize modules de l'afficheur LED se connectent au bus I2C avec une addresse unique et la méthode permettant d'afficher du texte sur l'afficheur a été dévelopée. Ainsi, lorsqu'un morceau est joué, on affiche le nom de l'auteur, le titre du morceau et le temps restant jusqu'à la fin de celui-ci. Deux problèmes persistent néanmoins avec l'afficheur. En premier lieu, certains des segments ne fonctionnent pas toujours. Nous avons déduit que cela est dû à des faux contacts sur les circuits imprimés qui composent l'afficheur. Cela n'est pas dramatique, car il suffit de dessouder les plaques disfonctionelles afin de réparer les mauvaises connections. Ce serait certes chronophages, mais cela reste simple à améliorer. Le second point, quant à lui, est au niveau du programme JavaScript. En effet, lorsque les titres et les noms des auteurs des morceaux sont trop longs, seuls les 12 premiers caractères sont affichés. Une solution serait de faire défiler le texte de droite à gauche, comme désiré initialement, néanmoins, ç'eut été compliqué à réaliser dans le programme et nous n'avons pas pu nous y atteler à cause du manque de temps.

En ce qui concerne l'amplificateur, il semble remplir son office et permet de jouer de la musique à la fois à partir d'un téléphone que depuis le CHIP. Pourtant, dans le second cas, il est arrivé que le subwoofer ne fonctionne pas. Il est à envisager que cela est dû au fait que le signal produit par le CHIP est d'une trop faible intensité et que l'électro-aimant du subwoofer ne soit pas activé à cause de cela. Dans ce cas, il serait possible d'installer un pré-amplificateur, ce qui devrait améliorer les résultats. Ainsi, tous les haut-parleurs ont tout de même fonctionné, même si aucune solution n'a été trouvée qui permette d'éviter les vibrations du subwoofer. Cependant, nous avons réussi à supprimer certains bruits en le coinçant avec de la mousse. Néanmoins, il semble qu'il y aie toujours des fréquences pour lesquelles quelque chose entre en résonnance et produit un son désagréable.

D'autre part, le slave I2C cardReader fonctionne très bien. Il n'y a pas eu un seul cas dans lequel il aurait arrêté de fonctionner de façon imprévue, ce qui est très impressionnant et encourage à réutiliser cette méthode dans d'autres projets. Le CHIP, au contraire, a posé davantage de problèmes. Tout d'abord parce que dès qu'il a été placé dans la valise, il avait tendance à perdre la connection WiFi, ce qui nous empêchait de travailler au moyen de Git. Cependant, nous avons pu régler cela en le faisant se connecter au WIFi d'un téléphone que l'on a placé juste à côté. En second lieu, le CHIP avait tendance à planter sans que nous puissions en identifier la cause. Cela reste un problème qui n'a pas pu être résolu. Un autre aspect discutable du projet est la façon que nous avons utilisée pour télécharger les morceaux. En effet, la méthode que nous avons utilisée ne prend pas compte des droits d'auteur. Par conséquent, il aurait été préférable de se procurer les morceaux autrement.

En outre, l'autonomie de la valise est acceptable. Par expérience, elle peut fonctionner pendant plusieurs dizaines de minutes. Néanmoins, lorsque les batteries sont quasiment vides, l'afficheur LED perd peu à peu son intensité. Alors, nous avons observé qu'il faut retirer les batteries au plus vite, car si elles se déchargent trop, il n'est plus possible de les charger. Afin, d'éviter ce problème, il serait possible de placer un composant permettant de mesurer la tension sur cardReader. En effet, la tension aux bornes d'une batterie chute avec son niveau de charge. Ainsi, nous pourrions détecter automatiquement quand les batteries doivent être changées.

Les apprentissages réalisés lors de ce projet ont donc été nombreux. En effet, nous avons dû nous confronter à des aspects d'électronique et d'informatique variés. Ainsi, on peut énoncer les acquis suivants:

  • Compréhension du fonctionnement de base d'un amplificateur et d'un haut-parleur
  • Contrôle de l'alimentation d'un circuit électrique complexe
  • Amélioration de technique de soudure de composants à montage de surface de petite taille
  • Programmation d'un Arduino
  • Création d'un esclave I2C
  • Multithread sur un arduino avec la librairie NilRTOS totalement méconnue jusque là
  • Amélioration des connaissances en programmation JavaScript : appropriation des objets, du démarrage de fichiers audio, de l'exécution de commandes terminal, des instances d'objets, ...

Dans l'ensemble, mener à bien seul un projet informatique d'une telle envergure n'est pas envisageable avec notre niveau actuel de connaissances dans ce domaine et une vaste aide a dû être obtenue pour concrétiser ce projet. Le sentiment qui en résulte est mitigé : nous avons certes un produit fonctionnel, bien qu'il ne soit pas fiable, mais il est d'une telle complexité qu'il ne nous est pas possible d'en apréhender profondément tous les mécanismes. Cette façon de procéder nous a néanmoins permis d'avoir un aperçu de nombreuses technologies que nous saurons réutiliser à l'avenir en se basant sur ce qui a été fait ici.

6. Conclusion

Finalement, tous les objectifs posés initialement ont été atteint excepté la possibilité de faire défiler un texte de droite à gauche sur l'afficheur LED. Le produit obtenu reste néanmoins très satisfaisant par rapport au temps accordé à ce projet. En effet, nous avons un lecteur MP3 fonctionnel avec deux modes (playlist et morceau unique) dans lequel les morceaux joués sont choisis au moyen de petits circuits imprimés. De plus, l'afficheur LED permet d'afficher diverses informations sur le morceau joué. Enfin, l'appareil n'est pas encore fiable car le CHIP s'éteint parfois sans raison apparente, mais il peut tout de même fonctionner pendant plusieurs dizaines de minutes dans de bonnes conditions, ce qui prouve aussi que son autonomie énergétique est considérable au vu de sa consommation.

Il aurait peut-être été préférable de réaliser un projet moins conséquent et dans un domaine que nous ne connaissions pas du tout, puisque cela aurait été une bonne occasion de s''initier à quelque chose. Ce n'est cependant qu'une préférence entre avoir un savoir général et la spécialisation dans un domaine. Il ne semble néanmoins pas péjoratif d'avoir approfondi les langages informatiques Arduino / C et javascript, puisqu'ils sont tous deux fortement répandus. La communication I2C a aussi été très intéressante, car elle a permis d'être très proche du micro-contrôleur: nous avons dû utiliser des programmes qui rédigent des paquets I2C bit par bit. Aussi, avoir toujours opté pour un code fractionné en fonctions indépendantes les unes des autres nous permettra de réutiliser les différentes parties du programme dans des projets futur. Par exemple, nous saurions faire un nouvel esclave I2C très facilement en récupérant les bons fichiers du programme Arduino. Après avoir profité de la masse d'information accessible sur le web, l'on pourrait considérer nos connaissances comme suffisantes pour partager à notre tour les projets que nous réalisons et les problèmes rencontrés, par exemple sur une plateforme teslle que Instructables (http://www.instructables.com/). Ce serait un moyen d'élargir ce projet et de lui donner une fin autre que purement personnelle. Dans cette optique, nous envisageons aussi de le présenter au LemanMake, un festival de makers (https://lemanmake.org/). Ainsi, nous pourrions avoir des avis extérieurs quant au travail réalisé, ce qui nous permettrait de nous améliorer encore davantage et de continuer à apprendre dans ce domaine.

7. Références

Notes

[1] Computers in Spaceflight: The NASA Experience - Chapter Two - Computers On Board The Apollo Spacecraft. (n.d.). Retrieved April 18, 2018, from https://history.nasa.gov/computers/Ch2-4.html

[2] How did the Apollo flight computers get men to the moon and back ? - Curious Droid. (2017). Retrieved April 18, 2018, from http://curious-droid.com/214/apollo-flight-computers-get-men-moon-back/

[3] Computers in Spaceflight: The NASA Experience - Chapter Two - Computers On Board The Apollo Spacecraft. (n.d.). Retrieved April 18, 2018, from https://history.nasa.gov/computers/Ch2-4.html

[4] 130+ Arduino Projects with Source Code, Schematics &amp; Complete DIY Explanation. (n.d.). Retrieved April 18, 2018, from https://circuitdigest.com/arduino-p...

[5] 200+ Arduino Projects List For Final Year Students. (n.d.). Retrieved April 18, 2018, from https://www.electronicshub.org/ardu...

[6] Get C.H.I.P. and C.H.I.P. Pro - The Smarter Way to Build Smart Things. (n.d.). Retrieved April 24, 2018, from https://getchip.com/pages/chip

[7] SFUPTOWNMAKER. (n.d.). I2C - learn.sparkfun.com. Retrieved April 28, 2018, from https://learn.sparkfun.com/tutorial...

[8] SFUPTOWNMAKER. (n.d.). I2C - learn.sparkfun.com. Retrieved April 28, 2018, from https://learn.sparkfun.com/tutorial...

[9] Retrieved May 12, 2018, fromhttp://qqtrading.com.my/dc-dc-step-...

[10] adafruit. (2015). PCA9685 - product data sheet. p. 8. Retrieved from https://cdn-shop.adafruit.com/datasheets/PCA9685.pdf

[11] FreeCAD: An open-source parametric 3D CAD modeler. (n.d.). Retrieved April 21, 2018, from https://www.freecadweb.org/

[12] Multithreading Definition. (2008). Retrieved April 24, 2018, from https://techterms.com/definition/mu...

[13] Le code récupéré est celui du commit 31f9d76e5fb9615eacc46422a5802c925644640f

[14] greiman (GitHub username). (n.d.). A tiny RTOS for Arduino AVR boards (Arduino library). Retrieved September 4, 2018, from https://github.com/greiman/NilRTOS-...

[15] Ce programme est basé sur les programmes d'exemple de la librairie.

[16] Jean Rabault. (2015). Arduino watchdog. Retrieved May 8, 2018, from https://folk.uio.no/jeanra/Microele...

[17] cornelam (instructables username). (2009). I2C Between Arduinos. Retrieved May 13, 2018, from http://www.instructables.com/id/I2C-between-Arduinos/

[18] Visual Studio Code - Code Editing. Redefined. (n.d.). Retrieved May 13, 2018, from https://code.visualstudio.com/

[19] Node.js. (n.d.). Retrieved May 13, 2018, from https://nodejs.org/en/

[20] Fivdi. (n.d.). I2C serial bus access with Node.js. Retrieved September 4, 2018, from https://github.com/fivdi/i2c-bus

[21] cdunford (npm username). (n.d.). mplayer-as-promised (npm package). Retrieved September 4, 2018, from https://www.npmjs.com/package/mplayer-as-promised

[22] perrywu (npm username). (n.d.). pilla-lib-mp3info (npm package). Retrieved September 4, 2018, from https://www.npmjs.com/package/pilla...

[23] Node.js. (n.d.). Retrieved May 13, 2018, from https://nodejs.org/en/