Programme C un bouton pour effectuer une tâche une fois lorsqu'il est pressé (latch)
Je suis relativement nouveau à c et le Raspberry Pi et suis en train de simples programmes. Ce que je voudrais, c'est quand le bouton est pressé, il printfs une fois et de ne pas le printf de nouveau jusqu'à ce que le bouton est pressé de nouveau, même si le bouton est maintenu enfoncé (sorte de verrou). J'ai pensé que peut-être l'ajout de la deuxième boucle while dans permettrait de résoudre ce problème, mais parfois, il n'est toujours pas en mesure de détecter l'appui sur un bouton.
#include <bcm2835.h>
#include <stdio.h>
#define PIN RPI_GPIO_P1_11
int main()
{
if(!bcm2835_init())
return 1;
bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_INPT);
while(1)
{
if(bcm2835_gpio_lev(PIN))
{
printf("The button has been pressed\n");
}
while(bcm2835_gpio_lev(PIN)){}
}
bcm2835_close();
return 0;
}
Vous pourriez trouver une recherche google pour "bouton anti-rebond" pour être utile.
C'est une question de savoir quel est le terme technique pour que je puisse regarder. Merci
Heureux de vous aider - je ne pense pas qu'il méritait une réponse, mais avoir le bon terme à rechercher aide vraiment parfois!
C'est une question de savoir quel est le terme technique pour que je puisse regarder. Merci
Heureux de vous aider - je ne pense pas qu'il méritait une réponse, mais avoir le bon terme à rechercher aide vraiment parfois!
OriginalL'auteur Marmstrong | 2013-04-30
Vous devez vous connecter pour publier un commentaire.
Pour un programme simple comme cela, à l'aide occupé des boucles comme vous l'avez fait est très bien. Cependant, je vous suggère de sortir de l'habitude, car il est souvent inacceptable dans quelque chose de plus qu'un jouet projet.
Il y a autant de façons d'antirebond un bouton comme il y a des gens de l'écriture de code. Le faire dans le matériel peut être le chemin à parcourir dans certains cas, mais ce n'est pas sans ses inconvénients. En tout cas, puisque c'est une programmation de site, nous supposons que vous ne pouvez pas (ou ne voulez pas) changer le matériel.
Un rapide et sale de la modification est de vérifier périodiquement le bouton dans la boucle principale, et seulement si, il a changé. Puisque vous êtes nouveau à C et à et à de la programmation embarquée, je vais éviter les minuteries et les interruptions, mais sachez que vous pouvez rendre le code plus compréhensible et maintenable une fois que vous apprendre à leur sujet.
Le problème avec cette solution est que la valeur nécessaire pour
BUTTON_DEBOUNCE_CHECKS
ne dépend pas seulement des caractéristiques de l'interrupteur, mais aussi la vitesse du processeur, et le temps d'exécution de l' "reste de votre look principal code". Il a également occupé-attend" - avec aucun autre appel de blocage dans la boucle principale de l'utilisation du PROCESSEUR aller à 100%, ans mourir de faim d'autres processus provoquant la faiblesse de l'ensemble du système. Si vous voulez être en mesure de faire d'autres travaux, tout en surveillant d'un bouton de la presse, il pourrait être préférable d'utiliser un thread séparé avec unusleep()
appel à maintenir la charge CPU minimal.Je suis absolument d'accord sur le caractère fragile de la
BUTTON_DEBOUNCE_CHECKS
valeur et a dit beaucoup de choses à la fois le texte et le code. Cependant, je sentais qu'il vaut mieux éviter trop de discussion sur les minuteurs, des interruptions, et de la planification pour quelqu'un vient juste d'apprendre à propos de l'anti-rebond. Je suis en désaccord sur le code occupé attente. Il n'y a rien qui empêche le "reste" du code" à partir de céder ou de dormir. Comme l'écrit, il va le sucer jusqu'à tous les cycles de processeur seulement si c'est purement coopérative OS multitâche ou il n'y a pas d'autres tâches. Je ne suis pas assez familier avec la Raspberry Pi pour savoir quel système d'exploitation temps réel il utilise (le cas échéant).comme pour
usleep()
, la prestation sera grandement diminué ou éliminé si il n'y a pas d'autres tâches exécutables (bon d'accord, il peut être utile de pouvoir dessiner et associés à la génération de chaleur dans certains systèmes). C'est très simple programme de test, l'OP ne peut plan de cesse de s'étendre à terme avec d'autres tâches. Il va certainement bloquer le thread appelant, bien que plus poliment que brut de spin-attendre. Même si vous le faites dans un autre thread, votre thread principal aura toujours besoin de rendement ou de sommeil, qui, comme je l'ai dit peut-être déjà fait. Par la manière, est-ce que le Raspberry Pi OS est compatible POSIX?Si votre bouton si très asymétrique, vous pouvez utiliser différents anti-rebond longueurs pour chaque direction. Matériel peuvent avoir le même genre de problème avec la recherche d'un bon compromis entre la réaction et de l'anti-rebond. Il prend également de l'espace sur la carte, affecte le coût unitaire, et est moins souple. Contrairement à un logiciel, vous ne pouvez pas changer à distance de matériel [eh bien, peut-être un FPGA, si vous considérez que le matériel 🙂 ]. Cependant, il prend la charge de travail hors de votre MCU et vous pouvez même mettre le bouton sur un pin d'interruption (si il y en a), ce qui vous permettra d'aller dans un mode de faible consommation et de la reprendre sur le bouton appuyez sur.
OriginalL'auteur jerry
Votre logique est correcte et que cela ne peut fonctionner si les boutons étaient parfaits. Mais ils ne le sont pas. Vous devez antirebond le signal de la touche. Deux méthodes pour l'atteindre (qui fonctionne le mieux lorsqu'il est combiné):
I. Ajouter un condensateur entre les deux broches de la touche (ou essayer encore plus sophistiqués bouton debouncer circuits), et/ou
II. utiliser un logiciel anti-rebond (pseudo-C):
etc.
Edit: @jerry l'a souligné, le ci-dessus ne fonctionne pas "correctement" lorsque le bouton est maintenu. Voici un couple de de plus en plus professionnels des extraits de code vous pouvez utiliser pour répondre à toutes les exigences.
C'est le droit. Ajouté que, ainsi qu'un lien pour de meilleures alternatives.
Si vous avez changé
while (elapsed_time < offset)
àwhile (elapsed_time < offset || button_pressed)
il permettrait de résoudre ce problème en particulierOriginalL'auteur
La fonction suivante sondages sur le bouton nominale de 1 milliseconde intervalles et a exigé que l'etat restent les "sorties" de 20 jours dans les sondages. Qui sera généralement suffisant pour antirebond la plupart des commutateurs, tout en conservant la réactivité.
Remplacer votre
while(bcm2835_gpio_lev(PIN)){}
boucle avec un appel àwaitButtonRelease()
.Vous trouverez peut-être nécessaire aussi d'anti-rebond appuie sur un bouton ainsi que les rejets. Qui est fait de la même manière, mais en comptant l'état opposé:
Ou peut-être une seule fonction d'anti-rebond d'état:
Compte tenu de cette dernière fonction, votre principale tandis que la boucle pourrait ressembler à:
Si vous avez accès à un oscilloscope à mémoire numérique, vous pouvez sonde, le signal de commande directement pour voir exactement ce que le le rebond de l'interrupteur ressemble. Il peut vous aider à comprendre le problème et aussi pour adapter l'anti-rebond pour les caractéristiques de votre commutateur.
usleep(1000)
appel doit être à l'intérieur de la boucle while. Sinon, vous n'allez pas faire beaucoup de rebond.Bon spot - grâce.
OriginalL'auteur Clifford