ENIB 2024 : Le Cyclone Breton

De Les Fabriques du Ponant
Révision datée du 25 janvier 2024 à 12:54 par MartinC (discussion | contributions) (outil et matériel)
Aller à : navigation, rechercher

Titre de la fiche expérience :

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   /*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 :

Le Cyclone Breton Leds.jpg


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

Le cyclone breton circuit.PNG

Étape 2 : Code

  • 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 ?

Sources et documentation complémentaire

ne pas modifier sous cette ligne