J'ai un bouton matériel connecté à une interruption, mais mon problème est qu'il rebondit un peu, ce qui rend la pression sur le bouton peu fiable. Je pense qu'une bonne partie de ces problèmes seraient résolus par l'échantillonnage dans la boucle principale, mais cela semble techniquement incorrect.
Les interruptions conviennent-elles mieux à la communication intra-circuit ou les interruptions conviennent-elles également aux commutateurs matériels? Si oui, quelles techniques anti-rebond puis-je utiliser?
J'ai essayé de conserver une variable de minuterie et de la comparer à l'heure actuelle, aux retards et à d'autres techniques. Il semble que les rebonds soient si rapides que cela n'a pas d'importance.
interrupts
button
sampling
OneChillDude
la source
la source
Réponses:
L'anti-rebond est une FAQ. Vous devriez pouvoir trouver ... un nombre presque illimité de pages Web sur le sujet. Smith a également commenté le PDF largement lu de Jack Ganssle sur le sujet. Et avec toutes ces réponses, vous avez à la fois des méthodes matérielles et logicielles.
J'ajouterai un peu à cette "littérature" en parlant principalement d'idées qui ne sont pas déjà bien couvertes. Mais avant de le faire, un ou deux points:
Depuis que je l' ai mentionné en utilisant une impulsion d' étirement 74121 et puisque Jack Ganssle ne pas le mentionner, ni personne ici ne encore, je peux aussi bien fournir ce supplémentaire lien comme suggéré supplémentaire de lecture sur l' utilisation du 74121 ou 555 comme un one-shot minuterie pour anti-rebond des commutateurs.
Passons maintenant à l'observation avec un microcontrôleur.
J'utilise généralement une machine à états pour gérer le rebond. Ceci est presque toujours piloté par un temporisateur "rythme cardiaque" que j'ai réglé à environ , si possible. (Je n'utilise généralement PAS les événements d'interruption déclenchés par le front pour plusieurs raisons.)8SP
La machine d'état ressemble à ceci:
simuler ce circuit - Schéma créé à l'aide de CircuitLab
La valeur DEBOUNCED pour le commutateur peut prendre des valeurs "inactif", "actif" et "inconnu". De cette façon, vous pouvez vous assurer que votre logiciel attend que la valeur du commutateur se stabilise après l'initialisation. Mais d'habitude, je ne m'embête pas avec ça. Je remplace la valeur "inconnue" par une valeur par défaut et j'utilise simplement un système de valeurs binaires à la place.
La machine d'état est entrée en définissant d'abord la valeur anti-rebond à sa valeur par défaut, puis en entrant dans l'état "CHANGING" de la machine d'état. À chaque intervalle de temps (généralement si je peux m'en tirer), je vais lire la valeur actuelle du commutateur et effectuer une mise à jour de l'état actuel et éventuellement de la valeur anti-rebond. Ensuite, je viens de sortir. Le code de haut niveau accède alors uniquement à l'état rebondi.8SP
Si cela m'importe, je peux également conserver un état antérieur de la déclaration. Dans ces cas, lors de la mise à jour de l'état anti-rebond lui-même, je copierai d'abord cet état dans un «état anti-rebond antérieur». Je peux ensuite utiliser la paire de valeurs pour déterminer s'il y a eu une transition anti-rebond. Parfois, je me fiche des transitions. Parfois je fais. Cela dépend donc. Mais dans tous les cas, je veux seulement connaître les transitions qui ont été dénoncées. Je ne me soucie jamais des transitions runt . Le code de haut niveau n'utilise jamais l'état interne que la machine d'état utilise pour son propre travail.
L'une des bonnes choses à propos de cette méthode est que je peux faire rebondir un port entier de commutateurs à la fois. Et je peux le faire sans une seule branche dans le code d'interruption, aussi. Cela signifie un code anti-rebond très rapide et court jusqu'à la largeur de port du microcontrôleur (généralement 8 bits de large). Un exemple de l'Atmel AT90 montre comment cela est réalisé en utilisant un événement d'interruption Timer0:
Cet exemple montre maintenant l'intégralité de l'accord, y compris les valeurs de commutateur anti-rebond précédentes et actuelles. Et il effectue également toutes les transitions d'état nécessaires. Je ne montre pas l'initialisation de ce code. Mais ce qui précède fait comprendre à quel point la machine d'état est facile à utiliser et le peu de code requis pour le faire. C'est assez rapide et simple et ne nécessite pas de branchement (ce qui implique parfois des cycles supplémentaires ainsi que de l'espace de code supplémentaire.)
Je préfère utiliser le timing car de longs, longs tests avec une variété de personnes différentes utilisant des équipements sur lesquels j'ai travaillé dans le passé m'ont conduit là-bas. J'ai essayé des périodes plus longues et quand je le fais, je commence à faire dire aux gens que la "réactivité" n'est pas assez "vive". (De nos jours, avec des enfants qui grandissent en jouant aux jeux de tir en temps réel, je pourrais même les raccourcir davantage. Ils se plaindront amèrement des retards, même légers, causés par les téléviseurs numériques modernes dans la configuration et l'affichage d'un cadre.)8SP
Certaines personnes auront des sentiments très clairs sur la netteté et la réactivité d'un système. Croustillant et réactif signifie échantillonner plus souvent, pas moins. Mais personnellement, je trouve périodes d'observation acceptables. ( Cependant, je ne trouve pas les périodes plus longues suffisantes, même pour moi.)20SP
Veuillez noter que la machine d'état que j'ai mentionnée doit d'abord entrer dans l'état SETTLED, puis y rester pendant une fois de plus avant que la valeur de DEBOUNCED ne soit mise à jour. Donc, appuyer sur un bouton et le maintenir, même dans les meilleures circonstances, nécessitera ces transistions:
Un nouvel état anti-rebond nécessite donc un minimum de 3 périodes d'échantillonnage pour être atteint.
Un bouton-poussoir nécessitera au moins 6 temps d'échantillonnage pour passer d'inactif à actif, puis revenir à inactif.
J'ai mentionné les détails ci-dessus afin qu'il soit absolument clair qu'un temps d'échantillonnage de signifie qu'il se situe quelque part entre pour passer d'inactif à un résultat anti-rebond actif reconnu. Et il faudra encore avant que l'état ne redevienne inactif. C'est un minimum de pour passer par un cycle complet de bouton poussoir.8SP 16ms <t≤24SP 24SP 40ms <t≤48SP
L'utilisation de durées d'échantillonnage plus longues aura des périodes correspondantes plus longues. Utiliser le j'ai déjà mentionné comme "acceptable" signifie alors quelque part autour de pour un cycle complet de bouton-poussoir . Et qui devient carrément vers le haut dans la zone où les gens n'ont tendance à remarquer. Je n'aime certainement pas la "sensation" si elle devient plus longue que cela.20SP 100ms <t≤120SP
Si vous optez pour cette voie, ne soyez pas cavalier quant à l'utilisation de temps d'échantillonnage plus longs. Si vous devez, alors je pense que vous devez également faire beaucoup de tests avec les utilisateurs / consommateurs.
Et si vous développez du code pour un clavier de saisie, utilisez des temps plus courts. Le record pour une dactylo a été établi il y a des décennies à 217 mots par minute. Il en résulte environ une clé tous les . Des dactylographes comme ça frappent plusieurs touches dans un ordre contrôlé. Pour obtenir de bonnes performances pour les dactylographes très rapides qui utilisent un système de commutation de relais à anche humidifié au mercure, j'ai constaté que45SP 2ms fonctionnait bien.
la source
Le rebond peut être fait dans le logiciel en masquant les IRQ pour le temps de rebond ou dans le matériel en ajoutant un condensateur de maintien avec votre RC = T> temps de rebond allant de 1 à 15 ms selon la taille du commutateur.
la source
Pour effectuer un rebond SW, enregistrez l'horodatage de l'événement en cours et vérifiez le retard par rapport au dernier événement valide:
UPD: avec peu de modifications, vous pouvez enregistrer des doubles-clics:
la source
Les interruptions sont également parfaites pour les commutateurs matériels. En utilisant des interruptions, vous évitez un grand gaspillage de ressources et éventuellement d'énergie, surtout si vous avez affaire à des appareils alimentés par batterie.
De plus, à mesure que votre code devient de plus en plus gros, vous verrez qu'il est encore plus facile d'implémenter les interruptions pour les boutons que de les interroger dans votre boucle principale.
Quant à votre anti-rebond, c'est probablement un problème de codage. J'utilise généralement une minuterie de ~ 10 ms pour anti-rebond, tout en vérifiant la libération du bouton. Veillez également à désactiver temporairement l'interruption du bouton pendant que vous la rebondissez, afin que la routine d'interruption ne soit pas exécutée plusieurs fois.
Si vous rencontrez toujours des problèmes, publiez le code ici, afin que nous puissions vous aider.
la source
Ceci est assez similaire à la réponse de Tony Stewart, mais je pense qu'elle pourrait être développée en partie.
Le schéma supérieur correspond à une interruption sur un front bas ou sur un front descendant. Le schéma du bas correspond à une interruption sur un front haut ou montant.
simuler ce circuit - Schéma créé à l'aide de CircuitLab
personnellement, étant donné le coût d'un condensateur, cela vaut la peine de simplement l'utiliser, plutôt que de m'inquiéter si mon logiciel rebounce est buggé.
Notez que, comme l'a dit Tony Stewart, la constante de temps dans ce circuit est de 10 ms(R∗C ou 10kΩ∗1μF) . Cela va prendre entre trois et cinq constantes de temps (selon la sensibilité de votre microcontrôleur pour que le bouton se réinitialise, donc si votre microcontrôleur a des problèmes avec la répétition de la fonction d'interruption, cela peut être la cause, et vous devrez peut-être ajustez le capuchon / la résistance pour que l'interruption ne se produise pas plusieurs fois (c'est-à-dire uniquement si votre interruption est configurée pour fonctionner sur un signal haut ou bas, et non sur le front montant ou descendant.
Lié au rebond matériel
la source
Les humains sont lents, nous n'avons pas besoin de l'attention immédiate d'un micro qui est de l'ordre des microsecondes.
Ce n'est bien sûr pas la seule ni la bonne façon de toujours le faire, mais je trouve généralement plus judicieux de configurer une minuterie (de nombreux micros ont des sys ticks) pour déclencher une interruption à intervalles fixes et déplacer l'état de la broche dans un variable pour le code à examiner plus tard. Vous vous retrouvez avec un var plein de cendres lors du rebond
10010110 frêne
mais à certains moments, vous obtiendrez ces 4 valeurs:
01111111 front montant vient de rebondir
11111111 bouton en régime permanent vers le haut
10000000 front descendant vient de rebondir
00000000 bouton en régime permanent vers le bas
La plupart du temps, cependant, j'utilise simplement un compteur qui se réinitialise pendant le rebond. C'est rapide, testé et facile à faire.
Si cela échoue, j'essaye quelque chose de plus intelligent du document Ganssle que d'autres ont suggéré!
la source