Peguei um ESP8266 ontem e comecei a mexer, estou programando ele diretamente (não estou usando de módulo para o arduino) direto pela IDE do arduino.

Estou com um problema, no código abaixo tem uma interrupção que lê um botão, basicamente se eu mudo rapidamente o status do botão, a placa pode travar, não é tão comum, mas aperto e solto rapidamente, volto a apertar e soltar, repito isso diversas vezes, o software do ESP trava e também a IDE do arduino.

Como podem ver, o código é extremamente simples:

Exibições: 2871

Anexos

Responder esta

Respostas a este tópico

Respondendo de modo geral, obrigado a todos.

Valeu pelas respostas, trabalhei com programação em freescale, mas estou há 8 meses sem programar nada, estou bem enferrujado. Realmente esqueci que não pode ter delays dentro de interrupções, curiosamente um dos problemas que tive no estágio foi justamente esse.

Notei com um osciloscópio que após a interrupção ser habilitada existe um pequeno intervalo onde o valor flutua, basicamente ao apertar o botão ele não está 100% pressionado, um pouco depois ele cai para zero, volta para 1, cai para zero..., então preciso de uns microssegundos para que o HIGH se estabilize.

Mesmo habilitando as interrupções com o interrupts(); o problema continuou, troquei por: for(int x = 0; x<30000; x++){__asm__("nop\n\t");} e resolveu.

É problemático deixar o microcontrolador executar 30 mil instruções inúteis?

Setei o 14 como input e removi o delay, agora o código está funcionando perfeitamente, obrigado a todos.

ok JM.

Então vamos à realidade:

1) você está continuamente enviando o "state" via terminal (serial). Tudo bem aqui.

2) você está gerando uma IRQ ("Interrupt Request") quando aciona o botão. Isto provoca sua ISR ser executada. E claro, reabilitamos interrupções no início dela, para não bloquear o background do Sistema (e assim evitar, por exemplo, que o WDT atue provocando um CRASH). Lá dentro da ISR você lê o status do botão.

   Então o que está errado? Vamos lá:

1) seu botão tem um "bouncing", ou ruído mecânico, e cada vez que vc o aciona, ele provoca não uma, mas várias IRQs, inclusive depois que uma já foi executada, caso o "bouncing" seja muito "brabo". Então primeiro de tudo: deve eleiminar o "bouncing". Isto deve ser feito por hardware ou por software. Por hardware, acrescente um capacitor em  paralelo com o Resistor externo que vc ligou junto ao botão. O valor do capacitor depende de duas coisas: o quão "brabo" é o seu "bouncing", e o resistor externo que você ligou junto ao botão. Por favor, se possível nos envie aqui o circuito para que possamos calcular o valor mais adequado. Mas no geral, não precisa se preocupar muito, pois certamente deverá ficar entre 0.1uF e uns 4.7uF.

2) uma vez que ocorrem várias IRQs devido ao bouncing mecânico do botão, quando você entra na ISR e vai ler o botão, ele já pode ter sido liberado, devido ao próprio "bouncing", já que o atendimento e processamento da ISR é bem rápido. Então o que ocorre? você acaba lendo "LOW", pois o botaõ foi liberado devido ao "bouncing". E o delay(10) no início da ISR, certamente é maior que os spikes provocados pelo "bouncing", piorando ainda mais a situação, já que é quase certo que o "bouncing" vai mascarar o acionamento do botão.

   Então faça isso:

1) minimize o bouncing, através da colocação do capacitor, conforme te expliquei. E,

2) altere a ISR:

state = digitalRead(14);

delay(1);

interrupts();

delay(10);

Veja que esta alteração na ISR vai funcionar também como um "anti-bouncing", por motivos óbvios. O delay(1) é um tanto empírico, pois o correto é saber o limite do mesmo (devido ao Background), e o quanto é "brabo" o "bouncing" do seu botão. No entanto, veja que se o Capacitor que mencionei tiver o valor adequado, você pode até eliminar todos os delays dentro da ISR.

Note: é possível fazer isso tudo apenas por software, mesmo sem usar o capacitor externo, e eliminando inclusive todos os delays dentro da ISR. Basta que implemente uma lógica de confirmação do estado do botão antes de enviar seu status pela serial. Para isso, use o "micros" ou o "millis" para cadenciar esta lógica de confirmação, mas isso deve ser feito fora da ISR, ok?

Espero ter ajudado, e como disse antes, é preciso usar a técnica adequada para cada situação.

abrçs,

Elcids

Valeu pela ajuda.

O circuito é bem besta, mesmo, só o esp, o botão (com pulldown) e o led.

Peguei um desses botões de protoboard, acho que não da para esperar muito de algo de uns 20 centavos, ao apertar ele não deve estar bem preso, então perde o contato rapidamente com as trilhas e logo volta, até porque mudando o local da protoboard o bouncing chegou a sumir.

Empiricamente coloquei um capacitor cerâmico, fui testando com vários que tinha aqui até achar o melhor no osciloscópio (um que não distorcesse tanto a borda de descida)

Por enquanto não estou fazendo nenhum circuito, só voltando a mexer com isso para lembrar bem como tudo funciona, então só de ter entendido a razão desse erro já está ótimo.

Muito obrigado pela ajuda.

ok JM.

Mas não se iluda:  mesmo o melhor de todos os botões (seja com contato de ouro ou estanho), vai ter algum "bouncing". Eu realmente fico surpreso que o pessoal use "a torto e a direito" os botões por aí, e não se preocupem com isso.

É muito fácil eliminar o "bouncing". O ideal, é usar um capacitor em paralelo com o botão, e que a entrada usada seja do tipo "Schmitt-Trigger". Caso a entrada não possa ser do tipo "Schmitt-Trigger", use uma externa, como por exemplo através de algo como um 74HC14 (que é uma ótima escolha, pois além de barato, é facilmente encontrado). Claro, usando um inversor com "Schmitt-Trigger",  compense a inversão da lógica de estado provocada por ele, bastanto para isso "negar" sua variável no código logo após a leitura do botão).

Mas se seu Sistema (hardware), não estiver sendo utilizado em um ambiente muito eletricamente ruidoso (que é, por exemplo um ambiente industrial), então você pode até dispensar o uso do "Schmitt-Trigger", e por isso eu não sugeri isso anteriormente.

Abrçs,

Elcids

ah, e se vc usar algo como o 74HC14, e "sobrar" inversores, não vai deixar estes que sobraram "largados" de qualquer jeito. Se vc os deixar "largados", isso pode ser bastante desastroso (e em alguns casos, vai parecer "fantasmagórico").

http://www.onsemi.com/pub/Collateral/MC74HC14A-D.PDF

(coloquei o link da ON, pra te agradar, já que vc disse que trabalhou com Freescale)

Abrçs

Elcids

ah sim cometi uma comida de bola violenta (até fico com vergonha pela trapalhada):

o capacitor deve estar em paralelo com seu botão, e NÃO com o Resistor externo. Mas o Resistor deve existir (ou usar pullup ou pulldown).

e esqueci de mencionar:

como um único acionamento do botão provoca várias IRQs (a quantidade depende do quão "brabo" é o "bouncing" do seu botão), devem estar ocorrendo Interrupções Reentrantes, já que reabilitamos as Interrupções. Isso não seria um problema, se você souber o efeito delas (isso é moleza, já que o código da sua ISR é muito simples), e se a quantidade de reentrâncias não provocar um "STACK OVERFLOW" (o que também resulta em um "CRASH" no Sistema).

Assim, peço desculpas, pois não me atentei a isso quando na minha primeira resposta eu sugeri reabilitar as Interrupções. Note que o "delay(1)" que coloquei posteriormente, é na tentativa de impedir essa reentrância, mas o valor exato depende da intensidade do "bouncing" (e de evitar o bloqueio das tarefas no background).

Siga o conselho do capacitor, e poderá eliminar por completo os delays da ISR, e claro não precisará reabilitar as Interrupções lá dentro.

Abrçs

Elcids

O capacitor resolveu perfeitamente.

Valeu!

Geralmente costumo resolver o problema do bounce via software, anexo arquivo do programa e imagem de um exemplo pratico simulado no Proteus VSM Arduino um liga desliga LED via botão usando interrupção.

Meu canal: AQUI

Abs.

CK

Anexos

RSS

© 2024   Criado por Marcelo Rodrigues.   Ativado por

Badges  |  Relatar um incidente  |  Termos de serviço