Eu tenho um botão de hardware conectado a uma interrupção, mas meu problema é que ele salta um pouco, fazendo com que o botão não seja confiável. Eu acho que muitas dessas questões seriam resolvidas com a amostragem no loop principal, mas isso parece tecnicamente errado.
As interrupções são mais apropriadas para comunicação intra-circuito ou as interrupções também são apropriadas para comutadores de hardware? Em caso afirmativo, quais técnicas de devolução posso usar?
Tentei manter uma variável de timer e compará-la com a hora atual, atrasos e outras técnicas. Parece que os saltos são tão rápidos que não importa.
interrupts
button
sampling
OneChillDude
fonte
fonte
Respostas:
A devolução é um FAQ. Você deve ser capaz de encontrar ... quase um número ilimitado de páginas da web sobre o assunto. Smith também comentou sobre o PDF amplamente lido de Jack Ganssle sobre o assunto. E com todas essas respostas, você tem métodos de hardware e software.
Vou acrescentar a essa "literatura" apenas um pouco falando principalmente sobre idéias que ainda não foram abordadas bem. Mas antes disso, um ou dois pontos:
Como eu mencionei o alongamento de pulso usando um 74121 e como Jack Ganssle não o menciona, e também ninguém aqui, eu também posso fornecer esse link adicional como uma leitura adicional sugerida sobre o uso do 74121 ou 555 como one-shot temporizador para interrupção de interruptores.
Agora, vamos fazer isso através da observação com um microcontrolador.
Normalmente, uso uma máquina de estado para lidar com a devolução. Isso quase sempre é acionado por um timer regular de "pulsação" que eu defino para cerca de , sempre que possível. (Geralmente, NÃO uso eventos de interrupção acionados por borda por vários motivos.)8em
A máquina de estado fica assim:
simular este circuito - esquemático criado usando o CircuitLab
O valor de DEBOUNCED para o comutador pode assumir os valores "inativo", "ativo" e "desconhecido". Dessa forma, você pode garantir que o software aguarde até que o valor do comutador seja estabelecido após a inicialização. Mas geralmente, eu não me importo com isso. Substituo o valor "desconhecido" por algum valor padrão e, em vez disso, apenas uso um sistema de valores binários.
A máquina de estados é inserida definindo primeiro o valor debitado como seu padrão e, em seguida, inserindo o estado "ALTERANDO" da máquina de estados. A cada intervalo de tempo (normalmente se eu puder me safar), lerei o valor atual da chave e executarei uma atualização do estado atual e, possivelmente, do valor debitado. Então eu apenas saio. O código de alto nível acessa apenas o estado de devolução.8em
Se isso for importante para mim, também posso manter um estado debitado prévio. Nesses casos, ao atualizar o próprio estado debitado, primeiro copio esse estado para um 'estado debitado anterior'. Em seguida, posso usar o par de valores para determinar se houve uma transição rebocada. Às vezes, não me importo com transições. Ás vezes eu faço. Então depende. Mas em todos os casos, eu só quero saber sobre as transições que foram rebatidas. Eu nunca se preocupam com runt transições. Portanto, o código de alto nível nunca usa nenhum estado interno que a máquina de estado usa para seu próprio trabalho.
Uma das coisas boas sobre esse método é que posso renunciar a uma porta inteira de switches de uma só vez. E eu posso fazer isso sem uma única ramificação no código de interrupção também. Isso significa um código de depuração muito rápido e curto para a largura da porta do microcontrolador (geralmente com 8 bits de largura). Um exemplo do Atmel AT90 mostra como isso é alcançado usando um evento de interrupção Timer0:
Agora, este exemplo mostra a oferta completa, incluindo os valores anteriores e atuais da opção debitada. E ele executa todas as transições de estado necessárias também. Não mostro a inicialização deste código. Mas o exposto acima mostra o quão fácil é a máquina de estado e como é necessário pouco código para fazê-lo. É bastante rápido e simples e não requer ramificação (o que às vezes envolve ciclos adicionais e espaço de código adicional).
Prefiro usar o tempo porque testes longos e longos com várias pessoas diferentes usando equipamentos nos quais trabalhei no passado me levaram até lá. Eu tentei períodos mais longos e, quando faço isso, começo a fazer as pessoas me dizerem que a "capacidade de resposta" não é "rápida" o suficiente. (Hoje em dia, com crianças crescendo em jogos em tempo real "atirar neles", posso até reduzi-lo ainda mais. Eles vão reclamar amargamente dos atrasos leves causados pelas modernas TVs digitais na configuração e exibição de um quadro.)8em
Algumas pessoas têm sentimentos muito claros sobre o quão preciso e responsivo um sistema deve ser. Nítido e responsivo significa amostrar com mais frequência, não menos. Mas, pessoalmente, considero aceitáveis períodos de observação. ( Porém, não acho que os tempos mais longos sejam bons o suficiente para mim.)20em
Observe que a máquina de estado que mencionei deve primeiro entrar no estado SETTLED e, em seguida, permanecer lá por mais um tempo de amostra antes que o valor de DEBOUNCED seja atualizado. Então, apertar um botão e segurá-lo, mesmo nas melhores circunstâncias, exigirá as seguintes transições:
Portanto, um novo estado debocado requer um período mínimo de 3 períodos de amostra para ser alcançado.
Um botão de pressão exigirá pelo menos 6 tempos de amostra para passar de inativo para ativo e depois voltar para inativo.
Mencionei os detalhes acima para que fique absolutamente claro que um tempo de amostragem de significa que está entre passar de inativo a um resultado reconhecido ativo debitado. E serão necessários outros antes que o estado possa retornar para inativo. Isso é no mínimo para passar por um ciclo inteiro de botões.8em 16ms <t≤24em 24em 40.ms <t≤48em
O uso de tempos de amostragem mais longos terá períodos correspondentemente mais longos. O uso de eu mencionei como "aceitável" para mim já significa algo em torno de por um ciclo completo de botões . E isso está ficando diretamente para dentro da área onde as pessoas não tendem a aviso prévio. Eu certamente não gosto da "sensação" se ficar mais tempo do que isso.20em 100ms <t≤120em
Se você seguir esse caminho, não seja descuidado ao usar tempos de amostragem mais longos. Se você precisar, acho que também deve fazer muitos testes com usuários / consumidores.
E se você estiver desenvolvendo código para um teclado de digitação, use tempos mais curtos. O recorde para um datilógrafo foi estabelecido décadas atrás em 217 wpm. Isso resulta em cerca de uma chave a cada . Datilógrafos como esse estão pressionando várias teclas em uma ordem controlada. Para obter um bom desempenho para datilógrafos muito rápidos que usam um sistema de comutação de relé com palheta úmida de mercúrio, descobri que funcionava bem.45em 2em
fonte
O debounce pode ser feito no software, mascarando os IRQs para o tempo de ressalto ou no hardware, adicionando um capacitor de retenção com seu tempo de ressalto RC = T> variando de 1 a 15ms, dependendo do tamanho do comutador.
fonte
Para fazer um retorno do SW, registre o registro de data e hora do evento atual e verifique se há atraso no último evento válido:
UPD: com poucas modificações, você pode registrar dois cliques:
fonte
As interrupções são definitivamente ótimas também para switches de hardware. Ao usar interrupções, você evita um grande desperdício de recursos e possivelmente energia, principalmente se estiver lidando com dispositivos alimentados por bateria.
Além disso, à medida que seu código aumenta, você verá que é ainda mais fácil implementar as interrupções para os botões do que pesquisá-los no loop principal.
Quanto à sua devolução, provavelmente é um problema de codificação. Eu geralmente uso um timer de ~ 10ms para rebater, enquanto checo a liberação do botão. Também desative temporariamente a interrupção do botão enquanto você a renuncia, para que a rotina de interrupção não seja executada várias vezes.
Se você ainda estiver com problemas, poste o código aqui, para que possamos ajudá-lo.
fonte
Isso é bem parecido com a resposta de Tony Stewart, mas acho que poderia ser expandido.
O esquema superior é para uma interrupção na borda baixa ou na borda descendente. O esquema inferior é para uma interrupção na borda alta ou ascendente.
simular este circuito - esquemático criado usando o CircuitLab
pessoalmente, dado o custo de um capacitor, vale a pena usá-lo simplesmente, em vez de me preocupar se o debounce do meu software é incorreto.
Observe que, como Tony Stewart disse, a constante de tempo neste circuito é de 10ms ou . Vai levar de três a cinco constantes de tempo (dependendo da sensibilidade do seu microcontrolador para o botão se redefinir, portanto, se o seu microcontrolador tiver problemas com a repetição da função de interrupção, isso pode ser a causa, e talvez você precise ajuste a tampa / resistor para que a interrupção não ocorra várias vezes (ou seja, apenas se a interrupção estiver configurada para funcionar com um sinal alto ou baixo, e não com a borda ascendente ou descendente).(R∗C 10kΩ∗1μF)
Relacionadas à depuração de hardware
fonte
Os seres humanos são lentos, não precisamos da atenção imediata de um micro que esteja na faixa de microssegundos.
Naturalmente, essa não é a única nem a maneira correta de fazê-lo, mas geralmente acho mais sensato configurar um temporizador (muitos micros possuem ticks de sistema) para acionar uma interrupção em intervalos fixos e mudar o estado do pino para um variável para o código examinar posteriormente. Você acaba com um var cheio de cinzas durante o salto
10010110 ash
mas em determinados momentos, você obtém esses 4 valores:
01111111 borda ascendente recém-lançada
11111111 botão em estado estacionário acima
10000000 borda descendente recém-lançada
botão 00000000 em estado estacionário desativado
Na maioria das vezes, porém, eu apenas uso um contador que é redefinido durante o salto. É rápido, testado e fácil de fazer.
Se falhar, tento algo mais inteligente no documento de Ganssle que outros sugeriram!
fonte