Implementar STOP/STAR no mesmo botão

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

Implementar STOP/STAR no mesmo botão

Mensagempor Cefas » 29 Set 2012 16:09

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?
Cefas
Nibble
 
Mensagens: 58
Registrado em: 26 Dez 2011 19:47

Mensagempor Iran » 29 Set 2012 17:32

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.
Avatar do usuário
Iran
Word
 
Mensagens: 558
Registrado em: 16 Out 2006 18:10
Localização: Imperatriz - MA

Mensagempor Cefas » 29 Set 2012 19:07

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...
Cefas
Nibble
 
Mensagens: 58
Registrado em: 26 Dez 2011 19:47

Mensagempor Cefas » 29 Set 2012 19:08

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...
Cefas
Nibble
 
Mensagens: 58
Registrado em: 26 Dez 2011 19:47

Mensagempor EvandrPic » 29 Set 2012 20:35

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...
EvandrPic
Dword
 
Mensagens: 2116
Registrado em: 31 Mar 2010 15:05

Mensagempor MOR_AL » 29 Set 2012 22:23

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.

Imagem

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
"Para o triunfo do mal só é preciso que os bons homens não façam nada." Edmund Burke.
"Nunca discutas com pessoas estúpidas. Elas irão te arrastar ao nível delas e vencê-lo por possuir mais experiência em ser ignorante". Mark Twain
Avatar do usuário
MOR_AL
Dword
 
Mensagens: 2934
Registrado em: 19 Out 2006 09:38
Localização: Mangaratiba - RJ

Mensagempor xultz » 30 Set 2012 11:16

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é.
98% das vezes estou certo, e não estou nem aí pros outros 3%.
Avatar do usuário
xultz
Dword
 
Mensagens: 3001
Registrado em: 13 Out 2006 18:41
Localização: Curitiba

Mensagempor ze » 30 Set 2012 11:49

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;
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Mensagempor MOR_AL » 30 Set 2012 12:39

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!!! 8)
MOR_AL
"Para o triunfo do mal só é preciso que os bons homens não façam nada." Edmund Burke.
"Nunca discutas com pessoas estúpidas. Elas irão te arrastar ao nível delas e vencê-lo por possuir mais experiência em ser ignorante". Mark Twain
Avatar do usuário
MOR_AL
Dword
 
Mensagens: 2934
Registrado em: 19 Out 2006 09:38
Localização: Mangaratiba - RJ

Mensagempor jorgeluiz » 01 Out 2012 00:34

faz a interrupçao na borda de SUBIDA. Voce aperta o botao, aterra, ele só vai pra interrupçao na hora que solta.
Avatar do usuário
jorgeluiz
Byte
 
Mensagens: 448
Registrado em: 26 Mar 2007 02:26

Mensagempor MOR_AL » 01 Out 2012 14:49

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
"Para o triunfo do mal só é preciso que os bons homens não façam nada." Edmund Burke.
"Nunca discutas com pessoas estúpidas. Elas irão te arrastar ao nível delas e vencê-lo por possuir mais experiência em ser ignorante". Mark Twain
Avatar do usuário
MOR_AL
Dword
 
Mensagens: 2934
Registrado em: 19 Out 2006 09:38
Localização: Mangaratiba - RJ

Mensagempor xultz » 01 Out 2012 17:43

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.
98% das vezes estou certo, e não estou nem aí pros outros 3%.
Avatar do usuário
xultz
Dword
 
Mensagens: 3001
Registrado em: 13 Out 2006 18:41
Localização: Curitiba

Mensagempor morais » 01 Out 2012 18:05

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!.
morais
Bit
 
Mensagens: 13
Registrado em: 06 Jun 2010 22:09
Localização: MA

Mensagempor RobL » 02 Out 2012 14:29

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.
RobL
Dword
 
Mensagens: 1546
Registrado em: 20 Fev 2007 17:56


Voltar para PIC

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante

x