a partir de la premiere entrée détectée, le programme dispose de deux secondes pour lire la suivante. soit 4 seconde pour les deux.
si après 4 secondes les entrées ne sont pas détectées alors le scan repart à 0
la première :
enum {0001, 0010, 0011,0100...} portB;
lister en binaire ou en hexa toutes les valeurs dans les parenthèses
puis :
switch (etatCourant) {
case 0001:
// faire quelque chose
la deuxième :
lire les entrées qui passe à 1 pendant 4 secondes
si E1 passe à 1 alors sortie 1 passe à un
si E2 passe à 1 alors sortie 2 passe à un
si E3 passe à 1 alors sortie 3 passe à un
si E4 passe à 1 alors sortie 4 passe à un
lire l'état du port de sortie et en fonction de la valeur exécuter une tache
// La librairie de gestion des boutons
#include <OneButton.h>
const byte buttonPin = 2; // notre bouton est sur la pin 4
const byte buttonPin2 = 3;
OneButton button(buttonPin, true); // true pour le mettre en INPUT_PULLUP
OneButton button2(buttonPin2, true); // true pour le mettre en INPUT_PULLUP
// les pins utilisées pour les LEDs
const byte pinLedRouge = 8;
const byte pinLedOrange = 9;
const byte pinLedJaune = 10;
const byte pinLedVerte = 11;
// On introduit le temps comme évènement supplémentaire
unsigned long chrono; // attention, type unsigned long comme millis()
const unsigned long TimeOut = -5000ul; // 5 secondes (le ul à la fin pour unsigned long)
// la liste des états possible de notre système
// ainsi qu'une variable etatCourant prenant une de ces valeurs
enum {REPOS, ETAT_V, ETAT_VJ, ETAT_VJO, ETAT_VJOR} etatCourant;
enum {REPOS2, ETAT_V2, ETAT_VJ2, ETAT_VJO2, ETAT_VJOR2} etatCourant2;
// ------------------------------------------------------
// Cette fonction installe l'état initial
// ------------------------------------------------------
void mettreAuRepos()
{
digitalWrite(pinLedVerte, LOW);
digitalWrite(pinLedJaune, LOW);
digitalWrite(pinLedOrange, LOW);
digitalWrite(pinLedRouge, LOW);
etatCourant = REPOS;
}
// ------------------------------------------------------
// La fonction de call back, appellée automatiquement quand on clique
// ------------------------------------------------------
void simpleclick()
{
switch (etatCourant) {
case REPOS: // on était au repos et on a un appui, on allume la verte
digitalWrite(pinLedRouge, HIGH); // LED verte alimentée
etatCourant = ETAT_V; // on note le nouvel état de notre système
break;
}
switch (etatCourant2) {
case REPOS2: // on était au repos et on a un appui, on allume la verte
digitalWrite(pinLedOrange, HIGH); // LED verte alimentée
etatCourant2 = ETAT_V2; // on note le nouvel état de notre système
break;
}
chrono = millis(); // on vient d'avoir une action donc on ré-arme notre chronomètre
}
void timeOut()
{
/* // version longue si on veut le switch case
switch (etatCourant) {
case ETAT_V: // pour tous les états
case ETAT_VO: // sauf celui au repos
case ETAT_VOJ: // on doit tout éteindre
case ETAT_VOJR: // et revenir à l'état initial
mettreAuRepos(); // ce que fait cette fonction
break;
}
*/
// version courte, si on n'est pas au repos, alors passer au repos
if (etatCourant != REPOS) mettreAuRepos();
// à noter que le timeOut continuera de se déclencher toutes les 15 secondes
// mais ne fera rien puisqu'on sera au repos
// ça peut être utile pour continuer à faire autre chose
// sinon il faut tester avant de l’appeler qu’on n’est pas au repos
}
// ------------------------------------------------------
// On initialise notre système dans le setup
// ------------------------------------------------------
void setup() {
pinMode (pinLedRouge, OUTPUT);
pinMode (pinLedOrange, OUTPUT);
pinMode (pinLedJaune, OUTPUT);
pinMode (pinLedVerte, OUTPUT);
//conditions Initiales
mettreAuRepos();
// On attache la fonction simpleClick() comme callBack en cas de simple click
button.attachClick(simpleclick);
button2.attachClick(simpleclick);
}
void loop() {
// On vérifie l'état des boutons, ce qui déclenche l'appel d'une des fonctions callBack si nécessaire
button.tick();
button2.tick();
// On vérifie le timer et on déclenche l'évènement si nécéssaire
// rajouter dans la condition “&& (etatCourant != REPOS)” si vous ne souhaitez pas
// appeler la fonction au repos
if (millis() - chrono >= TimeOut) {
timeOut();
chrono = millis(); // on ré-arme notre chronomètre
}
// ici on peut faire autre chose du moment que ça ne prend pas trop longtemps
}
je ne comprends pas pour quand j appuie sur l'entrée 1 les led1 & 2 s'allument ?
l'appuie sur le bouton 2 ne déclenche rien et la tempo ne fonctionne plus .
ce que j essayer de faire c'est de "scanner "les entrées et en fonction du résultat , jouer un scénario , il y a 16 possibilités , je sais pas comment m y prendre
il vous faut déjà une machine à états qui envoie un évènement correspondant à l'état de vos 3 entrées suivant votre règle :
(il faudrait clarifier si les entrées restent à HIGH ou si c'est un front et ce qu'il se passe si dans les 2s la même entrée est à nouveau activée, est-ce que c'est une annulation, est-ce qu'on prolonge de 2s quand même etc)
En suivant le diagramme ci dessus (mais avec 4 au lieu de 3), la machine à état qui envoie l'action avec une variable qui représente le code reconnu est assez simple à implémenter
voici à quoi ça pourrait ressembler dans le simulateur
on simule les fronts par un appui sur le bouton
l'ordre d'appui n'est pas pris en compte, la fonction action() reçoit un octet dont les bits correspondants aux boutons sont à 1 si le bouton a été appuyé.
le code
/* ============================================
code is placed under the MIT license
Copyright (c) 2024 J-M-L
For the Arduino Forum : https://forum.arduino.cc/u/j-m-l
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================
*/
#include <Toggle.h>
const byte brochesBoutons[] = {2, 3, 4, 5};
const byte nbBoutons = sizeof brochesBoutons / sizeof * brochesBoutons;
Toggle boutons[nbBoutons];
enum {REPOS, ACTIVATION} etatEntrees = REPOS;
void action(byte configuration) {
Serial.print("ACTION\t");
for (int i = nbBoutons - 1; i >= 0; --i) Serial.print(bitRead(configuration, i));
Serial.println();
}
void gesionEntrees() {
static unsigned long t0;
static byte memoireEntrees = 0;
switch (etatEntrees) {
case REPOS:
for (byte i = 0; i < nbBoutons; i++) {
boutons[i].poll();
if (boutons[i].onPress()) {
Serial.print("Appui bouton "); Serial.println(i);
t0 = millis();
memoireEntrees = (1 << i);
etatEntrees = ACTIVATION;
break;
}
}
break;
case ACTIVATION:
if (millis() - t0 >= 2000) {
action(memoireEntrees);
memoireEntrees = 0;
etatEntrees = REPOS;
} else {
for (byte i = 0; i < nbBoutons; i++) {
if (bitRead(memoireEntrees, i)) continue; // on ne teste pas deux fois
boutons[i].poll();
if (boutons[i].onPress()) {
Serial.print("Appui bouton "); Serial.println(i);
t0 = millis();
memoireEntrees |= (1 << i);
if (memoireEntrees == ((1 << nbBoutons) - 1)) { // si tous les boutons sont choisis
action(memoireEntrees);
memoireEntrees = 0;
etatEntrees = REPOS;
}
break;
}
}
}
break;
}
}
void setup() {
for (byte i = 0; i < nbBoutons; i++) boutons[i].begin(brochesBoutons[i]);
Serial.begin(115200);
}
void loop() {
gesionEntrees();
}
Je ne suis pas sûre d'avoir bien compris ta question.
la fonction affiche sur le moniteur série, la valeur binaire de du byte donné en paramètre(memoireEntrees) @J-M-L utilisant cette variable pour stocker les appuis sur chaque bouton, le bouton 1(ou 0 en valeur numérique) étant stocké dans le premier bit de cette entier.
Donc si tu appuis sur le bouton 1, tu aura 0001, puis le bouton 2 => 0011
Mode provoque On, c'est une méthode moche, pour éviter de gaspiller bêtement de la mémoire en allouant 8bits par bouton
Ca dépend des combinaison que tu veux tester.
mais par exemple plusieurs if de la forme (configuration & 0b0001) ou (configuration & 1) ou (configuration & 0b010) ou (configuration & 2)
donc si on reprend ton exemple:
if (memoireEntrees & 0b0001 ){
//do 1
}
tu ne peux pas tester directement l'égalité.
Si par exemple deux boutons sont appuyer, memoireEntrees sera différent de 1.