Maintien d'une variable (bistable ON / OFF)

Bonjour @toutes et @tous

Voilà je souhaite faire ce montage : (pour mon hexapode)

  • un bp poussoir
  • une led
  • mon arduino

avec comme code :

if ETAT_BP==APPUI && LED==OFF => LED=ON
if ETAT_BP==APPUI && LED==ON => LED=OFF
if ETAT_BP==PAS_APPUI && LED==OFF => LED=OFF
if ETAT_BP==PAS_APPUI && LED==ON => LED=ON

En gros je cherche à coder un état bistable ON / OFF
ainsi si je relâche le bp poussoir, la led reste allumée et si je rappui, elle s'éteint.

(peut être avec une mémorisation de l'état dans une variable, mais j'ai le même problème : la variable se remet à zéro quand je relâche le bp :frowning: )

Merci d'avance :smiley:

Tu compliques drôlement...

if (bouton==1){
 led =! led;
}

@Jean-François : :astonished: et ça marche ?? pourrais-tu préciser ton idée ? stp :relaxed:

L'état de la led est inversé à chaque appuis sur le bouton.

Ok :stuck_out_tongue:
En gros cela donne ça : :cold_sweat:

const int APPUI=0;
const int PAS_APPUI=1;
const int BP=52;
const int LED=13;
int ETAT_BP;
int ETAT_LED=LOW;

void setup()
{
  pinMode(LED, OUTPUT);
  pinMode(BP, INPUT);
  digitalWrite(BP, HIGH) ;
}

void loop()
{
  ETAT_BP=digitalRead(BP);
  if (ETAT_BP==APPUI)
  {
    ETAT_LED != ETAT_LED
  }
  
  digitalWrite(LED,ETAT_LED);

j'ai bon ? :~

Oui c'est ça, mais j'ai peut-être fait une erreur :

etat_led = !etat_led

à la place de :

etat_led != etat_led

et mets ça :

bolean ETAT_LED=LOW;

à la place de :

int ETAT_LED=LOW;

@Jean-françois : Merci ^^/ mais :frowning:
tu as raison en disant :

ETAT_LED != ETAT_LED;

car

Opérateurs logiques de comparaison :

  • x == y (x est égal à y)
  • x != y (x est différent de y)
  • x < y (x est inférieur à y)
  • x > y (x est supérieur à y)
  • x <= y (x est inférieur ou égal à y)
  • x >= y (x est supérieur ou égal à y)

Mais le programme ne marche pas :frowning:

Au départ j'étais parti sur ce programme :

const int APPUI=0;
const int PAS_APPUI=1;
const int BP=52;
const int LED=13;
int ETAT_BP;

void setup()
{
  pinMode(LED, OUTPUT);
  pinMode(BP, INPUT);
  digitalWrite(BP, HIGH) ;
}

void loop()
{
  ETAT_BP=digitalRead(BP);
  if (ETAT_BP==APPUI)
  {
    digitalWrite(LED,1);
  }
  else
  {
    digitalWrite(LED,0);
  }
}

y-a-t-il pas moyen de le modifier ? pour qu'il fasse comme je le souhaites ? car moi je sèche complètement :~ :cold_sweat: :frowning:

Merci d'avance et désolé pour ces questions. :slight_smile:

Essaye ça :

const int BP=52;
const int LED=13;
bolean ETAT_LED=LOW;

void setup()
{
  pinMode(LED, OUTPUT);
  pinMode(BP, INPUT);
  digitalWrite(BP, LOW) ;
}

void loop()
{
  
  if (digitalRead(BP)==1)
  {
    ETAT_LED = !ETAT_LED;
  }
  
  digitalWrite(LED,ETAT_LED);
}

En fait ce n'est pas tout à fait aussi simple.
Si tu tiens le bouton appuyé la LED va clignoter. A chaque boucle on rentre dans le IF et on complémente l'état.

En fait il faut:

  • Tester l'appui c'est à dire le changement de l'état repos à l'état actif.
  • Changer l'état de la LED
  • Attendre le retour à l'état repos

Bonjour,

dans les exemples du soft arduino il y a plusieurs exemples, si l'on est pas anglophobe cela peut aider XD
je crois que c'est le sketch "debounce" qui correspond à ce cas de figure.

@fdufnews > c'est juste j'avais pas pensé à ça... :roll_eyes:

@ MrAlexis > J'ai fais des essais avec Debounce et c'est pas encore ça. :~ (en fait Debonce est pour l'anti-rebond)

Pour limiter l'effet de rebond ce qui marche très bien c'est de mettre un condo (moi je mets 1µF) sur l'entrée. Sinon au niveau code, si on veut prendre en compte le mentien, il faut faire ça :

const int BP=52;
const int LED=13;
bolean ETAT_LED=LOW;

void setup()
{
  pinMode(LED, OUTPUT);
  pinMode(BP, INPUT);
  digitalWrite(BP, LOW) ;
}

void loop()
{
  
  if (digitalRead(BP)==1)
  {
    ETAT_LED = !ETAT_LED;
delay(1);
while (digitalRead(BP)==1) {
}
  }
  
  digitalWrite(LED,ETAT_LED);
}

Valeur du delay() à ajuster.

Là, changement de l'état de la led à chaque appui et l'état de la led est préservé en cas d'appui prolongé :

const int BP=52;
const int LED=13;
boolean ETAT_LED=LOW;
boolean ETAT_BP=HIGH;

void setup()
{
  pinMode(LED, OUTPUT);
  pinMode(BP, INPUT);
  digitalWrite(BP, LOW) ;
}

void loop()
{
 if(ETAT_BP==HIGH){
  if (digitalRead(BP)==0)
  {
    delay(5);
    ETAT_LED = !ETAT_LED;
    ETAT_BP = LOW;
  }}
  else if(digitalRead(BP)==1){
   
    ETAT_BP=HIGH;}
    digitalWrite(LED,ETAT_LED);

}
  • l'anti rebond de B@tto :wink:

@Jean-François, @B@tto, @MrAlexis44600 , @fdufnews :

Merci pour vos conseils et vos codes, j'essaie cela ce jour et vous retournerai les résultats :smiley:
MERCI :slight_smile: encore :stuck_out_tongue:

@Jean-François : Merci pour ton programme ça MARCHE ^^/

const int BP=52;
const int LED=13;
boolean ETAT_LED=LOW;
boolean ETAT_BP=HIGH;

void setup()
{
  pinMode(LED, OUTPUT);
  pinMode(BP, INPUT);
  digitalWrite(BP, LOW) ;
}

void loop()
{
 if(ETAT_BP==HIGH){
  if (digitalRead(BP)==0)
  {
    delay(5);
    ETAT_LED = !ETAT_LED;
    ETAT_BP = LOW;
  }}
  else if(digitalRead(BP)==1){
   
    ETAT_BP=HIGH;}
    digitalWrite(LED,ETAT_LED);

}

J'ai remplacé la ligne :

    delay(5);

par

    delay(2);

ça évite de bugger si j'actionne rapidement le bp

MERCI encore @toutes et @tous pour votre précieuse aide 8)

Bonsoir,
Il existe une manière plus simple de réaliser cela en utilisant attachInterrupt
Exemple du site Arduino ( référence langage )

int pin = 13;
volatile int state = LOW;

void setup()
{
  pinMode(pin, OUTPUT);
  attachInterrupt(0, blink, CHANGE); 
}

void loop()
{
  digitalWrite(pin, state);
}

void blink()
{
  state = !state;
}
  • LOW to trigger the interrupt whenever the pin is low,
  • CHANGE to trigger the interrupt whenever the pin changes value
  • RISING to trigger when the pin goes from low to high,
  • FALLING for when the pin goes from high to low.

Il reste à écrire le code de gestion du bouton poussoir ... sur digital pin 2 :wink:
Salutations.

Effectivement c'est plus simple.... :slight_smile:

d'un autre coté le code que j'ai mis avant permet de faire un changement avec une valeur analogique (pour un seuil par exemple), ce qui peutt être intéressant. :wink:

En plus, la place prise n'est pas la même :

avec attachInterrupt() >> size: 2462 bytes

Avec mon code >> size: 1736 bytes

Et encore y'a pas d'anti rebond et de gestion du "rester appuyé"

J'osais pas le dire :grin:

Bonjour,
Il est vrai que je n'avais pas considéré l'occupation en mémoire flash aussi j'ai repris mes réflexes AVR Studio.
et j'ai ressorti un programme tiré d'un tutorial WEB dont voici le code:

// **********************************************************************
// Télérupteur testé sur Arduino UNO et DUEMILANOVE
// Bouton poussoir sur entrée digitale 2 
// LED sur pin 13 ( bien pratique )
// Occupation Flash : [b]506 bytes.[/b]
// **********************************************************************
#define F_CPU 16000000UL       // pas sûr que cela soit nécessaire .....
#define BUTTON_DDR DDRD        // PORTD bouton direction
#define BUTTON_PORT PORTD       
#define BUTTON_PIN PIND         
#define BUTTON_BIT PORTD2  
#define LED_PORT PORTB          
#define LED_BIT PORTB5          
#define LED_DDR DDRB  
#define DEBOUNCE_TIME 25        // delay debounce bouton */
#define LOCK_INPUT_TIME 300     // delai après bouton pressé */

#include "avr\io.h"
#include <util/delay.h>

 
int button_is_pressed()
{        
        if (bit_is_clear(BUTTON_PIN, BUTTON_BIT))
        {
           _delay_ms(DEBOUNCE_TIME);
           if (bit_is_clear(BUTTON_PIN, BUTTON_BIT)) return 1;
        }        
        return 0;
}

void init_io() {        
        
        LED_DDR |= (1 << 5);              //  LED pin 13 en sortie        
        BUTTON_PORT |= _BV(BUTTON_BIT);   //  pull-up résistance pour le bouton 
}

void toggle_led()
{
        LED_PORT ^= _BV(LED_BIT);
}

void setup()
{
      init_io();   
}
void loop()
{
     if (button_is_pressed())
     {
      toggle_led();
      _delay_ms(LOCK_INPUT_TIME);
     }
}

Le gain est intéressant :slight_smile:
Bien sûr il reste la gestion du maintien :wink:
Salutations.