Je vous propose de vous expliquer le phénomène , anti-rebond , qu'il faut traiter dès que l'on utilise un interrupteur, en particulier ,nos chers boutons-poussoirs.
On appelle phénomène rebond , le fait que le contact d'un BP n'est pas franc, de part l’élasticité des matériaux utilisés et de l'architecture mécanique , induisant plusieurs pic de tension, très rapide.
Le passage de l'état haut à l’état bas, peut donc être interpréter plusieurs fois lors d'un seul appui, si votre programme tourne vite !
Il y a plusieurs méthodes pour palier à ceci, certaines avec des inconvénients .
voici un rebond, lors du passage de l’état bas à l’état haut d'un bouton poussoir.
On remarque lors de l'appui des pics se forment avant de se stabiliser à l’état haut .
Ce sont ces rebonds qu'il va falloir "masquer".
Méthode en hard :
Mettre un condensateur en parallèle sur le BP , au plus prêt de celui ci .
Ainsi lors de la montée et de la descente du pic de tension, le condensateur va "amortir" ces pics de tension et les "lisser" en quelques sortes.
Méthode en Soft:
Pour des questions de raisonnement , je détermine qu'au repos le BP est relâché et que la broche du µC, est donc relié a GND (par la pull-down), Lors d'un appui on met le potentiel de la broche à Vcc.
1/ créer une pause afin d'attendre la stabilisation de la tension . et ré-vérifier l’état haut pour valider l'action a faire.
On obtiendrai ceci :
Code : Tout sélectionner
while(1) // Ici c'est notre boucle sans fin.
{
if (BP == 1) // Si le BP est appuyé
{delay_ms(10);} // On marque une pause pour attendre la stabilisation à l'état haut.
// Je met les accolades par reflex même si avec une seule action dans le "if" je pouvais m'en passé.
if (BP == 1) // Si après la pause l’état est toujours à 1 (Vcc) alors valide notre action , et on peut l’exécuter.
{Action à réaliser après un appui}
}
les inconvénients de cette méthode sont que le programme est bloqué pendant les 10ms de pause .Pause qui est peut être variable suivant les BP, leurs mécaniques , leurs anciennetés etc ( entre 10ms et 50ms en général).
Et la deuxième , c'est que si vous laissé appuyer trop longtemps, il se peut que le programme fasse un deuxième tour et détecte un autre appui ;
2/ amélioration de la première méthode
Pour palier au problème de répétition d'appui, lors d'un appui prolongé , nous allons autoriser le programme à repartir seulement quand le BP est relâché .
Ainsi je vais créer une boucle vide , tant que le BP sera à l'état haut.
Code : Tout sélectionner
while(1) // Ici c'est notre boucle sans fin.
{
if (BP == 1) // Si le BP est appuyé
{delay_ms(10);} // On marque une pause pour attendre la stabilisation à l'état haut
// Je met les accolades par reflex même si avec une seule action dans le "if" je pouvais m'en passé.
if (BP == 1) // Si après la pause l’état est toujours à 1 (Vcc) alors valide notre action , et on peut l’exécuter.
{Action à réaliser après un appui}
while (BP ==1) {} // Ici notre boucle qui tourne sur elle même, tant que le BP est appuyé il faut donc obligatoirement relâché le BP pour sortir .
{delay_ms(10);} // On marque une pause pour attendre la stabilisation à l'état bas.
}
Dans cette méthode, c'est nous même qui bloquons le programme, si jamais le bouton reste appuyé. Mais on ne peut effectuer plusieurs fois la même action si on laisse le doigt appuyé . c'est a vous de faire des compromis et de trouve ce qui vous va le mieux .
3/ La meilleure pour moi
Ici on va compliquer un peu, mais cela va libérer le programme. En effet ce qui nous bloque c'est le fait de détecter et comparer l'appui sur le BP .
Pour palier à ce problème nous allons travailler avec un flag ( *drapeau ).
Voici le déroulement du programme :
- On détecte l'appui du BP, par un passage à l'état haut et on temporise pour éviter les rebonds (rien de neuf).
- On passe notre flag à 1 . Ce flag à pour but de nous indiqué que le BP à été appuyé(mémorisation) . Donc nous avons eu un front montant.
- Ensuite l'astuce: On compare l'état actuel du BP , à l'état d’avant( notre mémorisation) .
- Si nous avons eu un front montant, et que maintenant nous sommes à l'état bas , c'est qu'il y a eu un front descendant, donc un appui.
Code : Tout sélectionner
//################################# Boucle infinie #########################################
while(1) // Ici c'est notre boucle sans fin.
{
if (BP == 1) // Si notre Bp est appuyé
{
delay_ms(10); // On fait une pause stabiliser notre niveau logique . ( avec 1ms ça suffit sur mes BP).
etat_Bp = 1; // On met notre flag à 1, pour signaler que notre Bp à été appuyé
}
// L'astuce es ici
if (etat_Bp == 1 && (BP == 0)) // Si notre BP à été appuyé ET qu'actuellement sont état est relâché. Alors c'est qu'il y a front descendant donc un appui est validé
{ // Si notre BP n'avait pas été appuyé donc état_Bp =0 , nous aurions pas incrémenter notre chiffre.
unite++; // Si notre BP à été appuyé mais que son état actuel est toujours appuyé , nous aurions pas incrémenter notre chiffre.
etat_Bp = 0; // Résultat on as bien détecter un front montant ( BP appuyé) et un front descendant (BP relâché)
delay_ms(10); // On incrémente le chiffre
// Ici on remet notre flag à 0 pour ré-armer notre détection de front montant
} // On fait une pause pour le éviter les rebonds au relâchement
affichage() ;
} // Nous arrivons à la parenthèse de la boucle infini, donc on repart au début et ainsi de suite .
} // Fin de notre fonction principale
Voila , je n'ai pas trouvé mieux pour faire un anti-rebond efficace !
Maintenant ceux qui travaille avec MikroC peuvent utilisé la fonction "button" , qui simplifie le code, car elle comprends l’état du bouton , la tempo .
Voici le même exemple en utilisant "button".
Code : Tout sélectionner
//################################# Boucle infinie #########################################
while(1) // Ici c'est notre boucle sans fin.
{
if ( Button(&PORTC, 0, 10, 1)) // ( nom du port, N° broche du BP, temporisation anti rebond (10ms), état du BP (0 ou 1) )
etat_Bp = 1; // On met notre flag à 1, pour signaler que notre Bp à été appuyé
if ( etat_Bp == 1 && Button(&PORTC, 0, 10, 0)) // comparaison de notre ancien état(état BP) , à l’état actuel avec tempo ( fonction "button")
{
unite++; // On incrémente le chiffre
etat_Bp = 0; // Ici on remet notre flag à 0 pour ré-armer notre détection de front montant
}
affichage() ;
} // Nous arrivons à la parenthèse de la boucle infini, donc on repart au début et ainsi de suite .
} // Fin de notre fonction principale
Configuration :
-IDE : MikroC Pro for PIC Version 6.6.2
-Compilateur : Mikro prog suite fo PIC V 2.32
-Plaque Easy PIC V7
L'objectif :
Visualiser l'effet indésirable du rebond ( ou plutôt de l'appui prolongé)
Je n'ai pas réussis à faire un programme permettant de compter le nombre de pics de tension lors d'un appui. Encore une fois si un Expert passe par la !
[spoil]
Code : Tout sélectionner
//################################# Boucle infinie #########################################
while(1) // Ici c'est notre boucle sans fin.
{
if (BP == 1) // Si le BP est appuyé
delay_ms(10); // On attend pour stabilisation
if (BP == 1) // Si il est toujours appuyé ce n'est pas un rebond
{unite++;} // On incrémente le chiffre
while (BP ==1){ affichage() ;} // Ici on boucle tant qu'on a pas relâché le BP.Delay_us Mais je n'aurai plus d'affichage
// Comme ceci bloque, alors j'ai mis l’affichage dans la boucle pour la démo !
affichage() ;
} // Nous arrivons à la parenthèse de la boucle infini, donc on repart au début et ainsi de suite .
} // Fin de notre fonction principale
La vidéo est un peu sombre pour limiter les scintillement des afficheurs.
http://www.dailymotion.com/video/x31kqz9
Conseils :
- Les flags, sont des variables de type "bit" , donc pouvant prendre la valeur de 0 et 1 seulement. Ils sont très utiles, car prendre peu de place, et peuvent changer d’état facilement ( en leur ajoutant 1 par exemple il passe 1 à 0 ou de 0 à 1) .
- dans les programmes j’écris par exemple "etat_Bp == 1" , ceci peut être remplacé implicitement par "etat_Bp" , cela serait interprété pareil . maintenant si vous n'êtes pas à l’aise , continuer d'écrire avec "==" ça évitera les ennuis .