2008-09-30 4 views
6

Avez-vous une routine de débrayage simple pour gérer une seule entrée de commutateur?Simple Debounce Routine

Ceci est un système simple sans système d'exploitation.

Je souhaite éviter une construction en boucle avec un nombre spécifique, car la vitesse du processeur peut fluctuer.

Répondre

10

Je pense que vous pouvez en apprendre beaucoup sur ce ici: http://www.ganssle.com/debouncing.pdf

Votre meilleur pari est toujours de le faire dans le matériel si possible, mais il y a quelques réflexions sur les logiciels là-dedans aussi.

code exemple simple de TFA:

#define CHECK_MSEC 5 // Read hardware every 5 msec 
#define PRESS_MSEC 10 // Stable time before registering pressed 
#define RELEASE_MSEC 100 // Stable time before registering released 
// This function reads the key state from the hardware. 
extern bool_t RawKeyPressed(); 
// This holds the debounced state of the key. 
bool_t DebouncedKeyPress = false; 
// Service routine called every CHECK_MSEC to 
// debounce both edges 
void DebounceSwitch1(bool_t *Key_changed, bool_t *Key_pressed) 
{ 
    static uint8_t Count = RELEASE_MSEC/CHECK_MSEC; 
    bool_t RawState; 
    *Key_changed = false; 
    *Key_pressed = DebouncedKeyPress; 
    RawState = RawKeyPressed(); 
    if (RawState == DebouncedKeyPress) { 
     // Set the timer which allows a change from current state. 
     if (DebouncedKeyPress) Count = RELEASE_MSEC/CHECK_MSEC; 
     else Count = PRESS_MSEC/CHECK_MSEC; 
    } else { 
     // Key has changed - wait for new state to become stable. 
     if (--Count == 0) { 
      // Timer expired - accept the change. 
      DebouncedKeyPress = RawState; 
      *Key_changed=true; 
      *Key_pressed=DebouncedKeyPress; 
      // And reset the timer. 
      if (DebouncedKeyPress) Count = RELEASE_MSEC/CHECK_MSEC; 
      else Count = PRESS_MSEC/CHECK_MSEC; 
     } 
    } 

}

+0

en fait, il trouve environ 10 minutes après avoir posé la question. Tout à fait pratique. Je suis d'accord avec la solution HW ... si seulement ... – Benoit

+0

@Benoit: Bon, marquez-moi répondre! ;) – GEOCHET

1

Pour annuler, vous voulez ignorer tout basculement qui dure en dessous d'un certain seuil. Vous pouvez activer un temporisateur matériel ou utiliser un indicateur défini par une interruption périodique.

1

Si vous pouvez vous en sortir avec elle, la meilleure solution dans le matériel est d'avoir le commutateur ont deux états distincts sans état entre les deux. C'est-à-dire, utilisez un commutateur SPDT, avec chaque pôle alimentant soit les lignes R ou S d'un flip/flop. Câblé de cette façon, la sortie du flip/flop devrait être débattue.

+0

Je suis d'accord que HW serait mieux mais ce n'est pas dans les dés. – Benoit

+0

Si c'est quelque chose qu'une personne est en train de changer, vous avez presque toujours besoin de l'annuler, même s'il y a un blocage du matériel. Les mains des gens tremblent, ils n'utilisent pas assez ou trop de force sur le bouton, ou de la merde est entrée dans le bouton - ils peuvent * mécaniquement * créer un rebond de cette façon, ce que votre SPDT rapportera alors fidèlement. Le rebondissement du matériel est génial, et, si rien d'autre, vous permet de réduire votre temps de rebond et d'obtenir un clavier plus réactif. –

2

Il n'existe pas de solution simple unique qui fonctionne pour tous les types de boutons. Peu importe ce que quelqu'un vous dit d'utiliser, vous devrez l'essayer avec votre matériel et voir comment cela fonctionne. Et regardez les signaux sur une portée, pour vous assurer que vous savez vraiment ce qui se passe. Le lien de Rich B vers le pdf semble être un bon point de départ.

9

Les solutions les plus simples sont souvent les meilleures, et j'ai trouvé que simplement lire l'état du commutateur toutes les N millsecondes (entre 10 et 50, selon les commutateurs) a toujours fonctionné pour moi. J'ai éliminé les routines de rebond cassées et complexes et les ai remplacées par un simple sondage lent, et les résultats ont toujours été assez bons de cette façon. Pour l'implémenter, vous aurez besoin d'une simple interruption de minuterie périodique sur votre système (en supposant qu'il n'y a pas de support RTOS), mais si vous avez l'habitude de le programmer au bare metal, cela ne devrait pas être difficile.

Notez que cette approche simple ajoute un retard à la détection du changement d'état. Si un commutateur prend T ms pour atteindre un nouvel état stable, et qu'il est interrogé toutes les X ms, alors le délai le plus défavorable pour détecter la presse est T + X ms. Votre intervalle d'interrogation X doit être être plus grand que le temps de rebond du cas le plus défavorable T.

+0

Je suis d'accord qu'une période stable fonctionne parfaitement bien - j'utilise souvent mon cycle de rafraîchissement d'affichage pour faire rebondir "depuis que je suis là" et cela fonctionne bien. Il vous manque la "logique anti-rebond" ici, à moins que vous ne déclenchiez toujours un changement d'état, ce qui ne fonctionnera tout simplement pas à chaque fois. –

+3

@Tom, tout le point est là * est * pas de logique de rebond: Vous n'en avez pas besoin. Switch 'bounce' est vraiment juste un artefact causé par l'échantillonnage d'une clusure de contact mécanique plus rapidement que prévu pour fonctionner. En baissant la fréquence d'échantillonnage, vous évitez le problème. (et oui, la fréquence d'actualisation vidéo est sur place pour la plupart des bons commutateurs) – Roddy

+0

Très intéressant, je n'y avais pas pensé de cette façon. Après quelques gribouillages, je crois que vous avez prouvé que la période d'interrogation est entre deux fois le plus long cycle de rebond de votre matériel et la moitié de la plus courte pression de bouton que vous accepterez, aussi longtemps que vous êtes prêt à accepter un délai de (parfois) jusqu'à deux cycles d'interrogation complets. (Pour un taux de rafraîchissement de l'écran de 60Hz, cela implique un cycle de rebond de <9ms par exemple. Je dois avoir été grincheux, je vous ai marqué - et apparemment je ne peux pas changer cela. :-(Si vous changez légèrement votre réponse, je peux la marquer à nouveau –

2

J'ai utilisé une méthode de vote majoritaire pour annuler une entrée. J'ai mis en place un simple type de structure de données à trois registres à décalage d'état, et décale chaque échantillon et prend les deux meilleurs sur trois comme la valeur "correcte". Il s'agit évidemment d'une fonction de votre gestionnaire d'interruptions ou d'un scrutateur, selon la méthode utilisée pour lire le matériel. Mais, le meilleur conseil est de demander à votre concepteur matériel amical de "verrouiller" la valeur et de vous permettre d'effacer cette valeur quand vous y arriverez.

+0

Cela ne me semble pas juste.Sur l'ordre dans lequel ils entrent est important? Par exemple, si votre registre à décalage dit Up Down Up, vous êtes sûrement "au milieu d'un rebond" et vous devez attendre une période de plus –

0

Ce que je fais habituellement est d'avoir trois variables ou plus la largeur du registre d'entrée. Chaque sondage, généralement à partir d'une interruption, décale les valeurs pour faire place au nouvel échantillon.Ensuite, j'ai une variable débité formé en définissant le logique et des échantillons, et en effaçant l'inverse logique ou. à-dire (non testé, de la mémoire)

input3 = input2; 
input2 = input1; 
input1 = (*PORTA); 

debounced |= input1 & input2 & input3; 
debounced &= (input1 | input2 | input3); 

Voici un exemple:

antirebond a xxxx (où 'x' est "whatever")

input1 = 0110, 
input2 = 1100, 
input3 = 0100 

Avec les informations ci-dessus,

Nous devons commuter seulement les bits 2 à 1, et les bits 0 à 0. Les autres sont encore en train de "rebondir".

debounced |= (0100); //set only bit 2 
debounced &= (1110); //clear only bit 0 

Le résultat est que maintenant = x1x0 anti-rebond

+0

J'ai trouvé votre algorithme intéressant (proche de ce que je recherche), je l'ai édité pour enlever la négation '~ », ce que je pense était incorrect – JACH

0

gourou embarqué Jack Ganssle a donné ce beaucoup de réflexion. Son PDF de 26 pages sur le sujet (A Guide to Debouncing) est le meilleur que j'ai lu sur ce sujet.

0

L'algorithme de ganssle.com pourrait contenir un bogue. J'ai l'impression afin d'éviter les rebonds correctement la presse initiale, la ligne suivante

static uint8_t Count = RELEASE_MSEC/CHECK_MSEC; 

devrait lire

static uint8_t Count = PRESS_MSEC/CHECK_MSEC; 

.

0

Au niveau matériel la routine anti-rebond de base doit prendre en compte les segments suivants d'un comportement de clé physique (ou du commutateur):

clés assis tranquillement:> doigt touche la touche et commence à pousser aval> biefs clés Le doigt commence à relâcher la touche et le ressort appuie sur la touche. Le doigt et la clé vibrent un peu jusqu'à ce qu'il se mette à

Toutes ces étapes impliquent 2 raclages et frottements de métal et se bousculer les uns les autres, faisant varier la tension de 0 à maximum sur des périodes de millisecondes, donc il y a du bruit électrique à chaque étape:

(1) Bruit lorsque la clé n'est pas touchée, causée par des problèmes environnementaux tels que l'humidité, les vibrations, les changements de température, etc.provoquant des changements de tension dans les contacts principaux

(2) le bruit provoqué que la touche est pressée vers le bas

(3) de bruit en tant que la touche est maintenue enfoncée

(4) de bruit en tant que la clé est être libéré

(5) le bruit que les clés vibre après avoir été libéré

est ici l'algorithme par lequel on devine essentiellement que la touche est pressée par une personne:

lire l'état de la clé, qui peut être "peut être pressé", "est définitivement pressé", "n'est pas pressé", "ne peut pas être pressé"

boucle lorsque la touche "peut être" enfoncée (s'il s'agit de matériel, il s'agit d'un échantillon de tension supérieur à une certaine valeur de seuil), jusqu'à ce qu'il soit "not not not" (inférieur à la tension de seuil) (initialisation en attente de bruit) quiesce, définition de « peut-être » et « certainement pas » dépend de l'application spécifique)

boucle

alors que la clé est « certainement pas » enfoncé jusqu'à ce que la touche « pourrait être » pressé

lorsque la touche "pourrait être" enfoncée, commencer à boucler et échantillonner l'état de la touche, et garder la trace de la durée pendant laquelle la touche "pourrait être" - si la clé remonte à "peut-être pas" ou "appuyez sur l'état avant un certain laps de temps, redémarrez la procédure - à un certain temps (nombre de millisecondes) que vous avez choisi (généralement en expérimentant avec différentes valeurs) vous décidez que la valeur de l'échantillon n'est plus causée par le bruit, mais est très probablement causé par la clé effectivement tenue par un doigt humain et vous retournez la valeur « pressé »


while(keyvalue = maybepressed){ 
//loop - wait for transition to notpressed 
sample keyvalue here; 
maybe require it to be "notpressed" a number of times before you assume 
it's really notpressed; 
} 
while(keyvalue = notpressed){ 
//loop - wait for transition to maybepressed 
sample keyvalue 
again, maybe require a "maybepressed" value a number of times before you 
transition 
} 
while(keyvalue=maybepressed){ 
    presstime+=1; 
    if presstime>required_presstime return pressed_affirmative 
    } 
} 
return pressed_negative 
Questions connexes