Projet IMA3 P2, 2017/2018, TD2

De Wiki de Projets IMA

Projet IMA3-SC 2017-2018 : Le Jeu du Simon

Cahier des charges

Description du système

A l'instar du mondialement connu jeu du Simon, notre système aura pour mission de générer aléatoirement une séquence de signaux lumineux, à l'aide de 4 LED. Une fois la séquence terminée, ce sera au tour de l'utilisateur de reproduire cette dernière de façon identique, en appuyant sur des interrupteurs. Chaque bouton correspondra alors à une couleur. Il faudra donc également mettre en place un système indiquant à l'utilisateur si il a réussi ou non.

On pourra, via la partie serveur Web, paramétrer les parties en gérant la vitesse ainsi que la taille de la séquence. De plus, c'est côté web que sera généré la séquence aléatoire d'allumage des LED, pour être ensuite envoyé vers la FPGA et son système électronique.

Evolutions possibles du projet

Si le temps nous le permet, nous avons déjà pensé à des améliorations pour notre projet. Nous pourrions installer un mode multijoueur en ajoutant une LED RGB supplémentaire. Elle prendra la couleur du joueur qui devra alors exécuter la prochaine séquence.

depuis la partie serveur Web, nous pourrions alors gérer le nombre de joueurs, et le mode de jeu choisi.

De plus, nous pouvons également envisager l'utiliser des capteur à ultrasons à la place de simples boutons lorsque l'utilisateur rentrera sa séquence. Il n'aura alors qu'à positionner sa main devant les capteurs souhaités.

Protocole de fonctionnement

L'envoi, la réception et la comparaison des données se fera de la façon suivante. On trouvera entre parenthèses le composant participant à la réalisation de l'étape.

  • Entrée des divers paramètres de jeu par l'utilisateur (Application web)
  • Génération aléatoire de la séquence (Application web)
  • Envoi et réception du signal de début (Port série -> FPGA)
  • Envoi des données octet par octet (Port série)
  • Réception et mise en mémoire de la séquence d'allumage (FPGA)
  • Envoi du signal de fin (Port série -> FPGA)
  • Mise en mémoire de la séquence réalisée par l'utilisateur (FPGA)
  • Comparaison entre la séquence aléatoire et la séquence réalisée par l'utilisateur (FPGA)
  • Envoi d'un booléen Vrai ou Faux indiquant le succès ou non de l'opération (FPGA -> Port série)
  • Affichage du succès ou non sur l'écran du smartphone (Application web)


Matériel nécessaire

  • 4 LEDs de couleurs différentes
  • 4 Interrupteurs (faisant office de boutons de jeu)
  • FPGA
  • Raspberry PI 3
  • 1 LED RGB

Séance 1

  • Choix du sujet
  • Répartition des taches à effectuer pour la partie électronique (garder en mémoire un signal d'entrée, l'afficher et vérifier si le signal "créé" par l'utilisateur est le même, et envoyer la réponse à l'application) et la partie application (génération d'un signal aléatoire, choix de la vitesse, de la taille des séquences et du mode de jeu.

Nous avons également dû adapter les étapes de notre projets aux nouvelles informations qui nous étaient données : nous n'avions pas compris, au début du projet, l'importance de la partie FPGA et son fonctionnement exact. Alors que notre idée de départ était de reposer le côté électronique en majeure partie sur la carte Arduino, nous avons ensuite imaginé utiliser le FPGA comme interface entre Application Web et Arduino, avant de mettre finalement de côté toute la partie Arduino pour ne réaliser la partie programmation électronique que via la FPGA et ses circuits logiques.

Cependant, dû au probable manque de temps qui nous est accordé pour réaliser tout ce que nous voulons faire sur FPGA, nous devrons impérativement réaliser en premier lieu toute la partie électronique sur Arduino. Cette dernière nous servira à vérifier le bon envoi des données depuis l'application web.

Nous devons nous attendre à ce que nous n'ayons malheureusement pas le temps de connecter partie FPGA et partie Web. C'est pour cela que la réalisation sur Arduino dans un premier temps reste indispensable, pour avoir au moins un jeu fonctionnel.

Partie Informatique

Tout d'abord, il a fallu installer un système d'exploitation sur la Raspberry. Il existe quelques distributions GNU/Linux qui sont assez légère pour fonctionner sur la Raspberry. On nous a conseillé d'utiliser Raspbian sans interface graphique. Après avoir crée une carte sd bootable pour la raspberry, on a modifié quelques fichiers pour pouvoir utiliser le port série, et continuer la configuration de la Raspberry. Ensuite, il a été nécessaire de mettre à jour la distribution. On a eu quelques soucis, à cause d'un tutoriel qui comportait quelques erreurs. Puis, pour pourvoir installer un serveur web sur la raspberry, il faut la configurer pour quelle soit déjà connectée sur internet et aussi la configurer en point d'accès, ces deux choses étant faites à la fin de la première séance. A ce stade, la raspberry possède un OS correctement installé, et peut servir de point d'accès. Il manque juste l'installation d'un serveur web.

Partie Electronique

Dans un premier temps, nous avons découvert et pris en main la carte FPGA via un tutoriel de réalisation d'un compteur 4 bits sur Altium. Ensuite, nous sommes remontés rejoindre l'autre partie du groupe pour faire le point et décider du protocole de réalisation du projet, ainsi que la répartition des tâches.

Après avoir appris que nous devrions passer par l'Arduino dans un premier temps, nous nous sommes attelés à la réalisation d'un premier circuit électonique. Au niveau de la partie code, nous nous sommes attardés sur l'interrupteur, plus précisement sur le fonctionnement de la fonction INPUT_PULLUP qui nous permettra de recevoir les informations voulues lorsque l'utilisateur rentrera la séquence.

Travail Personnel

Entre les deux séances, nous avons réalisé l'intégralité de la partie Arduino du jeu du Simon que nous comptons ensuite développer sur FPGA. Bien que cette partie ne soit pas censée se retrouver dans le projet final, elle servira au binôme en charge de la partie informatique pour lui permettre de vérifier le bon fonctionnement de l'envoi des paquets de bits à travers le port série.

Séance 2

Partie Informatique

Lors de cette séance, on s'est tout d'abord concentré sur l'installation d'un serveur Web sur la Raspberry Pi, de manière à pouvoir exécuter du code sur la Raspberry. On a donc téléchargé les paquetage apache2 et php. On a ainsi, dans un premier temps, créé une simple page html comportant un bouton "Jouer". On a modifier cette page par la suite.

Ensuite, on a chercher une méthode permettant à la Raspberry de communiquer avec un micro-contrôleur. Comme conseillé, on a donc utilisé une communication série. Pour cela, on a donc choisit d'utiliser un serveur websocket, facilement contactable via un programme javascript tournant sur le navigateur.


Partie FPGA

Le système FPGA

D'un autre côté, un binôme s'est attardé sur la partie FPGA. Voici leur témoignage, au travers de leurs expériences, de leurs espoirs, mais surtout de leurs désillusions :

Nous avons commencé à reproduire le programme Arduino sur FPGA. Pour commencer, nous nous sommes attardés sur la réception de l'information par le port série, et sur la mise en mémoire et l'allumage d'une seule LED pour une séquence de 5 étapes, qu'il nous suffira ensuite de reproduire pour les 3 autres LED.

Pour ce faire, nous sommes alors partis du principe qu'un message d'un octet envoyé par le port série correspondrait à une seule étape de la séquence. Il faudrait alors envoyer 5 octets avant que ce soit à l'utilisateur de jouer. Le message serait composé de 2 x 4 bits identiques, la première partie du message servirait à allumer directement la LED alors que la seconde partie serait dirigée vers la mise en mémoire. Chaque LED correspond à un bit, et donc un seul bit sur les 4 peut être à 1 à la fois. (exemple : le message 10001000 allumera la led rouge, 01000100 allumera la led jaune, 00100010 allumera la verte et 00010001 allumera la bleue).

Comme dit précédemment, nous nous sommes concentrés uniquement sur une seule LED, le traitement du message reçu, et la mise en mémoire du bit correspondant pour chaque étape de la séquence. Comme nous sommes partis sur une base de 5 étapes, nous avons choisi d'utiliser 5 bascules D dans lesquelles nous stockerons l'état 1 ou 0 de la LED à chaque étape, grâce à un démultiplexeur relié à un compteur modulo 5, déclenché par l'impulsion envoyée lors de chaque envoi par le port série. (voir schéma)

Malheureusement, après avoir implanté le module RS232 simulant l'envoi d'un message sur le port série, et après avoir envoyé ce message via un logiciel annexe, nous nous sommes rendus compte que quelque chose clochait dans notre montage logique. Nous avons alors pris un temps pour tester chaque élément indépendamment : notre compteur fonctionne, le démultiplexeur aussi... Nous sommes donc en phase de recherche de la raison pour laquelle la LED voulue ne s'allume pas lorsque nous le souhaitons. Nous n'abandonnons pas et continuerons nos recherches lors de la prochaine séance.

Séance 3

Partie Informatique

Lors de cette séance, nous avons programmé un code javascript pour notre site web, sur la raspberry. Ce code nous permet ainsi de généré 4 valeurs aléatoires. Ces valeur correspondent chacune à un nombre sur 8 bits, chacun correspondant à une de nos quatre LED de la partie arduino. On initialise ensuite un tableau vide de taille 5, que l'on remplit ensuite de ces valeurs générée aléatoirement. Au final, on obtient un tableau composé d'une série de 5 octets. Ceux-ci vont ensuite être transmit via le port série. Du coté arduino, on utilise la bibliothèque Serial pour récupérer les 5 octets. On a ainsi pu testé un programme qui lit chacun de ces octets et allume la LED correspondante en conséquence.

On a ainsi pu créer la première partie "Communication" de notre site web avec l'arduino. Maintenant, on souhaiterai complexifier cette partie en ajoutant notamment la possibilité pour le joueur de choisir la taille de la séquence à jouer, ou alors modifier la vitesse à chaque fois que le joueur réussissait à effectuer une série correctement. La partie "vitesse" semble plus complexe à transmettre, nous nous sommes donc d'abord penché sur la modification de la taille de la séquence.

Partie FPGA

Réponses aux signaux envoyés sur le port série et traités via FPGA

De ce côté-ci, les 4h ont encore une fois été passées sur la partie FPGA. Nous espérons toujours arriver à transmettre le signal du port série de 5 bits de valeurs 0 ou 1 et faire alors comprendre au FPGA quelle LED allumer ou non. Nous sommes proches d'obtenir un résultat correct mais des erreurs subsistent au niveau du stockage de la valeur en mémoire, puis de la transmission à la LED correspondante. Ainsi, nos résultats s'en trouvent toujours faussés. Nous décidons donc d'observer exactement ce qu'il se passe au niveau des signaux grâce à un oscilloscope. A gauche se trouve le résultat obtenu en envoyant 5 bits de valeur 1 sur le port série (signaux D8 à D12). On constate que 3 des 5 sont bien reçus, et passent à 1 pendant une durée correcte, permettant à la LED de s'allumer. Mais on constate également que parmi les deux signaux restants, l'un ne reçoit rien et l'autre ne passe pas à 1 pendant une durée suffisante pour que la LED correspondante s'allume.

A l'issue de cette séance, nous pensons laisser de côté la partie FPGA. Après avoir passé 8h dessus sans résultat nous permettant de faire avancer le projet, nous pensons qu'il sera plus bénéfique de présenter un résultat sous forme de carte Arduino, mais bien fonctionnel. Nous décidons alors d'orienter nos efforts lors des séances bonus vers l'amélioration de notre programme Arduino et des fonctionnalités du jeu, ainsi que la programmation de la Raspberry et du Websocket.

Séances bonus

Ajout d'un potentiomètre

A la suite des 3 séances de projet, nous avons continué son élaboration au fil du semestre. Plusieurs fonctionnalités lui ont été ajoutées, et plusieurs tests effectués, comme nous allons le décrire ici.

Partie Informatique

De ce côté-ci, alors que notre Raspberry était correctement configuré et envoyait de signaux vers l'Arduino, nous souhaitions maintenant envoyer des informations particulières qui auraient permis à l'utilisateur de jouer au Simon depuis le serveur distant (bouton "jouer", choix, de la durée de la séquence, indication "succès" ou "échec"...). C'est alors qu'un malheureux évènement est venu bousculer nos plans, car notre Raspberry a tout bonnement et simplement planté, sans aucune possibilité de le rallumer. Découragés mais pas démotivés, nous avons alors reçu un nouveau Raspberry qu'il a fallu configurer puis auquel nous avons implanté le Websocket. Le code web étant perdu, nous avons tout de même pu récupérer une version antérieure, enregistrée sur l'ordinateur. Nous l'avons donc modifiée pour envoyer, comme lors de notre premier "succès", une séquence aléatoire de 5 octets correspondant à 5 LED à allumer dans un ordre précis par l'arduino. Après reconfiguration, nous constatons que l'envoi des informations fonctionne, nous pouvons bien lire nos octets sur un terminal, mais ils ne sont plus lus par l'arduino qui n'affiche pas les LED en conséquence. Nous travaillons encore actuellement sur le débug de ce programme, que nous pensons provenir soit du fait que notre code est très différent du précédent (partie modification de la taille de la séquence supprimée), soit du fait que nous avons fortement modifié l'architecture de nos LED.

Partie Arduino

Dans un premier temps, nous décidons de mieux organiser et d'améliorer la lisibilité du programme. Tout était codé d'affilée dans la fonction "loop", et nous avons alors pris le temps de le séparer en différentes fonctions. Ensuite, nous avons l'idée d'un paramètre de jeu qui pourrait être réglable directement par l'utilisateur depuis la breadboard : nous optons pour le choix de la vitesse d'allumage des LED, et ainsi de la séquence. Ainsi, en ajoutant un potentiomètre à notre montage, l'utilisateur peut régler lui-même sa difficulté de jeu, allant d'une LED qui s'allume toutes les 300ms à une LED toutes les 1000ms. Le montage en l'état actuel des choses est alors celui présenté à droite.

Nous pensions donc, à ce stade, faire le reste via communication avec la raspberry PI et les commandes qui seraient alors envoyées. Cependant, comme décrit précédemment, le problème de plantage et de reconfiguration d'une nouvelle Raspberry est arrivé. Arrivant à la fin du projet, et dans l'éventualité où nous ne trouverions pas le temps ou la solution à notre problème pour communiquer avec l'ordinateur, nous avons décidé d'agrémenter encore plus notre code Arduino et d'ajouter des composants, pour que l'on puisse jouer au jeu du Simon juste en alimentant la carte.

Plusieurs améliorations et révisions du code ont alors été mises en place :

  • Pour un meilleur confort de jeu nous avons ajouté le fait que, lorsque c'est au tour de l'utilisateur de reproduire la séquence, la LED correspondant au bouton appuyé s'allume en même temps.
  • L'ajout majeur de ce travail a été l'implémentation d'un écran LCD 16x2 au jeu. Alors, nous pouvons y inscrire diverses informations, pour savoir où l'utilisateur en est de sa partie. Ces informations étaient auparavant transmises via le port série et s'affichaient sur l'écran de l'ordinateur (comme les "SUCCES!" ou "ECHEC", lorsque l'utilisateur avait terminé sa séquence).

En ajoutant l'écran LCD, nous avons utilisé les 6 ports numériques restants sur l'Arduino (les ports 12, 13, 6, 7 et surtout 0 et 1). Un problème est alors apparu car les ports 0 et 1 sont également utilisés pour les liaisons séries en RX et TX. De ce fait, comme la liaison série était initialisée pour indiquer les informations sur l'ordinateur, les caractères affichés sur l'écran LCD étaient loin de ceux souhaités, problème certainement dû à l'usage intensif de cette liaison série. Nous avons alors essayé de fermer la liaison série à chaque fois que nous voulions inscrire des informations sur l'écran LCD (avec serial.end(), puis la rouvrir après (avec serial.begin(9600)) mais cela a vite alourdi le code. De plus, même si cette méthode fonctionnait sur l'écran LCD, l'affichage série sur l'ordinateur perdait énormément en clarté. Nous avons alors décidé de supprimer tout ce qui touchait à la liaison série de notre code (ces lignes ont été mises en commentaires), de façon à n'avoir aucune interférence. De toute manière, celle-ci n'avait plus d'utilité puisque le nouveau but que nous nous sommes fixés est d'avoir un jeu fonctionnel et compréhensible sans avoir besoin d'un ordinateur mais uniquement d'une alimentation.

Schema de câblage de la version finale
Le jeu terminé et operationnel

L'écran LCD indique alors plusieurs informations :

  • Premièrement, la difficulté sélectionnée par l'utilisateur. En fonction de la valeur du potentiomètre et donc de la vitesse d'allumage des LED, l'écran affichera sur sa première ligne "mode DIFFICILE" si les valeurs sont entre 300 et 500ms, "mode MOYEN" si entre 500 et 700ms, et "mode FACILE" si entre 700 et 1000ms.
  • Deuxièmement, un système de niveau a été ajouté, s'incrémentant à chaque fois que l'utilisateur réussit a reproduire des séquences d'affilée. Si il rate, le niveau retombe à 1.

A noter que, malheureusement, aucun critère ne change entre chaque niveau. Nous voulions au départ incrémenter la séquence d'allumage de 1 LED pour chaque niveau mais nous sommes retrouvés face à des erreurs de compilation. En effet, nous avions choisi d'utiliser des tableaux de la taille de durée de la séquence pour mettre la séquence en mémoire et avons donc crée une valeur de type const int au début de notre programme, qui ne peut donc pas être modifiée en cours d'exécution (la valeur par défaut est 5 ici). Des solutions auraient pu être mises en place, telles que l'utilisations de liste contigües ou chaînées plutôt qu'un tableau pour stocker les séquences.

  • Enfin, comme le faisait le port série, en plus d'allumer une LED verte ou rouge en fonction de la réussite du niveau par l'utilisateur, un message "SUCCES" ou "ECHEC" s'affiche en bas à droite de l'écran, et le niveau sera alors changé en conséquence (s'incrémentera ou retombera à 1).

Ci-joints, la photo du montage opérationnel terminé, et une vue schématique du cablâge, ce dernier étant peu clair au premier abord.

Bilan

Vidéo de démonstration

Média:Demo_Simon.mp4

Sur la vidéo, on peut donc voir les différents modules du jeu : la LED s'allumant en fonction de la réussite ou de l'échec de l'utilisateur, les informations de jeu sur l'écran LCD, la difficulté s'incrémentant avec le potard ...

Respect des objectifs

Comme on peut le lire tout au long de ce Wiki, les objectifs finaux sont bien différents de ceux de départ. Des complications et incompréhensions ont fait que nous avons dû faire des choix, de façon à toujours essayer de compenser l'absence d'une fonctionnalité par l'ajout d'une autre. On remarquera alors qu'en étant contraint de laisser de côté la partie FPGA, et en ayant avancé sur la partie Raspberry, mais pas assez pour établir une réelle liaison, nous avons amélioré le projet du jeu de base qui ne consistait qu'en 4 boutons et 4 LED, pour obtenir un "système embarqué" fonctionnel, doté d'un écran et de potentiomètres pour régler des paramètres. On notera également que des améliorations qui avaient été proposées, telles qu'une LED RGB pour indiquer le tour du joueur (nous pensions également à un servo-moteur qui tournerait et pointerait vers le joueur désigné), n'ont pas pu être implémentées à cause d'une autre raison : tous les 13 ports numériques disponibles de l'Ardunio ont été utilisés. Nous avons dû alors faire le choix de ce qui s'avérait le plus utile, et l'écran l'a emporté, du fait qu'il peut indiquer plus d'informations simultanément (et pourrait même, justement indiquer le tour du joueur pour une partie en multijoueurs).

Améliorations possibles

Des améliorations à ce projet sont bien évidemment possibles. Sans reparler de l'implémentation du FPGA ou de la Raspberry, nous pourrions commencer par imprimer en 3D un boitier de jeu, pour un confort évident de jeu. Associé à cela, nous pourrions imprimer des cartes électroniques pour mieux répartir les composants et éviter de tout avoir à serrer et mélanger les câbles sur la Breadboard. De plus, des cartes imprimées nous permettraient peut-être de libérer certains ports de l'Arduino et ainsi implémenter plus de fonctionnalités.

Nous pourrions également transformer ce système simple de 4 boutons, 4 LED en une plateforme multijeux : C'est à dire simplement implémenter d'autres jeux et pouvoir sélectionner le jeu souhaité (qui s'inscrirait alors sur l'écran LCD) via un interrupteur, un potentiomètre ou même un clavier. Nous pensions notamment comme deuxième jeu à un "Tape-Taupe", je de réflexe au cours duquel il faudrait appuyer le plus vite possible sur le bouton correspondant lorsqu'une LED s'allume.

Conclusion

En conclusion, ce projet SC nous a donné l'occasion de découvrir plusieurs champs du milieu des Systèmes Communicants. Pour notre part, c'est surtout l'Arduino que nous avons mis en avant et donc de découvrir les fonctionnalités. Ceci était simplifié par les connaissances en langage C que nous avions déja acquises. Egalement, nous avons eu l'occasion de configurer non pas une, mais deux Raspberry PI, ce qui nous sera certainement fort utile au cours des projets dans les années à venir. Enfin, réaliser ce projet nous a offert l'occasion de s'organiser et répartir les tâches en équipe, et surtout de revoir constamment ses objectifs et priorités en fonction des imprévus et non-fonctionnement de certains aspects.

Dans l'ensemble, ce projet s'est avéré interessant, même si un plus grand nombre de séances, réparties au long du semstre, nous seraient à tous certainement bénéfique. Egalement, quasiment l'intégralité des aspects de ce projet, que ce soit Arduino, FPGA ou Raspberry PI étaient nouveaux pour nous et nous n'avions malheureusement pas eu l'occasion d'avoir de cours dessus. Peut-être que quelques séances d'apprentissages de ces différents systèmes au préalable nous permettraient de les utiliser au mieux au cours de ce projet SC (surtout pour la partie FPGA, qui est selon nous la plus compliquée à appréhender). Enfin, comme beaucoup d'outils étaient nouveaux pour nous, beaucoup de questions étaient posées et beaucoup d'aide devait être apportée, et les tuteurs étaient souvent débordés. Peut-être faudrait-il prévoir plus d'enseignants pour y répondre lors des prochaines éditions.

Annexes

En Annexe, voici une archive comportant le programme Arduino utilisé pour notre jeu, ainsi que le schématic Fritzing : Fichier:Simon.zip