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
Matériel :
1 Arduino-Nano
1 Anneau WS2812 avec 60 LED
1 Encodeur rotatif avec bouton-poussoir
Gros bouton Arcade fait maison
Transistor à usage général NPN
Avertisseur sonore
2 Résistance 220 ohms
1 Résistance à trou traversant, 820 ohm
Batterie ??
Bobine d'étain
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 /*if (gameState == 6) {
191 period = ledSpeed[5];
192 if (millis() > time_now + period) {
193 time_now = millis();
194 if (findRandom) {
195 spot = random(56) + 3;
196 findRandom = false;
197 }
198 leds[spot].setRGB(0, 255, 0);
199 sleds[5].setRGB(0, 150, 255);
200 PlayGame(spot , spot);
201 }
202 if (digitalRead(A3) == LOW) {
203 delay(300);
204 if (Position == spot+1) {
205 level = gameState;
206 gameState = 98;
207 } else {
208 gameState = 99;
209 }
210 }
211 }*/
212
213 if (gameState == 98) {
214 winner();
215 }
216 if (gameState == 99) {
217 loser();
218 }
219 }
220 void PlayGame(byte bound1, byte bound2) {
221 leds[Position].setRGB(255, 0, 0); //Allume la LED à la position actuelle (Position) avec une couleur rouge
222 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.
223 //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
224 leds[Position - 1].setRGB(0, 0, 0);//Si la condition est vraie, alors cela signifie que la position a dépassé les limites,
225 //et la LED à la position précédente (leds[Position - 1]) est éteinte en la mettant à la couleur noire (0, 0, 0)
226 }
227 FastLED.show();
228 Position++; //Passe à la position suivante
229 if (Position >= NUM_LEDS) { //Cette condition vérifie si la position a dépassé le nombre total de LEDs (NUM_LEDS).
230 //Si c'est le cas, cela signifie que la position a atteint la fin de la séquence de LEDs.
231 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,
232 //et la position est réinitialisée à 0 pour recommencer le jeu
233 Position = 0;
234 }
235 }
236
237 void winner() { //fonction de victoire
238 win_sound(); //Mario victoire
239 for (byte i = 0; i < 3; i++) {
240 for (byte j = 0; j < NUM_LEDS; j++) {
241 leds[j].setRGB(0, 255, 0); //on met toutes les leds en vert
242
243
244 }
245 FastLED.show();
246 delay(500);
247 clearLEDS();
248 FastLED.show();
249 delay(500);
250
251 }
252
253 findRandom = true;
254 Position = 0;
255
256 gameState = level + 1;
257 if (gameState > 5) {
258 gameState = 0;
259 }
260 }
261 void loser() { //fonction de defaite
262 lose_sound(); //imperial march lose
263 for (byte i = 0; i < 3; i++) {
264 for (byte j = 0; j < NUM_LEDS; j++) {
265 leds[j].setRGB(255, 0, 0); //on met toutes les leds en rouge
266 //tone(9, 200, 250);
267
268
269 }
270 FastLED.show();
271 delay(500);
272 clearLEDS();
273 FastLED.show();
274 delay(500);
275 }
276
277 gameState = 0;
278 }
279 void win_sound(){ //Mario victoire
280 for (byte k = 0; k < 3; k++){
281 tone(9, 659, 250);
282 delay(400);}
283 tone(9, 659, 750);
284 delay(400);
285 tone(9, 523, 750);
286 delay(400);
287 tone(9, 587, 750);
288 delay(400);
289 tone(9, 659, 250);
290 delay(400);
291 tone(9, 587, 250);
292 delay(400);
293 tone(9, 659, 250);
294 delay(400);
295 }
296
297 void lose_sound(){ //Marche imperial defaite
298 for (byte k = 0; k < 3; k++){
299 tone(9, 440, 500);
300 delay(500);
301 }
302 tone(9, 349, 350);
303 delay(400);
304 tone(9, 523, 150);
305 delay(150);
306 tone(9, 440, 500);
307 delay(500);
308 tone(9, 349, 350);
309 delay(400);
310 tone(9, 523, 150);
311 delay(150);
312 tone(9, 440, 1000);
313 delay(1000);
314 tone(9, 659, 659);
315 delay(659);
316 tone(9, 659, 659);
317 delay(659);
318 tone(9, 659, 659);
319 delay(659);
320 tone(9, 698, 698);
321 delay(698);
322 tone(9, 523, 523);
323 delay(523);
324 tone(9, 415, 415);
325 delay(415);
326 tone(9, 349, 349);
327 delay(349);
328 tone(9, 523, 523);
329 delay(523);
330 tone(9, 440, 440);
331 delay(440);
332 }
333 void clearLEDS() {
334 for (byte i = 0; i < NUM_LEDS; i++) {
335 leds[i].setRGB(0, 0, 0); //on eteint les leds
336 }
337 }
é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
- 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 ?