ENIB 2024 : Le Cyclone Breton
Titre de la fiche expérience :
Sommaire
description
Nous sommes 5 élèves ingénieurs de 3ème année à l'ENIB : Thomas Mauger, Gregory Jourdain, Benjamin Le Corre, Romaric Hubert, et Martin Candoni
Dans le cadre de l'inter-semestre 3 à l'ENIB, nous avons fait, lors d'un Hackathon, le jeu du cyclone (appelé ici "Le cyclone Breton").
Le but du jeu est d'appuyer sur le bouton quand la led verte (celle qui tourne autour du cercle) est au même endroit que la zone à atteindre (celle en rouge sur le cercle).
Il y a 5 niveaux différents, avec une musique de victoire et une musique de défaite.
Introduction
éventuelle vidéo
outil et matériel
Outils :
- Fer à souder pour l’étain
- Scie
- Pistolet à colle
- Imprimante 3D (facultatif)
- Découpeuse laser (facultatif)
Matériel :
1 Arduino-Nano
1 Anneau WS2812 avec 60 LED
1 Bouton-poussoir
1 Transistor à usage général NPN
1 Plaque labdec*
25 fils électriques
1 Avertisseur sonore
2 Résistance 220 ohms
1 Résistance à trou traversant, 820 ohm
1 Batterie portable (5 Volts, 3 Ampères)
Bobine d'étain
Colle
fichiers à joindre
code, ficher d'impression 3D, de découpe laser ou vinyle, ...
Code Arduino
1
2 //----------------------Variables----------------------
3
4 #include "FastLED.h"
5 #define NUM_LEDS 60 //on utilise 60 leds
6 #define DATA_PIN A0
7 #define SCORE_PIN 6
8 #define SCORE_LEDS 6
9 #define BRIGHTNESS 30 //luminosite de la led
10 CRGB leds[NUM_LEDS]; //variable constante leds
11 CRGB sleds[NUM_LEDS]; //variable constante score leds
12
13 bool reachedEnd = false;
14
15 byte gameState = 0; //niveau du jeu
16 //byte ledSpeed = 0;
17 int period = 1000;
18 unsigned long time_now = 0;
19 byte Position = 0; //position de la led
20 byte level = 0;
21
22 const byte ledSpeed[6] = {50, 40, 30, 20, 14, 7}; //differentes vitesses de la led rouge
23
24 //Debounce
25 bool findRandom = false; //Indique si une nouvelle position aléatoire doit être trouvée
26 byte spot = 0; //On y stocke la position aleatoire
27
28 //-----------------------------------------------------
29
30 void setup() {
31 // put your setup code here, to run once:
32 FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS); //configure la bibliothèque FastLED pour utiliser des LEDs de type WS2812B (ou compatibles) avec la broche DATA_PIN.
33 //Les LEDs sont déclarées dans le tableau leds et le nombre total de LEDs est spécifié par NUM_LEDS
34
35 FastLED.addLeds<WS2812B, SCORE_PIN, GRB>(sleds, SCORE_LEDS);
36 pinMode(A3, INPUT_PULLUP); //Configure la broche A3 en mode d'entrée avec résistance de tirage vers le haut (INPUT_PULLUP)
37 Serial.begin(9600);// Initialise la communication série avec une vitesse de transmission de 9600 bauds.
38 //Cela permet de communiquer avec le moniteur série de l'IDE Arduino pour déboguer et afficher des informations pendant l'exécution du programme.
39 Serial.println("Reset"); //Envoie le message "Reset" via la communication série.
40 //Cela peut être utile pour signaler le redémarrage du microcontrôleur ou pour des fins de débogage.
41 }
42
43 void loop() {
44 // put your main code here, to run repeatedly:
45 FastLED.setBrightness(BRIGHTNESS );
46 if (gameState == 0) {
47
48 fill_rainbow(leds, NUM_LEDS, 0, 20); //2 = longer gradient strip
49 fill_rainbow(sleds, SCORE_LEDS, 0, 40); //2 = longer gradient strip
50
51 if (digitalRead(A3) == LOW) { //on vient lire la broche A3, si c'est en LOW (bas), on exécute le code ci-dessous
52 Position = 0;
53 findRandom = true;
54 delay(500); //fait une pause de 500 millisecondes
55 for (byte i = 0; i < NUM_LEDS; i++) {
56 leds[i].setRGB(0, 0, 0); //on eteint toutes les leds
57 delay(40);
58 FastLED.show(); //Met à jour l'affichage pour refléter les changements sur les leds.
59 int thisPitch = map (i, 60, 0, 100, 1500); //Utilise la fonction map pour convertir la valeur de i d'une plage de 60 à 0 en une plage de 100 à 1500. Cette valeur est utilisée comme fréquence pour générer un ton.
60 //tone(9, thisPitch,120); //Genere une note sur la broche 9, à la frequence thisPitch (en Hz) pendant 120 millisecondes
61 }
62 for (byte i = 0; i < SCORE_LEDS; i++) {
63 sleds[i].setRGB(0, 0, 0); //eteindre toutes les leds de score
64 delay(100);
65 FastLED.show();
66 }
67 gameState = 1; //passer au niveau 1
68 }
69 FastLED.show();
70 }
71 if (gameState == 1) {
72 period = ledSpeed[0];
73 if (millis() > time_now + period) {
74 time_now = millis();
75 if (findRandom) {
76 spot = random(56) + 3;
77 findRandom = false;
78 }
79 leds[spot - 1].setRGB(255, 140, 0);
80 leds[spot].setRGB(0, 255, 0);
81 leds[spot + 1].setRGB(255, 110, 0);
82 sleds[0].setRGB(0, 255, 0);
83 PlayGame(spot - 1, spot + 1);
84 }
85 if (digitalRead(A3) == LOW) {
86 delay(300);
87 findRandom = false;
88 if (Position > spot - 1 && Position < spot + 3) {
89 level = gameState;
90 gameState = 98;
91 } else {
92 gameState = 99;
93 }
94 }
95 }
96 if (gameState == 2) {
97 // period = 320;
98 period = ledSpeed[1];
99 if (millis() > time_now + period) {
100 time_now = millis();
101 if (findRandom) {
102 spot = random(56) + 3;
103 findRandom = false;
104 }
105 leds[spot - 1].setRGB(255, 190, 0);
106 leds[spot].setRGB(0, 255, 0);
107 leds[spot + 1].setRGB(255, 190, 0);
108 sleds[1].setRGB(255, 255, 0);
109 PlayGame(spot - 1, spot + 1);
110 }
111 if (digitalRead(A3) == LOW) {
112 delay(300);
113 if (spot - 1 && Position < spot + 3) {
114 level = gameState;
115 gameState = 98;
116 } else {
117 gameState = 99;
118 }
119 }
120 }
121 if (gameState == 3) {
122 period = ledSpeed[2];
123 if (millis() > time_now + period) {
124 time_now = millis();
125 if (findRandom) {
126 spot = random(56) + 3;
127 findRandom = false;
128 }
129 leds[spot].setRGB(0, 255, 0);
130 sleds[2].setRGB(255, 50, 0);
131 PlayGame(spot, spot);
132 }
133 if (digitalRead(A3) == LOW) {
134 delay(300);
135 if (Position == spot+1) {
136
137 level = gameState;
138 gameState = 98;
139 } else {
140 gameState = 99;
141 }
142 }
143 }
144 if (gameState == 4) {
145 period = ledSpeed[3];
146 if (millis() > time_now + period) {
147 time_now = millis();
148 if (findRandom) {
149 spot = random(56) + 3;
150 findRandom = false;
151 }
152 leds[spot].setRGB(0, 255, 0);
153 sleds[3].setRGB(255, 0, 0);
154 PlayGame(spot, spot);
155 }
156 if (digitalRead(A3) == LOW) {
157 delay(300);
158 if (Position == spot+1) {
159 level = gameState;
160 gameState = 98;
161 } else {
162 gameState = 99;
163 }
164 }
165 }
166
167 if (gameState == 5) {
168 period = ledSpeed[4];
169 if (millis() > time_now + period) {
170 time_now = millis();
171 if (findRandom) {
172 spot = random(56) + 3;
173 findRandom = false;
174 }
175 leds[spot].setRGB(0, 255, 0);
176 sleds[4].setRGB(0, 150, 255);
177 PlayGame(spot , spot);
178 }
179 if (digitalRead(A3) == LOW) {
180 delay(300);
181 if (Position == spot+1) {
182 level = gameState;
183 gameState = 98;
184 } else {
185 gameState = 99;
186 }
187 }
188 }
189
190
191 if (gameState == 98) {
192 winner();
193 }
194 if (gameState == 99) {
195 loser();
196 }
197 }
198 void PlayGame(byte bound1, byte bound2) {
199 leds[Position].setRGB(255, 0, 0); //Allume la LED à la position actuelle (Position) avec une couleur rouge
200 if (Position < bound1 + 1 || Position > bound2 + 1) { //Cette condition vérifie si la position actuelle est en dehors des limites spécifiées par bound1 et bound2.
201 //Si la position est inférieure à bound1 + 1 ou supérieure à bound2 + 1, cela signifie que la position actuelle est en dehors des limites permises
202 leds[Position - 1].setRGB(0, 0, 0);//Si la condition est vraie, alors cela signifie que la position a dépassé les limites,
203 //et la LED à la position précédente (leds[Position - 1]) est éteinte en la mettant à la couleur noire (0, 0, 0)
204 }
205 FastLED.show();
206 Position++; //Passe à la position suivante
207 if (Position >= NUM_LEDS) { //Cette condition vérifie si la position a dépassé le nombre total de LEDs (NUM_LEDS).
208 //Si c'est le cas, cela signifie que la position a atteint la fin de la séquence de LEDs.
209 leds[Position - 1].setRGB(0, 0, 0); //Si la condition est vraie, alors la LED à la dernière position est éteinte (leds[Position - 1].setRGB(0, 0, 0)) en la mettant à la couleur noire,
210 //et la position est réinitialisée à 0 pour recommencer le jeu
211 Position = 0;
212 }
213 }
214
215 void winner() { //fonction de victoire
216 win_sound(); //Mario victoire
217 for (byte i = 0; i < 3; i++) {
218 for (byte j = 0; j < NUM_LEDS; j++) {
219 leds[j].setRGB(0, 255, 0); //on met toutes les leds en vert
220
221
222 }
223 FastLED.show();
224 delay(500);
225 clearLEDS();
226 FastLED.show();
227 delay(500);
228
229 }
230
231 findRandom = true;
232 Position = 0;
233
234 gameState = level + 1;
235 if (gameState > 5) {
236 gameState = 0;
237 }
238 }
239 void loser() { //fonction de defaite
240 lose_sound(); //imperial march lose
241 for (byte i = 0; i < 3; i++) {
242 for (byte j = 0; j < NUM_LEDS; j++) {
243 leds[j].setRGB(255, 0, 0); //on met toutes les leds en rouge
244 //tone(9, 200, 250);
245
246
247 }
248 FastLED.show();
249 delay(500);
250 clearLEDS();
251 FastLED.show();
252 delay(500);
253 }
254
255 gameState = 0;
256 }
257 void win_sound(){ //Mario victoire
258 for (byte k = 0; k < 3; k++){
259 tone(9, 659, 250);
260 delay(400);}
261 tone(9, 659, 750);
262 delay(400);
263 tone(9, 523, 750);
264 delay(400);
265 tone(9, 587, 750);
266 delay(400);
267 tone(9, 659, 250);
268 delay(400);
269 tone(9, 587, 250);
270 delay(400);
271 tone(9, 659, 250);
272 delay(400);
273 }
274
275 void lose_sound(){ //Marche imperial defaite
276 for (byte k = 0; k < 3; k++){
277 tone(9, 440, 500);
278 delay(500);
279 }
280 tone(9, 349, 350);
281 delay(400);
282 tone(9, 523, 150);
283 delay(150);
284 tone(9, 440, 500);
285 delay(500);
286 tone(9, 349, 350);
287 delay(400);
288 tone(9, 523, 150);
289 delay(150);
290 tone(9, 440, 1000);
291 delay(1000);
292 tone(9, 659, 659);
293 delay(659);
294 tone(9, 659, 659);
295 delay(659);
296 tone(9, 659, 659);
297 delay(659);
298 tone(9, 698, 698);
299 delay(698);
300 tone(9, 523, 523);
301 delay(523);
302 tone(9, 415, 415);
303 delay(415);
304 tone(9, 349, 349);
305 delay(349);
306 tone(9, 523, 523);
307 delay(523);
308 tone(9, 440, 440);
309 delay(440);
310 }
311 void clearLEDS() {
312 for (byte i = 0; i < NUM_LEDS; i++) {
313 leds[i].setRGB(0, 0, 0); //on eteint les leds
314 }
315 }
étapes de fabrication
indiquer autant d'étape que nécessaire, chacune illustrée par des images (phot, dessins, ...)
Étape 1 : Electronique
Utilisez le fer à souder pour souder des fils :
- Aux 5 Leds
- Au bouton
- Au bouton
Exemple pour les Leds :
Ensuite, il faut cabler le circuit en suivant le schéma suivant :
ATENTION ! Il ne faut pas cabler la batterie comme sur le schéma, il faut faire comme si elle n'était pas la. Il faut la brancher directement à la carte avec un cable USB-B
Étape 2 : Code
- Télécharger le dossier zip FastLed au lien suivant : https://www.hackster.io/focalintent/fastled-f872e5, le dezipper
- Démarrer le logiciel Arduino
- Copier dans le logiciel le programme ci-dessus, l'enregistrer dans le dossier FastLED-master/src puis aller dans « édition » et cliquer sur « téléversement »
Étape 3 : Montage
Étape 4 : Résultat
Si tout se passe bien, sur le cercle de LEDs, il y aura une LED verte fixe qui est l’objectif, une zone jaune qui est la zone acceptable de réussite (qui se réduira selon les niveaux) et une LED rouge qui parcourt tout le cercle.
Le joueur aura à sa disposition un bouton sur lequel il devra appuyer quand il estime que la LED rouge est au même niveau que la LED verte ou dans la zone acceptable.
S’il réussit, le joueur passera au niveau supérieur et une nouvelle LED sur un bandeau représentant les niveaux s’allumera.
Enfin, s'il passe tous les niveaux, une musique de victoire se lancera et de même en cas de défaite.
Les problèmes possibles
Quelles sont difficultés, les problèmes, quelles sont les solutions, les trucs et astuces pour que ça marche ?