Depuis quelques jours je bricole un ancien jeu électronique pour en modifier les règles par arduino.
Le jeu comporte un moteur auquel j'ai ajouté 4 boutons poussoir pour 4 joueurs.
L'idée c'est que lorsque les joueurs appuient sur leur bouton le moteur accélère temporairement. Ces accélération peuvent s'additionner en fonction du nombre de joueurs appuyant sur le bouton au même moment.
Une fois sur mon sketch arduino je me confronte à un problème :
je ne voit pas par quel moyen je pourrais activer temporairement des gradations de vitesse avec des boucles conditionnel (type if ou while) puisque visiblement celle-ci empercherait que d'autres boutons soit appuyées pendant cette séquence (d'autant plus qu'il y a un temporisation de l’accélération).
Quelqu'un aurait-il une idée pour pouvoir gérer l'addition de plusieurs accélérations par plusieurs boutons ?
Il ne faut pas utiliser de while.
Dans ta loop dans un premier temps tu lit les touches appuyées.
Ensuite en fonction du nombre de touches appuyées tu pilotes le moteur.
Je vois bien comment capter l'appuie sur les boutons et donc comment faire varier la vitesse une fois par boutons. Mais cela provoque plusieurs problème : le "delay" "verrouille" le programme et empêche qu'un autre joueur appuie à sont tour sur un bouton pour lui aussi augmente d'un palier la vitesse du moteur.
l'idéal serait que chaque joueur puisse augmenter la vitesse d'un "palier" quand il le souhaite et que cela ne dure qu'un court instant, sans pour autant que le code reste bloqué à un endroit. Mais je ne suis pas encore assez expérimenté en arduino pour trouvé une solution viable
void classicmode() {
digitalWrite(motorPin1, HIGH);
digitalWrite(motorPin2, LOW);
analogWrite(enablePin, motorSpeedClassic);
if (digitalRead (Button1) == HIGH || (Button2) == HIGH || (Button3) == HIGH || (Button4) == HIGH) {
boolean vitesse2 = true;
}
if (vitesse2 = true) {
analogWrite(enablePin, motorSpeedClassic + motorSpeedClassic /2);
delay(500);
boolean vitesse2 = false;
}
}
Voici ce que j'ai testé pour l'instant, avez-vous des pistes pour améliorer ce bout de programme ?
Il te faut deux choses. L'une est capitale: bannir à jamais la fonction delay(), qui comme tu le dis si justement est bloquante. Un appel à millis() permet d'obtenir le nombre de milliseconde écoulée depuis le démarrage de la carte. Quand tu as besoin d'attendre un délai, tu fais un appel à millis et enregistre cette valeur dans une variable long. Puis tu compares, à chaque boucle, une nouvelle lecture de millis() avec ta valeur enregitrée. Lorsque la différence entre les deux est supérieure à la temporisation voulue, tu lance l'action choisie.
Pour incrémenter la vitesse, tu peux par exemple utiliser une variable, appelons-là vitesse, qui s'initialise sur une valeur qui correspond au fonctionnement normal. Par exemple, 1. Puis pour chaque appui sur un bouton, tu incrémente cette variable d'une certaine quantité, (par exemple, un appui = +1), et tu initialise le compteur que tu as mis en place plus haut. Et encore une fois à chaque boucle, tu teste la valeur de vitesse, si elle est de 1 tu demandes au moteur d'avancer à sa vitesse nominale, si elle est supérieure tu adaptes le comportement.
Et quand ta temporisation est passée, tu remets vitesse à sa valeur initiale. Du coup d'une part le programme continue à tourner et à écouter ce qui se passe même quand le moteur tourne plus vite, et d'autre part tu peux appuyer autant que tu veux sur les boutons, la temporisation se réinitialise à chaque nouvel appui.
Et rien ne t'empêche, une fois que tu as mis en place cette structure plus souple, de déterminer plusieurs niveaux de vitesses en cas d'appuis successifs, ou une fonction qui empêche le rappui sur un bouton pendant un temps donné, etc.
Plutot que d'utiliser un booleen, tu peux utiliser un compteur pour compter le nombre de boutons appuyés et t'en servir pour calculer la vitesse.
Ce qui donne par exemple:
void loop() {
digitalWrite(motorPin1, HIGH);
digitalWrite(motorPin2, LOW);
int nbAppui=0; // nombre de boutons appuyés
if (digitalRead (Button1) == HIGH)
nbAppui++;
if (digitalRead (Button2) == HIGH)
nbAppui++;
if (digitalRead (Button3) == HIGH)
nbAppui++;
if (digitalRead (Button4) == HIGH)
nbAppui++;
analogWrite(enablePin, 255/2 + 255/2/4*nbAppui); // voir la loi de variation
delay(20);
}
Grace à vos conseil je crois que je viens de trouver quelque chose de fonctionnel et satisfaisant.
Je connaissais le principe des algorigramme, je dois dire que ca faisait longtemps que je ne m’était pas essayé a l'exercice. Au final, ça à bien clarifier la chose de passer sur papier.
Du coup, j'ai révisé le fonctionnement du jeu et ça donne ceci.
void classicmode() {
digitalWrite(motorPin1, HIGH); //Démarage du moteur en sens anti-horaire
digitalWrite(motorPin2, LOW);
if (digitalRead (Button1) == LOW) { // Appuie et/ou maintien du bouton 1
Push1 = 1;
if (chrono1 > turboTime) {
Turbo1 = 1;
Push1 = 0;
}
}
if (digitalRead (Button1) == HIGH) {
chrono1 = 0;
Turbo1 = 0;
Push1 = 0;
}
if (digitalRead (Button2) == LOW) { // Appuie et/ou maintien du bouton 2
Push2 = 1;
if (chrono2 > turboTime) {
Turbo2 = 1;
Push2 = 0;
}
}
if (digitalRead (Button2) == HIGH) {
chrono2 = 0;
Turbo2 = 0;
Push2 = 0;
}
if (digitalRead (Button3) == LOW) { // Appuie et/ou maintien du bouton 3
Push3 = 1;
if (chrono3 > turboTime) {
Turbo3 = 1;
Push3 = 0;
}
}
if (digitalRead (Button3) == HIGH) {
chrono3 = 0;
Turbo3 = 0;
Push3 = 0;
}
if (digitalRead (Button4) == LOW) { // Appuie et/ou maintien du bouton 4
Push4 = 1;
if (chrono4 > turboTime) {
Turbo4 = 1;
Push4 = 0;
}
}
if (digitalRead (Button4) == HIGH) {
chrono4 = 0;
Turbo4 = 0;
Push4 = 0;
}
speedStep = Turbo1 + Turbo2 + Turbo3 + Turbo4; // Calcule du palier de vitesse en fonction des boutons appuyés
if (Push1 == 1 || Push2 == 1 || Push3 == 1 || Push4 == 1) { // activation du "turbo"
speedStep = 4;
}
Serial.println(speedStep);
analogWrite(enablePin, motorSpeedClassic + speedStepVal * speedStep); // Calcul et application de la vitesse au moteur
delay(20);
}
J'ai été étonné, je pensais que les fonctions "if" étaient exclusive et qu'une seule pouvait être activé à la fois. En tout cas, sans délais, on obtient quelque chose de plus fluide et de pas forcement trop difficile à manipuler.
Voyez-vous éventuellement des choses de retoucher voir a simplifier dans ce code ?
C'est bien si tu as réussit à faire ce qui te convient
Comme on ne voit pas comment sont calculées le valeurs de chronoX et turboTime on ne voit pas très bien ce que tu veux faire.
Une petite optimisation: au lieu de faire if (digitalRead (Button1) == LOW) {...} if (digitalRead (Button1) == HIGH) {...}
tu peux faire: if (digitalRead (Button1) == LOW) {...} else {...}