Calcul mental

Bonjour à tous,

Je viens vers vous, car j'aurais besoin de votre aide pour la réalisation d'un petit système pour la révision du calcul mental de mon fils.

Je viens de me remettre à la programmation, mes derniers essais dates de l'époque de l'école (delphi il y'a 15ans) Je me débrouille avec la gestion de I/O sans trop de souci, mon problème viens de la logique pour mon programme.

J'aimerais votre aide pour m'aider à valider mon approche, je compte me débrouiller le plus possible avec le code.

Le projet:

Un arduino Uno Un ecran LCD 2x12 Des boutons poussoirs

J'aimerai affiché sur l'écran soit une addition, multiplication ou soustraction (aléatoire)

Avec une gamme de chiffre allant de 0 à 12 pour chaque opérations (fait, j'ai réussi ce point mais avec un seul opérateur)

Un compteur de temps (3 minutes pour 30 opération) Un bouton vrai, lors de l'appui j'affiche le prochain calcul et ajoute 1 au total de juste Un bouton faux, lors de l'appui j'affiche le prochain calcul et ajoute -1 au total de juste

A la fin des 3 minutes j'aimerai voir le score affiché.

Je bloque sur l'usage des boucles pour stopper mes différentes opération.

Merci par avance Minicup

hello il nous faut au moins ton code et ton cablage

ICI

Il te faut programmer :

  • Un chrono qui compte le temps jusqu'à 3 minutes (soit 180000 ms)
  • Un compteur pour vérifier que tu ne fais pas plus de 30 exercices
  • Un compteur pour le score
  • Apprendre à te servir d'un générateur aléatoire : je conseille la bibliothèque truerandom

Pour ce projet, tu n'as (presque) pas besoin de boucles. La loop va vérifier que le temps et le nombre d'exercices ne sont pas dépassés. Tant que tu n'as pas dépassé ces limites, tu es dans un 'if' (ou un autre 'tant que') :

  • Si tu attends une réponse (tant qu'aucun bouton n'est appuyé), tu scrutes l'état des boutons
  • Si un bouton est appuyé (pense à traiter les rebonds) tu vérifies la réponse et incrémentes ou décrémentes le score, puis tu génères un autre exercice

Je te conseille de bien réfléchir à l'enchainement de l'algorithme de ton programme - tu peux faire un schéma ou un graphe pour bien le visualiser. Une fois que c'est prêt, tu écris des petites fonctions qui font toutes les actions élémentaires (affichage de la question, lecture des boutons, génération de l'exercice, etc) et tu les testes une par une. Enfin, il te restera à écrire le code principal (le contenu de la loop) qui va appeler les fonctions élémentaires et les mettre en oeuvre (avec le while et le if)...

Bon courage. Poste ton code lorsque tu seras un peu avancé.

Si tu as besoin d'infos sur les boutons poussoirs : ici Pour le LCD, je ne connais pas le format 2 x 12, mais il y a un tuto ici

Merci pour la réponse, je vais mettre le code, mais il s’agit d’un draft bien pauvre pour le moment.

D’ou ma question sur le concept du programme plutôt que le code pour le moment.

Je joint aussi le dessin de câblage.

Pour l’instant un câblage sans écran, pour tester le programme dans la console, je me préoccuperai de l’affichage matériel dans un second temps.

int Intervrai = 0;


void setup() {

Serial.begin(9600);
randomSeed(analogRead(0));
pinMode (2,INPUT);

}

void loop() {
  
  Intervrai = digitalRead (2);
  long nombre1 = random(0,13); // chiffre 1
  long nombre2 = random(0,13); // chiffre 2
  long nombre = random(1,4); // choix de l'opérateur
  long operateur1 ;

if (nombre= 1)
      { operateur1 = ("+"); }
    


if (Intervrai == HIGH)
      
     { Serial.print(nombre1);
      Serial.print(operateur1);
      Serial.print(nombre2);
      Serial.print(" = ");
      Serial.println("?");}

else    (Intervrai == LOW);
     { Serial.print("");}
      




 delay (100);
}

c’est typiquement une définition de programme qui se prête bien à la programmation par machine à états (cf mon tuto éventuellement, ça pourrait vous donner des idées pour la structuration du code)

Bonsoir,

Merci beaucoup pour vos premières réponses bien complète, je vais potasser tout ca, je serais en vacances semaine prochaine, je devrais pouvoir finaliser tout ca, je vous envoi le code dès que possible.

Vraiment grand merci pour l'assistance

Bonjour,

J’ai avancé sur le code aujourd’hui, j’ai réussi à gérer le côté aléatoire des calculs. VOIR CODE 1

Par contre j’ai essayé d’utilisé la bibliothèque des boutons selon le tutoriel que vous m’avez inviter à suivre et la je bloque car je n’arrive rien à afficher dans la console avec cette biblio. VOIR CODE 2

Si vous pouviez me guider, cela me rendrait bien service. Mais merci pour les premiers conseils, car j’ai déjà bien avancé

CODE 1

int Intervrai = 0;


void setup() {

  Serial.begin(9600);
  randomSeed(analogRead(0));
  pinMode (2, INPUT);

}

void loop() {

  Intervrai = digitalRead (2);
  int nombre1 = random(1, 13); // chiffre 1
  int nombre2 = random(1, 13); // chiffre 2
  char message[16] = "" ;
  char message1[16] = "" ;
  char message2[16] = "" ;
  int aleatoire = random (0, 3);

  if (Intervrai == HIGH && aleatoire == 0)

    {sprintf  (message, "%d x %d ", nombre1, nombre2);
    Serial.println (message);}
    
   if (Intervrai == HIGH && aleatoire == 1)

    {sprintf   (message1, "%d + %d ", nombre1, nombre2);
    Serial.println (message1);}


   if (Intervrai == HIGH && aleatoire == 2)
  
    {sprintf   (message2, "%d - %d ", nombre1, nombre2);
    Serial.println (message2);}
    
delay (200);

  
  }

CODE 2

//librairie de gestion des boutons
#include <OneButton.h>
const byte buttonPin = 2; //bouton sur la Pin 2
OneButton button(buttonPin, true); // true pour bouton INPUT PULLUP Start


//Fonction call back utilisé lors de l'appui du button start

void simpleclick()

{ int aleatoire = random (0, 3);
  int nombre1 = random(1, 13); // chiffre 1
  int nombre2 = random(1, 13); // chiffre 2
  char message[16] = "" ;
  char message1[16] = "" ;
  char message2[16] = "" ;

  if (aleatoire == 0)

  { sprintf  (message, "%d x %d ", nombre1, nombre2);
    Serial.println (message);
  }

  if (aleatoire == 1)

  { sprintf   (message1, "%d + %d ", nombre1, nombre2);
    Serial.println (message1);
  }


  if (aleatoire == 2)

  { sprintf   (message2, "%d - %d ", nombre1, nombre2);
    Serial.println (message2);
  }
}


void setup() {

  button.attachClick(simpleclick);

}

void loop() {
  button.tick();
}

Je te propose une possibilité, qui reprend une partie de ton code, mais n’utilise pas la bibliothèque :

#define BoutonVRAI 2
#define BoutonFAUX 3
#define MaxOps 30    // nombre de questions
#define Duree 180000 // ms : durée du jeu
unsigned long timer = 0;
int score = 0;       // int car peut passer négatif
byte compteur = 0;   // nombre de questions posées
enum etat {Question, Attente, Verif, Fin};
etat quoi = Question;
bool solution = true;
bool reponse;

void setup() {
  pinMode (BoutonVRAI, INPUT_PULLUP);
  pinMode (BoutonFAUX, INPUT_PULLUP);
  Serial.begin(9600);
  randomSeed(analogRead(0));
  timer = millis();
}

void loop() {
  while (compteur < MaxOps && millis() - timer < Duree && quoi != Fin) {
    switch (quoi) {
      case Question :
        PoseQuestion();
        break;
      case Attente :
        AttenteReponse();
        break;
      case Verif :
        Verification();
        break;
    }
  }
  Serial.print ("Fin du jeu !!! Score = ");
  Serial.println (score);
  while (1);
}

void PoseQuestion () {
  quoi = Attente;
  compteur ++;
  byte operation = random (3);
  byte nombre1 = random(1, 13); // chiffre 1
  byte nombre2 = random(1, 13); // chiffre 2
  int resultat = 0;
  if (random(2)) solution = false;
  // En cas de soustraction, on vérifie que nombre2 est inférieur à nombre1
  if (operation == 2) {
    while (nombre2 > nombre1) {
      nombre1 = random(1, 13);
      nombre2 = random(1, 13);
    }
  }

  Serial.print(nombre1);
  switch (operation) {
    case 0: // Multiplication
      Serial.print(" x ");
      resultat = nombre1 * nombre2;
      break;
    case 1 : // Addition
      Serial.print(" + ");
      resultat = nombre1 + nombre2;
      break;
    case 2 : // Soustraction
      Serial.print(" - ");
      resultat = nombre1 - nombre2;
      break;
  }
  if (!solution) resultat = resultat - 3 + random(7); // Si la réponse est fausse
  Serial.print(nombre 2);
  Serial.print (" = ");
  Serial.print (resultat);
  Serial.println (" ?");
}


void AttenteReponse () {
  while (millis() - timer < Duree && digitalRead(BoutonVRAI) + digitalRead(BoutonFAUX)) {
    // Attente bouton ou temps
  }
  if (millis() - timer > Duree) { // Fin du jeu, temps dépassé
    quoi = Fin;
    return;
  }
  quoi = Verif;
  if (digitalRead(BoutonVRAI)) reponse = true;
  if (digitalRead(BoutonFAUX)) reponse = false;
}

void Verification () {
  quoi = Attente;
  if (reponse == solution) score++;
  else score--;
}

Je n’ai pas testé, il y a sûrement des bugs…

juste pour aider le compilateur dans ses décisions de type de données et éviter des bugs suivant comment c'est utilisé, au lieu de #define Duree 180000 // ms : durée du jeuje propose#define Duree 180000ul // ms : durée du jeu ou encoreconst unsigned long Duree = 180000ul; // ms : durée du jeu

pour gratter quelques octets, autant passer l'enum sur 1 octet plutôt que les 2 d'un entier (par défaut)

enum : byte etat {Question, Attente, Verif, Fin};