LED Arcade
Un Pong maison sur matrice LED, joué sur enceinte de voiture
L'idée
Faire un Pong sans PC et sans écran classique. Juste un Arduino, une bande LED adressable repliée en matrice pour servir d’écran, et une vieille enceinte de voiture branchée sur une broche pour le son. Tout le code embarqué sur la carte, qui démarre toute seule une fois alimentée.
Pong se prête bien à l’exercice : deux raquettes, une balle, des collisions simples, une logique qui tient dans la mémoire d’un Arduino sans forcer. Le low-tech n’est pas un compromis sur le gameplay, c’est ce qui le rend possible.
On était trois sur le projet. J’ai pris toute la partie code Arduino, en particulier le morceau le plus tendu côté timing : faire cohabiter le rendu de l’image et la sortie audio sur le même cerveau.
Le matériel
Le côté low-tech était assumé dès le départ. Sans Raspberry Pi, sans carte son ni écran, on n’utilise que ce qu’on peut brancher directement sur un Arduino.
Le montage tient en trois éléments.
- un Arduino comme cerveau, avec tout le code en C/C++ embarqué
- une bande LED adressable repliée pour faire une matrice, c’est l’écran sur lequel on rend la balle, les raquettes et le score
- une vieille enceinte de voiture pour la sortie audio, attaquée par un signal carré sur une broche
Mono-thread et interruptions
C’est le morceau qui m’a pris le plus de temps, à cause du conflit de timing entre la bande LED et l’audio. L’Arduino est mono-thread : tout ce qui doit tourner en parallèle de la boucle principale doit passer par une interruption matérielle.
Pour le rafraîchissement de l’image, j’ai fait simple. Dans la boucle principale, j’accumule le delta time dans une variable, et un if déclenche le refresh quand on atteint le seuil, avant de remettre la variable à zéro. Pas besoin d’interruption pour ça.
Pour l’audio, c’est différent. Chaque note est un signal carré à une fréquence précise sur la broche enceinte, et garder cette fréquence stable demande une interruption matérielle qui toggle le pin à intervalles réguliers, sans dépendre de ce que fait la boucle.
Le problème vient du protocole d’envoi des données aux bandes LED adressables, très sensible au timing. Si une interruption tombe au milieu de la trame, le signal est corrompu et les LEDs partent en sucette. Je désactive donc les interruptions pendant le refresh, je pousse les pixels, puis je réarme l’interruption audio sur la note suivante de la séquence.
Ça a trois conséquences.
- la “musique” du jeu est découpée en notes, chacune jouant entre deux refresh de frame
- le tempo est implicitement lié au framerate du jeu
- pas de désynchro, le son redémarre juste après chaque refresh
Le rendu sonore n’a pas la richesse d’une vraie carte son, mais c’est exactement ce qu’on voulait : un grain de signal carré qui colle à l’esthétique LED, et un beep à chaque rebond de la balle qui passe juste.