Voici un petit programme pour arduino que j’ai écrit et dont la fonction est d’assurer l’auto-maintien et l’anti-rebond pour un bouton poussoir monté en pull up.
« Kénécétoussa??? »
Petits rappels si jamais tu te poses la question.
Montage pull up
En théorie (quel beau pays!) tout est parfait. Mais en pratique on est souvent confronté à des phénomènes aléatoires. C’est le cas avec les entrées en électronique. L’arduino n’échappe pas à cette règle. Je vais essayer de la faire courte et simple.
Une entrée va agir un peu comme une antenne, et va capter toutes sortes d’interférences, des parasites. Pour éliminer ces parasites deux solutions.
Mettre l’entrée à la masse (via une résistance pour ne pas créer de court-circuit), auquel cas on amènera le +5V par le bouton, c’est le montage pull down (la résistance « tire » le potentiel de l’entrée vers le bas).
Mettre l’entrée au +5V (via une résistance, sinon court-circuit), le bouton se chargera de la mettre à la masse lorsqu’il sera appuyé. C’est le montage pull up (la résistance « tire » le potentiel de l’entrée vers le haut). Il faudra alors inverser la lecture de l’entrée dans le programme.
L’arduino dispose de résistances de pull up intégrées, ce qui facilite nos montages. L’utilisation de cette résistance interne se fait à la configuration de l’entrée:
pinMode(1, INPUT); // Configuration classique
pinMode(1, INPUT_PULLUP); // Configuration avec résistance pull up interne
Auto-maintien
Un bouton poussoir, à la différence de l’interrupteur, n’envoie qu’une impulsion. Si on utilise un poussoir pour, par exemple, allumer une LED, la LED ne sera allumée que le temps que le bouton poussoir sera appuyé.
void setup(){
pinMode(1, INPUT); // L'entrée du bouton poussoir
pinMode(2, OUTPUT); // La sortie de la LED
}
void loop(){
if(digitalRead(1) == HIGH){ // Si un appui sur le poussoir est détecté
digitalWrite(2, HIGH); // On active la sortie
}
}
Mais nous on veut que le poussoir change l’état de la LED et que cet état soit maintenu jusqu’à l’appui suivant: c’est là qu’intervient l’auto-maintien.
Un auto-maintien seul est très facile à coder. En réalité c’est un changement d’état, et non un véritable auto-maintien comme on pourrait faire en logique de contact dans un circuit électrique. On part d’un état LOW pour la sortie (la LED), et on vient inverser cet état à chaque appui sur le bouton. Ça tient en quelques lignes de code, l’affaire est pliée.
boolean etatLed; // Déclaration de la variable etatLed
void setup(){
pinMode(1, INPUT); // L'entrée du bouton poussoir
pinMode(2, OUTPUT); // La sortie de la LED
etatLed = false; // Initialisation de la variable etatLed
}
void loop(){
if(digitalRead(1) == HIGH){ // Si un appui sur le poussoir est détecté
etatLed = !etatLed; // On inverse l'état de la variable etatLed
}
digitalWrite(2, etatLed); // On active ou pas la sortie en fonction de etatLed
}
En théorie cet exemple fonctionne parfaitement. Mais en pratique ce n’est pas, comme souvent, le cas.
Anti-rebond
Les boutons poussoirs, et tous les contacts en général, ne génèrent pas un signal franc. des petites oscillations vont apparaître à chaque changement d’état. Ces oscillations vont être interprétées par l’arduino qui va, de manière erratique, interpréter des états qui n’ont pas lieu d’être. C’est le phénomène de rebond. Et c’est là qu’intervient, tu l’as deviné, l’anti-rebond. Sur le principe il s’agit de détecter l’appui et de le confirmer après un bref délai (quelques dizaines de millisecondes).
Le code en question
Le code qui va suivre intègre ces deux fonctions. Il est moins explicite que les deux exemples ci-dessus mais est intégrable dans un programme et peut être utilisé tel quel ou presque.
Ce code sert d’auto-maintien et d’anti-rebond pour bouton poussoir monté en pullup.
- Les variables sont à déclarer en début de programme. Adapter leur nom au programme si besoin.
- La fonction setup n’est pas à copier, elle ne sert que pour le fonctionnement de ce programme de manière autonome.
- La fonction loop représente le programme de destination et ne sert qu’à appeler la fonction « antiRebondAvecVerrouillage » et à représenter son résultat sur une sortie. Elle n’est pas à copier.
- La fonction « antiRebondAvecVerrouillage »:
- Est à copier dans le programme et à renommer si besoin.
- Prend comme argument le numéro de l’entrée à lire ou la variable correspondante.
- Retourne une variable de type int qui représente l’état du contact auto-maintenu.
Note: J’ai utilisé une variable de type int comme retour de la fonction parce qu’avec une variable de type boolean la sortie était systématiquement à 1 dès le démarrage du programme, et ce pour une raison que j’ignore. Pour déboguer j’ai affiché sur le moniteur série la valeur de outFonction, le programme s’est alors mis à fonctionner correctement (c’est à dire sortie à 0 au démarrage) sans aucune autre modification. En commentant cette ligne de débogage la sortie repasse à 1 au démarrage. Pour l’instant je ne connais pas la raison de ce fonctionnement, je me demande si ce n’est pas un bug.
/*
- Ce code sert d'auto-maintien et d'anti-rebond pour bouton poussoir monté en pullup.
- Les variables sont à déclarer en début de programme. Adapter leur nom au programme si besoin.
- La fonction setup doit être ignorée, elle ne sert que pour le fonctionnement de ce programme de manière autonome.
- La fonction loop représente le programme de destination et ne sert qu'à appeler la fonction "antiRebondAvecVerrouillage" et à représenter son résultat sur une sortie. Elle n'est pas à copier.
- La fonction "antiRebondAvecVerrouillage":
- Est à copier dans le programme et à renommer si besoin.
- Prend comme argument le numéro de l'entrée à lire ou la variable correspondante.
- Retourne une variable de type int qui représente l'état du contact auto-maintenu.
*/
const int POUSSOIR = 2; //Constante, ne sert que pour ce programme, ne pas intégrer.
int out = 0;
boolean verrouillage = 0;
unsigned long int t1;
void setup(){
pinMode(POUSSOIR, INPUT_PULLUP);
pinMode(10, OUTPUT);
}
void loop(){
int outFonction = antiRebondAvecVerrouillage(POUSSOIR);
if (outFonction == 1){
digitalWrite(10, HIGH);
}
if (outFonction == 0){
digitalWrite(10, LOW);
}
}
int antiRebondAvecVerrouillage(int inPoussoir){
if(digitalRead(inPoussoir) == HIGH){
t1 = 0;
verrouillage = 0;
}
if((digitalRead(inPoussoir) == LOW) and (t1 == 0)){
t1 = millis();
}
if((digitalRead(inPoussoir) == LOW) and (millis() - t1 >= 50) and (verrouillage == 0)){
switch(out){
case 0:
out = 1;
verrouillage = 1;
break;
case 1:
out = 0;
verrouillage = 1;
break;
}
return out;
}
}