ENIB 2024 : Le cyclone COMUR : Différence entre versions
(→outil et matériel) |
(→étape 7 : finir la maquette) |
||
(77 révisions intermédiaires par 2 utilisateurs non affichées) | |||
Ligne 1 : | Ligne 1 : | ||
Titre de la fiche expérience : | Titre de la fiche expérience : | ||
==Description (résumé)== | ==Description (résumé)== | ||
− | Notre jeu s'appelle "Le cyclone". Le but est simple, appuyer sur le bouton quand la led tournante atteint la led statique sur le cercle de 60 leds. Il y a 5 niveaux de difficultés différentes. La vitesse d'allumage des leds augmente à chaque niveau. Voici une | + | Notre jeu s'appelle "Le cyclone". Le but est simple, appuyer sur le bouton quand la led tournante atteint la led statique sur le cercle de 60 leds. Il y a 5 niveaux de difficultés différentes. La vitesse d'allumage des leds augmente à chaque niveau. Ci-dessous vous verrez une vidéo exemple de notre jeu : |
+ | |||
+ | <html> | ||
+ | <blockquote class="twitter-tweet"><p lang="en" dir="ltr">👉Don't forget to have fun with the kids while doing the project.<br>➡️ Follow us <a href="https://twitter.com/OffiCuteLava?ref_src=twsrc%5Etfw">@officutelava</a>👍<br>➡️ Video by <a href="https://twitter.com/stevenkroon?ref_src=twsrc%5Etfw">@stevenkroon</a> 👏👏<a href="https://twitter.com/hashtag/microcontroller?src=hash&ref_src=twsrc%5Etfw">#microcontroller</a> <a href="https://twitter.com/hashtag/engineers?src=hash&ref_src=twsrc%5Etfw">#engineers</a> <a href="https://twitter.com/hashtag/Electronic?src=hash&ref_src=twsrc%5Etfw">#Electronic</a> <a href="https://twitter.com/hashtag/engineering?src=hash&ref_src=twsrc%5Etfw">#engineering</a> <a href="https://twitter.com/hashtag/technology?src=hash&ref_src=twsrc%5Etfw">#technology</a> <a href="https://twitter.com/hashtag/electronics?src=hash&ref_src=twsrc%5Etfw">#electronics</a> <a href="https://twitter.com/hashtag/diyprojects?src=hash&ref_src=twsrc%5Etfw">#diyprojects</a> <a href="https://twitter.com/hashtag/arduino?src=hash&ref_src=twsrc%5Etfw">#arduino</a> <a href="https://twitter.com/hashtag/arduinoproject?src=hash&ref_src=twsrc%5Etfw">#arduinoproject</a> <a href="https://twitter.com/hashtag/arduinofun?src=hash&ref_src=twsrc%5Etfw">#arduinofun</a> <a href="https://twitter.com/hashtag/kids?src=hash&ref_src=twsrc%5Etfw">#kids</a> <a href="https://twitter.com/hashtag/fun?src=hash&ref_src=twsrc%5Etfw">#fun</a> <a href="https://t.co/JvCprJGtyo">pic.twitter.com/JvCprJGtyo</a></p>— Cute Lava (@OffiCuteLava) <a href="https://twitter.com/OffiCuteLava/status/1223093120054845445?ref_src=twsrc%5Etfw">January 31, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> | ||
+ | </html> | ||
+ | |||
+ | ==Introduction== | ||
+ | |||
+ | Voici une photo de notre groupe : | ||
[[ Fichier:Photo groupe cyclone COMUR.jpeg |400px]] | [[ Fichier:Photo groupe cyclone COMUR.jpeg |400px]] | ||
− | + | Notre groupe est composé de : | |
+ | |||
+ | - Sofiya Debois | ||
+ | |||
+ | - Korao Layo Fatima Nadjad | ||
+ | |||
+ | - Maximin Bourgeais | ||
+ | |||
+ | - Côme Beaudouin | ||
− | + | - Arthur Bernel | |
− | + | - Azad Arbab Chirani | |
− | |||
− | |||
==Outil et matériel== | ==Outil et matériel== | ||
− | == | + | Ici, on va pouvoir retrouver la liste de matériels ainsi que les outils nécessaire à la confection de notre jeu. |
+ | |||
+ | Il nous faut : | ||
+ | |||
+ | - une pochette avec le matériel de base | ||
+ | |||
+ | [[Fichier:Photo matériel cyclone COMUR.jpeg|200px]] | ||
+ | |||
+ | - une carte ESP WROOM 32 | ||
+ | |||
+ | [[Fichier:Arduino cyclone.jpg |200px]] | ||
+ | |||
+ | - des résistances pour arriver à 219 Ohms (il nous faut 2 fois ça) | ||
+ | |||
+ | [[ Fichier:Rési 219Ohm.jpg |200px]] | ||
+ | |||
+ | - des résistances pour arriver à 830 Ohms | ||
+ | |||
+ | [[ Fichier:Rési 830 Ohm.jpg |200px]] | ||
+ | |||
+ | - un buzzer | ||
+ | |||
+ | [[Fichier:Buzzerpassif.jpg |200px]] | ||
+ | |||
+ | - une batterie portative | ||
+ | |||
+ | [[Fichier:Batterieportative.jpg |200px]] | ||
+ | |||
+ | - des câbles | ||
+ | |||
+ | [[Fichier:Câbles.jpg |200px]] | ||
+ | |||
+ | ==Fichiers à joindre== | ||
code, ficher d'impression 3D, de découpe laser ou vinyle, ... | code, ficher d'impression 3D, de découpe laser ou vinyle, ... | ||
===Mettre du code Arduino=== | ===Mettre du code Arduino=== | ||
− | <syntaxhighlight lang="Arduino" line> | + | <syntaxhighlight lang="Arduino" line>//jeu |
− | + | /* | |
− | #include | + | code trouvé sur https://www.hackster.io/mircemk/diy-arduino-cyclone-game-with-ws2812b-led-ring-738c58 |
+ | */ | ||
+ | |||
+ | #include "FastLED.h" //Bibliothèque permettant de gérer les LEDs | ||
+ | #define NUM_LEDS 60 //Le nombre de LEDs sur le ring | ||
+ | #define DATA_PIN 0 //Pin correspondant au ring | ||
+ | #define BUTTON_PIN 2 //Pin du bouton | ||
+ | #define SCORE_PIN 4 //Pin de la bande LED du score | ||
+ | #define SCORE_LEDS 5 //Le nombre de LEDs sur la bande du score | ||
+ | #define BRIGHTNESS 60 //Luminosité des LEDs du jeu | ||
+ | CRGB leds[NUM_LEDS]; //ring LED | ||
+ | CRGB sleds[NUM_LEDS]; //bande LED | ||
+ | |||
+ | byte gameState = 0; //Variable pour suivre l'étape du jeu | ||
+ | int period = 1000; //On instantie une variable qui déterminera la vitesse de déroulement du jeu | ||
+ | unsigned long time_now = 0; //Variable qui garde en mémoire le temps à un instant précis | ||
+ | byte Position = 0; //La position de la LED du joueur | ||
+ | byte level = 0; //Variable qui garde en mémoire le niveau actuel | ||
+ | |||
+ | const byte ledSpeed[5] = {50, 40, 30, 20, 10}; //Liste contenant toutes les vitesses des différents niveaux | ||
+ | |||
+ | bool findRandom = false; //Variable booléenne pour lancer la recherche d'un nouvel objectif à chaque passage de niveau | ||
+ | byte spot = 0; //Variable correspondant à la position de la LED objectif | ||
void setup() { | void setup() { | ||
− | // | + | FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS); |
+ | FastLED.addLeds<WS2812B, SCORE_PIN, GRB>(sleds, SCORE_LEDS); | ||
+ | pinMode(BUTTON_PIN, INPUT_PULLUP); | ||
+ | pinMode(DATA_PIN, OUTPUT); | ||
+ | Serial.begin(9600); | ||
+ | Serial.println("Reset"); | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | FastLED.setBrightness(BRIGHTNESS); //Mise à jour du niveau de luminosité des LEDs | ||
+ | if (gameState == 0) { | ||
+ | fill_rainbow(leds, NUM_LEDS, 0, 20); //2 = longer gradient strip | ||
+ | fill_rainbow(sleds, SCORE_LEDS, 0, 40); //2 = longer gradient strip | ||
+ | |||
+ | if (digitalRead(2) == LOW) { //Bouton appuyé | ||
+ | Position = 0; //On initialise la position du joueur à 0 | ||
+ | findRandom = true; | ||
+ | delay(500); | ||
+ | for (byte i = 0; i < NUM_LEDS; i++) { //On éteint les LEDs du ring progressivement | ||
+ | leds[i].setRGB(0, 0, 0); | ||
+ | delay(40); | ||
+ | FastLED.show(); | ||
+ | tone(5, 400); | ||
+ | } | ||
+ | for (byte i = 0; i < SCORE_LEDS; i++) { //On éteint les LEDs de la bande progressivement | ||
+ | sleds[i].setRGB(0, 0, 0); | ||
+ | delay(100); | ||
+ | FastLED.show(); | ||
+ | tone(5, 400); | ||
+ | } | ||
+ | noTone(5); | ||
+ | gameState = 1; //Passage à la prochaine étape du jeu | ||
+ | } | ||
+ | FastLED.show(); | ||
+ | } | ||
+ | if (gameState == 1) { | ||
+ | period = ledSpeed[0]; | ||
+ | if (millis() > time_now + period) { | ||
+ | time_now = millis(); | ||
+ | if (findRandom) { | ||
+ | spot = random(56) + 3; //Choix de l'objectif aléatoirement | ||
+ | findRandom = false; | ||
+ | } | ||
+ | leds[spot - 1].setRGB(255, 140, 0); //Allumage des LEDs objectif | ||
+ | leds[spot].setRGB(0, 255, 0); | ||
+ | leds[spot + 1].setRGB(255, 110, 0); | ||
+ | sleds[0].setRGB(0, 255, 0); | ||
+ | PlayGame(spot - 1, spot + 1); //Avancement de la LED joueur | ||
+ | } | ||
+ | if (digitalRead(2) == LOW) { | ||
+ | delay(300); | ||
+ | findRandom = false; | ||
+ | if (Position > spot - 1 && Position < spot + 3) { //Vérification de la position du joueur au moment de l'appui | ||
+ | level = gameState; | ||
+ | gameState = 98; | ||
+ | } else { | ||
+ | gameState = 99; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | if (gameState == 2) { | ||
+ | period = 320; | ||
+ | period = ledSpeed[1]; | ||
+ | if (millis() > time_now + period) { | ||
+ | time_now = millis(); | ||
+ | if (findRandom) { | ||
+ | spot = random(56) + 3; | ||
+ | findRandom = false; | ||
+ | } | ||
+ | leds[spot - 1].setRGB(255, 190, 0); | ||
+ | leds[spot].setRGB(0, 255, 0); | ||
+ | leds[spot + 1].setRGB(255, 190, 0); | ||
+ | sleds[1].setRGB(255, 255, 0); | ||
+ | PlayGame(spot - 1, spot + 1); | ||
+ | } | ||
+ | if (digitalRead(2) == LOW) { | ||
+ | delay(300); | ||
+ | if (spot - 1 && Position < spot + 3) { | ||
+ | level = gameState; | ||
+ | gameState = 98; | ||
+ | } else { | ||
+ | gameState = 99; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | if (gameState == 3) { | ||
+ | period = ledSpeed[2]; | ||
+ | if (millis() > time_now + period) { | ||
+ | time_now = millis(); | ||
+ | if (findRandom) { | ||
+ | spot = random(56) + 3; | ||
+ | findRandom = false; | ||
+ | } | ||
+ | leds[spot].setRGB(0, 255, 0); | ||
+ | sleds[2].setRGB(255, 50, 0); | ||
+ | PlayGame(spot, spot); | ||
+ | } | ||
+ | if (digitalRead(2) == LOW) { | ||
+ | delay(300); | ||
+ | if (Position == spot+1) { | ||
+ | level = gameState; | ||
+ | gameState = 98; | ||
+ | } else { | ||
+ | gameState = 99; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | if (gameState == 4) { | ||
+ | period = ledSpeed[3]; | ||
+ | if (millis() > time_now + period) { | ||
+ | time_now = millis(); | ||
+ | if (findRandom) { | ||
+ | spot = random(56) + 3; | ||
+ | findRandom = false; | ||
+ | } | ||
+ | leds[spot].setRGB(0, 255, 0); | ||
+ | sleds[3].setRGB(255, 0, 0); | ||
+ | PlayGame(spot, spot); | ||
+ | } | ||
+ | if (digitalRead(2) == LOW) { | ||
+ | delay(300); | ||
+ | if (Position == spot+1) { | ||
+ | level = gameState; | ||
+ | gameState = 98; | ||
+ | } else { | ||
+ | gameState = 99; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | if (gameState == 5) { | ||
+ | period = ledSpeed[4]; | ||
+ | if (millis() > time_now + period) { | ||
+ | time_now = millis(); | ||
+ | if (findRandom) { | ||
+ | spot = random(56) + 3; | ||
+ | findRandom = false; | ||
+ | } | ||
+ | leds[spot].setRGB(0, 255, 0); | ||
+ | sleds[4].setRGB(0, 50, 255); | ||
+ | PlayGame(spot , spot); | ||
+ | } | ||
+ | if (digitalRead(2) == LOW) { | ||
+ | delay(300); | ||
+ | if (Position == spot+1) { | ||
+ | level = gameState; | ||
+ | gameState = 98; | ||
+ | } else { | ||
+ | gameState = 99; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | if (gameState == 98) { | ||
+ | winner(); | ||
+ | } | ||
+ | if (gameState == 99) { | ||
+ | loser(); | ||
+ | } | ||
} | } | ||
+ | void PlayGame(byte bound1, byte bound2) { | ||
+ | leds[Position].setRGB(255, 0, 0); //on allume la led à la position du joueur | ||
+ | if (Position < bound1 + 1 || Position > bound2 + 1) { | ||
+ | leds[Position - 1].setRGB(0, 0, 0); | ||
+ | } | ||
+ | FastLED.show(); | ||
+ | Position++; | ||
+ | if (Position >= NUM_LEDS) { | ||
+ | leds[Position - 1].setRGB(0, 0, 0); | ||
+ | Position = 0; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | void winner() { | ||
+ | tone(5, 720); | ||
+ | delay(240); | ||
+ | noTone(5); | ||
+ | for (byte i = 0; i < 3; i++) { | ||
+ | for (byte j = 0; j < NUM_LEDS; j++) { | ||
+ | leds[j].setRGB(0, 255, 0); | ||
+ | } | ||
+ | FastLED.show(); | ||
+ | delay(500); | ||
+ | clearLEDS(); | ||
+ | FastLED.show(); | ||
+ | delay(500); | ||
+ | |||
+ | } | ||
+ | findRandom = true; | ||
+ | Position = 0; | ||
− | void | + | gameState = level + 1; |
− | + | if (gameState > 5) { | |
+ | winAll(); | ||
+ | } | ||
+ | } | ||
+ | void loser() { | ||
+ | for (byte i = 0; i < 3; i++) { | ||
+ | for (byte j = 0; j < NUM_LEDS; j++) { | ||
+ | leds[j].setRGB(255, 0, 0); | ||
+ | } | ||
+ | FastLED.show(); | ||
+ | tone(5, 280); | ||
+ | delay(500); | ||
+ | clearLEDS(); | ||
+ | noTone(5); | ||
+ | FastLED.show(); | ||
+ | delay(500); | ||
+ | } | ||
+ | gameState = 0; | ||
+ | } | ||
+ | void clearLEDS() { | ||
+ | for (byte k = 0; k < NUM_LEDS; k++) { | ||
+ | leds[k].setRGB(0, 0, 0); | ||
+ | } | ||
+ | } | ||
+ | void winAll(){ | ||
+ | gameState = 0; | ||
+ | } | ||
+ | void freq(){ | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | == | + | ==Étapes de fabrication== |
− | indiquer | + | |
+ | On va indiquer ici toutes les étapes de la création du prototype à la version finale de notre projet (avec des photos, dessins...). | ||
+ | |||
+ | ===étape 1 : comprendre le fonctionnement du jeu=== | ||
+ | |||
+ | En allant sur le [https://www.wiki.lesfabriquesduponant.net/index.php?title=Jeux_num%C3%A9riques_utilisant_des_leds#Le_Cyclone/ wiki] de la fabrique du ponant, vous pouvez retrouver des vidéos montrant le fonctionnement du jeu (voir la vidéo dessus). On retrouve aussi un prototype de code qu'on va modifier pour qu'il fonctionne avec notre matériel. | ||
+ | |||
+ | ===étape 2 : réunir le matériel nécessaire=== | ||
+ | |||
+ | Au niveau du matériel, dès le début, vous avez une pochette avec à l'intérieur, une ring avec 60 leds, une bande de 5 leds, un transistor, une plaquette pour les liaisons entre les résistances et les câbles et un bouton. | ||
+ | Il a fallu qu'on aille chercher en plus : | ||
+ | |||
+ | - une carte ESP WROOM 32 | ||
+ | |||
+ | - des câbles | ||
+ | |||
+ | - une résistance 830 Ohms (on l'a décomposé en une résistance de 680 Ohms et une résistance de 150 Ohms) | ||
+ | |||
+ | - deux résistances de 219 Ohms (on les a décomposé en trois résistance de 68 ohms et une résistance de 15 Ohms) | ||
+ | |||
+ | - un buzzer | ||
− | ===étape | + | - une batterie portative |
− | ===étape | + | |
− | ===étape ...=== | + | ===étape 3 : dessiner le design sur papier=== |
− | === | + | |
− | + | Avant de faire la découpe du carton, on a dessiné un design sur papier. | |
+ | |||
+ | [[Fichier:Dessin1.jpg|200px]] [[Fichier:Dessin2.jpg|200px]] | ||
+ | |||
+ | ===étape 4 : découper le socle=== | ||
+ | |||
+ | On a décidé de faire notre jeu en carton. Voici les découpes qu'on a réalisé : | ||
+ | |||
+ | [[Fichier:Découpe carton.jpg|200px]] [[Fichier:Découpe.jpg|200px]] | ||
+ | |||
+ | On a rajouté cette découpe en noir pour la customisation de notre jeu. | ||
+ | |||
+ | ===étape 5 : faire le câblage sur Tinkercad=== | ||
+ | |||
+ | Avant de réaliser notre câblage avec des vrais composants, nous avons réalisé un câblage sur Tinkercad. | ||
+ | |||
+ | [[Fichier:Cablagetc.png|400px]] [[Fichier:Image rési tc.png|324px]] | ||
+ | |||
+ | L'image à droite représente les 2 résistances sur l'image à gauche (219 Ohms en 4 résistances). | ||
+ | |||
+ | ===étape 6 : réaliser le câblage et tester le code=== | ||
+ | |||
+ | On réalise le câblage final pour voir si tout fonctionne bien (le code, le téléversement sur la carte...). | ||
+ | |||
+ | [[Fichier:Câblagefin.jpg|200px]] | ||
+ | |||
+ | ===étape 7 : finir la maquette=== | ||
+ | |||
+ | Voici des photos du résultat final de notre jeu "Le cyclone" : | ||
+ | |||
+ | [[Fichier:Pf1.jpg |200px]] [[Fichier:Pf2.jpg |200px]] | ||
+ | |||
+ | ===Troubleshouting=== | ||
+ | |||
+ | Le premier problème qu'on a rencontré est au niveau du code. Au lieu d'avoir le jeu du cyclone, on a toute les leds qui s'allument ce qui n'est pas normal (voir photo). | ||
+ | |||
+ | [[Fichier:Erreurcâblage.jpg|300px]] | ||
+ | |||
+ | Le problème venait des entrées sur le code car nous n'avons pas la même carte que le code qu'on nous a donné. | ||
+ | |||
+ | <syntaxhighlight lang="Arduino" line>#include "FastLED.h" //Bibliothèque permettant de gérer les LEDs | ||
+ | #define NUM_LEDS 60 //Le nombre de LEDs sur le ring | ||
+ | #define DATA_PIN 0 //Pin correspondant au ring | ||
+ | #define BUTTON_PIN 2 //Pin du bouton | ||
+ | #define SCORE_PIN 4 //Pin de la bande LED du score | ||
+ | #define SCORE_LEDS 5 //Le nombre de LEDs sur la bande du score | ||
+ | #define BRIGHTNESS 10 //Luminosité des LEDs du jeu | ||
+ | CRGB leds[NUM_LEDS]; //ring LED | ||
+ | CRGB sleds[NUM_LEDS]; //bande LED | ||
+ | |||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | Le second problème était un problème de temps. A chaque fois qu'on passait au niveau suivant, on devait attendre une trentaine de secondes, ce qui est vachement long. | ||
+ | |||
+ | Le problème venait entre autre du buzzer. Notre jeu a normalement besoin d'un buzzer passif et notre programme doit générer une fréquence pour ce buzzer. Elle était créé par la fonction arduino "tone", qui ralentissait énormément notre programme. On a donc pris un haut parleur passif qui génère des fréquences à différents moments clés du jeu (niveau passé, lorsqu'on a perdu...). | ||
==Sources et documentation complémentaire== | ==Sources et documentation complémentaire== | ||
− | + | [[Media:Cyclone.svg|Téléchargez le fichier de découpe]] | |
==ne pas modifier sous cette ligne== | ==ne pas modifier sous cette ligne== | ||
[[Catégorie:Enib2024]] | [[Catégorie:Enib2024]] |
Version actuelle datée du 25 janvier 2024 à 14:56
Titre de la fiche expérience :
Sommaire
- 1 Description (résumé)
- 2 Introduction
- 3 Outil et matériel
- 4 Fichiers à joindre
- 5 Étapes de fabrication
- 5.1 étape 1 : comprendre le fonctionnement du jeu
- 5.2 étape 2 : réunir le matériel nécessaire
- 5.3 étape 3 : dessiner le design sur papier
- 5.4 étape 4 : découper le socle
- 5.5 étape 5 : faire le câblage sur Tinkercad
- 5.6 étape 6 : réaliser le câblage et tester le code
- 5.7 étape 7 : finir la maquette
- 5.8 Troubleshouting
- 6 Sources et documentation complémentaire
- 7 ne pas modifier sous cette ligne
Description (résumé)
Notre jeu s'appelle "Le cyclone". Le but est simple, appuyer sur le bouton quand la led tournante atteint la led statique sur le cercle de 60 leds. Il y a 5 niveaux de difficultés différentes. La vitesse d'allumage des leds augmente à chaque niveau. Ci-dessous vous verrez une vidéo exemple de notre jeu :
👉Don't forget to have fun with the kids while doing the project.
— Cute Lava (@OffiCuteLava) January 31, 2020
➡️ Follow us @officutelava👍
➡️ Video by @stevenkroon 👏👏#microcontroller #engineers #Electronic #engineering #technology #electronics #diyprojects #arduino #arduinoproject #arduinofun #kids #fun pic.twitter.com/JvCprJGtyo
Introduction
Voici une photo de notre groupe :
Notre groupe est composé de :
- Sofiya Debois
- Korao Layo Fatima Nadjad
- Maximin Bourgeais
- Côme Beaudouin
- Arthur Bernel
- Azad Arbab Chirani
Outil et matériel
Ici, on va pouvoir retrouver la liste de matériels ainsi que les outils nécessaire à la confection de notre jeu.
Il nous faut :
- une pochette avec le matériel de base
- une carte ESP WROOM 32
- des résistances pour arriver à 219 Ohms (il nous faut 2 fois ça)
- des résistances pour arriver à 830 Ohms
- un buzzer
- une batterie portative
- des câbles
Fichiers à joindre
code, ficher d'impression 3D, de découpe laser ou vinyle, ...
Mettre du code Arduino
1 //jeu
2 /*
3 code trouvé sur https://www.hackster.io/mircemk/diy-arduino-cyclone-game-with-ws2812b-led-ring-738c58
4 */
5
6 #include "FastLED.h" //Bibliothèque permettant de gérer les LEDs
7 #define NUM_LEDS 60 //Le nombre de LEDs sur le ring
8 #define DATA_PIN 0 //Pin correspondant au ring
9 #define BUTTON_PIN 2 //Pin du bouton
10 #define SCORE_PIN 4 //Pin de la bande LED du score
11 #define SCORE_LEDS 5 //Le nombre de LEDs sur la bande du score
12 #define BRIGHTNESS 60 //Luminosité des LEDs du jeu
13 CRGB leds[NUM_LEDS]; //ring LED
14 CRGB sleds[NUM_LEDS]; //bande LED
15
16 byte gameState = 0; //Variable pour suivre l'étape du jeu
17 int period = 1000; //On instantie une variable qui déterminera la vitesse de déroulement du jeu
18 unsigned long time_now = 0; //Variable qui garde en mémoire le temps à un instant précis
19 byte Position = 0; //La position de la LED du joueur
20 byte level = 0; //Variable qui garde en mémoire le niveau actuel
21
22 const byte ledSpeed[5] = {50, 40, 30, 20, 10}; //Liste contenant toutes les vitesses des différents niveaux
23
24 bool findRandom = false; //Variable booléenne pour lancer la recherche d'un nouvel objectif à chaque passage de niveau
25 byte spot = 0; //Variable correspondant à la position de la LED objectif
26
27 void setup() {
28 FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
29 FastLED.addLeds<WS2812B, SCORE_PIN, GRB>(sleds, SCORE_LEDS);
30 pinMode(BUTTON_PIN, INPUT_PULLUP);
31 pinMode(DATA_PIN, OUTPUT);
32 Serial.begin(9600);
33 Serial.println("Reset");
34 }
35
36 void loop() {
37 FastLED.setBrightness(BRIGHTNESS); //Mise à jour du niveau de luminosité des LEDs
38 if (gameState == 0) {
39 fill_rainbow(leds, NUM_LEDS, 0, 20); //2 = longer gradient strip
40 fill_rainbow(sleds, SCORE_LEDS, 0, 40); //2 = longer gradient strip
41
42 if (digitalRead(2) == LOW) { //Bouton appuyé
43 Position = 0; //On initialise la position du joueur à 0
44 findRandom = true;
45 delay(500);
46 for (byte i = 0; i < NUM_LEDS; i++) { //On éteint les LEDs du ring progressivement
47 leds[i].setRGB(0, 0, 0);
48 delay(40);
49 FastLED.show();
50 tone(5, 400);
51 }
52 for (byte i = 0; i < SCORE_LEDS; i++) { //On éteint les LEDs de la bande progressivement
53 sleds[i].setRGB(0, 0, 0);
54 delay(100);
55 FastLED.show();
56 tone(5, 400);
57 }
58 noTone(5);
59 gameState = 1; //Passage à la prochaine étape du jeu
60 }
61 FastLED.show();
62 }
63
64 if (gameState == 1) {
65 period = ledSpeed[0];
66 if (millis() > time_now + period) {
67 time_now = millis();
68 if (findRandom) {
69 spot = random(56) + 3; //Choix de l'objectif aléatoirement
70 findRandom = false;
71 }
72 leds[spot - 1].setRGB(255, 140, 0); //Allumage des LEDs objectif
73 leds[spot].setRGB(0, 255, 0);
74 leds[spot + 1].setRGB(255, 110, 0);
75 sleds[0].setRGB(0, 255, 0);
76 PlayGame(spot - 1, spot + 1); //Avancement de la LED joueur
77 }
78 if (digitalRead(2) == LOW) {
79 delay(300);
80 findRandom = false;
81 if (Position > spot - 1 && Position < spot + 3) { //Vérification de la position du joueur au moment de l'appui
82 level = gameState;
83 gameState = 98;
84 } else {
85 gameState = 99;
86 }
87 }
88 }
89 if (gameState == 2) {
90 period = 320;
91 period = ledSpeed[1];
92 if (millis() > time_now + period) {
93 time_now = millis();
94 if (findRandom) {
95 spot = random(56) + 3;
96 findRandom = false;
97 }
98 leds[spot - 1].setRGB(255, 190, 0);
99 leds[spot].setRGB(0, 255, 0);
100 leds[spot + 1].setRGB(255, 190, 0);
101 sleds[1].setRGB(255, 255, 0);
102 PlayGame(spot - 1, spot + 1);
103 }
104 if (digitalRead(2) == LOW) {
105 delay(300);
106 if (spot - 1 && Position < spot + 3) {
107 level = gameState;
108 gameState = 98;
109 } else {
110 gameState = 99;
111 }
112 }
113 }
114 if (gameState == 3) {
115 period = ledSpeed[2];
116 if (millis() > time_now + period) {
117 time_now = millis();
118 if (findRandom) {
119 spot = random(56) + 3;
120 findRandom = false;
121 }
122 leds[spot].setRGB(0, 255, 0);
123 sleds[2].setRGB(255, 50, 0);
124 PlayGame(spot, spot);
125 }
126 if (digitalRead(2) == LOW) {
127 delay(300);
128 if (Position == spot+1) {
129 level = gameState;
130 gameState = 98;
131 } else {
132 gameState = 99;
133 }
134 }
135 }
136 if (gameState == 4) {
137 period = ledSpeed[3];
138 if (millis() > time_now + period) {
139 time_now = millis();
140 if (findRandom) {
141 spot = random(56) + 3;
142 findRandom = false;
143 }
144 leds[spot].setRGB(0, 255, 0);
145 sleds[3].setRGB(255, 0, 0);
146 PlayGame(spot, spot);
147 }
148 if (digitalRead(2) == LOW) {
149 delay(300);
150 if (Position == spot+1) {
151 level = gameState;
152 gameState = 98;
153 } else {
154 gameState = 99;
155 }
156 }
157 }
158
159 if (gameState == 5) {
160 period = ledSpeed[4];
161 if (millis() > time_now + period) {
162 time_now = millis();
163 if (findRandom) {
164 spot = random(56) + 3;
165 findRandom = false;
166 }
167 leds[spot].setRGB(0, 255, 0);
168 sleds[4].setRGB(0, 50, 255);
169 PlayGame(spot , spot);
170 }
171 if (digitalRead(2) == LOW) {
172 delay(300);
173 if (Position == spot+1) {
174 level = gameState;
175 gameState = 98;
176 } else {
177 gameState = 99;
178 }
179 }
180 }
181
182 if (gameState == 98) {
183 winner();
184 }
185 if (gameState == 99) {
186 loser();
187 }
188 }
189 void PlayGame(byte bound1, byte bound2) {
190 leds[Position].setRGB(255, 0, 0); //on allume la led à la position du joueur
191 if (Position < bound1 + 1 || Position > bound2 + 1) {
192 leds[Position - 1].setRGB(0, 0, 0);
193 }
194 FastLED.show();
195 Position++;
196 if (Position >= NUM_LEDS) {
197 leds[Position - 1].setRGB(0, 0, 0);
198 Position = 0;
199 }
200 }
201
202 void winner() {
203 tone(5, 720);
204 delay(240);
205 noTone(5);
206 for (byte i = 0; i < 3; i++) {
207 for (byte j = 0; j < NUM_LEDS; j++) {
208 leds[j].setRGB(0, 255, 0);
209 }
210 FastLED.show();
211 delay(500);
212 clearLEDS();
213 FastLED.show();
214 delay(500);
215
216 }
217 findRandom = true;
218 Position = 0;
219
220 gameState = level + 1;
221 if (gameState > 5) {
222 winAll();
223 }
224 }
225 void loser() {
226 for (byte i = 0; i < 3; i++) {
227 for (byte j = 0; j < NUM_LEDS; j++) {
228 leds[j].setRGB(255, 0, 0);
229 }
230 FastLED.show();
231 tone(5, 280);
232 delay(500);
233 clearLEDS();
234 noTone(5);
235 FastLED.show();
236 delay(500);
237 }
238 gameState = 0;
239 }
240 void clearLEDS() {
241 for (byte k = 0; k < NUM_LEDS; k++) {
242 leds[k].setRGB(0, 0, 0);
243 }
244 }
245 void winAll(){
246 gameState = 0;
247 }
248
249 void freq(){
250 }
Étapes de fabrication
On va indiquer ici toutes les étapes de la création du prototype à la version finale de notre projet (avec des photos, dessins...).
étape 1 : comprendre le fonctionnement du jeu
En allant sur le wiki de la fabrique du ponant, vous pouvez retrouver des vidéos montrant le fonctionnement du jeu (voir la vidéo dessus). On retrouve aussi un prototype de code qu'on va modifier pour qu'il fonctionne avec notre matériel.
étape 2 : réunir le matériel nécessaire
Au niveau du matériel, dès le début, vous avez une pochette avec à l'intérieur, une ring avec 60 leds, une bande de 5 leds, un transistor, une plaquette pour les liaisons entre les résistances et les câbles et un bouton. Il a fallu qu'on aille chercher en plus :
- une carte ESP WROOM 32
- des câbles
- une résistance 830 Ohms (on l'a décomposé en une résistance de 680 Ohms et une résistance de 150 Ohms)
- deux résistances de 219 Ohms (on les a décomposé en trois résistance de 68 ohms et une résistance de 15 Ohms)
- un buzzer
- une batterie portative
étape 3 : dessiner le design sur papier
Avant de faire la découpe du carton, on a dessiné un design sur papier.
étape 4 : découper le socle
On a décidé de faire notre jeu en carton. Voici les découpes qu'on a réalisé :
On a rajouté cette découpe en noir pour la customisation de notre jeu.
étape 5 : faire le câblage sur Tinkercad
Avant de réaliser notre câblage avec des vrais composants, nous avons réalisé un câblage sur Tinkercad.
L'image à droite représente les 2 résistances sur l'image à gauche (219 Ohms en 4 résistances).
étape 6 : réaliser le câblage et tester le code
On réalise le câblage final pour voir si tout fonctionne bien (le code, le téléversement sur la carte...).
étape 7 : finir la maquette
Voici des photos du résultat final de notre jeu "Le cyclone" :
Troubleshouting
Le premier problème qu'on a rencontré est au niveau du code. Au lieu d'avoir le jeu du cyclone, on a toute les leds qui s'allument ce qui n'est pas normal (voir photo).
Le problème venait des entrées sur le code car nous n'avons pas la même carte que le code qu'on nous a donné.
1 #include "FastLED.h" //Bibliothèque permettant de gérer les LEDs
2 #define NUM_LEDS 60 //Le nombre de LEDs sur le ring
3 #define DATA_PIN 0 //Pin correspondant au ring
4 #define BUTTON_PIN 2 //Pin du bouton
5 #define SCORE_PIN 4 //Pin de la bande LED du score
6 #define SCORE_LEDS 5 //Le nombre de LEDs sur la bande du score
7 #define BRIGHTNESS 10 //Luminosité des LEDs du jeu
8 CRGB leds[NUM_LEDS]; //ring LED
9 CRGB sleds[NUM_LEDS]; //bande LED
Le second problème était un problème de temps. A chaque fois qu'on passait au niveau suivant, on devait attendre une trentaine de secondes, ce qui est vachement long.
Le problème venait entre autre du buzzer. Notre jeu a normalement besoin d'un buzzer passif et notre programme doit générer une fréquence pour ce buzzer. Elle était créé par la fonction arduino "tone", qui ralentissait énormément notre programme. On a donc pris un haut parleur passif qui génère des fréquences à différents moments clés du jeu (niveau passé, lorsqu'on a perdu...).
Sources et documentation complémentaire
Téléchargez le fichier de découpe