const int inter=6;
int etat;
const int led=7;
void setup() {
pinMode(inter, INPUT_PULLUP);
pinMode(led, OUTPUT);
digitalWrite(led, LOW);
Serial.begin(9600);
etat=0;
}
void loop() {
int val_inter = digitalRead(12);
if (val_inter==0 && etat==0) {
digitalWrite(led, HIGH);
etat=1;
delay(500);
}
else if (val_inter==0 && etat==1) {
digitalWrite(led, LOW);
etat=0;
delay(500);
}
}
}
En fait il me sert a changer d'état une lampe a chaque appuie sur un bouton poussoirs, mais le problème est que si on reste appuyé sur ce dit bouton la lampe s'allume et s'éteint toute les 500ms....
Or j'aimerais que ça ne ce produise pas, je pensé a compter le temps que le BP passait à "0" et grâce a une boucle while, si ce temps excédé 500ms, arrêter le changement d'état, j'ai pas mal cherché mais a part découvrir la fonction millis qui ne me sers a rien je n'ai pas appris grand chose la dessus ^^'
const int inter = 6;
...
pinMode(inter, INPUT_PULLUP);
...
int val_inter = digitalRead(12);
il est connecté où réellement votre interrupteur en 6 ou en 12?
virez les delay(500);
si vous voulez éventuellement debouncer le bouton, 10 à 15ms est suffisant généralement (mais au lieu de bloquer vaudrait mieux faire cela avec millis()
else if (val_inter [color=red]== 0[/color] && etat == 1) {
ne pensez vous pas qu'il faut tester plutôt HIGH que LOW (vous avez un INPUT_PULLUP)?
Oups pardon, j'avais testé sur le 12 et j'ai oublié de le changé, réellement il est connecté sur le 6
Merci Mais en fait je bloque le programme prsq sinon le programme s’exécute tellement rapidement que je n'ai pas le temps d'appuyer qu'il a déjà changé trois fois d'état (Mais je ne vois pas comment utiliser millis() dans ce cas)
Vu que j'ai activé le pull up pour ne pas avoir de rebonds et prsq pour un pull down il faudrait mettre en place un circuit en plus j'ai juste inversé les valeurs vu que le courant est "tiré" vers le haut
Onirix753:
Merci Mais en fait je bloque le programme prsq sinon le programme s’exécute tellement rapidement que je n'ai pas le temps d'appuyer qu'il a déjà changé trois fois d'état (Mais je ne vois pas comment utiliser millis() dans ce cas)
c'est pas grave que ça tourne rapidement, il va faire sans doute même 1000 boucles le temps que vous appuyez c'est plutôt une bonne chose.
le pb c'est que vous avez 2 états à mémoriser et qu'une seule variable. il faut capturer le retour du bouton en haut.
voilà un peu de code à étudier
const int inter = 6;
const int led = 7;
byte etat;
boolean boutonRelache;
void setup() {
Serial.begin(115200);
pinMode(inter, INPUT_PULLUP);
pinMode(led, OUTPUT);
// on vérifie l'état du bouton au cas où il est déjà enfoncé quand on commence
boutonRelache = (digitalRead(inter) == HIGH);
etat = boutonRelache ? LOW : HIGH;
digitalWrite(led, etat); // on allume la LED en fonction de l'état
}
void loop() {
if (digitalRead(inter) == HIGH) { // PULLUP = logique inversée, le bouton est relâché en HIGH
if (!boutonRelache) { // on vient de relâcher, on debounce et mémorise
delay(20); // debounce
boutonRelache = true;
}
} else {
// le bouton est appuyé. est-ce un nouvel appui?
if (boutonRelache) {
// le bouton n'était pas appuyé avant donc c'est un nouvel appui, on inverse l'état de la lampe
boutonRelache = false;
etat = (etat == HIGH) ? LOW : HIGH; // ou de façon pas très propre etat = 1 - etat;
digitalWrite(led, etat);
delay(20); // debounce
}
}
}
Je suis tout a fait d'accord que c'est bon que le programme tourne rapidemment mais du coup pour mon code ça posais un soucis (du justement a la seule variable enregistrant deux états), mais.... qu'est ce que vous entendez par "capturer le retour du bouton en haut" c'est l'état haut ?
Sinon j'ai regardé votre programme et c'est effectivement assez différent de ce que j'avais imaginé ^^'
Mais la encore je n'ai pas compris toutes les lignes (Je vais le commenter pour vous dire ce que j'ai compris...ou pas )
const int inter = 6;
const int led = 7;
byte etat;
boolean boutonRelache;
//Bon jusque la j'ai compris ^^
void setup() {
Serial.begin(115200); //ici en générale on initialise a 9600 bauds, pourquoi 115200 ? Pour que la lecture soit plus rapide ?
pinMode(inter, INPUT_PULLUP); // ok
pinMode(led, OUTPUT); // ok
// on vérifie l'état du bouton au cas où il est déjà enfoncé quand on commence
boutonRelache = (digitalRead(inter) == HIGH); // Je n'ai pas compris cette ligne on initialise le boutonRelache à HIGH ?
etat = boutonRelache ? LOW : HIGH; //Celle la non plus, je n'arrive pas a comprendre la notation
digitalWrite(led, etat); // on allume la LED en fonction de l'état <-- ok
}
void loop() {
if (digitalRead(inter) == HIGH) { // PULLUP = logique inversée, le bouton est relâché en HIGH <-- ok
if (!boutonRelache) { // on vient de relâcher, on debounce et mémorise <-- le"!" signifie different ?
delay(20); // debounce <-- ok
boutonRelache = true; // C'est le changement d'état ?
}
} else {
// le bouton est appuyé. est-ce un nouvel appui?
if (boutonRelache) { // Je ne comprend pas ici la condition, ça veut dire "si boutonRelache est vrai (HIGH)" ?
// le bouton n'était pas appuyé avant donc c'est un nouvel appui, on inverse l'état de la lampe <-- Je ne comprend pas copmment ça marche Oo
boutonRelache = false;
etat = (etat == HIGH) ? LOW : HIGH; // ou de façon pas très propre etat = 1 - etat; <-- la non plus :/
digitalWrite(led, etat);
delay(20); // debounce
}
}
}
En fait il y a pas mal de morceau que je comprend pas prsq je ne connais pas les sylmboles, et d'autres prsq je ne vois pas comment ça marche ^^'
Mais il n'y a pas un moyen plus simple de le faire ?
Prsq après je souhaite rajouter une commande de la lampe grâce a de l'infrarouge
Vous avez un bouton que vous appuyez - quand il est enfoncé vous déclenchez une action mais ce qu'il faut faire c'est attendre qu'il soit remonte / relâché (c'est mon booléen boutonRelache)avant d'attendre une nouvelle pression sur le bouton pour juger que c'est un second appui.donc je cherche mémoriser quand le bouton n'est pas enfoncé dans une véritable de type booléen qui donc ne prend que 2 valeurs vrai (true) ou faux (false).
Serial.begin(115200);
C'est parce que plus votre arduino parle lentement a votre PC plus vous avez de chances de saturer le buffer de communication si vous écrivez Bcp de chose. Comme la communication série est gérée en hardware si le buffer est plein le prochain Serial.print sera bloquant en attendant que le buffer ne se vide ==> pourquoi vouloir bloquer votre programme alors que 115200 ne pose aucun soucis
boutonRelache = (digitalRead(inter) == HIGH);
C'est l'initiation de mon booléen qui me dit si le bouton est déjà enfoncé ou pas (au cas où un petit malin testerait le programme en allumant L'Arduino avec le bouton déjà enfoncé - dans ce cas je note cet état et j'allume la lampe). Voici la façon dont cela fonctionne: je Lis l'interrupteur, je compare sa valeur à High par (digitalRead(inter) == HIGH). c'est un test logique donc ça renvoit Vrai ou Faux et je mémorise cet état dans ma variable qui indique si le bouton est Relâché boutonRelache
La formulation
condition ? A : B;
C'est là même chose qu'écrire If (condition) A else B;
donc quand j'écris
etat = boutonRelache ? LOW : HIGH;
C'est comme si je faisais
Si le bouton est relâché alors etat prend la valeur LOW sinon HIGH
Le [b]![/b] C'est pour not - l'opposé d'une valeur de vérité !true c'est false et !false c'est true
Donc if (!boutonRelache) ça veut dire si l'opposé de boutonRelache est vrai, c'est à dire si le bouton était enfoncé avant (alors oui je change d'état puisque si j'arrive là je sais que mon bouton est relâché mais juste avant il était encore enfoncé)
Je reviens vers vous car en relisant le code (j'avais mis ce projet en pause pendant quelques semaines) j'aurais une question pour être sur de l'avoir biens compris, il y a en (très) gros 2 parties, la premiere avec le 1er if() qui est la partie "anti-rebondissement" c'est la qu'on va valider l'appuie du bouton et la 2eme partie (le else) qui lui vas s'occuper de changer l'état de la LED, c'est ça ?
Et dans le setup on initialise l'appuie du bouton et on verifie l'état c'est ça ?
(Ah, et j'ai juste encore un soucis avec une notation, celle la
etat = (etat == HIGH) ? LOW : HIGH;
vous avez indiqués "ou de façon pas très propre etat = 1 - etat" mais j'avoue ne pas comprendre cela ^^')
Oui les tests c'est pour savoir où on en est. En français ça donne ça
Lors de l'initialisation je m'assure que mes varuables et la lampe sont en accord avec la réalité. si quand je demarre l'arduino le bouton est déjà enfoncé alors j'allume la lampe et je memorise l'état de la lampe (HIGH) ainsi que celui du bouton qui est enfoncé (donc pas relâché)
ensuite eans la boucle
Est-ce que le bouton est relâché?
Si oui,*
Je teste l'état: était il enfoncé juste avant?*
Si oui c'est que je viens de le relâcher alors,*
j'attends un peu pour amortir les oscillations (debounce)*
Je mémorise que le bouton est remonté, l'appui précédent est fini*
Si non rien de spécial faire*
Si non (le bouton est donc enfoncé, il faut savoir si c'est un nouvel appui ou pas)*
Je teste donc si le bouton était relaché juste avant?*
Si oui, le bouton n'était pas appuyé avant donc c'est un nouvel appui,*
on inverse l'état de la lampe*
On mémorise que le bouton est enfoncé*
Si non, rien de particulier à faire, on a déjà traité cet appui*
Ah, et j'ai juste encore un soucis avec une notation, celle la
Code: [Select]
etat = (etat == HIGH) ? LOW : HIGH;
vous avez indiqués "ou de façon pas très propre etat = 1 - etat" mais j'avoue ne pas comprendre cela ^^')
La formulation ?: ça veut dire je fais un test, s'il est vrais j'exécute la partie avant le : et je retourne la valeur évaluée, sinon j'exécute la seconde partie, celle après le : et retourne la valeur de cette seconde expression
Donc si état est HIGH alors je retourne LOW sinon HIGH
Comme j'ai état = juste devant ça met le résultat à nouveau dans état.
En français c'est :
Donner comme nouvelle valeur à état soit HIGH si état était LOW avant, soit LOW si état était HIGH avant , bref on inverse l'état
Le commentaire sur la partie moins propre c'est que HIGH c'est une constante qui vaut 1 et LOW une constante qui vaut zéro. comme on veut changer l'état ça veut dire que si c'était zero avant on veut que la nouvelle valeur soit 1 et si c'était 1 avant on veut que la nouvelle valeur soit zero.
Et bien par un tour de magie mathématique etat = 1 - etat; ça fait exactement ça
J'ai enfin finalisé mon code afin d'avoir en plus du bouton poussoirs un actionnage via une télécommande IR et afin de l'inclure dans le code j'ai juste mis le bout de code nécessaire après celui du BP ce qui donne ceci:
#include <IRremote.h>
const int inter = 6;
const int led = 7;
int receptionIr = 2;
byte etat; //1 ou 0
boolean boutonRelache; //Vrai ou faux (true/false)
IRrecv irrecv(receptionIr); //Initialisation de la réception du récepteur Infrarouge
decode_results resultat; //Stock le code reçus dans resultat
void setup() {
Serial.begin(115200); // Vitesse de transmission moins rapide afin de saturer le buffer
pinMode(inter, INPUT_PULLUP); //entrée interrupteur, en Pull up afin d'avoir un signale claire (et car il est integré a l'arduino contrairement au pull down <-- nécessite un circuit en plus)
pinMode(led, OUTPUT);
// on vérifie l'état du bouton au cas où il est déjà enfoncé quand on commence
boutonRelache = (digitalRead(inter) == HIGH); //Initialisation de la variable "boutonRelache", on teste la variable inter pour savoir si elle = HIGH, si oui boutonRelache = 0, si non boutonRelache = 1
etat = boutonRelache ? LOW : HIGH; //if(), si boutonRelache = true (valeur boolean), état = LOW, sinon etat = HIGH
// on allume la LED en fonction de l'état (etat = LOW ou a HIGH, a 1 ou a 0)
irrecv.enableIRIn(); //Activation de la réception
}
void loop() {
if (digitalRead(inter) == HIGH) { // PULLUP = logique inversée, le bouton est relâché en HIGH
if (!boutonRelache) { // on vient de relâcher, on debounce et mémorise
delay(20); // debounce
boutonRelache = true;
}
} else {
// le bouton est appuyé. est-ce un nouvel appui?
if (boutonRelache) {
// le bouton n'était pas appuyé avant donc c'est un nouvel appui, on inverse l'état de la lampe
boutonRelache = false;
etat = (etat == HIGH) ? LOW : HIGH; // ou de façon pas très propre etat = 1 - etat <-- Inverser l'état (qui vaut 0 ou 1);
delay(20); // debounce
digitalWrite(led, etat);
}
}
if (irrecv.decode(&resultat)) //Si il y a reception d'un code qui est stocké dans resulat
{
if (resultat.value==0xFF30CF){ //Si le code reçus vaut le code du bouton que vous avez programmé (ici c'est 0xFF30CF qui est égale au bouton 1 de ma télécommande)
etat = (etat == HIGH) ? LOW : HIGH;
}
irrecv.resume(); //Il ce prépare a recevoire le prochain code
}
digitalWrite(led, etat);
}
Comme vous le voyez j'ai mis le changement d'état de la lampe après tout les changement d'état de la boucle (sinon tout n'était pas pris en compte), j'ai testé, ça fonctionne super biens (même l'IR car si on reste appuyé sur la télécommande ça n'envoie pas d'autres signales), voila
Juste une dernière chose, ce n'est pas nécessaire en sois mais j'aimerais juste comprendre pourquoi 115200 bauds, qu'est ce que ça change ?
Merci beaucoup pour votre aide !!
PS: Si vous voyez des erreurs ou autres n'hésitez pas a me les indiquer
Le principal défaut logique, bien que sans conséquence, me semble être que ton dernier digitalWrite(led,etat) est effectué de manière systématique à chaque loop(), alors que je pense que tu aurais voulu le mettre dans le même bloc que le changement de valeur de la variable etat.
Après pour pinailler :
receptionIr devrait être en const int
ton commentaire qui suit la déclaration de la variable etat ne donne pas les bonnes valeurs (1 ou 0 au lieu de HIGH ou LOW)
je pense que ton code pourrait être un poil plus factorisé, comme ceci
if (boutonRelache != (digitalRead(inter) == HIGH)) { //L'état du bouton vient de changer
if (boutonRelache) { //c'est un appui
etat = (etat == HIGH) ? LOW : HIGH; // ou de façon pas très propre etat = 1 - etat <-- Inverser l'état (qui vaut 0 ou 1);
digitalWrite(led, etat);
}
boutonRelache = !boutonRelache; //on retourne la chaussette
delay(20); //debounce
}
La valeur 0xFF30CF serait avantageusement placée dans une constante bouton_1 en début de code, ce qui t'évitera d'avoir à la chercher le jour où tu voudras changer de touche de la télécommande.
De manière générale il vaut toujours mieux déclarer toutes ses constantes en début de code (autre exemple : la durée du debounce)
Merci de ta réponse
Et en fait j'ai mis le digitalWrite(led, etat) a la fin car en fait j'ai un changement d'état dans deux boucles différentes (et en fonction de si on utilise le bouton ou l'IR c'est une des deux qui fait le changement d'état j'ai donc simplement mit mon digitalWrite a la fin
Après oui c'est vrai je vais de ce pas essayer de le simplifier et l'optimiser au max sur les constantes etc (après pour le commentaire c'était surtout pour m'y retrouver ^^' mais sinon vu que la variable etat est de type byte, ce n'est pas 0 et 1 ?)
Sinon après j’essayerai de le factoriser mais j'ai un peu de mal avec cette notation donc je ferrais ça petit a petit
Et oui bonne idée pour le bouton_1 (et les variables en generale)