Olá amigos.

Preciso fazer a leitura de um encoder utilizando a função de interrupção pela placa wemos d1 mini. Porém, ao plotar as leituras está resultando uma forma de onda irregular.

Então eu testei fazer a leitura sem a função de interrupção, apenas com digitalRead, e ao plotar, a forma de onda foi como esperada.

No meu projeto não posso usar apenas digitalRead pois posso perder leituras durante a execução de outras funções. Alguma solução pra esse problema?

Em anexo estão as formas de onda que eu obtive em cada um dos testes, por meio do Plotter Serial .

Em anexo também está o código simplificado que usei para fazer apenas esses testes de leitura e o circuito do encoder. circuit%20encoder%20%2B%20motor%20%2B%20wemos%20d1.jpeg

Exibições: 587

Anexos

Responder esta

Respostas a este tópico

Boa noite CA, (se não gosta que te chame pelas iniciais, avise),

testa este código e diga o resultado.

sketch_jan11a.ino

RV mineirin

Não funcionou. na sua sugestão apenas foi modificada a forma de chamada da função que passou a ser na borda de subida.

Olá, Cleiton!

   Tem certeza que a onda correta é a que usa o digitalRead() ?

   Já mediu com um osciloscópio a onda "real" para ver como ela se parece?

   Se não tiver acesso a um osciloscópio, uma solução mais barata, que não é a mesma coisa mas que pode ajudar muito neste caso, é um analisador lógico. 

   O RV tem um que eu acho muito legal, inclusive é compatível com o famoso ( e muito mais caro ) Saleae. Ele pode te indicar.

Saúde e Sucesso!

D.T. Ribeiro.

Boa noite,

Se precisar de um analisador lógico, pode tentar isso:

https://labdegaragem.com/profiles/blogs/tutorial-analisador-l-gico-...

Bom dia CA, 

use a variável dentro do interrupt como volátil.

ao invés de :

"boolean signal_encoder = 0;" 

use assim: 

"volatile boolean signal_encoder = 0;" 

RV mineirin

tentei aqui, mas nao houve mudança

Bom dia CA,

Vou montar aqui usando um ESP8266 normal.

Manda uma foto do que tem montado no eixo do motor gerando os pulsos.

RV mineirin

olá Cleiton.

      Por favor,  teste este código:   "Encoder_IRQ_Wemos_D1_02.zip"

      Eu testei aqui e funcionou.

      Depois que vc confirmar o funcionamento, eu explicarei o que estava ocorrendo de "errado" no seu Sistema, caso vc precise de alguma instrução sobre isto.

      Pela velocidade do seu Motor e pelas características do disco usado no seu Encoder,  o valor que deixei para a constante "debouncing_ms"  foi de 2 ms (dois mili-segundos), e me parece ok.  Esta definição vc pode ver na figura a seguir, onde marquei em verde o valor:

(clique na figura para "zoom")

      Mas caso deseje, vc pode mudar esse valor, e pode ser que tenha que colocar um valor fracionário tipo 1.5 ms (se isso for realmente necessário, eu te mostrarei como fazê-lo).

      Abrçs,

      Elcids

olá novamente Cleiton.

      Alterei o código que postei antes, para que o valor de "debouncing_ms"  possa também ser fracionário, caso isso seja necessário.

      O código alterado é este:  "Encoder_IRQ_Wemos_D1_02a.zip"

      Neste "novo" código,  veja por exemplo como ficaria a definição  para que  o "debouncing_ms"  seja de  1.6  mili-segundos:

(clique na figura para "zoom")

      Fique à vontade para perguntar, caso tenha alguma dúvida sobre isto.

      Abrçs,

      Elcids

Oi EC, vc vez um "filtro passa baixa" via código ne. Dentro da função de interrupção são selecionados apenas os pulsos dentro do intervalo de tempo especificado.

Estou testando aqui e aparentemente funcionou sim! Vou continuar os testes e ajustar o melhor valor de debouncing para evitar que algum ruído indesejado seja contabilizado. 

Gostei muito também da forma que vc comentou e organizou o código. Vou adotar essa forma em próximas dúvidas que eu postar aqui. 

Muito obrigado mesmo! Tirou um pesadelo da minha cabeça!

olá Cleiton.

      Sim,  vc pode ver isto como um FPB (Filtro Passa Baixas) implementado no código.

      Mas está mais para um "anti-bouncing" (ou "debouncing", se vc preferir). Veja porquê:

      1)  todos os Motores quando em funcionamento, além de girar, sempre tem uma vibração no eixo.  Assim, o Disco usado no Sensor Encoder,  também terá uma vibração (seja este Disco acoplado direto no eixo,  seja acoplado via engrenagens).

      2)  quando um furo do Disco  está entrando  na região ótica do Sensor Encoder, a vibração transmitida pelo Motor faz com que esta "entrada" ocorra diversas vezes. Ou seja, o limiar físico do furo deixa passar e interrompe a luz do Sensor várias vezes, devido à vibração do Disco. Isto ocorre também quando um furo do Disco está saindo  da região ótica do Sensor Encoder.  Como o Opto-acoplador  do Sensor é rápido o suficiente (chaveia em torno de alguns micro-segundos),  ele consegue detectar estas várias entradas e saídas, resultantes da vibração do Disco, e assim gera diversos pulsos no "sinal" do Encoder.  E estes diversos pulsos "falsos" do Encoder também geram IRQ (Interrupt Request), levando a uma detecção errônea caso nenhum tratamento seja feito.

      Vc pode impedir o problema por Hardware  também, usando um circuito de um FPB (adequadamente calculado).  Mas claro, isso ocupa espaço,  tem custo,   e não tem a mesma versatilidade que uma implementação no código.

      A ISR (Interrupt Service Routine) que trata as IRQs, é bastante simples, e mostrada na figura a seguir:

(clique na figura para "zoom")

      Observe que a parte que marquei em verde, é uma constante, que é resolvida no tempo de compilação. Ou seja, esta parte não é calculada durante a execução do código, e portanto não consome tempo de processamento.

      Caso tenha alguma dúvida, fique à vontade para perguntar.

      Mas fiquei com uma curiosidade sobre seu Sistema:  por que vc precisa "ver" estes pulsos via Terminal do Arduino ?

      Abrçs,

      Elcids

ah esqueci disso:

      No seu post inicial, quando vc fez a leitura do sinal do Encoder  via "digitalRead"  dentro do "loop"  do Arduino,  vc fez também uma filtragem semelhante a um FPB,  já que a leitura estava cadenciada pelo "delay(2)"  (ou seja: vc estava amostrando o sinal aproximadamente a cada 2 ms).  Assim praticamente vc acabava ignorando os pulsos mais rápidos e estreitos resultantes da vibração do Disco (mas eventualmente, em algum momento, vc poderia também ler um "falso" pulso).

      E não se esqueça:  se vc  alterar  uma variável  dentro de uma ISR, e essa mesma variável também estiver sendo acessada fora da ISR, ela deve ser obrigatoriamente declarada com o atributo "volatile"  (como foi o caso da variável "signal_encoder").

      Abrçs,

      Elcids

RSS

© 2024   Criado por Marcelo Rodrigues.   Ativado por

Badges  |  Relatar um incidente  |  Termos de serviço