ENIB 2024 : Le Cyclone Breton

De Les Fabriques du Ponant
Révision datée du 25 janvier 2024 à 12:00 par Izgreg (discussion | contributions) (Code Arduino)
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   
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 :

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