ENIB 2024 : Le Cyclone Breton : Différence entre versions
(→étapes de fabrication) |
(→Introduction) |
||
(40 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== |
− | + | 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. | |
− | == | + | |
+ | ==Image== | ||
+ | |||
+ | [[Fichier:Le Cyclone Breton Fini.jpg|300px]] | ||
+ | |||
+ | ==Outils et matériel== | ||
'''Outils :''' | '''Outils :''' | ||
Ligne 16 : | Ligne 22 : | ||
- Scie | - Scie | ||
+ | - Pistolet à colle | ||
+ | |||
+ | - Imprimante 3D (facultatif) | ||
+ | |||
+ | - Découpeuse laser (facultatif) | ||
'''Matériel :''' | '''Matériel :''' | ||
Ligne 23 : | Ligne 34 : | ||
1 Anneau WS2812 avec 60 LED | 1 Anneau WS2812 avec 60 LED | ||
− | 1 | + | 1 Bouton-poussoir |
− | + | 1 Transistor à usage général NPN | |
− | + | 1 Plaque labdec* | |
− | Avertisseur sonore | + | 25 fils électriques |
+ | |||
+ | 1 Avertisseur sonore | ||
2 Résistance 220 ohms | 2 Résistance 220 ohms | ||
Ligne 35 : | Ligne 48 : | ||
1 Résistance à trou traversant, 820 ohm | 1 Résistance à trou traversant, 820 ohm | ||
− | Batterie | + | 1 Batterie portable (5 Volts, 3 Ampères) |
+ | |||
+ | 1 élastique | ||
Bobine d'étain | Bobine d'étain | ||
− | == | + | Colle |
− | + | ||
+ | Plaques de bois | ||
+ | |||
+ | Scotch | ||
+ | |||
+ | Plastique d'imprimante | ||
+ | |||
+ | ==Fichiers à joindre== | ||
+ | Si vous voulez faire le même montage, voici les documents. C'est un .zip à télécharger et à extraire sur votre ordinateur. | ||
+ | [[Fichier:Le Cyclone Breton.zip|vignette]] | ||
===Code Arduino=== | ===Code Arduino=== | ||
<syntaxhighlight lang="Arduino" line> | <syntaxhighlight lang="Arduino" line> | ||
+ | //----------------------Variables---------------------- | ||
+ | |||
#include "FastLED.h" | #include "FastLED.h" | ||
− | #define NUM_LEDS 60 | + | #define NUM_LEDS 60 //on utilise 60 leds |
#define DATA_PIN A0 | #define DATA_PIN A0 | ||
− | #define SCORE_PIN | + | #define SCORE_PIN 6 |
− | #define SCORE_LEDS | + | #define SCORE_LEDS 6 |
− | #define BRIGHTNESS | + | #define BRIGHTNESS 15 //luminosite de la led |
− | CRGB leds[NUM_LEDS]; | + | CRGB leds[NUM_LEDS]; //variable constante leds |
− | CRGB sleds[NUM_LEDS]; | + | CRGB sleds[NUM_LEDS]; //variable constante score leds |
bool reachedEnd = false; | bool reachedEnd = false; | ||
− | byte gameState = 0; | + | |
+ | byte gameState = 0; //niveau du jeu | ||
//byte ledSpeed = 0; | //byte ledSpeed = 0; | ||
int period = 1000; | int period = 1000; | ||
unsigned long time_now = 0; | unsigned long time_now = 0; | ||
− | byte Position = 0; | + | byte Position = 0; //position de la led |
byte level = 0; | byte level = 0; | ||
− | const byte ledSpeed[6] = {50, 40, 30, 20, 14, 7}; | + | const byte ledSpeed[6] = {50, 40, 30, 20, 14, 7}; //differentes vitesses de la led rouge |
//Debounce | //Debounce | ||
− | bool findRandom = false; | + | bool findRandom = false; //Indique si une nouvelle position aléatoire doit être trouvée |
− | byte spot = 0; | + | byte spot = 0; //On y stocke la position aleatoire |
+ | |||
+ | //----------------------------------------------------- | ||
void setup() { | void setup() { | ||
// put your setup code here, to run once: | // put your setup code here, to run once: | ||
− | FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS); | + | 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. |
+ | //Les LEDs sont déclarées dans le tableau leds et le nombre total de LEDs est spécifié par NUM_LEDS | ||
+ | |||
FastLED.addLeds<WS2812B, SCORE_PIN, GRB>(sleds, SCORE_LEDS); | FastLED.addLeds<WS2812B, SCORE_PIN, GRB>(sleds, SCORE_LEDS); | ||
− | pinMode(A3, INPUT_PULLUP); | + | pinMode(A3, INPUT_PULLUP); //Configure la broche A3 en mode d'entrée avec résistance de tirage vers le haut (INPUT_PULLUP) |
− | Serial.begin(9600); | + | Serial.begin(9600);// Initialise la communication série avec une vitesse de transmission de 9600 bauds. |
− | Serial.println("Reset"); | + | //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. |
+ | Serial.println("Reset"); //Envoie le message "Reset" via la communication série. | ||
+ | //Cela peut être utile pour signaler le redémarrage du microcontrôleur ou pour des fins de débogage. | ||
} | } | ||
Ligne 79 : | Ligne 112 : | ||
FastLED.setBrightness(BRIGHTNESS ); | FastLED.setBrightness(BRIGHTNESS ); | ||
if (gameState == 0) { | if (gameState == 0) { | ||
+ | |||
fill_rainbow(leds, NUM_LEDS, 0, 20); //2 = longer gradient strip | fill_rainbow(leds, NUM_LEDS, 0, 20); //2 = longer gradient strip | ||
fill_rainbow(sleds, SCORE_LEDS, 0, 40); //2 = longer gradient strip | fill_rainbow(sleds, SCORE_LEDS, 0, 40); //2 = longer gradient strip | ||
− | if (digitalRead(A3) == LOW) { | + | if (digitalRead(A3) == LOW) { //on vient lire la broche A3, si c'est en LOW (bas), on exécute le code ci-dessous |
Position = 0; | Position = 0; | ||
findRandom = true; | findRandom = true; | ||
− | delay(500); | + | delay(500); //fait une pause de 500 millisecondes |
for (byte i = 0; i < NUM_LEDS; i++) { | for (byte i = 0; i < NUM_LEDS; i++) { | ||
− | leds[i].setRGB(0, 0, 0); | + | leds[i].setRGB(0, 0, 0); //on eteint toutes les leds |
delay(40); | delay(40); | ||
− | FastLED.show(); | + | FastLED.show(); //Met à jour l'affichage pour refléter les changements sur les leds. |
− | int thisPitch = map (i, 60, 0, 100, 1500); | + | 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. |
− | tone(9, thisPitch,120); | + | //tone(9, thisPitch,120); //Genere une note sur la broche 9, à la frequence thisPitch (en Hz) pendant 120 millisecondes |
} | } | ||
for (byte i = 0; i < SCORE_LEDS; i++) { | for (byte i = 0; i < SCORE_LEDS; i++) { | ||
− | sleds[i].setRGB(0, 0, 0); | + | sleds[i].setRGB(0, 0, 0); //eteindre toutes les leds de score |
delay(100); | delay(100); | ||
− | FastLED.show(); | + | FastLED.show(); |
} | } | ||
− | gameState = 1; | + | gameState = 1; //passer au niveau 1 |
} | } | ||
FastLED.show(); | FastLED.show(); | ||
Ligne 167 : | Ligne 201 : | ||
delay(300); | delay(300); | ||
if (Position == spot+1) { | if (Position == spot+1) { | ||
+ | |||
level = gameState; | level = gameState; | ||
gameState = 98; | gameState = 98; | ||
Ligne 219 : | Ligne 254 : | ||
} | } | ||
} | } | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
if (gameState == 98) { | if (gameState == 98) { | ||
Ligne 251 : | Ligne 263 : | ||
} | } | ||
void PlayGame(byte bound1, byte bound2) { | void PlayGame(byte bound1, byte bound2) { | ||
− | leds[Position].setRGB(255, 0, 0); | + | leds[Position].setRGB(255, 0, 0); //Allume la LED à la position actuelle (Position) avec une couleur rouge |
− | if (Position < bound1 + 1 || Position > bound2 + 1) { | + | 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. |
− | leds[Position - 1].setRGB(0, 0, 0); | + | //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 |
+ | leds[Position - 1].setRGB(0, 0, 0);//Si la condition est vraie, alors cela signifie que la position a dépassé les limites, | ||
+ | //et la LED à la position précédente (leds[Position - 1]) est éteinte en la mettant à la couleur noire (0, 0, 0) | ||
} | } | ||
FastLED.show(); | FastLED.show(); | ||
− | Position++; | + | Position++; //Passe à la position suivante |
− | if (Position >= NUM_LEDS) { | + | if (Position >= NUM_LEDS) { //Cette condition vérifie si la position a dépassé le nombre total de LEDs (NUM_LEDS). |
− | leds[Position - 1].setRGB(0, 0, 0); | + | //Si c'est le cas, cela signifie que la position a atteint la fin de la séquence de LEDs. |
+ | 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, | ||
+ | //et la position est réinitialisée à 0 pour recommencer le jeu | ||
Position = 0; | Position = 0; | ||
} | } | ||
} | } | ||
− | void winner() { | + | void winner() { //fonction de victoire |
+ | win_sound(); //Final Fantasy 7 victoire | ||
for (byte i = 0; i < 3; i++) { | for (byte i = 0; i < 3; i++) { | ||
for (byte j = 0; j < NUM_LEDS; j++) { | for (byte j = 0; j < NUM_LEDS; j++) { | ||
− | leds[j].setRGB(0, 255, 0); | + | leds[j].setRGB(0, 255, 0); //on met toutes les leds en vert |
− | + | ||
− | + | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
} | } | ||
FastLED.show(); | FastLED.show(); | ||
Ligne 285 : | Ligne 294 : | ||
} | } | ||
+ | |||
findRandom = true; | findRandom = true; | ||
Position = 0; | Position = 0; | ||
Ligne 293 : | Ligne 303 : | ||
} | } | ||
} | } | ||
− | void loser() { | + | void loser() { //fonction de defaite |
+ | lose_sound(); //imperial march lose | ||
for (byte i = 0; i < 3; i++) { | for (byte i = 0; i < 3; i++) { | ||
for (byte j = 0; j < NUM_LEDS; j++) { | for (byte j = 0; j < NUM_LEDS; j++) { | ||
− | leds[j].setRGB(255, 0, 0); | + | leds[j].setRGB(255, 0, 0); //on met toutes les leds en rouge |
//tone(9, 200, 250); | //tone(9, 200, 250); | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
} | } | ||
Ligne 325 : | Ligne 318 : | ||
delay(500); | delay(500); | ||
} | } | ||
+ | |||
gameState = 0; | gameState = 0; | ||
+ | } | ||
+ | void win_sound(){ //Final Fantasy 7 victoire | ||
+ | for (byte k = 0; k < 3; k++){ | ||
+ | tone(9, 659, 250); | ||
+ | delay(400);} | ||
+ | tone(9, 659, 750); | ||
+ | delay(400); | ||
+ | tone(9, 523, 750); | ||
+ | delay(400); | ||
+ | tone(9, 587, 750); | ||
+ | delay(400); | ||
+ | tone(9, 659, 250); | ||
+ | delay(400); | ||
+ | tone(9, 587, 250); | ||
+ | delay(400); | ||
+ | tone(9, 659, 250); | ||
+ | delay(400); | ||
+ | } | ||
+ | |||
+ | void lose_sound(){ //Marche imperial defaite | ||
+ | for (byte k = 0; k < 3; k++){ | ||
+ | tone(9, 440, 500); | ||
+ | delay(200); | ||
+ | } | ||
+ | tone(9, 349, 350); | ||
+ | delay(200); | ||
+ | tone(9, 523, 150); | ||
+ | delay(200); | ||
+ | tone(9, 440, 500); | ||
+ | delay(200); | ||
+ | tone(9, 349, 350); | ||
+ | delay(200); | ||
+ | tone(9, 523, 150); | ||
+ | delay(200); | ||
+ | tone(9, 440, 1000); | ||
+ | delay(200); | ||
+ | tone(9, 659, 659); | ||
+ | delay(200); | ||
+ | tone(9, 659, 659); | ||
+ | delay(200); | ||
+ | tone(9, 659, 659); | ||
+ | delay(200); | ||
+ | tone(9, 698, 698); | ||
+ | delay(200); | ||
+ | tone(9, 523, 523); | ||
+ | delay(200); | ||
+ | tone(9, 415, 415); | ||
+ | delay(200); | ||
+ | tone(9, 349, 349); | ||
+ | delay(200); | ||
+ | tone(9, 523, 523); | ||
+ | delay(200); | ||
+ | tone(9, 440, 440); | ||
+ | delay(200); | ||
} | } | ||
void clearLEDS() { | void clearLEDS() { | ||
for (byte i = 0; i < NUM_LEDS; i++) { | for (byte i = 0; i < NUM_LEDS; i++) { | ||
− | leds[i].setRGB(0, 0, 0); | + | leds[i].setRGB(0, 0, 0); //on eteint les leds |
} | } | ||
} | } | ||
− | + | ||
− | + | ||
− | |||
</syntaxhighlight> | </syntaxhighlight> | ||
− | == | + | ==Etapes de fabrication== |
− | |||
===Étape 1 : Electronique === | ===Étape 1 : Electronique === | ||
Ligne 345 : | Ligne 391 : | ||
Utilisez le fer à souder pour souder des fils : | Utilisez le fer à souder pour souder des fils : | ||
− | * Aux Leds | + | * Aux 5 Leds |
* Au bouton | * Au bouton | ||
Ligne 351 : | Ligne 397 : | ||
* Au bouton | * Au bouton | ||
− | Ensuite, il faut cabler le circuit en suivant le schéma suivant : | + | Exemple pour les Leds : |
+ | |||
+ | [[Fichier:Le Cyclone Breton Leds.jpg|100px]] | ||
+ | |||
+ | |||
+ | 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 | ||
+ | |||
+ | [[Fichier:Le cyclone breton circuit.PNG|500px]] | ||
===Étape 2 : Code === | ===Étape 2 : Code === | ||
− | * Télécharger le dossier zip FastLed au lien suivant : https://www.hackster.io/focalintent/fastled-f872e5 <br> | + | * Télécharger le logiciel Arduino au lien suivant : https://www.arduino.cc/en/software et l'exécuter |
+ | |||
+ | * Télécharger le dossier zip FastLed au lien suivant : https://www.hackster.io/focalintent/fastled-f872e5, le dezipper <br> | ||
* Démarrer le logiciel Arduino<br> | * Démarrer le logiciel Arduino<br> | ||
+ | |||
+ | * Brancher l'ordinateur à la carte Arduino | ||
+ | |||
+ | * Aller dans "outil" --> "carte" --> Arduino AVR Boards, et choisir "Arduino Nano" | ||
+ | |||
+ | * Aller dans "outil" --> "Port" et sélectionner le bon port USB (celui où est branché la carte sur votre ordinateur) | ||
* 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 » | * 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 3 : Impression 3D (facultatif)=== |
+ | |||
+ | Le but est de faire un petit socle pour le cercle de 60 leds. Il est facultatif mais ca permet de faire une petite protection en plus. Il a pris 9g (0,5 centimes pour une bobine à 18 euros le kilo) et 1h10 d'impression. | ||
+ | |||
+ | Le fichier s'appelle Cercle_pour_60_Leds.stl | ||
+ | |||
+ | |||
+ | Nous avons aussi fait une protection pour les 5 petites leds (voir fichier), il a pris 2,2g de plastique et 13 minutes d'impression. | ||
+ | |||
+ | Le fichier d'appelle protection_5_lets.STL | ||
+ | |||
+ | |||
+ | Il y a également les supports de batterie à imprimer dans le dossier. Il prend 18 minutes à imprimer et 6,2g de plastique. | ||
+ | Le dossier d'appelle support_batterie.stl | ||
+ | |||
+ | |||
+ | Une fois que vous avez imprimé les pièces (si vous voulez faire le même design que sur la photo), vous pouvez passer à l'étape suivante. | ||
+ | |||
+ | ===Étape 4 : Découpe laser (facultatif)=== | ||
+ | |||
+ | Cela nous permet de faire toute l'armature en bois. Il est décomposer en 4 pièces, vous pouvez découper du bois avec la découpeuse laser. | ||
+ | Il faut utiliser les dossiers que vous avez téléchargé au début : contour.svg, dessus.svg, dessous.svg et Fermeture_en_U.svg | ||
+ | |||
+ | Il faut imprimer au moins 3 Fermetures en U pour bien fermer la boite et qu'elle soit droite quand on la pose sur une table. | ||
+ | |||
+ | Une fois que vous avez découpé les 4 pièces (si vous avez besoin d'une armature), vous pouvez passer à l'étape suivante. | ||
+ | |||
+ | ===Étape 6 : Montage=== | ||
+ | |||
+ | * Utiliser de la colle (pistolet ou pas) pour coller les 2 parties du contour. Coller ensuite le dessus avec le contour collé. | ||
+ | |||
+ | * Mettre le bouton poussoir dans le trou prévu, le sérer avec le boulon en plastique pour ne pas qu'il s'échappe. | ||
+ | |||
+ | * Coller le cercle en plastique pour les 60 leds au centre du dessus en bois, et les leds au cercle en plastique. | ||
+ | |||
+ | * Coller également la ligne de 5 leds au centre du cercle, bien faire passer les fils électriques par le trou et les branchements. Coller la protection par dessus. | ||
+ | |||
+ | * Accrocher ensuite la plaque labdec à l'intérieur de la boite | ||
+ | |||
+ | * Faire passer le cable de la batterie à l'extérieur par le trou prévu. | ||
+ | |||
+ | * Accrocher les supports batterie sur le coté de la boite (à l'extérieur) | ||
+ | |||
+ | * Mettre la batterie dans le support et la brancher | ||
+ | |||
+ | * Bloquer la batterie avec un élastique de chaque coté | ||
+ | |||
+ | * Fermer la boite et la bloquer en métant plusieurs fermetures en U (minimum 3) | ||
+ | |||
+ | |||
+ | Image de l'intérieur : | ||
+ | [[Fichier:Le Cyclone Breton interieur.jpg|200px]] | ||
+ | |||
+ | |||
+ | Image de la fabrication : | ||
+ | [[Fichier:Le Cyclone Breton fabrication1.jpg|200px]] | ||
+ | |||
+ | ===Étape 5 : 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. <br> | 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. <br> | ||
Ligne 370 : | Ligne 490 : | ||
===Les problèmes possibles=== | ===Les problèmes possibles=== | ||
− | + | ||
+ | * Si ça ne fonctionne pas | ||
+ | Vérifier le câblage, ça peut être un mauvais câblage, un faux contact, un composant défectueux etc... | ||
+ | |||
+ | |||
+ | *Des fois, le jeu annonce une victoire à la place d'une défaite (ou le contraire), cela arrive une fois de temps en temps, c'est parce que la carte Arduino a beaucoup de lignes de code à gérer en même temps. Nous ne pouvons rien faire pour contrer ca sauf si on prend une carte Arduino plus puissante. | ||
+ | |||
+ | |||
+ | *Ne pas hésiter à éteindre puis rallumer en débranchant la batterie. | ||
+ | |||
+ | |||
+ | *Si on n'arrive pas à téléverser le code | ||
+ | Sur le logiciel Arduino, aller dans l'onglet "outil" --> "port" pour vérifier que la carte est branchée sur le bon port USB de l'ordinateur. | ||
+ | |||
+ | Sinon, aller sur "outil" --> "carte" et vérifier qu'on ait bien la carte "Arduino Nano" | ||
+ | |||
+ | Sinon, aller dans "outil" --> "processor" et sélectionner "ATmega328P (Old Bootloader)" | ||
+ | |||
+ | |||
+ | * Comment fermer la boîte ? | ||
+ | On a décidé de créer des pièces en U à mettre de part et d'autre de la boîte avec la partie supérieure et la partie inférieure dans les U. | ||
+ | |||
+ | |||
+ | * La carte Arduino ne tient pas sur la plaque Labdec | ||
+ | On a mis un élastique pour la tenir en place. | ||
==Sources et documentation complémentaire== | ==Sources et documentation complémentaire== |
Version actuelle datée du 25 janvier 2024 à 15:16
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.
Image
Outils 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)
1 élastique
Bobine d'étain
Colle
Plaques de bois
Scotch
Plastique d'imprimante
Fichiers à joindre
Si vous voulez faire le même montage, voici les documents. C'est un .zip à télécharger et à extraire sur votre ordinateur. Fichier:Le Cyclone Breton.zip
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 15 //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 == 98) {
191 winner();
192 }
193 if (gameState == 99) {
194 loser();
195 }
196 }
197 void PlayGame(byte bound1, byte bound2) {
198 leds[Position].setRGB(255, 0, 0); //Allume la LED à la position actuelle (Position) avec une couleur rouge
199 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.
200 //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
201 leds[Position - 1].setRGB(0, 0, 0);//Si la condition est vraie, alors cela signifie que la position a dépassé les limites,
202 //et la LED à la position précédente (leds[Position - 1]) est éteinte en la mettant à la couleur noire (0, 0, 0)
203 }
204 FastLED.show();
205 Position++; //Passe à la position suivante
206 if (Position >= NUM_LEDS) { //Cette condition vérifie si la position a dépassé le nombre total de LEDs (NUM_LEDS).
207 //Si c'est le cas, cela signifie que la position a atteint la fin de la séquence de LEDs.
208 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,
209 //et la position est réinitialisée à 0 pour recommencer le jeu
210 Position = 0;
211 }
212 }
213
214 void winner() { //fonction de victoire
215 win_sound(); //Final Fantasy 7 victoire
216 for (byte i = 0; i < 3; i++) {
217 for (byte j = 0; j < NUM_LEDS; j++) {
218 leds[j].setRGB(0, 255, 0); //on met toutes les leds en vert
219
220
221 }
222 FastLED.show();
223 delay(500);
224 clearLEDS();
225 FastLED.show();
226 delay(500);
227
228 }
229
230 findRandom = true;
231 Position = 0;
232
233 gameState = level + 1;
234 if (gameState > 5) {
235 gameState = 0;
236 }
237 }
238 void loser() { //fonction de defaite
239 lose_sound(); //imperial march lose
240 for (byte i = 0; i < 3; i++) {
241 for (byte j = 0; j < NUM_LEDS; j++) {
242 leds[j].setRGB(255, 0, 0); //on met toutes les leds en rouge
243 //tone(9, 200, 250);
244
245
246 }
247 FastLED.show();
248 delay(500);
249 clearLEDS();
250 FastLED.show();
251 delay(500);
252 }
253
254 gameState = 0;
255 }
256 void win_sound(){ //Final Fantasy 7 victoire
257 for (byte k = 0; k < 3; k++){
258 tone(9, 659, 250);
259 delay(400);}
260 tone(9, 659, 750);
261 delay(400);
262 tone(9, 523, 750);
263 delay(400);
264 tone(9, 587, 750);
265 delay(400);
266 tone(9, 659, 250);
267 delay(400);
268 tone(9, 587, 250);
269 delay(400);
270 tone(9, 659, 250);
271 delay(400);
272 }
273
274 void lose_sound(){ //Marche imperial defaite
275 for (byte k = 0; k < 3; k++){
276 tone(9, 440, 500);
277 delay(200);
278 }
279 tone(9, 349, 350);
280 delay(200);
281 tone(9, 523, 150);
282 delay(200);
283 tone(9, 440, 500);
284 delay(200);
285 tone(9, 349, 350);
286 delay(200);
287 tone(9, 523, 150);
288 delay(200);
289 tone(9, 440, 1000);
290 delay(200);
291 tone(9, 659, 659);
292 delay(200);
293 tone(9, 659, 659);
294 delay(200);
295 tone(9, 659, 659);
296 delay(200);
297 tone(9, 698, 698);
298 delay(200);
299 tone(9, 523, 523);
300 delay(200);
301 tone(9, 415, 415);
302 delay(200);
303 tone(9, 349, 349);
304 delay(200);
305 tone(9, 523, 523);
306 delay(200);
307 tone(9, 440, 440);
308 delay(200);
309 }
310 void clearLEDS() {
311 for (byte i = 0; i < NUM_LEDS; i++) {
312 leds[i].setRGB(0, 0, 0); //on eteint les leds
313 }
314 }
Etapes de fabrication
É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 logiciel Arduino au lien suivant : https://www.arduino.cc/en/software et l'exécuter
- Télécharger le dossier zip FastLed au lien suivant : https://www.hackster.io/focalintent/fastled-f872e5, le dezipper
- Démarrer le logiciel Arduino
- Brancher l'ordinateur à la carte Arduino
- Aller dans "outil" --> "carte" --> Arduino AVR Boards, et choisir "Arduino Nano"
- Aller dans "outil" --> "Port" et sélectionner le bon port USB (celui où est branché la carte sur votre ordinateur)
- 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 : Impression 3D (facultatif)
Le but est de faire un petit socle pour le cercle de 60 leds. Il est facultatif mais ca permet de faire une petite protection en plus. Il a pris 9g (0,5 centimes pour une bobine à 18 euros le kilo) et 1h10 d'impression.
Le fichier s'appelle Cercle_pour_60_Leds.stl
Nous avons aussi fait une protection pour les 5 petites leds (voir fichier), il a pris 2,2g de plastique et 13 minutes d'impression.
Le fichier d'appelle protection_5_lets.STL
Il y a également les supports de batterie à imprimer dans le dossier. Il prend 18 minutes à imprimer et 6,2g de plastique.
Le dossier d'appelle support_batterie.stl
Une fois que vous avez imprimé les pièces (si vous voulez faire le même design que sur la photo), vous pouvez passer à l'étape suivante.
Étape 4 : Découpe laser (facultatif)
Cela nous permet de faire toute l'armature en bois. Il est décomposer en 4 pièces, vous pouvez découper du bois avec la découpeuse laser. Il faut utiliser les dossiers que vous avez téléchargé au début : contour.svg, dessus.svg, dessous.svg et Fermeture_en_U.svg
Il faut imprimer au moins 3 Fermetures en U pour bien fermer la boite et qu'elle soit droite quand on la pose sur une table.
Une fois que vous avez découpé les 4 pièces (si vous avez besoin d'une armature), vous pouvez passer à l'étape suivante.
Étape 6 : Montage
- Utiliser de la colle (pistolet ou pas) pour coller les 2 parties du contour. Coller ensuite le dessus avec le contour collé.
- Mettre le bouton poussoir dans le trou prévu, le sérer avec le boulon en plastique pour ne pas qu'il s'échappe.
- Coller le cercle en plastique pour les 60 leds au centre du dessus en bois, et les leds au cercle en plastique.
- Coller également la ligne de 5 leds au centre du cercle, bien faire passer les fils électriques par le trou et les branchements. Coller la protection par dessus.
- Accrocher ensuite la plaque labdec à l'intérieur de la boite
- Faire passer le cable de la batterie à l'extérieur par le trou prévu.
- Accrocher les supports batterie sur le coté de la boite (à l'extérieur)
- Mettre la batterie dans le support et la brancher
- Bloquer la batterie avec un élastique de chaque coté
- Fermer la boite et la bloquer en métant plusieurs fermetures en U (minimum 3)
Étape 5 : 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
- Si ça ne fonctionne pas
Vérifier le câblage, ça peut être un mauvais câblage, un faux contact, un composant défectueux etc...
- Des fois, le jeu annonce une victoire à la place d'une défaite (ou le contraire), cela arrive une fois de temps en temps, c'est parce que la carte Arduino a beaucoup de lignes de code à gérer en même temps. Nous ne pouvons rien faire pour contrer ca sauf si on prend une carte Arduino plus puissante.
- Ne pas hésiter à éteindre puis rallumer en débranchant la batterie.
- Si on n'arrive pas à téléverser le code
Sur le logiciel Arduino, aller dans l'onglet "outil" --> "port" pour vérifier que la carte est branchée sur le bon port USB de l'ordinateur.
Sinon, aller sur "outil" --> "carte" et vérifier qu'on ait bien la carte "Arduino Nano"
Sinon, aller dans "outil" --> "processor" et sélectionner "ATmega328P (Old Bootloader)"
- Comment fermer la boîte ?
On a décidé de créer des pièces en U à mettre de part et d'autre de la boîte avec la partie supérieure et la partie inférieure dans les U.
- La carte Arduino ne tient pas sur la plaque Labdec
On a mis un élastique pour la tenir en place.