ENIB 2024 : CatchTheJackpot : Différence entre versions

De Les Fabriques du Ponant
Aller à : navigation, rechercher
(fichiers à joindre)
(Code :)
 
(17 révisions intermédiaires par 2 utilisateurs non affichées)
Ligne 1 : Ligne 1 :
[[Fichier:Ahok.jpg|vignette]]
 
Titre de la fiche expérience :
 
 
==description==
 
==description==
  
Ligne 22 : Ligne 20 :
 
* 2 rubans de LED adressable (85 LEDs pour être exacte)  
 
* 2 rubans de LED adressable (85 LEDs pour être exacte)  
 
* Carton
 
* Carton
 +
* Bois
 
* Câbles mini-USB
 
* Câbles mini-USB
 
* Câbles
 
* Câbles
 +
* écran LCD
 +
* Breadboard
 +
* 2 résistances de 500kΩ
 +
* Buzzer
  
 
==Outils==
 
==Outils==
Ligne 32 : Ligne 35 :
 
* Scotch
 
* Scotch
 
* Fer à souder
 
* Fer à souder
 
+
* Scie à bois
 +
* Perceuse
 
* Bibliothèque Arduino FastLed  
 
* Bibliothèque Arduino FastLed  
 
   https://fastled.io/
 
   https://fastled.io/
==fichiers à joindre==
 
code, ficher d'impression 3D, de découpe laser ou vinyle, ...
 
  
===Code :===
+
==Code :==
<syntaxhighlight lang="Arduino" line>
+
 
 +
<syntaxhighlight lang="Arduino" line>  
 +
 
 +
//Programme fait sur carte STM8266 / WEMOS D1 mini
 +
#include "pitches.h"
 
#include "FastLED.h"                    //bibliothèque pour controler le ruban led
 
#include "FastLED.h"                    //bibliothèque pour controler le ruban led
 +
#include <Wire.h>                  //bibliothèque écran
 +
#include <LiquidCrystal_I2C.h>    //bibliothèque écran
 +
#define REST 0
 
#define NUM_LEDS 86
 
#define NUM_LEDS 86
 
#define NUM_OF_LEDS_BY_LEVEL 17        // nombre de leds par niveau
 
#define NUM_OF_LEDS_BY_LEVEL 17        // nombre de leds par niveau
 
#define NUM_OF_LEVELS 5                  // nombre de niveaux
 
#define NUM_OF_LEVELS 5                  // nombre de niveaux
#define PIN_BTN 3                       // Entree du bouton
+
#define PIN_BTN D3                       // Entree du bouton
#define PIN_LEDS 2                     // Sortie du ruban led
+
#define PIN_LEDS D4                     // Sortie du ruban led
 +
#define PIN_BUZZER D8                    // Signal de sortie buzzer
  
// Dans ce programme nous avons utilisé presque intégralement des variables globales
 
  
CRGB leds[NUM_LEDS];
+
// -------- INIT VARIABLES --------
 +
LiquidCrystal_I2C lcd(0x27, 16, 2);
 +
CRGB leds[NUM_LEDS]; //Création d'une liste avec chaque led
 +
CRGB randomcolor  = CHSV(random(192), 255, 255);
 
int level = 0;        // niveau auquel le joueur est
 
int level = 0;        // niveau auquel le joueur est
 
int delay_level = 30; // délai qui permet de controler la vitesse de déplacement de la led
 
int delay_level = 30; // délai qui permet de controler la vitesse de déplacement de la led
auto color = CRGB::Purple; // couleur de la led qui se déplace
+
auto color = CRGB::Blue; // couleur de la led qui se déplace
int score = 0;          // socre du joueur
+
int score = 0;          // score du joueur
const double coef[] = {1, 1.4, 1.7, 1.9, 2, 2.2}; // coefficient multiplicateur de point par niveau
+
const double coef[] = {1,1.5,2,2.5,3}; // coefficient multiplicateur de point par niveau
int last_point = 0;    // sauvegarde de la derniere led allumée pour la rallumer après flash()
+
int last_point[NUM_OF_LEVELS];    // sauvegarde de la derniere led allumée pour la rallumer après flash()
 +
bool game_in_progress = false;
 +
int last_point_visu = 0;
  
  
// Déclarations de fonctions
+
 
int compute_score(int score_of_level);    // calcul du score par niveau
+
// -------- INIT FONCTIONS --------
int up();          // deplacement led
+
 
int down();         // deplacement led dans l'autre sense
+
int move();           // déplacement de la led
 
void level_up();    // passage de niveau
 
void level_up();    // passage de niveau
 +
void waiting_start_game(); //affichage d'attente de début du jeu
 
void flash();      // animation de victoire d'un niveau
 
void flash();      // animation de victoire d'un niveau
  
 
+
// -------- PROGRAMME --------
 
void setup() {
 
void setup() {
   FastLED.addLeds<NEOPIXEL, 2>(leds, NUM_LEDS);    // setup du ruban de led sur la sortie PIN_LEDS => 2
+
   FastLED.addLeds<NEOPIXEL, D4>(leds, NUM_LEDS);    // setup du ruban de led sur la sortie PIN_LEDS => 2
 
   pinMode(PIN_BTN, INPUT);                          // setup du bouton dur l'entrée PIN_BTN => 3
 
   pinMode(PIN_BTN, INPUT);                          // setup du bouton dur l'entrée PIN_BTN => 3
   Serial.begin(9600);                              // setup moniteur série pour debug
+
  FastLED.setBrightness(50);                    // setup de la luminosité
 +
   Serial.begin(9600);                              // setup moniteur série pour debug  
 +
  int last_point[NUM_OF_LEVELS];
 +
  pinMode(PIN_BUZZER, OUTPUT);
 +
 
 +
  // -------- ECRAN --------
 +
  lcd.init();                        // Initialize I2C LCD module
 +
  lcd.backlight();                  // Turn backlight ON
 
}
 
}
 +
  
 
void loop() {
 
void loop() {
 
+
  waiting_start_game();
  int score_of_level;
+
    lcd.setCursor(0,0);
   if (score_of_level = up())             // led avance dans un sense
+
    lcd.print("    Cliquer ");
  {
+
    lcd.setCursor(0,1);
    score += compute_score(score_of_level);      // ajout score du niveau
+
    lcd.print(" pour commencer");
    level_up();
+
    FastLED.clear();
 +
   if (digitalRead(PIN_BTN)==LOW){
 +
    musique();
 +
    game_in_progress = true;
 +
    lcd.clear();
 +
    lcd.setCursor(0,0);
 +
    lcd.print("Partie en cours !");
 +
    lcd.setCursor(0,1);
 +
    lcd.print("XoXoXoXoXoXoXoXo");
 +
    FastLED.clear();
 +
    delay(400);
 +
    while(game_in_progress){
 +
      move();
 +
       if (digitalRead(PIN_BTN)==LOW && game_in_progress==true){
 +
        level_up();
 +
      }
 +
    }
 
   }
 
   }
  else if (score_of_level = down())      // led avance dans l'autre sense
 
  {
 
    score += compute_score(score_of_level);      // ajout score du niveau
 
    level_up();
 
  }
 
 
 
 
}
 
}
  
int compute_score(int score_of_level)
 
{
 
  return (NUM_OF_LEDS_BY_LEVEL/2 - (int)abs((level * NUM_OF_LEDS_BY_LEVEL + NUM_OF_LEDS_BY_LEVEL / 2) - score_of_level)) * coef[level] + 1;
 
  // On calcul le nombre de leds d'un niveau moins la différence entre la led du joueur et celle du milieu on ajoute 2 et on multiplie par le coefficient de points du level
 
}
 
  
int up()
+
int move(){
{
+
  // Permet de faire bouger la LED de gauche à droite
   for (int i = NUM_OF_LEDS_BY_LEVEL * level; i <= (NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL - 1); i++)
+
   for (int i = NUM_OF_LEDS_BY_LEVEL * level; i <= (NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL - 1); i++){
  {
+
    // -------- DEBUGGING -------- //
     if (digitalRead(PIN_BTN))  // appuie sur le bouton
+
    /*
     {
+
    Serial.print("val de la led: ");
      while (digitalRead(PIN_BTN))    // blocage du bouton tant que celui-ci n'a pas été relaché
+
    Serial.print(i);
       {
+
    Serial.print("\n");
         delay(2);
+
    */
 +
     if (digitalRead(PIN_BTN)==LOW){    //Stock des scores LEDs 1 -> 9 -> 1
 +
      int center = abs(i - (NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL / 2));
 +
      if (center <= NUM_OF_LEDS_BY_LEVEL/2) {
 +
        last_point[level] = NUM_OF_LEDS_BY_LEVEL/2 - center + 1;  // Les points augmentent jusqu'à 9
 +
      } else {
 +
        last_point[level] = 0;  // À partir de la position 9, les points diminuent
 +
      }
 +
    //   if(i<(1/2*NUM_OF_LEDS_BY_LEVEL)){
 +
    //    last_point[level] = i;
 +
    //   }
 +
     //  else{
 +
    //    for(int degr = 1; degr<NUM_OF_LEDS_BY_LEVEL; degr++)
 +
    //    last_point[level] = (i - degr);
 +
     
 +
    // }
 +
      int last_point_visu = i-1;
 +
      return i-1;
 +
      // -------- DEBUGGING -------- //
 +
      /*
 +
      Serial.print("last_point_visu");
 +
      Serial.print(last_point_visu);
 +
     
 +
       for(int z=0; z<NUM_OF_LEVELS; z++){
 +
         Serial.print(last_point[z]);
 +
        Serial.print("\n");
 
       }
 
       }
       last_point = i-1;    // on concerve la valeur de la led choisie pour la réafficher après le flash
+
       */
       return i - 1;  // renvoie la position de la led au moment de l'appuie sur le bouton
+
        
 +
     
 
     }
 
     }
 +
    //Eteins les LEDs derrière la LED mouvante
 
     leds[i - 1] = CRGB::Black;
 
     leds[i - 1] = CRGB::Black;
 
     delay(3);
 
     delay(3);
 
+
     leds[level * NUM_OF_LEDS_BY_LEVEL + NUM_OF_LEDS_BY_LEVEL / 2] = CRGB::Yellow;
     leds[level * NUM_OF_LEDS_BY_LEVEL + NUM_OF_LEDS_BY_LEVEL / 2] = CRGB::White;
 
 
     leds[i] = color;
 
     leds[i] = color;
 
 
     FastLED.show();
 
     FastLED.show();
 
     delay(delay_level);
 
     delay(delay_level);
Ligne 120 : Ligne 172 :
 
   FastLED.show();
 
   FastLED.show();
 
   delay(delay_level);
 
   delay(delay_level);
  return 0;
 
 
}
 
 
int down()
 
{
 
 
 
   for (int i = NUM_OF_LEDS_BY_LEVEL * level +  NUM_OF_LEDS_BY_LEVEL - 1; i >= NUM_OF_LEDS_BY_LEVEL * level ; i--)
 
   for (int i = NUM_OF_LEDS_BY_LEVEL * level +  NUM_OF_LEDS_BY_LEVEL - 1; i >= NUM_OF_LEDS_BY_LEVEL * level ; i--)
 
   {
 
   {
     if (digitalRead(PIN_BTN))
+
    // -------- DEBUGGING -------- //
    {
+
    /*
       while (digitalRead(PIN_BTN))
+
    Serial.print("val de la led: ");
       {
+
    Serial.print(i);
         delay(2);
+
    Serial.print("\n");
 +
    */
 +
     if (digitalRead(PIN_BTN)==LOW){          //Stock des scores LEDs 1 -> 9 -> 1
 +
      int center = abs(i - (NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL / 2));
 +
      if (center <= NUM_OF_LEDS_BY_LEVEL/2) {
 +
        last_point[level] = NUM_OF_LEDS_BY_LEVEL/2 - center + 1;  // Les points augmentent jusqu'à 9
 +
      } else {
 +
        last_point[level] = 0;  // À partir de la position 9, les points diminuent
 +
      }
 +
      // if(i<(1/2*NUM_OF_LEDS_BY_LEVEL)){
 +
      //  last_point[level] = i;
 +
      // }
 +
      // else{
 +
       //  for(int degr = 1; degr<NUM_OF_LEDS_BY_LEVEL; degr++)
 +
      //  last_point[level] = (i - degr);
 +
      //  }
 +
   
 +
      int last_point_visu = i+1;
 +
      return i+1;
 +
     
 +
      // -------- DEBUGGING -------- //
 +
      /*
 +
      Serial.print("last_point_visu");
 +
      Serial.print(last_point_visu);
 +
     
 +
       for(int z=0; z<NUM_OF_LEVELS; z++){
 +
         Serial.print(last_point[z]);
 +
        Serial.print("\n");
 
       }
 
       }
       last_point = i+1;
+
       */
       return i + 1;  // renvoie la position de la led au moment de l'appuie sur le bouton
+
        
 
     }
 
     }
 +
    //Eteins les LEDs derrière la LED mouvante
 
     leds[i + 1] = CRGB::Black;
 
     leds[i + 1] = CRGB::Black;
 
     delay(3);
 
     delay(3);
 
+
     leds[level * NUM_OF_LEDS_BY_LEVEL + NUM_OF_LEDS_BY_LEVEL / 2] = CRGB::Yellow;
     leds[level * NUM_OF_LEDS_BY_LEVEL + NUM_OF_LEDS_BY_LEVEL / 2] = CRGB::White;
 
 
     leds[i] = color;
 
     leds[i] = color;
 
 
     FastLED.show();
 
     FastLED.show();
 
     delay(delay_level);
 
     delay(delay_level);
 
   }
 
   }
  leds[NUM_OF_LEDS_BY_LEVEL] = CRGB::Black;
+
    leds[NUM_OF_LEDS_BY_LEVEL] = CRGB::Black;
  FastLED.show();
+
    FastLED.show();
  delay(delay_level);
+
    delay(delay_level);
 
   return 0;
 
   return 0;
 +
}
  
 
}
 
 
void flash()  // fonction de décoration qui fait clignoter les leds en blanc avant le passage de niveau
 
void flash()  // fonction de décoration qui fait clignoter les leds en blanc avant le passage de niveau
 
{
 
{
Ligne 160 : Ligne 230 :
 
     for (int i = NUM_OF_LEDS_BY_LEVEL * level; i <= (NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL - 1); i++)  // On met toute les leds du niveau en blanc
 
     for (int i = NUM_OF_LEDS_BY_LEVEL * level; i <= (NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL - 1); i++)  // On met toute les leds du niveau en blanc
 
     {
 
     {
       leds[i] = CRGB::White;
+
       leds[i] = CRGB::Green;
 
     }
 
     }
 
     FastLED.show();
 
     FastLED.show();
 
 
     delay(100);
 
     delay(100);
 
     for (int i = NUM_OF_LEDS_BY_LEVEL * level; i <= (NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL - 1); i++) // On éteint toutes les leds du niveau
 
     for (int i = NUM_OF_LEDS_BY_LEVEL * level; i <= (NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL - 1); i++) // On éteint toutes les leds du niveau
Ligne 172 : Ligne 241 :
 
     delay(100);
 
     delay(100);
 
   }
 
   }
   leds[last_point] = CRGB::Red;
+
   leds[last_point_visu] = CRGB::Purple;
 
}
 
}
  
void score_leds()  // affichage du score avec les leds
+
void level_up()  // changement de niveau
 
{
 
{
   for (int i = 0; i < score; i++)
+
   flash(); // animation
 +
  level++;  // incrémentation de la variable niveau
 +
  delay_level -= 4; // le jeu devient de plus en plus rapide
 +
 
 +
  if (level >= NUM_OF_LEVELS)   // fin du jeu
 
   {
 
   {
     leds[i] = CRGB::Red;
+
     compute_score(); //Calcul le score
 +
    show_score(); //Affiche le score sur un écran à crystaux liquides
  
     FastLED.show();
+
     //Remise des valeurs pas défaut
     delay(10);
+
    level = 0;     
 +
    score = 0;
 +
    delay_level = 30;
 +
    game_in_progress = false;
 +
     for(int w=0; w<NUM_OF_LEVELS;w++){
 +
      last_point[w] = 0;
 +
    }
 
   }
 
   }
 
}
 
}
  
void reset_leds()  // on éteint toutes les leds
+
void waiting_start_game(){
{
+
   // Allume toutes les LEDs en bleu avant de faire commencer la partie
   for (int i = 0; i < NUM_LEDS; i++)
+
   for (int w = 0; w < NUM_LEDS; w++){
  {
+
     leds[w] = CRGB::Blue;
     leds[i] = CRGB::Black;
 
 
 
 
   }
 
   }
 
   FastLED.show();
 
   FastLED.show();
 
}
 
}
  
void animation_attente()
+
int compute_score(){
{
+
  // Récupere les élements du tableau last_point et les additionnes
    for(int i = 0; i < NUM_LEDS; i++)
+
  for (int i = 0; i<NUM_OF_LEVELS; i++){
     {
+
     if (i > 2) {
       leds[i].red = random(0,255);
+
       // Pour les niveaux 4 et 5, le score est diviser par deux
       leds[i].green = random(0,255);
+
       score += last_point[i] / 2;
       leds[i].blue = random(0,255);
+
    } else {
 +
       score += last_point[i];
 
     }
 
     }
    FastLED.show();
+
  }
 +
  // -------- DEBUGGING -------- //
 +
  /*
 +
  Serial.print("Score : ");
 +
  Serial.println(score);
 +
  */
 +
  return score;
 +
}
 +
 
 +
int show_score(){
 +
  lcd.clear();
 +
  lcd.setCursor(0,0);
 +
  lcd.print("  Score : ");
 +
  lcd.print(score);
 +
  lcd.setCursor(0,1);
 +
  lcd.print("  Bien joue !!"); // Je ne sais pas comment mettre des caractères speciaux (hors ASCII 128)
 +
  delay(5000);
 +
  lcd.clear();
 +
  return 0;
 +
}
 +
 
 +
 
 +
 
 +
 
 +
 
 +
 
 +
// ----- MUSIQUE ----- //
 +
 
 +
int melody[] = {
 +
 
 +
  //Based on the arrangement at https://www.flutetunes.com/tunes.php?id=169
 +
 
 +
  NOTE_AS4,-2,  NOTE_F4,8,  NOTE_F4,8,  NOTE_AS4,8,//1
 +
  NOTE_GS4,16,  NOTE_FS4,16,  NOTE_GS4,-2,
 +
  NOTE_AS4,-2,  NOTE_FS4,8,  NOTE_FS4,8,  NOTE_AS4,8,
 +
  NOTE_A4,16,  NOTE_G4,16,  NOTE_A4,-2,
 +
  REST,1,
 +
 
 +
  NOTE_AS4,4,  NOTE_F4,-4,  NOTE_AS4,8,  NOTE_AS4,16,  NOTE_C5,16, NOTE_D5,16, NOTE_DS5,16,//7
 +
  NOTE_F5,2,  NOTE_F5,8,  NOTE_F5,8,  NOTE_F5,8,  NOTE_FS5,16, NOTE_GS5,16,
 +
  NOTE_AS5,-2,  NOTE_AS5,8,  NOTE_AS5,8,  NOTE_GS5,8,  NOTE_FS5,16,
 +
  NOTE_GS5,-8,  NOTE_FS5,16,  NOTE_F5,2,  NOTE_F5,4,
 +
 
 +
  NOTE_DS5,-8, NOTE_F5,16, NOTE_FS5,2, NOTE_F5,8, NOTE_DS5,8, //11
 +
  NOTE_CS5,-8, NOTE_DS5,16, NOTE_F5,2, NOTE_DS5,8, NOTE_CS5,8,
 +
  NOTE_C5,-8, NOTE_D5,16, NOTE_E5,2, NOTE_G5,8,
 +
  NOTE_F5,16, NOTE_F4,16, NOTE_F4,16, NOTE_F4,16,NOTE_F4,16,NOTE_F4,16,NOTE_F4,16,NOTE_F4,16,NOTE_F4,8, NOTE_F4,16,NOTE_F4,8,
 +
 
 +
  NOTE_AS4,4,  NOTE_F4,-4,  NOTE_AS4,8,  NOTE_AS4,16,  NOTE_C5,16, NOTE_D5,16, NOTE_DS5,16,//15
 +
  NOTE_F5,2,  NOTE_F5,8,  NOTE_F5,8,  NOTE_F5,8,  NOTE_FS5,16, NOTE_GS5,16,
 +
  NOTE_AS5,-2, NOTE_CS6,4,
 +
  NOTE_C6,4, NOTE_A5,2, NOTE_F5,4,
 +
  NOTE_FS5,-2, NOTE_AS5,4,
 +
  NOTE_A5,4, NOTE_F5,2, NOTE_F5,4,
 +
 
 +
  NOTE_FS5,-2, NOTE_AS5,4,
 +
  NOTE_A5,4, NOTE_F5,2, NOTE_D5,4,
 +
  NOTE_DS5,-2, NOTE_FS5,4,
 +
  NOTE_F5,4, NOTE_CS5,2, NOTE_AS4,4,
 +
  NOTE_C5,-8, NOTE_D5,16, NOTE_E5,2, NOTE_G5,8,
 +
  NOTE_F5,16, NOTE_F4,16, NOTE_F4,16, NOTE_F4,16,NOTE_F4,16,NOTE_F4,16,NOTE_F4,16,NOTE_F4,16,NOTE_F4,8, NOTE_F4,16,NOTE_F4,8
 +
 
 +
};
 +
 
 +
void musique(){
 +
  int tempo = 60;
 +
  // sizeof gives the number of bytes, each int value is composed of two bytes (16 bits)
 +
  // there are two values per note (pitch and duration), so for each note there are four bytes
 +
  int notes = sizeof(melody) / sizeof(melody[0]) / 2;
 +
 
 +
  // this calculates the duration of a whole note in ms
 +
  int wholenote = (60000 * 2) / tempo;
 
    
 
    
}
+
  int divider = 0, noteDuration = 0;
void level_up()   // changement de niveau
+
   // iterate over the notes of the melody.
{
+
   // Remember, the array is twice the number of notes (notes + durations)
   flash();  // animation
+
   for (int thisNote = 0; thisNote < notes * 2; thisNote = thisNote + 2) {
  level++;  // incrémentation de la variable niveau
+
 
   delay_level -= 4; // le jeu devient de plus en plus rapide
+
     // calculates the duration of each note
  if (level >= NUM_OF_LEVELS)   // fin du jeu
+
     divider = melody[thisNote + 1];
  {
+
     if (divider > 0) {
    reset_leds();
+
      // regular note, just proceed
     score_leds();  // affichage score
+
       noteDuration = (wholenote) / divider;
     delay(3000);
+
     } else if (divider < 0) {
     reset_leds();
+
      // dotted notes are represented with negative durations!!
    while (!digitalRead(PIN_BTN))  // on attend que l'utilisateur appuie sur un bonton
+
       noteDuration = (wholenote) / abs(divider);
    {
+
      noteDuration *= 1.5; // increases the duration in half for dotted notes
       animation_attente();
 
      delay(200);
 
     }
 
    while (digitalRead(PIN_BTN)// on vérifie que le bouton n'est pas resté appuyé
 
    {
 
       delay(10);
 
 
     }
 
     }
    // on réinitialise le jeu
 
    level = 0;     
 
    reset_leds();
 
    score = 0;
 
    delay_level = 30;
 
  
 +
    // we only play the note for 90% of the duration, leaving 10% as a pause
 +
    tone(PIN_BUZZER, melody[thisNote], noteDuration*0.9);
  
 +
    // Wait for the specief duration before playing the next note.
 +
    delay(noteDuration);
 +
   
 +
    // stop the waveform generation before the next note.
 +
    noTone(PIN_BUZZER);
 
   }
 
   }
 
 
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
Ligne 244 : Ligne 388 :
  
 
===étape 1: câbler et souder===
 
===étape 1: câbler et souder===
câbler les fils entre les leds, la carte arduino et le bouton puis souder les fils si nécessaire
+
câbler les fils entre différents composants (selon le schéma) puis souder les fils si nécessaire et enfin téléverser le programme dans la carte si nécessaire.
  
 
[[Fichier:Cablage.jpg|200px]]
 
[[Fichier:Cablage.jpg|200px]]
  
 
===étape 2: le support===
 
===étape 2: le support===
réaliser le support en coupant et collant les cartons
+
réaliser le prototype en carton
 +
 
 +
 
 +
[[Fichier:Tonk1.jpg|200px]]
 +
[[Fichier:Tonk2.jpg|200px]]
 +
 
 +
===étape 3 : support en bois===
 +
 
 +
On réalise en suite le support en bois.
 +
 
 +
Grâce au prototype en carton on dessine le support en bois puis on reporte les mesures sur des plaques en bois pour ensuite les découper.
 +
 
 +
Une fois les différentes parties du support faites on les assemble.
  
===étape ...===
 
 
===troubleshouting===
 
===troubleshouting===
 
quelles sont difficultés, les problèmes, quelles sont les solutions, les trucs et astuces pour que ça marche ?
 
quelles sont difficultés, les problèmes, quelles sont les solutions, les trucs et astuces pour que ça marche ?
 +
 +
1er problème : le programme ne marchait pas car la LED était montée à l'envers
 +
 +
On a mit la led ans le bon sens puis on a adapté le programme.
 +
 +
2ème problème : adapter la taille du support qui était d'abord trop grand
 +
 +
On a utilisé le support en carton pour créer un support en bois plus petit.
  
 
==Sources et documentation complémentaire==
 
==Sources et documentation complémentaire==
Ligne 259 : Ligne 422 :
 
==ne pas modifier sous cette ligne==
 
==ne pas modifier sous cette ligne==
 
[[Catégorie:Enib2024]]
 
[[Catégorie:Enib2024]]
 +
[[Catégorie:N]]

Version actuelle datée du 6 mars 2024 à 15:13

description

Ce projet fonction grâce à une carte Arduino, des LEDs et un bouton.

Une lumière traverse le ruban de gauche à droite et lorsqu'elle est au milieu, il faut appuyer sur le bouton au bon moment pour gagner.

réalisé par :

-Arnaud Genty
-Maxime Bintein
-Tristan Le Coz

Introduction

éventuelle vidéo

Liste des composants

  • Bouton poussoir style Arcade
  • Arduino nano
  • 2 rubans de LED adressable (85 LEDs pour être exacte)
  • Carton
  • Bois
  • Câbles mini-USB
  • Câbles
  • écran LCD
  • Breadboard
  • 2 résistances de 500kΩ
  • Buzzer

Outils

  • Cutter
  • Marqueur noir
  • Pistolet à colle
  • Scotch
  • Fer à souder
  • Scie à bois
  • Perceuse
  • Bibliothèque Arduino FastLed
 https://fastled.io/

Code :

  1  
  2 
  3 //Programme fait sur carte STM8266 / WEMOS D1 mini
  4 #include "pitches.h"
  5 #include "FastLED.h"                    //bibliothèque pour controler le ruban led
  6 #include <Wire.h>                  //bibliothèque écran
  7 #include <LiquidCrystal_I2C.h>     //bibliothèque écran
  8 #define REST 0
  9 #define NUM_LEDS 86
 10 #define NUM_OF_LEDS_BY_LEVEL 17         // nombre de leds par niveau
 11 #define NUM_OF_LEVELS 5                  // nombre de niveaux
 12 #define PIN_BTN D3                       // Entree du bouton
 13 #define PIN_LEDS D4                      // Sortie du ruban led
 14 #define PIN_BUZZER D8                    // Signal de sortie buzzer
 15 
 16 
 17 // -------- INIT VARIABLES --------
 18 LiquidCrystal_I2C lcd(0x27, 16, 2);
 19 CRGB leds[NUM_LEDS]; //Création d'une liste avec chaque led
 20 CRGB randomcolor  = CHSV(random(192), 255, 255);
 21 int level = 0;        // niveau auquel le joueur est
 22 int delay_level = 30; // délai qui permet de controler la vitesse de déplacement de la led
 23 auto color = CRGB::Blue; // couleur de la led qui se déplace
 24 int score = 0;           // score du joueur
 25 const double coef[] = {1,1.5,2,2.5,3}; // coefficient multiplicateur de point par niveau
 26 int last_point[NUM_OF_LEVELS];     // sauvegarde de la derniere led allumée pour la rallumer après flash()
 27 bool game_in_progress = false;
 28 int last_point_visu = 0;
 29 
 30 
 31 
 32 // -------- INIT FONCTIONS --------
 33 
 34 int move();            // déplacement de la led
 35 void level_up();    // passage de niveau
 36 void waiting_start_game(); //affichage d'attente de début du jeu
 37 void flash();       // animation de victoire d'un niveau
 38 
 39 // -------- PROGRAMME --------
 40 void setup() {
 41   FastLED.addLeds<NEOPIXEL, D4>(leds, NUM_LEDS);     // setup du ruban de led sur la sortie PIN_LEDS => 2
 42   pinMode(PIN_BTN, INPUT);                          // setup du bouton dur l'entrée PIN_BTN => 3
 43   FastLED.setBrightness(50);                    // setup de la luminosité
 44   Serial.begin(9600);                               // setup moniteur série pour debug 
 45   int last_point[NUM_OF_LEVELS];
 46   pinMode(PIN_BUZZER, OUTPUT);
 47 
 48   // -------- ECRAN --------
 49   lcd.init();                        // Initialize I2C LCD module
 50   lcd.backlight();                   // Turn backlight ON
 51 }
 52 
 53 
 54 void loop() {
 55   waiting_start_game();
 56     lcd.setCursor(0,0);
 57     lcd.print("    Cliquer ");
 58     lcd.setCursor(0,1);
 59     lcd.print(" pour commencer");
 60     FastLED.clear();
 61   if (digitalRead(PIN_BTN)==LOW){
 62     musique();
 63     game_in_progress = true;
 64     lcd.clear();
 65     lcd.setCursor(0,0);
 66     lcd.print("Partie en cours !");
 67     lcd.setCursor(0,1);
 68     lcd.print("XoXoXoXoXoXoXoXo");
 69     FastLED.clear();
 70     delay(400);
 71     while(game_in_progress){
 72       move();
 73       if (digitalRead(PIN_BTN)==LOW && game_in_progress==true){
 74         level_up();
 75       }
 76     }
 77   }
 78 }
 79 
 80 
 81 int move(){
 82   // Permet de faire bouger la LED de gauche à droite
 83   for (int i = NUM_OF_LEDS_BY_LEVEL * level; i <= (NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL - 1); i++){
 84     // -------- DEBUGGING -------- // 
 85     /*
 86     Serial.print("val de la led: ");
 87     Serial.print(i);
 88     Serial.print("\n");
 89     */
 90     if (digitalRead(PIN_BTN)==LOW){     //Stock des scores LEDs 1 -> 9 -> 1
 91       int center = abs(i - (NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL / 2));
 92       if (center <= NUM_OF_LEDS_BY_LEVEL/2) {
 93         last_point[level] = NUM_OF_LEDS_BY_LEVEL/2 - center + 1;  // Les points augmentent jusqu'à 9
 94       } else {
 95         last_point[level] = 0;  // À partir de la position 9, les points diminuent
 96       }
 97     //   if(i<(1/2*NUM_OF_LEDS_BY_LEVEL)){
 98     //     last_point[level] = i;
 99     //   }
100     //   else{
101     //     for(int degr = 1; degr<NUM_OF_LEDS_BY_LEVEL; degr++)
102     //     last_point[level] = (i - degr);
103       
104     // }
105       int last_point_visu = i-1;
106       return i-1;
107       // -------- DEBUGGING -------- //
108       /*
109       Serial.print("last_point_visu");
110       Serial.print(last_point_visu);
111        
112       for(int z=0; z<NUM_OF_LEVELS; z++){
113         Serial.print(last_point[z]);
114         Serial.print("\n");
115       }
116       */
117       
118       
119     }
120     //Eteins les LEDs derrière la LED mouvante
121     leds[i - 1] = CRGB::Black;
122     delay(3);
123     leds[level * NUM_OF_LEDS_BY_LEVEL + NUM_OF_LEDS_BY_LEVEL / 2] = CRGB::Yellow;
124     leds[i] = color;
125     FastLED.show();
126     delay(delay_level);
127   }
128   leds[NUM_OF_LEDS_BY_LEVEL * level + 20] = CRGB::Black;
129   FastLED.show();
130   delay(delay_level);
131   for (int i = NUM_OF_LEDS_BY_LEVEL * level +  NUM_OF_LEDS_BY_LEVEL - 1; i >= NUM_OF_LEDS_BY_LEVEL * level ; i--)
132   {
133     // -------- DEBUGGING -------- //
134     /*
135     Serial.print("val de la led: ");
136     Serial.print(i);
137     Serial.print("\n");
138     */
139     if (digitalRead(PIN_BTN)==LOW){           //Stock des scores LEDs 1 -> 9 -> 1
140       int center = abs(i - (NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL / 2));
141       if (center <= NUM_OF_LEDS_BY_LEVEL/2) {
142         last_point[level] = NUM_OF_LEDS_BY_LEVEL/2 - center + 1;  // Les points augmentent jusqu'à 9
143       } else {
144         last_point[level] = 0;  // À partir de la position 9, les points diminuent
145       }
146       // if(i<(1/2*NUM_OF_LEDS_BY_LEVEL)){
147       //   last_point[level] = i;
148       // }
149       // else{
150       //   for(int degr = 1; degr<NUM_OF_LEDS_BY_LEVEL; degr++)
151       //   last_point[level] = (i - degr);
152       //   }
153     
154       int last_point_visu = i+1;
155       return i+1;
156       
157       // -------- DEBUGGING -------- //
158       /*
159       Serial.print("last_point_visu");
160       Serial.print(last_point_visu);
161       
162       for(int z=0; z<NUM_OF_LEVELS; z++){
163         Serial.print(last_point[z]);
164         Serial.print("\n");
165       }
166       */
167       
168     }
169     //Eteins les LEDs derrière la LED mouvante
170     leds[i + 1] = CRGB::Black;
171     delay(3);
172     leds[level * NUM_OF_LEDS_BY_LEVEL + NUM_OF_LEDS_BY_LEVEL / 2] = CRGB::Yellow;
173     leds[i] = color;
174     FastLED.show();
175     delay(delay_level);
176   }
177     leds[NUM_OF_LEDS_BY_LEVEL] = CRGB::Black;
178     FastLED.show();
179     delay(delay_level);
180   return 0;
181 }
182 
183 void flash()   // fonction de décoration qui fait clignoter les leds en blanc avant le passage de niveau
184 {
185   for (int cpt = 0; cpt < 4; cpt++) 
186   {
187     for (int i = NUM_OF_LEDS_BY_LEVEL * level; i <= (NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL - 1); i++)  // On met toute les leds du niveau en blanc
188     {
189       leds[i] = CRGB::Green;
190     }
191     FastLED.show();
192     delay(100);
193     for (int i = NUM_OF_LEDS_BY_LEVEL * level; i <= (NUM_OF_LEDS_BY_LEVEL * level + NUM_OF_LEDS_BY_LEVEL - 1); i++) // On éteint toutes les leds du niveau
194     {
195       leds[i] = CRGB::Black;
196     }
197     FastLED.show();
198     delay(100);
199   }
200   leds[last_point_visu] = CRGB::Purple;
201 }
202 
203 void level_up()   // changement de niveau
204 {
205   flash();  // animation
206   level++;  // incrémentation de la variable niveau
207   delay_level -= 4; // le jeu devient de plus en plus rapide
208 
209   if (level >= NUM_OF_LEVELS)   // fin du jeu
210   {
211     compute_score(); //Calcul le score
212     show_score(); //Affiche le score sur un écran à crystaux liquides
213 
214     //Remise des valeurs pas défaut
215     level = 0;      
216     score = 0;
217     delay_level = 30;
218     game_in_progress = false;
219     for(int w=0; w<NUM_OF_LEVELS;w++){
220       last_point[w] = 0;
221     }
222   }
223 }
224 
225 void waiting_start_game(){
226   // Allume toutes les LEDs en bleu avant de faire commencer la partie
227   for (int w = 0; w < NUM_LEDS; w++){
228     leds[w] = CRGB::Blue;
229   }
230   FastLED.show();
231 }
232 
233 int compute_score(){
234   // Récupere les élements du tableau last_point et les additionnes
235   for (int i = 0; i<NUM_OF_LEVELS; i++){
236     if (i > 2) {
237       // Pour les niveaux 4 et 5, le score est diviser par deux
238       score += last_point[i] / 2;
239     } else {
240       score += last_point[i];
241     }
242   }
243   // -------- DEBUGGING -------- //
244   /*
245   Serial.print("Score : ");
246   Serial.println(score);
247   */
248   return score;
249 }
250 
251 int show_score(){
252   lcd.clear();
253   lcd.setCursor(0,0);
254   lcd.print("   Score : ");
255   lcd.print(score);
256   lcd.setCursor(0,1);
257   lcd.print("  Bien joue !!"); // Je ne sais pas comment mettre des caractères speciaux (hors ASCII 128)
258   delay(5000);
259   lcd.clear();
260   return 0;
261 }
262 
263 
264 
265 
266 
267 
268 // ----- MUSIQUE ----- // 
269 
270 int melody[] = {
271 
272   //Based on the arrangement at https://www.flutetunes.com/tunes.php?id=169
273   
274   NOTE_AS4,-2,  NOTE_F4,8,  NOTE_F4,8,  NOTE_AS4,8,//1
275   NOTE_GS4,16,  NOTE_FS4,16,  NOTE_GS4,-2,
276   NOTE_AS4,-2,  NOTE_FS4,8,  NOTE_FS4,8,  NOTE_AS4,8,
277   NOTE_A4,16,  NOTE_G4,16,  NOTE_A4,-2,
278   REST,1, 
279 
280   NOTE_AS4,4,  NOTE_F4,-4,  NOTE_AS4,8,  NOTE_AS4,16,  NOTE_C5,16, NOTE_D5,16, NOTE_DS5,16,//7
281   NOTE_F5,2,  NOTE_F5,8,  NOTE_F5,8,  NOTE_F5,8,  NOTE_FS5,16, NOTE_GS5,16,
282   NOTE_AS5,-2,  NOTE_AS5,8,  NOTE_AS5,8,  NOTE_GS5,8,  NOTE_FS5,16,
283   NOTE_GS5,-8,  NOTE_FS5,16,  NOTE_F5,2,  NOTE_F5,4, 
284 
285   NOTE_DS5,-8, NOTE_F5,16, NOTE_FS5,2, NOTE_F5,8, NOTE_DS5,8, //11
286   NOTE_CS5,-8, NOTE_DS5,16, NOTE_F5,2, NOTE_DS5,8, NOTE_CS5,8,
287   NOTE_C5,-8, NOTE_D5,16, NOTE_E5,2, NOTE_G5,8, 
288   NOTE_F5,16, NOTE_F4,16, NOTE_F4,16, NOTE_F4,16,NOTE_F4,16,NOTE_F4,16,NOTE_F4,16,NOTE_F4,16,NOTE_F4,8, NOTE_F4,16,NOTE_F4,8,
289 
290   NOTE_AS4,4,  NOTE_F4,-4,  NOTE_AS4,8,  NOTE_AS4,16,  NOTE_C5,16, NOTE_D5,16, NOTE_DS5,16,//15
291   NOTE_F5,2,  NOTE_F5,8,  NOTE_F5,8,  NOTE_F5,8,  NOTE_FS5,16, NOTE_GS5,16,
292   NOTE_AS5,-2, NOTE_CS6,4,
293   NOTE_C6,4, NOTE_A5,2, NOTE_F5,4,
294   NOTE_FS5,-2, NOTE_AS5,4,
295   NOTE_A5,4, NOTE_F5,2, NOTE_F5,4,
296 
297   NOTE_FS5,-2, NOTE_AS5,4,
298   NOTE_A5,4, NOTE_F5,2, NOTE_D5,4,
299   NOTE_DS5,-2, NOTE_FS5,4,
300   NOTE_F5,4, NOTE_CS5,2, NOTE_AS4,4,
301   NOTE_C5,-8, NOTE_D5,16, NOTE_E5,2, NOTE_G5,8, 
302   NOTE_F5,16, NOTE_F4,16, NOTE_F4,16, NOTE_F4,16,NOTE_F4,16,NOTE_F4,16,NOTE_F4,16,NOTE_F4,16,NOTE_F4,8, NOTE_F4,16,NOTE_F4,8
303   
304 };
305 
306 void musique(){
307   int tempo = 60;
308   // sizeof gives the number of bytes, each int value is composed of two bytes (16 bits)
309   // there are two values per note (pitch and duration), so for each note there are four bytes
310   int notes = sizeof(melody) / sizeof(melody[0]) / 2;
311   
312   // this calculates the duration of a whole note in ms
313   int wholenote = (60000 * 2) / tempo;
314   
315   int divider = 0, noteDuration = 0;
316   // iterate over the notes of the melody. 
317   // Remember, the array is twice the number of notes (notes + durations)
318   for (int thisNote = 0; thisNote < notes * 2; thisNote = thisNote + 2) {
319 
320     // calculates the duration of each note
321     divider = melody[thisNote + 1];
322     if (divider > 0) {
323       // regular note, just proceed
324       noteDuration = (wholenote) / divider;
325     } else if (divider < 0) {
326       // dotted notes are represented with negative durations!!
327       noteDuration = (wholenote) / abs(divider);
328       noteDuration *= 1.5; // increases the duration in half for dotted notes
329     }
330 
331     // we only play the note for 90% of the duration, leaving 10% as a pause
332     tone(PIN_BUZZER, melody[thisNote], noteDuration*0.9);
333 
334     // Wait for the specief duration before playing the next note.
335     delay(noteDuration);
336     
337     // stop the waveform generation before the next note.
338     noTone(PIN_BUZZER);
339   }
340 }

étapes de fabrication

étape 1: câbler et souder

câbler les fils entre différents composants (selon le schéma) puis souder les fils si nécessaire et enfin téléverser le programme dans la carte si nécessaire.

Cablage.jpg

étape 2: le support

réaliser le prototype en carton


Tonk1.jpg Tonk2.jpg

étape 3 : support en bois

On réalise en suite le support en bois.

Grâce au prototype en carton on dessine le support en bois puis on reporte les mesures sur des plaques en bois pour ensuite les découper.

Une fois les différentes parties du support faites on les assemble.

troubleshouting

quelles sont difficultés, les problèmes, quelles sont les solutions, les trucs et astuces pour que ça marche ?

1er problème : le programme ne marchait pas car la LED était montée à l'envers

On a mit la led ans le bon sens puis on a adapté le programme.

2ème problème : adapter la taille du support qui était d'abord trop grand

On a utilisé le support en carton pour créer un support en bois plus petit.

Sources et documentation complémentaire

ne pas modifier sous cette ligne