LOCODUINO

Les interrupteurs

Ou comment basculer d’un avis à l’autre...

.
Par : Thierry

DIFFICULTÉ :

Un interrupteur (’switch’ dans la langue du brexit) est un dispositif matériel destiné à changer un état permanent parmi deux choix possibles.

Des interrupteurs, vous en utilisez tous les jours : allumer la lumière, mettre son clignotant (enfin ceux qui les utilisent...), allumer son aspirateur (si, si, le truc bruyant qui vous réveille le samedi matin !). C’est un élément extrêmement courant de notre vie quotidienne.
Il ne faut pas confondre ces bascules matérielles avec des dispositifs logiciels qui remplissent la même fonction mais basés sur de simples poussoirs, comme les touches de votre télévision, de votre téléphone, de votre clim... Vous allez me dire, ’Oui, mais quand j’appuie sur le bouton On/Off de la télé, ça s’allume et ça s’éteint comme la lumière de la salle à manger !’. C’est vrai, mais c’est juste que le poussoir en question se sert d’une impulsion temporaire pour changer l’état courant et passer à l’autre état. Si la télé était éteinte, on va l’allumer, et inversement. Contrairement au bouton de la salle à manger qui va maintenir une connexion électrique dans une position, et la couper dans l’autre.
Les interrupteurs sont incroyablement variés dans leurs formes, leurs modes de fonctionnement, leurs prix !

PNG - 38.3 kio
En haut, des boutons ’bruts’ pour des montages électroniques. En bas, plutôt du joli pour un montage définitif.

La forme et le prix, c’est vous qui voyez, mais le fonctionnement doit être conforme à ce que le programme, et donc vous, en attendez. Les grandes caractéristiques à prendre en compte sont : la puissance électrique transmissible, la capacité à rester sur l’une de ses positions, le nombre de connexions commutées... Une terminologie a été adoptée comme un standard de fait pour le monde l’électronique et décrit les différents modèles :

Nom En clair Description Symbole
SPST Single pole, Single throw Dans une position le contact est établi entre une entrée et une sortie, dans l’autre position, le contact est rompu.
SPDT Single pole, Double throw Le contact est établi alternativement entre une entrée et deux sorties.
DPST Double pole, Single throw On a là deux entrées, connectées à deux sorties ou non connectées.
DPDT Double pole, Double throw Deux entrées sont connectées alternativement à deux sorties chacune. Chaque entrée et ses sorties sont électriquement indépendantes de l’autre entrée et ses sorties.
nPmT Multi pole, Multi throw ’n’ Entrées sont connectées à ’m’ sorties. Ici un 2P6T

D’autres configurations existent avec par exemple un point central stable qui permet de ne rien connecter dit ’Center Off’, ou plus de deux positions stables comme le gros bouton d’une machine à laver le linge ou de la sélection de source d’un vieil ampli HI-FI.

PNG - 30.6 kio
En haut, un ’Central Off’. En bas deux sélecteurs à multiples positions

Réagir à ces interrupteurs consiste à identifier le moment où un contact est activé ou relâché. Noter que tout comme un bouton poussoir, et comme tout dispositif mécanique de commutation, des rebonds sont présents au moment du changement d’état. Et il convient de les gérer dans le croquis Arduino.

Prenons un interrupteur SPST connecté à la broche 3 :

#define INTER 3

void setup()
{
  pinMode(INTER, INPUT);
}

void loop()
{
  if (digitalRead(INTER) == LOW) // Si la broche est LOW, faire :
    {instructions off}
  else // sinon, faire :
    {instructions on}
}

C’est le codage minimal. Il va nous exposer à plusieurs problèmes : les rebonds ne sont pas gérés, et la mémorisation de l’état courant n’est pas globale, ce qui fait qu’à chaque loop on va refaire les instructions on ou off... Ce qui peut être sans importance sur l’allumage d’une DEL par exemple, ou au contraire problématique dans un autre contexte. Voyons la version correcte, utilisant la bibliothèque Bounce2 recommandée par... LOCODUINO (et Arduino.cc, mais c’est accessoire...) !

#include <Bounce2.h>

#define INTER 3

// Créer (instancier) un objet Bounce
Bounce inter; 

void setup() 
{
  // Configure la broche avec la résistance de tirage
  pinMode(INTER, INPUT_PULLUP);
  // Attache l'objet 'inter' à la même broche
  inter.attach(INTER);
  inter.interval(5); // temps de latence entre deux mesures d'état
}

// Variable qui va contenir l'état courant du bouton
// On commence avec -1 qui est un état inconnu...
int courant = -1;

void loop() 
{
  // Mise à jour de l'état de inter : bouton pressé ou non ?
  inter.update();

  // Récupération de l'état du bouton
  int valeur = inter.read();

  // Si la valeur n'a pas changé depuis la dernière fois, ne rien faire.
  if (valeur == courant)
    return;

  // Agir en fonction de l'état du bouton
  if ( valeur == LOW)
    { Instructions On }
  else
    { Instructions Off }

  courant = valeur;
}

Dans cette version, grâce à Bounce on va bien éliminer les rebonds, et grâce à une petite gestion de valeur courante, on ne fera les choses qu’une seule fois... La connexion d’une broche de sortie d’un interrupteur répond exactement aux mêmes exigences que pour un bouton poussoir, en terme de présence ou non de résistance et de OUTPUT_PULLUP (plus d’explications ici).
Pour finir voyons le code pour un interrupteur à une entrée et deux sorties (SPDT) :

#include <Bounce2.h>

// Une broche par position
#define INTER_A 3
#define INTER_B 4

// Liste des états possibles de l'interrupteur. Les valeurs utilisées doivent juste être différentes entre elles.
// J'aurais d'ailleurs pu ré-utiliser INTER_A et INTER_B...
#define INTER_ETAT_INDEFINI  -1
#define INTER_ETAT_A  10
#define INTER_ETAT_B  20

// Créer (instancier) un objet Bounce pour chaque broche
Bounce interA; 
Bounce interB; 

void setup() 
{
  // Configure les broches avec la résistance de tirage
  pinMode(INTER_A, INPUT_PULLUP);
  pinMode(INTER_B, INPUT_PULLUP);

  // Attache l'objet 'interA' à sa broche
  interA.attach(INTER_A);
  interA.interval(5); // temps de latence entre deux mesures d'état

  // Attache l'objet 'interB' à sa broche
  interB.attach(INTER_B);
  interB.interval(5); // temps de latence entre deux mesures d'état
}

// Variable qui va contenir l'état courant du bouton
// On commence avec -1 qui est un état inconnu...
int courant = INTER_ETAT_INDEFINI;

void loop() 
{
  // Mise à jour de l'état des interA et B : bouton pressé ou non ?
  interA.update();
  interB.update();

  // Récupération de l'état des broches
  int valeurA = interA.read();
  int valeurB = interB.read();

  // Si la valeur n'a pas changé depuis la dernière fois, ne rien faire.
  if (valeurA == true && courant == INTER_ETAT_A)
    return;
  if (valeurB == true && courant == INTER_ETAT_B)
    return;

  if (valeurA == true)
    courant = INTER_ETAT_A;
  if (valeurB == true)
    courant = INTER_ETAT_B;

  // Agir en fonction de l'état du bouton
  if ( courant == INTER_ETAT_A)
    { Instructions etat A }
  else
    { Instructions etat B }
}

Il y a moyen de faire plus concis avec des tableaux, surtout si on veut augmenter le nombre de positions, mais au moins on comprend le principe. En fait chaque broche est gérée comme un bouton simple indépendant, alors que la variable ’courant’, elle, contient l’état général du switch.

Faites bien attention lorsque vous achetez ces interrupteurs, leurs caractéristiques électriques doivent être respectées (pas de 220V sur un switch pour montage électronique !), et il est très facile de se tromper en passant une commande sur le mode de fonctionnement : point milieu ou pas, nombre de positions stables, nombre de connexions commutées sur chaque position...

8 Messages

  • Les interrupteurs 10 septembre 2016 21:53, par Dominique

    Il y a peut-être une alternative à l’utilisation de la bibliothèque Bounce2 pour éliminer les rebonds :

    Le principe de l’anti-rebond est de faire 2 mesures espacées d’un temps de latence (quelques millisecondes), la 2ème mesure devant confirmer la première.

    Bounce2 embarque un temporisation dans chacun des objets dont les méthodes peuvent être appelées n’importe quand, et c’est bien normal. Si on appelle inter.update() dans la loop, cela déroule pas mal de code dans le processeur, à chaque tour de la loop donc pour presque rien.

    Si, par contre, on limite l’accès en lecture aux pins des inters, après l’écoulement d’une tempo qui est placée dans la loop, on n’a plus besoin de la bibliothèque bounce2, cette tempo pouvant être commune à tous les inters et poussoirs branchés sur des pins.

    Exemple :

      if (millis()-debounce > SAMPLE_TIME) {
        debounce = millis();   
        if ((digitalRead(STARTSTOP) == 0) && bouton ) {
          if (dccON) {
            digitalWrite(SIGNAL_ENABLE_PIN_MAIN,LOW);
            dccON = false;
          } else {
            digitalWrite(SIGNAL_ENABLE_PIN_MAIN,HIGH);
            dccON = true;
          }
          bouton = false;
        }
        if (digitalRead(STARTSTOP) == 1) {
          bouton = true;
        }      
      }

    Ici un seul bouton STARTSTOP est testé et comparé à sa valeur précédente "bouton" pour signaler un changement. J’aurais pu tester plusieurs inters et poussoirs dans le même temps.

    Puisque ce code retarde les mesures suivantes après la tempo "SAMPLE_TIME", on obtient le même résultat qu’avec Bounce2... en plus simple !

    Et pendant que la loop ne s’occupe pas des poussoirs et inters, elle a plus de temps pour les autres tâches.

    N’est-il pas ?

    Répondre

    • Les interrupteurs 11 septembre 2016 11:04, par Thierry

      C’est tout à fait juste. Bounce2 n’est que le moyen ’simple’ de mettre en oeuvre un timer logiciel sur chaque broche. Il n’est pas du tout obligatoire de s’en servir et on peut faire comme tu le fais ici avec un compteur de temps local. C’est d’ailleurs ce que j’avais utilisé dans UAD et ré-utilisé dans Commanders. Quant à gagner du temps en mutualisant ce timer, je ne suis pas sûr. Ce qui est sûr c’est que de la mémoire vive sera gagnée puisqu’un seul entier sera nécessaire au lieu d’un par broche, mais pour le temps d’exécution on ne gagne qu’un test entre deux entiers à chaque broche. A creuser...

      Répondre

  • Les interrupteurs 5 mai 2020 19:51, par Younes

    Bonjour,
    Tout d’habord merci pour ce partage.Voilà en fait,je travail sur un projet, et j’ai un soucis avec mon code,(je dois creer avec un arduino nano un systeme de clignotant avec un temps de clignotement de 6sec), mais le probleme c’est que l’interupteur que j’utilise(et je ne peux pas le changer :x) c’est un interupteur a bascule mais qui revient sur sa position initiale, je m’en sors vraiment pas, j’éspère avoir une reponse de votre part... *,*
    Merci d’avance :)

    Répondre

  • Les interrupteurs 20 août 2020 18:05, par sana

    comment faire le câblage d’un interrupteur KCD2 ave cart arduino ? merci

    Répondre

  • Les interrupteurs 20 août 2020 19:33, par msport

    Bonjour,
    Locoduino est un site participatif dédié au modélisme ferroviaire utilisant les Arduino.
    Si c’est le cas, décrivez votre projet sur le forum, rubrique "Vos projets", vous aurez probablement une réponse.
    Sinon relisez cette page, il y a certainement ce qu’il vous faut.
    Cordialement

    Répondre

  • Les interrupteurs 24 février 2022 17:06, par Claude Bouzerand

    Bonjour , J’essai de realiser un controle d’humidité pour une cave d’affinage pour fromage. Lhumidificateur est un refroidisseur d’air a eau avec ventilateur (essais concluants ) J’ai un Hygrostat 220 v avec un relais en sortie doc un contact sec . Je veux conserver ce "climatiseur avec son tableau de controle(vitesse ventilation,debit reglable eau...) la miise en route et l’arret se font aves un bouton poussoir simple premiere impulsion : Marche 2 eme appui :arret Avec un arduino Je veus faire ce contact a l’aide d’un relais Arduino 5 v. Que j’ai aussi. Mon idée est de meservir d’un contact du relais de l’hygrostat qui devient un interrupteur qui lors de ses changements d’etat enverra par la Uno un impulsion de 1/2s au relais qui etablira le contact arret ou marche de la "Clim."(J’ai tiré 2 fils en parallele du bouton poussoir soudes sur ses 2 contacts. Quel serait le programme le plus approprié pour cette realisrion de base... Je ne veux pas utiliser de hardware , batterie de relais. Je vous remercie de votre attention, ce n’est pas du modelisme ,ici...mais votre sie semble bien actif

    Répondre

  • Les interrupteurs 24 février 2022 20:26, par msport

    Bonjour,

    effectivement vous n’êtes pas sur le bon forum, voyez plutôt le forum.arduino.cc.
    Et vous trouverez certainement la solution avec la bibliothèque Bounce2 ci-dessous
    avec if ( debouncerB.fell() ) {...
    puis if ( debouncerB.rose() ) {...
    Cordialement

    Voir en ligne : Bibliothèque Bounce2

    Répondre

  • Les interrupteurs 18 août 2022 20:18, par MaX

    Je cherchais comment gérer un interrupteur ’Center Off’ et ce tuto est parfait !
    Merci beaucoup !

    Répondre

Réagissez à « Les interrupteurs »

Qui êtes-vous ?
Votre message

Pour créer des paragraphes, laissez simplement des lignes vides.

Lien hypertexte

(Si votre message se réfère à un article publié sur le Web, ou à une page fournissant plus d’informations, vous pouvez indiquer ci-après le titre de la page et son adresse.)

Rubrique « Matériel »

Les derniers articles

Les articles les plus lus