Batak Machine: l'entrainement aux réflexes

image principale Batak Machine: l'entrainement aux réflexes

Difficulté:

Tutoriel pour construire une machine à réflexes dont le but est de taper le plus rapidement possible des lumières qui s'allument aléatoirement. Cette machine est utilisée par les pilotes de formule 1 pour améliorer leurs réflexes. Plus modestement nous l'utiliserons pour la kermesse d'une école primaire. Ce tutoriel contient l'explication de la fabrication de ce jeu ainsi que le code en langage arduino utilisé.

Le but était de créer une Batak Machine comme celles que les coureurs de formule 1 utilisent mais qui puisse être adaptée pour l'usage des enfants ainsi que des durées de jeu variables pour jouer plus tranquillement ou se donner à fond. Un menu maintenance est caché afin de pouvoir faire face aux problèmes pouvant survenir permettant de vérifier le bon fonctionnement des  lumières, des boutons, du haut parleur, mais aussi pour remettre à zéro les meilleurs scores.


Matériel :

Budget : 120€

  • 1 Arduino Mega (disponible ici)
  • 1 fils et connecteurs divers
  • 1 haut parleur
  • 1 alimentation 5V (disponible ici)
  • 1 alimentation 15V (disponible ici)
  • 1 afficheur LCD avec son interface (disponible ici)
  • 2 Cable en nappe avec connecteurs 16 broches
  • 3 plaques d'essai
  • 12 Boutons lumineux arcade 60mm
  • 12 transistors 2N7000
  • 12 condensateurs de 47 à 100nF
  • 12 résistances 100Ω
  • 12 leds haute puissance
  • 24 résistances 10kΩ
  • 30 borniers

Etape 1 : La carte des sorties

On utilise pour le projet des boutons d'arcade lumineux 60mm. (Si vous avez les moyens il existe des boutons de 100mm qui éclairent correctement d'origine mais ils sont très chers) Afin d'avoir une luminosité suffisante des boutons, nous avons utilisé des leds haute puissance automobiles qui s'alimentent entre 12 et 15V car la led fournie avec le bouton n'éclaire pas suffisamment. Nous alimenterons ces leds avec une tension de 15V et une intensité de 60mA. L'arduino ne pouvant sortir cette tension nous devons réaliser une interface à l'aide de transistors mosfet 2N7000. 

On réalisera 12 fois le même montage pour les 12 leds sur la plaquette véroboard. On la relie avec un cable en nappe sur les pins de l'arduino.

Etape 2 : La carte des entrées

C'est un montage classique d'anti-rebons des boutons poussoirs. On le réalise 12 fois pour les 12 boutons comme dans la photo de la plaquette. On la relie avec un cable en nappe sur les pins de l'arduino. Sur la photo 3 j'ai mesuré à l’oscilloscope ce qui se passe lors de l'appui sur un bouton, on voit bien les rebonds de l'interrupteur cela peut poser des problèmes car l'arduino reçoit plusieurs appuis du bouton, c'est pour cela que l'on utilise des condensateurs. Sur la photo 4 avec les condensateurs il n'y a plus de rebonds.

Etape 3 : Les alimentations 5 et 15V

Il s'agit de simples régulateurs LM7805 et LM7815 alimentés par un transformateur 14V redressés par un pont d'iode et filté par un condensateur 2200µF.

Etape 4 : La structure

La taille de la plaque est de 120x120cm. Chacun pourra laisser ses talents de menuisier s'exprimer. Bien respecter l'implantation des boutons comme sur le schéma.

Etape 5 : L'assemblage

Les interconnections de l'arduino avec le reste:

  • On relie la carte des sorties aux pins 33; 31; 29; 27; 25; 23; 22; 24; 26; 28; 30; 32 de l'arduino avec le câble en nappe respectivement aux leds 1 à 12. (bien respecter l'ordre des pins avec les numéros des boutons comme dans le schéma)
  • On relie la carte des entrées aux pins 53; 51; 49; 47; 45; 43; 42; 44; 46; 48; 50; 52  de l'arduino avec le câble en nappe respectivement aux boutons 1 à 12. (bien respecter l'ordre des pins avec les numéros des boutons comme dans le schéma)
  • Voir photo pour le LCD et son interface I2C. (Comment faire ?) (SDA en pin 20 et SCL en pin 21)
  • Haut-parleur sur la pin 34
  • L'ordre des pins a été choisi judicieusement pour pouvoir utiliser du câble en nappe pour relier l'arduino avec les interfaces.
Etape 6 : Description du mode de fonctionnement

 Mode de fonctionnement : On allume un bouton aléatoirement qu’on doit éteindre en appuyant dessus ; on marque un point à chaque réussite. Si pas d’appui pendant 2 secondes on change de bouton. Le score final est le total de bouton éteint.

Road map :

Plusieurs modes de jeu :             - Mode 12 boutons

                                                          -Mode 8 boutons (pour les enfants de petite taille)

                                                           -2 durées 60 et 30 secondes

Mise en mémoire des meilleurs scores par catégorie même après extinction (EEprom)

Des musiques d’animation a l’allumage et a chaque incrémentation d’un best score

Un menu caché de maintenance pour tester toutes les fonctions (boutons/leds) et RAZ les bestscores

Visualisation du score et des commandes sur un écran LCD


Ceci est mon premier programme arduino, vous noterez une evolution du code au fur et à mesure de mon apprentissage (surtout au niveau du nom des variables et de l'utilisation des fonctions sur la fin du programme).

Ce projet m'a permis de découvrir plusieurs domaines de l'arduino en étant confronté aux problèmes de réalisation comme les tableaux la gestion du temps et les fonctions que l'expliquerai plus en détail dans les prochaines parties.

Etape 7 : La gestion des boutons

L'entree est branchée au + par une résistance pullup, et le bouton met cette entréee a la masse lors d'un appui. Ce qui donne un état LOW. Ce qu'il faut savoir pour gérer les boutons, c'est qu'il ne faut pas oublier de les bloquer. En effet si on fait simplement un if(digitalRead(bouton) == LOW) et que l'on met la condition elle se réalisera de nombreuses fois. à la fin de la condition il faut donc introduire un while qui bloquera le programme dans une boucle le temps que le bouton se relâche comme ceci.

boolean x = 0;
const byte bouton = 3;//pin du bouton = 3
const byte led = 12;//pin de la led = 12
void setup(){
pinMode(led, OUTPUT);//on initialise la led en tant que sortie
pinMode(bouton, INPUT);//on initialise le bouton en tant qu'entrée
}
void loop(){
if(digitalRead(bouton) == LOW){x=!x;}//Si le bouton est appuyé on switch la variable
while(digitalRead(bouton) == LOW){}//on attend que le bouton soit relâché
if(x==0){digitalWrite(led, HIGH);}//si la variable vaut 0 on éteint la lumière
if(x==1){digitalWrite(led, LOW);}//si elle vaut 1 on l'allume
}

Voilà un petit programme pour switch une led allumée et éteinte avec un seul bouton par exemple.

Etape 8 : Les tableaux / listes

Pour pouvoir choisir un bouton à allumer aléatoirement, il est plus facile d'utiliser les tableaux. Les tableaux sont des variables qui en contiennent plusieurs, et on peut ensuite appeler une variable du tableau en appelant le nom du tableau suivi du numéro de la variable (les numéros commencent par 0). Ainsi pour choisir un bouton aléatoirement on n'a plus qu'a choisir un nombre entre 0 et 11.

Pour déclarer on déclare le type de variables que l'on retrouve dans le tableau et on met des crochets après le nom du tableau et on met les variables du tableau entre crochets et on les sépare par des virgules.

char bouton[] = {53, 51, 49, 47, 45, 43, 42, 44, 46, 48, 50, 52}; // Pins des boutons respectivement de 1 a 12
char led[] = {33, 31, 29, 27, 25, 23, 22, 24, 26, 28, 30, 32}; // Pins des Leds respectivement de 1 a 12

Pour les appeler on fait ensuite comme ceci.

// Initialisation des entree sorties
for(int i = 0; i < 12; i ++){
pinMode(led[i], OUTPUT);
pinMode(bouton[i], INPUT);
digitalWrite(led[i], LOW);
}

Pour appeler un bouton aléatoirement on peut donc faire:

Serial.begin(9600);
randomSeed(analogRead(0)); // Initialisation de la graine aléatoire utilisée
alea = random(0, 12);//on choisi un numéro aléatoire de bouton entre 0 et 11
Serial.print(bouton[alea]);
Etape 9 : La gestion du temps

Parfois, on a besoin d'attendre dans le programme mais on ne peut pas utiliser la fonction delay car on a besoin que quelque chose d'autre s'effectue en arrière plan. On a donc besoin d'utiliser la fonction millis(), cette fonction permet de donner le nombre de millisecondes écoulées depuis le lancement du programme. Ainsi en sauvegardant cette valeur dans une variable on peut calculer la différence entre cette variable et la nouvelle valeur de millis() pour calculer une durée.

temps = millis();//on sauvegarde la référence de temps
score = 0;
while((millis() - temps) < (1000 * 60)){//on regarde si la durée de la partie est écoulé

Ainsi dans cet extrait du code la partie continue tant que 60 secondes ne sont pas écoulées.
Vous verrez dans le programme final que j'utilise beaucoup de variables pour le temps.

Etape 10 : Les fonctions

Les fonctions permettent d'appeler une partie de programme plus simplement dans un programme. Cela permet d’améliorer la clarté ou diminuer les répétitions. Par exemple dans ce programme on défini une fonction qui allume tous les boutons ou éteints tous les boutons.

void allumetout(){
  testleds=!testleds;
  if(testleds==1){for(int i = 0; i < 12; i++){
    digitalWrite(led[i], HIGH);}}
  if(testleds==0){for(int i = 0; i < 12; i++){
    digitalWrite(led[i], LOW);}}
}

On déclare la fonction en utilisant void puis le nom de la fonction des parenthèses et on ouvre l'accolade. Ensuite pour l'appeler on écrit le nom de la fonction avec des parenthèses comme ceci.

allumetout();

Les fonctions ont été utilisées pour la fin du programme principalement dans le menu maintenance.

Etape 11 : Sauvegarde du meilleur score dans EEPROM

Nous voulons conserver les meilleurs scores même lorsque la machine est éteinte, il faut donc les stocker dans des mémoires non volatiles de l'arduino. La mémoire EEPROM est une mémoire qui ne s’efface pas lorsque le programme s'arrête on peut donc stocker les meilleurs scores dedans. On ne s'en sert pas souvent car la mémoire EEPROM à un nombre d'écritures limité (25000) et elle n'est pas très rapide, ce qui convient bien pour stocker un meilleur score.

#include <EEPROM.h> // ajout de la librairie EEPROM pour sauvegarder les meilleurs scores

Pour écrire dedans on utilise la commande EEPROM.write(); le premier nombre est le slot de mémoire dans lequel on écrit et le deuxième est la valeur que l'on stocke.

if(score > bestScore){
bestScore = score;
if(temps4 == 0 && niveau == 0){EEPROM.write(0, bestScore);}
if(temps4 == 1 && niveau == 0){EEPROM.write(1, bestScore);}
if(temps4 == 0 && niveau == 1){EEPROM.write(2, bestScore);}
if(temps4 == 1 && niveau == 1){EEPROM.write(3, bestScore);}

Et on lit les variables EEPROM avec la commande EEPROM.read(); avec le numéro du slot que l'on souhaite.

// Lecture des meilleurs scores
bestScore30lv1 = EEPROM.read(0);                                                    
bestScore60lv1 = EEPROM.read(1);
bestScore30lv2 = EEPROM.read(2);
bestScore60lv2 = EEPROM.read(3);
Etape 12 : Le code

Maintenant vous voilà prêts pour le code je vous le présente ici j'ai commenté presque tout, si vous avez des questions dessus je peux y répondre avec plaisir.

// Declaration des variables

char menu = 0;
boolean testleds = 0;
long temps;//t0 stockage des millisecondes du début de la partie (référence du temps)
long temps2;//variable pour vérifier si 2 secondes passent entre chaque appui de bouton
long temps3 = 0;//durée de la partie jusqu'a maintenant en secondes
boolean temps4 = 0;//0 si 30 secondes 1 si 60 secondes
long temps5;//durée de la partie 30 ou 60 secondes
long temps6;//3 secondes avant la fin de la partie
long temps7;//variable pour tone a chaque secondes quand il en reste moins de 3
boolean x;//inconnue à trouver
boolean niveau;//0 Si facile et 1 si difficile
char niveau2;//le nombre de boutons (12 ou 8) en fonction de la difficulté (1 ou 0)
byte bestScore;
byte bestScore30lv1;//Meilleur score 30 secondes 8 boutons
byte bestScore60lv1;//Meilleur score 60 secondes 8 boutons
byte bestScore30lv2;//Meilleur score 30 secondes 12 boutons
byte bestScore60lv2;//Meilleur score 60 secondes 12 boutons
char alea;//numéro du bouton aléatoire qui s'allume
long score;//score

int Son[] = {262, 294, 330, 349, 392, 440, 494, 523, 587, 659, 698, 784}; // notes pour musique de début

// Declaration des sorties

const int buzzer = 34; //haut parleur à la pin 34
char led[] = {33, 31, 29, 27, 25, 23, 22, 24, 26, 28, 30, 32}; // Pins des Leds respectivement de 1 a 12
char led1 = 33; //led du bouton niveau
char led2 = 31; //led du bouton start
char led3 = 29; //led du bouton temps

// Declaration des entrees

char bouton[] = {53, 51, 49, 47, 45, 43, 42, 44, 46, 48, 50, 52}; // Pins des boutons respectivement de 1 a 12
char boutonNiveau = 53;  // bouton niveau
char boutonStart = 51;  // bouton start
char boutonTemps = 49;  // bouton temps

// Declaration des notes pour musique best score

unsigned int C6 = 1047;
unsigned int Ab5 = 831;
unsigned int Bb5 = 932;
unsigned int G5 = 784;
unsigned int F5 = 698;
unsigned int E5 = 659;
unsigned int Eb5 = 622;
unsigned int D5 = 587;
unsigned int Db5 = 554;
unsigned int C5 = 523;
unsigned int B4 = 494;
unsigned int Bb4 = 466;
unsigned int nA4 = 440;
unsigned int Ab4 = 415;
unsigned int G4 = 392;
unsigned int Gb4 = 370;
unsigned int F4 = 349;
unsigned int E4 = 330;
unsigned int Eb4 = 311;
unsigned int D4 = 294;
unsigned int Db4 = 277;
unsigned int C4 = 262;
unsigned int B3 = 247;
unsigned int Bb3 = 233;
unsigned int nA3 = 220;
unsigned int GS3 = 208;
unsigned int G3 = 196;
unsigned int Gb3 = 185;
unsigned int F3 = 175;
unsigned int E3 = 165;
char speakerPin = 34;

// Inclusion des librairies

#include <EEPROM.h> // ajout de la librairie EEPROM pour sauvegarder les meilleurs scores
#include <Wire.h>  // ajout de la librairie I2C pour communiquer avec le LCD
#include <LiquidCrystal_I2C.h> // ajout de la librairie LCD
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Adresse I2C 0x27 a remplacer par la votre si differente


void setup(){
// Initialisation des entree sorties
for(int i = 0; i < 12; i ++){
pinMode(led[i], OUTPUT);
pinMode(bouton[i], INPUT);
digitalWrite(led[i], LOW);
}

lcd.begin(20,4);  // Initialisation du LCD
randomSeed(analogRead(0)); // Initialisation de la graine aléatoire utilisée
niveau = 0; //mode facile (8 boutons) par défaut
pinMode(buzzer, OUTPUT); //initialisation du haut parleur en tant que sortie

// Animation a l'allumage

//on allume toutes les leds une par une avec un bruit
for(char i=0; i<sizeof(led); i++) {           
digitalWrite(led[i], HIGH);
tone(buzzer, Son[i]);
delay(300);
}
// on coupe le son et on attend un peu
noTone(buzzer);
delay(150);
// puis on les éteint de même, mais plus rapidement
for(char i=sizeof(led); i>0; i--) {
tone(buzzer, Son[i-1]);
delay(150);
digitalWrite(led[i-1], LOW);
}
// ainsi que le son
noTone(buzzer);
}


void loop(){
x = 0;
temps3 = 0;
temps6 = 3;
// Lecture des meilleurs scores
bestScore30lv1 = EEPROM.read(0);                                                    
bestScore60lv1 = EEPROM.read(1);
bestScore30lv2 = EEPROM.read(2);
bestScore60lv2 = EEPROM.read(3);

// Alumages des 3 boutons du menu
digitalWrite(led2, HIGH);                                                       
digitalWrite(led1, HIGH);
digitalWrite(led3, HIGH);

//tant que on n'a pas démarré la partie (appuyé sur start)
while(digitalRead(boutonStart) == HIGH){                                        
if(digitalRead(bouton[11]) == LOW && digitalRead(bouton[10])==LOW){           
modeusine();}// Si 11 et 12 apuyés passer en menu maintenance

// Affichage du menu sur LCD
lcd.setCursor(0,0);                                                           
lcd.print("Press Start to begin");
lcd.setCursor(0,1);
if(niveau == 0){
lcd.print("Facile 8 boutons");
}
else{
lcd.print("Difficile 12 boutons");
}
lcd.setCursor(0,2);
lcd.print("Duree:");
lcd.print(temps5);
lcd.print(" Secondes");
lcd.setCursor(0,3);
lcd.print("Score:");
lcd.print(score);
lcd.print(" ");
lcd.print("Best:");
lcd.print(bestScore);
lcd.print("  ");

//Changer la Durée
if(digitalRead(boutonTemps) == LOW){
temps4 = !temps4;
while(digitalRead(boutonTemps) == LOW) {}
}

//changer la difficulté (nombre de boutons)
if(digitalRead(boutonNiveau) == LOW){
lcd.setCursor(0,1);
lcd.print("                    ");
niveau = !niveau;
while(digitalRead(boutonNiveau) == LOW){}
}
//Changer niveau2(nombre de boutons) en fonction de niveau (difficulté)
if(niveau == 1){
niveau2 = 12;
}
else{
niveau2 = 8;
}

//Changer temps5(durée) en fonction de temps4 (0 si 30 sec et 1 si 60 sec)
if(temps4 == 1){
temps5 = 60;
}
else{
temps5 = 30;
}

//affichage du Meilleur score en fonction du mode choisi
if(temps4 == 0 && niveau == 0){bestScore = bestScore30lv1;}
if(temps4 == 1 && niveau == 0){bestScore = bestScore60lv1;}
if(temps4 == 0 && niveau == 1){bestScore = bestScore30lv2;}
if(temps4 == 1 && niveau == 1){bestScore = bestScore60lv2;}
}

//La partie commence
lcd.clear();
//On éteint les leds du menu
digitalWrite(led2, LOW);
digitalWrite(led1, LOW);
digitalWrite(led3, LOW); 

//décompte au démarage
for(int i = 0; i < 3; i++){
tone(buzzer, 1000);
delay(200);
for(int i = 0; i < niveau2; i ++){
digitalWrite(led[i], HIGH);}
noTone(buzzer);
delay(800);
for(int i = 0; i < niveau2; i ++){
digitalWrite(led[i], LOW);}
}
tone(buzzer, 2500);
delay(1000);
noTone(buzzer);
//fin décompte au démarage
//initialisation du temps
temps = millis();//on sauvegarde la référence de temps
temps2 = millis();
x = 0;
score = 0;
while((millis() - temps) < (1000 * temps5)){//on regarde si la durée de la partie est écoulé
alea = random(0, niveau2);//on choisi un numéro aléatoire de bouton à allumer entre 0 et le nombre de boutons total
digitalWrite(led[alea], HIGH);//on allume la led correspondant au bouton choisi aléatoirement
//tant que l'on à appuyé sur aucun bouton et que 2 secondes ne sont pas passées
while(digitalRead(bouton[0]) == HIGH && digitalRead(bouton[1]) == HIGH && digitalRead(bouton[2]) == HIGH && digitalRead(bouton[3]) == HIGH && digitalRead(bouton[4]) == HIGH && digitalRead(bouton[5]) == HIGH && digitalRead(bouton[6]) == HIGH && digitalRead(bouton[7]) == HIGH && digitalRead(bouton[8]) == HIGH && digitalRead(bouton[9]) == HIGH && digitalRead(bouton[10]) == HIGH && digitalRead(bouton[11]) == HIGH && (temps2 + 2000) > millis()){
//Le lcd affiche le score et le temps restant
//on affiche le score
lcd.setCursor(0,0);
lcd.print("Score=");
lcd.print(score);
//on affiche le temps restant
lcd.setCursor(0,1);
lcd.print("Temps Restant:");
if(millis() - temps - (1000 * temps3) > 1000){//si une seconde est passé
temps3++;//on augmente la durée de la partie jusqu'à maintenant d'une seconde
lcd.print("   ");//on clear l'ancienne valeur de temps restant
lcd.setCursor(14,1);//on se place derriere les deux points de "Temps Restant:"
lcd.print(temps5-temps3);//on affiche la nouvelle valeur du temps restant (temps total - temps écoulé)
}

//décompte si il reste moins de 3 secondes (buzz toutes les secondes)
if((millis() - temps) > (1000 * temps5 - (temps6 * 1000))){
temps6--;
tone(buzzer, 1000);
temps7 = millis();//variable pour la durée du buzz (300ms)
}
if(millis() - temps7 > 300){noTone(buzzer);}//au bout de 300ms on arrete le buzz
}//fin du temps que l'on à appuyé sur aucun bouton et que 2 secondes ne sont pas passées

if(digitalRead(bouton[0]) == LOW || digitalRead(bouton[1]) == LOW || digitalRead(bouton[2]) == LOW || digitalRead(bouton[3]) == LOW || digitalRead(bouton[4]) == LOW || digitalRead(bouton[5]) == LOW || digitalRead(bouton[6]) == LOW || digitalRead(bouton[7]) == LOW || digitalRead(bouton[8]) == LOW || digitalRead(bouton[9]) == LOW || digitalRead(bouton[10]) == LOW || digitalRead(bouton[11]) == LOW){
//Si on a appuyé sur un bouton
if(digitalRead(bouton[alea]) == LOW){//et que le bouton appuyé est le bon
score++;
}
}
while(digitalRead(bouton[0]) == LOW || digitalRead(bouton[1]) == LOW || digitalRead(bouton[2]) == LOW || digitalRead(bouton[3]) == LOW || digitalRead(bouton[4]) == LOW || digitalRead(bouton[5]) == LOW || digitalRead(bouton[6]) == LOW || digitalRead(bouton[7]) == LOW || digitalRead(bouton[8]) == LOW || digitalRead(bouton[9]) == LOW || digitalRead(bouton[10]) == LOW || digitalRead(bouton[11]) == LOW){
//tant que on n'a pas lâché le bouton (pour ne pas bloquer l'affichage du temps et pour rester coincé dans une boucle pour ne pas faire un score infini)
//buzz si 3 secondes restantes
if((millis() - temps) > (1000 * temps5 - (temps6 * 1000))){
temps6--;
tone(buzzer, 1000);
temps7 = millis();
}
if(millis() - temps7 > 300){noTone(buzzer);}
//affichage du score et du temps restant
lcd.setCursor(0,0);
lcd.print("Score=");
lcd.print(score);
lcd.setCursor(0,1);
lcd.print("Temps Restant:");
if(millis() - temps - (1000 * temps3) > 1000){
temps3++;
lcd.print("   ");
lcd.setCursor(14,1);
lcd.print(temps5-temps3);
}
}//quand on a enfin lache le bouton
//buzz si 3 secondes restantes
if((millis() - temps) > (1000 * temps5 - (temps6 * 1000))){
temps6--;
tone(buzzer, 1000);
temps7 = millis();
}
if(millis() - temps7 > 300){noTone(buzzer);}
//affichage du score et du temps restant
lcd.setCursor(0,0);
lcd.print("Score=");
lcd.print(score);
lcd.setCursor(0,1);
lcd.print("Temps Restant:");
if(millis() - temps - (1000 * temps3) > 1000){
temps3++;
lcd.print("   ");
lcd.setCursor(14,1);
lcd.print(temps5-temps3);
}
temps2 = millis();//on sauvegarde la référence du temps par rapport aux 2 secondes maximum entre 2 appuis de bouton
digitalWrite(led[alea], LOW);//on éteint la led du bouton qu'il fallait appuyer
}//fin de la partie

//animation fin
for(char i=0; i<12; i++) {//on allume toutes les leds
digitalWrite(led[i], HIGH);
}
// puis on les éteint une à une en jouant le son associé
for(char i=12; i>0; i--) {
tone(buzzer, Son[i-1]);
delay(150);
digitalWrite(led[i-1], LOW);
}
noTone(buzzer);// et on coupe le son
temps2 = millis();
digitalWrite(led[alea], LOW);
if(x == 0){
lcd.clear();
//incrémentation du score si c'est le meilleur
if(score > bestScore){
bestScore = score;
if(temps4 == 0 && niveau == 0){EEPROM.write(0, bestScore);}
if(temps4 == 1 && niveau == 0){EEPROM.write(1, bestScore);}
if(temps4 == 0 && niveau == 1){EEPROM.write(2, bestScore);}
if(temps4 == 1 && niveau == 1){EEPROM.write(3, bestScore);}
musiquebest();//joue la musique du meilleur score
}

}
lcd.print("Score=");
lcd.print(score);
lcd.setCursor(0,1);
lcd.print("Best Score=");
lcd.print(bestScore);
x = !x;
delay(2500);
lcd.clear();
}//fin de la boucle loop on revient au menu

//fait à la fin et à ce moment là j'ai compris l'utilité des fonctions

void modeusine(){
while(digitalRead(bouton[11]) == LOW && digitalRead(bouton[10]) == LOW){}
digitalWrite(led[0], LOW);digitalWrite(led[1], LOW);digitalWrite(led[2], LOW);
while(digitalRead(bouton[11]) == HIGH || digitalRead(bouton[10]) == HIGH){
if(digitalRead(bouton[2]) == LOW){menu++;
while(digitalRead(bouton[2]) == LOW){}}
if(menu>=2){menu=0;}
if(menu==0){
lcd.setCursor(0,0);
lcd.print("Bouton1:On/Off leds ");
lcd.setCursor(0,1);
lcd.print("Bouton2:test boutons");
lcd.setCursor(0,2);
lcd.print("Bouton4:test HP     ");
lcd.setCursor(0,3);
lcd.print("Bouton5:Raz scores  ");
if(digitalRead(bouton[0]) == LOW){while(digitalRead(bouton[0])==LOW){}
allumetout();}
if(digitalRead(bouton[1]) == LOW){while(digitalRead(bouton[1])==LOW){}
testboutons();}
if(digitalRead(bouton[3]) == LOW){while(digitalRead(bouton[3])==LOW){}
musiquebest();}
if(digitalRead(bouton[4]) == LOW){while(digitalRead(bouton[4])==LOW){}
EEPROM.write(0,0); EEPROM.write(1,0); EEPROM.write(2,0); EEPROM.write(3,0);}
}
if(menu==1){
lcd.setCursor(0,0);
lcd.print("Bouton1:Reset 8b30s ");
lcd.setCursor(0,1);
lcd.print("Bouton2:Reset 8b60s ");
lcd.setCursor(0,2);
lcd.print("Bouton4:Reset 12b30s");
lcd.setCursor(0,3);
lcd.print("Bouton5:Reset 12b60s");
if(digitalRead(bouton[0]) == LOW){while(digitalRead(bouton[0])==LOW){}
EEPROM.write(0,0);}
if(digitalRead(bouton[1]) == LOW){while(digitalRead(bouton[1])==LOW){}
EEPROM.write(1,0);}
if(digitalRead(bouton[3]) == LOW){while(digitalRead(bouton[3])==LOW){}
EEPROM.write(2,0);}
if(digitalRead(bouton[4]) == LOW){while(digitalRead(bouton[4])==LOW){}
EEPROM.write(3,0);}

}
}
while(digitalRead(bouton[11]) == LOW && digitalRead(bouton[10]) == LOW){}
digitalWrite(led2, HIGH);
digitalWrite(led1, HIGH);
digitalWrite(led3, HIGH);
lcd.clear();
}
void testboutons(){
if(testleds==1){for(int i = 0; i < 12; i++){
digitalWrite(led[i], LOW);}testleds=!testleds;}
for(int i = 0; i < 12; i++){
digitalWrite(led[i], HIGH);
while(digitalRead(bouton[i]) == HIGH){}
digitalWrite(led[i], LOW);
}
}
void allumetout(){
testleds=!testleds;
if(testleds==1){for(int i = 0; i < 12; i++){
digitalWrite(led[i], HIGH);}}
if(testleds==0){for(int i = 0; i < 12; i++){
digitalWrite(led[i], LOW);}}
}
void musiquebest(){
buzz(speakerPin,G3,166);
buzz(speakerPin,C4,166);
buzz(speakerPin,E4,166);
buzz(speakerPin,G4,166);
buzz(speakerPin,C5,166);
buzz(speakerPin,E5,166);
buzz(speakerPin,G5,500);
buzz(speakerPin,E5,500);
buzz(speakerPin,E3,166);
buzz(speakerPin,C4,166);
buzz(speakerPin,Eb4,166);
buzz(speakerPin,Ab4,166);
buzz(speakerPin,C5,166);
buzz(speakerPin,Eb5,166);
buzz(speakerPin,Ab5,500);
buzz(speakerPin,Eb5,500);
buzz(speakerPin,Bb3,166);
buzz(speakerPin,D4,166);
buzz(speakerPin,F4,166);
buzz(speakerPin,Bb4,166);
buzz(speakerPin,D5,166);
buzz(speakerPin,F5,166);
buzz(speakerPin,Bb5,500);
delay(50);
buzz(speakerPin,Bb5,166);
delay(50);
buzz(speakerPin,Bb5,166);
delay(50);
buzz(speakerPin,Bb5,166);
buzz(speakerPin,C6,1300);
}
void buzz(int targetPin, long frequency, long length) {
long delayValue = 1000000 / frequency / 2; // calculate the delay value between transitions
//// 1 second's worth of microseconds, divided by the frequency, then split in half since
//// there are two phases to each cycle
long numCycles = frequency * length / 1000; // calculate the number of cycles for proper timing
//// multiply frequency, which is really cycles per second, by the number of seconds to
//// get the total number of cycles to produce
for (long i = 0; i < numCycles; i++) { // for the calculated length of time...
digitalWrite(targetPin, HIGH); // write the buzzer pin high to push out the diaphram
delayMicroseconds(delayValue); // wait for the calculated delay value
digitalWrite(targetPin, LOW); // write the buzzer pin low to pull back the diaphram
delayMicroseconds(delayValue); // wait again or the calculated delay value
} 
}

Etape 13 : Place au jeu

Le jeu est très apprécié des grands et des petits et rencontre un franc succès dans la kermesse. Félicitations vous avez réussi à amuser la galerie. 

Mon meilleur score est 110 en 12 boutons et 60 secondes à vous de jouer.

Super tuto ! Depuis le temps que je cherchais un tuto autour de ce projet ! Je vais pouvoir terminer le mien ... ou investir dans un Mega pour faire un vrai batak ;)

un grand merci !

Hate de voir la partie Code pour m'aider a mieux comprendre !

J'avoue ne pas avoir tout compris sur l'électronique mais je vais lire et relire encore ;)

Encore merci

Cyril

Bonjour, merci pour ton commentaire n'hésite pas à poser des questions sur les choses que tu n'as pas comprises, je travaille sur l'explication de la partie code, ça arrive très bientôt. Stay tuned.

T'inquiète pas pour ça ... c'est vrai que la partie électronique semble relativement complexe ... je pensais q'avec de simple bouton arcade lumineux , un écran led ca ferait l'affaire ;) ... et bah nan ! Du coup je vais devoir essayer de comprendre les schémas :)

Bonjour, je vais essayer de me lancer dans l'aventure ... avez vous une liste précise du matos a acheter ?

C'est fait, elle avait disparu.

Tip top merci, j'ai tout commandé !
Dsl detre boulet ^^" mais aurais tu un schéma de l'ensemble de la partie electronique ? je suis pas du tout a l'aise avec ca :x merci d'avance !



Bonjour Odissine, merci beaucoup pour le projet est excellent, je le construis pour le moment, mais j'ai des doutes avec les connexions sur le tableau de contact des boutons et du led, pouvez-vous s'il vous plaît placer une photo de l'arrière? Désolé, mon français, mais je ne le parle pas, j'utilise la traduction. Je vous remercie d'avance

Bonjour, les cartes d'entrées et de sorties sont réalisées en fils volants. Elles dépendront de chacun. Il y a le schéma et les numéros de pins.

Bonjour j'ai mis à jour la liste des composants et des photos qui avaient disparu. N'hésitez pas à poser des questions


bonjour, je voulais recréer votre projet. malheureusement, je reçois une erreur dans la ligne LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);: 'POSITIVE' was not declared in this scope Qu'est-ce que j'ai fait de mal Salutations

Look at the I2C LiquidCrystal folder in your Libraries folder and look at the spelling of the folder name.
If it is spelled "LiquidCrystal_I2C"  it is the wrong library for the display code you are using.
You need fm's library from here :
https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads
When you remove the old library (you can't just rename it) and install fm's library , the new library
folder name will be "LiquidCrystal" , NOT "LiquidCrystal_I2C".

Il semblerait que vous ayez installé la mauvaise librairie liquid crystal.
Regardez dans votre dossier de librairies pour voir le nom du dossier qui contient celle que vous avez installé.
Si le nom est Liquid_Crystal_I2C c'est que vous avez installé la mauvaise, vous pouvez trouver la bonne à cette adresse là.

https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads
Cependant, pour les importer les deux librairies utilisent  #include <LiquidCrystal_I2C.h>, vous devez donc désinstaller la première avant de télécharger la bonne. Le bon nom de dossier pour la librairie est LiquidCrystal.

Bonjour,

un grand merci pour ce tuto, je viens de terminer le miens, les enfants adorent !

Le seul problème c'est que je n'ai pas trouvé la correspondance entre la numérotation BP/LED et la position physique sur le plan de jeux. J'ai pu recaler les boutons START/MODE/DUREE car ils sont facilement identifiable mais pour le mode 8 boutons je ne comprends pas. En effet, les boutons Mode / Duree font a priori partie des boutons à allumer en mode 8 boutons (Ils font parti des 8 qui clignotent au départ), pourtant, les boutons mode et durée sont situés dans la partie haute et donc pas accessible pour les enfants de petites taille. Je ne sais pas si ma question est clair, je suis peut être passé a coté de quelque chose... En tout cas merci encore pour le partage.

Bonjour, j'ai ajouté un schéma dans l'étape 4 qui indique le placement des boutons en fonction de leur numéros, l'image avait disparue ça arrive quelques fois.
Le bouton mode est le bouton 1, start le 2 et le 3 durée.
Amusez vous bien

Pour un problème de hauteur tu peux intervertir les boutons 1/3 avec 9/10.

Bonjour, merci pour votre contribution, j'ai construit le projet sans problème, mais dans la partie programmation je pense qu'il y a quelque chose qui ne fonctionne pas, dès que la première lumière est allumée et que vous appuyez sur le bouton correspondant, rien ne se passe. Je pense que le problème pourrait être dans la première boucle while où tous les boutons sont en HIGH?

Bonjour, j'ai acheté tous le nécessaire pour la batak, serait il possible d'avoir des photos du dessous des plaques pour voir les pontages ? merci d'avance. Pascal

bonjour. Déjà merci pour ce partage. J'essaye de le réaliser chez moi mais j'ai quelques difficultés. J'ai du mal à comprendre les liaisons des cartes entrée et sortie notamment sur l'alimentation 15V pour les lampes (Load = la lampe ou une pile?). Pour les condensateurs pourquoi avoir utilisé différentes capacités (si je dit pas de bétise 8 de 100nF, 2 de 47nF et 2 de 22 nF sur la carte des entrées.)?

Merci pour ton retour et bravo pour votre réalisation

Jérémy

Bonjour, félicitation pour votre travail, j'ai commencé le projet mais je bloque sur les branchement sous les cartes, serait-il possible possible d'avoir des photos ? Par avance merci. Grégory

Bonjour.

Avez-vous pu obtenir de telles photos ? Et avez-vous été au bout de ce projet ?

Dans ce cas vous serait-il possible de mettre des photos de votre montage à disposition ? 

Merci à vous.

Bonjour pouvons nous avoir des photos du branchement des boutons sur la carte arduino svp Merci

Ces tutoriels devraient vous plaire

vignette Montez facilement votre console de jeu rétrogaming avec RECALBOX !
Montez facilement votre console de jeu rétrogaming avec RECALBOX !
vignette Arduino et Porte automatique de poulailler
Arduino et Porte automatique de poulailler
vignette Préparer un fichier pour une découpe et une gravure laser
Préparer un fichier pour une découpe et une gravure laser
avaatar quentingard

quentingard

Suivre

Vues: 5936
Mis en favoris: 27

Découvrez d'autres tutoriels de

quentingard

Découvrez tous les tutoriels partagés sur Oui Are Makers

Powered by Oui Are Makers