Página 1 de 1
Implementar STOP/STAR no mesmo botão

Enviado:
29 Set 2012 16:09
por Cefas
Olá Pessoal!
Tenho uma atividade na faculdade para implementar numa tecla a função de STOP e START, semelhante ao um cronometro. Consegui fazer isso através de uma interrupção Externa, porém isso só funciona quando pressiono a tecla rápido, quando permaneço muito tempo com a tecla pressionada volta para, parar a aplicação (STOP), volta para START. Isso esta acontecendo, pois não estou conseguindo tratar a INTERRPÇÂO. Alguem poderia me ajudar?

Enviado:
29 Set 2012 17:32
por Iran
Crie um flag de 1 bit que é sempre mudado na rotina, esse flag dirá se é para processar um start ou um stop.
PIC eu nao conheço, mas em outros MCUs interrupções disparadas pela borda podem gerar varias interrupções devido ao rebote da chave, crie rotina de atraso para esperar a chave estabilizar.
Pode também fazer com que o programa fique preso na rotina de tratamento até que a chave seja liberada.
Vá tentando até conseguir ou receber uma resposta melhor aqui.

Enviado:
29 Set 2012 19:07
por Cefas
Então fiz exatamente isso, habilitei a interrupção externa proveniente de um push-button, de modo que o botão esta ligado em uma entrada co pull-up habilita. Então toda vez que existe uma borda de descida o flag do bit da interrupção vai pra 1 e trato a interrupção e após fazer oque quero no vetor interrupção limpo o flag e volto para o main. Funciona quando pressiono a tecla rápido, pois se permaneço muito tempo com a tecla pressionado o programa para como esperado, mas se solto ele deve esperar no modo STOP até acontecer uma nova borda de descida para dar um START. Mas isso não esta acontecendo...

Enviado:
29 Set 2012 19:08
por Cefas
Então fiz exatamente isso, habilitei a interrupção externa proveniente de um push-button, de modo que o botão esta ligado em uma entrada co pull-up habilita. Então toda vez que existe uma borda de descida o flag do bit da interrupção vai pra 1 e trato a interrupção e após fazer oque quero no vetor interrupção limpo o flag e volto para o main. Funciona quando pressiono a tecla rápido, pois se permaneço muito tempo com a tecla pressionado o programa para como esperado, mas se solto ele deve esperar no modo STOP até acontecer uma nova borda de descida para dar um START. Mas isso não esta acontecendo...

Enviado:
29 Set 2012 20:35
por EvandrPic
O que o Iran falou é se você fez o debouncing da tecla?
Consiste em ler a tecla várias vezes durante uns 50 ms para então dar como certo o acionamento da tecla...

Enviado:
29 Set 2012 22:23
por MOR_AL
Desenvolvi uma rotina para retirar o bouncing da tecla pressionada.
O legal dela é que você que determina os detalhes. Tem funcionado.
Segue o fluxograma lógico da rotina. Estude-a que vai entender tudo.
Como está, são esperados 150ms após a chave ficar estável.
Enquanto a chave permanecer pressionada, o programa fica em loop a espera de despressionar (essa palavra não existe).
Ao despressionar, inicia-se mais um período de bouncing. O programa espera 150ms após ficar estável para aceitar que a tecla foi pressionada.
Você pode alterar o valor da variável n e do período de 30ms.
MOR_AL

Enviado:
30 Set 2012 11:16
por xultz
O único pepino que vejo nesta tua ISR é que ela leva 150ms + tempo de debounce para tratar. Dependendo do sistema, esse tempo todo numa ISR é fatal.
O ideal é aquele "n" ficar fora da ISR como variável global, e de alguma forma checar os 30ms pelo contador do timer. Ou seja, para cada bounce ele gera uma interrupção, mas ela é tratada muito rapidamente.
Eu fiz um debounce para um teclado que faz varredura, e ficou simples e funcionou: se varrer 5 vezes e tiver a mesma leitura, debounceou. Se estiver diferente, zera o contador. Ficou filé.

Enviado:
30 Set 2012 11:49
por ze
Sobre deboucing...
capacitor em paralelo com a tecla pode acabar com 99.99999999999% do problema. Mais ainda se a entrada for smt. trig. O resto, se voce prometer não ficar forçando o dedo no botão (e gostar) é só fazer while(!tecla) no inicio da interrupt. Ou um sw tipo maluco assim:
while(tmp--) if(!tecla) tmp=0xff;

Enviado:
30 Set 2012 12:39
por MOR_AL
xultz escreveu:O único pepino que vejo nesta tua ISR é que ela leva 150ms + tempo de debounce para tratar. Dependendo do sistema, esse tempo todo numa ISR é fatal.
O ideal é aquele "n" ficar fora da ISR como variável global, e de alguma forma checar os 30ms pelo contador do timer. Ou seja, para cada bounce ele gera uma interrupção, mas ela é tratada muito rapidamente.
Eu fiz um debounce para um teclado que faz varredura, e ficou simples e funcionou: se varrer 5 vezes e tiver a mesma leitura, debounceou. Se estiver diferente, zera o contador. Ficou filé.
Entendi!
Deixa a interrupção, gerada pelas teclas, atualizar e comparar os valores de n, habilitar o timer com interrupção para informar o final do tempo, identificar o estado da tecla e se n = valor e tecla = '0', então retorna com o valor da tecla.
É isso?
Até o momento não precisei dessa rapidez, mas se for necessário eu mudo.
Valeu!
Lelis!
Eu acho que tem só um 9 depois da vírgula!!!
MOR_AL

Enviado:
01 Out 2012 00:34
por jorgeluiz
faz a interrupçao na borda de SUBIDA. Voce aperta o botao, aterra, ele só vai pra interrupçao na hora que solta.

Enviado:
01 Out 2012 14:49
por MOR_AL
jorgeluiz escreveu:faz a interrupçao na borda de SUBIDA. Voce aperta o botao, aterra, ele só vai pra interrupçao na hora que solta.
.. É. Mas aí vai gerar interrupção quando houver bouncing, ao pressionar a tecla.
MOR_AL

Enviado:
01 Out 2012 17:43
por xultz
Eu não acho que ler a tecla por int seja a melhor solução, eu prefiro ler por pooling gerado por int de timer. O pressionamento da tecla e a resposta é uma atividade lenta, pro ser humano até 100ms de atraso no aperto do botão é imperceptível. A int por rampa é melhor para usar para ler sinais de hardwarwe, como por exemplo um CI que gera um sinal (que não bounça) e que precisa ser tratado ASAP.
Pode colocar capacitor, resistor, indutor, flip flop, botões sempre bounçam.

Enviado:
01 Out 2012 18:05
por morais
ta me parecendo falha na logica mesmo. Mas tenta filtrar a tecla ao pressionar e ao liberar tbm pra nao ocorrer multiplos eventos ao pressionar uma vez. Usa tempos como mencionaram acima 100ms pra nós é muito rapido, pro mcu nao!.

Enviado:
02 Out 2012 14:29
por RobL
Posso estar repetindo algo já colocado.
Sem cuidados tá +- ai:
1- crie um flag para TECLAPRESSIONADA.
2- crie um flag para STOP_START
3- crie um flag DEBOUNCE
3-No looping normal do seu programa:
Se tecla solta limpa flag TECLAPRESSIONADA
4-Na sequencia, por varredura, vai agora ler a tecla.
4-1 - Teste o flag TECLAPRESSIONADA. Se zero le tecla.
Se um salta, aguarda soltar a tecla.
4-2 - Se tecla pressionada (por exemplo alta) aciona um contador de tempo por no mínimo 20ms (depende do tipo de tecla). O programa segue seu fluxo normal, não fica preso. No looping continua testando, TECLAPRESSIONADA e a seguir DEBOUNCE.
4-3 - Testa o flag DEBOUNCE (após 20ms ficará alto)
4-4 - Se alto, executa um um XOR com o bit do flag STOP_START e muda o estado do flag (Flag ^= (1 << STOP_START).
4-5 - Le STOP_START e liga ou desliga lá o que for.
4-6 - Ao terminar limpa DEBOUNCE
4-7 - Sobe flag TECLAPRESSIONADA (para não pegar ela outra vez, desviar, não permite ler a tecla até ser solta)
Também, deve criar um tempo para debouce para limpar TECLAPRESSIONADA.
Se seu looping fizer sempre alguma tarefa maior que o tempo de debounce,após ler a tecla, não precisa o flag DEBOUNCE.