Bom dia, 

Desenvolvi um contador de peças para uma maquina dentro da industria onde trabalho, porem comecei a ter problemas com o acionamento do sensor infravermelho que trabalha em 5v e que esta ligado diretamente na entrada digital do arduino.

Ocorre o que sensor aciona do nada, sozinho sem ter peças na frente. Ao analisar percebi que ele aciona quando a maquina liga ou desliga a esteira, logo imagino ser interferência eletromagnética no sensor.

Sera que eu migrando para um sensor reflexivo de 24v com um rele acoplador seria a solução? Tendo em vista que se eu tirar o cabo da entrada digital a interferência não ocorre mais.

Grato pela ajuda!

Exibições: 1672

Responder esta

Respostas a este tópico

Olá Elcids, o display é um lcd 20x4 I2c.

A entrada é GPIO03, ou D0.

olá Renan.

      Marquei na figura a seguir na placa do Wemos D1, usando algumas cores, alguns pontos que estão relacionados com sua escolha para o pino usado para a leitura do Sensor:

(clique na figura para "zoom")

      Em relação à figura anterior, seguem então as seguintes considerações.

      Na cor "amarela", marquei o pino "GPIO03", que é o pino que vc disse estar usando para a leitura do Sensor.  Há um problema com essa escolha. Vou explicar.

      Ocorre que esse pino também é o RX da Serial do ESP8266, ou seja, é o pino por onde o ESP8266 recebe os dados da Interface Serial  correspondente ao "Terminal do Arduino" (no PC).

      Esta Serial  é implementada no Hardware do Wemos, através do circuito "ponte" USB para Serial  que corresponde ao Chip "CH340", marcado na cor "verde" na figura. O lado USB vai ao PC, e o lado Serial  vai ao ESP8266. Como no ESP8266 o "GPIO03" é o RX dessa Serial, em termos de circuito ele é uma Entrada DigitalVeja que marquei também na figura, dois Resistores, na cor "laranja", e normalmente estes Resistores tem o valor de 470 ohms (um valor relativamente baixo). Um desses Resistores está ligado justamente entre o "GPIO03" e a saída TX do "CH340". E normalmente esta saída TX do "CH340" fica em nível alto (nível lógico "1"), ou seja em 3.3 Volts. Conclusão: se vc conectar o Sensor ao "GPIO03", vc terá um Resistor de "Pullup" externo  conectado ao pino, sendo este um "Pullup" bem "forte" pois o Resistor tem apenas 470 ohms.

      Então isso limita o que vc pode fazer com esse pino. E veja que para usar o circuito que sugeri no início, vc não pode ter Resistor de "Pullup" no pino usado para ler o Sensor (conforme ressaltei no post anterior). Então usar o "GPIO03" limita o que vc pode conectar nesse pino.

      Minha sugestão é que para a leitura do Sensor, vc use um outro pino de Entrada Digital que esteja "livre" no seu Sistema. E se usar o circuito que sugeri, não ligue nem o "Pullup" nem o "Pulldown" neste pino.

      Veja na figura anterior que dentro de um retângulo na cor "rosa", além do próprio "GPIO03",  marquei também o pino "GPIO01". Este pino corresponde ao "TX" da Serial do ESP8266, e que está conectado ao "RX" do CH340 (a ponte USB <==> Serial). Esta conexão é feita através do outro Resistor de 470 ohms (área "laranja" na figura). Neste caso, a limitação é menor desde que vc use o pino como Saída Digital. Mas vc pode ter imprevistos durante o "Boot" do ESP8266,  pois este costuma "printar" dados via Serial  logo após o Reset (aquelas "tranqueiras" que vc vê no Terminal do Arduino logo que vc conecta ou reseta o Wemos). Assim se vc tiver "algo" ligado ao "GPIO01", este "algo" irá receber Níveis Lógicos não previstos no seu Sistema (por exemplo se vc usar o pino para controlar um Relé, o Relé poderá ligar/desligar de forma "aleatória" logo após o Reset do ESP8266, o que pode causar problemas dependendo do que esse Relé aciona).

      Então também é aconselhável evitar usar o "GPIO01". E como entrada, de jeito algum, pois irá provocar "contenção", que é o pior problema em um circuito digital (a "contenção" ocorrerá durante o "Boot" entre o pino TX e quem está "drivando" este pino, já que supostamente ele está recebendo Nível Lógico de algum outro dispositivo, uma vez que estaria sendo usado como entrada). Veja então que em relação ao CH340, não há problema com o "GPIO01". O problema é devido ao fato dele ser uma Saída Digital  durante o "Boot" do ESP8266.

      Em suma, aconselho não usar nem o "GPIO03" (o RX da Serial do ESP8266), nem o "GPIO01" (o TX da Serial), a fim de evitar problemas de Hardware (ou seja, problemas com os circuitos).

      Sobre a questão da imunidade na leitura do sinal do Sensor,  preparei um código de exemplo de como aumentar essa imunidade ainda mais (além é claro da imunidade proporcionada pelo circuito "básico" que mostrei), e logo publico aqui (falta preparar algumas figuras para o post).

      Uma coisa que pode ajudar no melhor funcionamento da imunidade, é saber qual a quantidade máxima de peças que vc detecta por segundo.  E vc saberia dizer durante quanto tempo a peça fica "na frente" do Sensor?   (esse tempo é o mesmo tempo que a saída do Sensor fica em "LOW")

      Abrçs,

      Elcids

Bom dia Elcids, entendi perfeitamente. 

Posso deixar de utilizar a GPIO03 e utilizar a D10 ou D11, tanto faz. Pois utilizo a D2 para acionar um relé e do D3 ao D9 um teclado matricial 3x4.

A quantidade de peças por minuto depende da máquina, nas que estou tendo problemas por interferência passam entre 3 e 10 peças por minuto e tempo de permanência da peça em baixo do sensor varia de 2500 a 3500 ms.

Segue foto do esquema de ligação. 

Nesta imagem o IR esta ligado no D11.

olá Renan.

      Estou publicando uma implementação cujo código aumenta muito a imunidade no processo de detecção de objetos (peças ou itens, conforme preferir designar), usando o Sensor de Proximidade E18-D80NK. Esse design poderá ser utilizado como referência para seu Sistema atual e suas futuras implementações com o E18-D80NK, e inclusive com outros sensores com comportamento similar (e não precisa necessariamente ser de proximidade).

      O ponto mais importante é definir três parâmetros no código, relacionados ao tempo que cada peça (objeto) fica "na frente" do sensor. Renan, conforme as informações que vc passou, mais à frente no texto eu mostro como podem ser especificados os três parâmetros de forma a atender seu Sistema.

      Mas não deixe de ler todo o texto, pois há considerações importantes nele.

  

      Sobre o uso do módulo Relé, aconselho a leitura de um tópico aqui no LDG, onde esclareço alguns pontos importantes sobre isolação e o controle desses módulos. É este aqui:  "Módulo Relé sem JD-VCC"

       Sobre o uso de um Teclado Matricial, faço algumas observações no final do post.

  

      Inicialmente, gostaria de esclarecer melhor a topologia que sugeri no post inicial, a fim de minimizar falhas na detecção usando o Sensor de Proximidade. Para isto, apenas reformulei o desenho da topologia evidenciando como ela é implementada, mostrando o cabo de conexão entre o Sensor e o Arduino. Isto pode ser visto na figura a seguir:

(clique na figura para "zoom")

 

 

      Aqui o ponto a ressaltar, é que a alimentação de 5V é enviada até o Sensor pela extensão do cabo. Assim, na extremidade do cabo conectada ao Sensor de Proximidade, há a filtragem da alimentação (na área em "verde claro" na figura anterior). Isto é implementado com R7, C5, e C6. As considerações sobre estes componentes (valores e tipo) são as mesmas que já ressaltei no post inicial, e são fundamentais (naquele post há também considerações sobre outros componentes usados no circuito da Interface/Driver que estão na área em "azul claro" na figura anterior).

 

 

      Não sei qual a extensão do cabo que está sendo usado entre o Sensor e o Wemos. Mas caso esta extensão seja de 10 metros ou mais (até mesmo 50 metros), aconselho usar uma implementação com Módulos RS-485. Estes módulos tem baixo custo e são facilmente encontrados no mercado (basta pesquisar por "modulo rs485" no famoso site de compras "ML"). O uso destes módulos aumenta tremendamente a imunidade a ruídos, pois eles trabalham com Drivers Diferenciais em "loop de corrente". Assim para o caso em questão, dois módulos são necessários: na ponta do lado do Sensor um módulo seria configurado como "transmissor", e na outra ponta no lado do Arduino o outro módulo é configurado como "receptor". Esta configuração é apenas no Hardware, ou seja, apenas com as ligações adequadas (no código nada precisa ser feito). Na figura a seguir mostro essa implementação:

(clique na figura para "zoom")

 

  

      Observar, que a alimentação ainda está sendo enviada pela extensão do cabo, e por isso há o mesmo circuito de filtragem mostrado anteriormente (agora de uma forma mais "realística" com a imagem dos componentes). Para o cabo, uma boa opção é usar cabo de rede "CAT5", devido à grande disponibilidade no mercado e ao seu baixo custo. Neste caso, observar que para a transmissão do sinal do Sensor, devem ser usados dois fios que constituem um "par-trançado", mostrados na figura como um fio de cor "verde" e "verde-branco". Observar também as ligações desse "par-trançado" aos módulos RS-485: note que o sinal "A" de um módulo vai ao sinal "A" do outro, o mesmo se aplicando para o sinal "B".

      Nesta configuração "A <==> A"  e  "B <==> B", a lógica de acionamento do Sensor de Proximidade é mantida, ou seja, quando um objeto é detectado e o sinal de saída do Sensor vai a "LOW",  isto também ocorre no sinal que chega ao pino do Arduino. Caso se deseje inverter esta lógica (ou seja, para que quando acionado o Sensor o sinal no pino do Arduino seja "HIGH"), basta trocar a ligação do "par-trançado" fazendo "A <==> B"  e  "B <==> A".

      Notar que as ligações aos módulos RS-485 são muito simples, mas devem ser feitas com atenção para evitar erros. Para a alimentação, na figura é mostrado o uso dos fios de cor "laranja" (para o 5V) e "marrom" (para o GND) do cabo "CAT5", mas pode-se usar qualquer outro "par-trançado" disponível no cabo (com isso aumenta-se a imunidade a ruídos na alimentação, principalmente no lado do próprio Arduino), apenas tomando-se o cuidado para não trocar 5V com GND em cada ponta do cabo.

      O Resistor do Filtro da Alimentação no lado do Sensor, foi reduzido para 10 Ω, pois o uso está previsto para cabos com grandes extensões.

      No lado do Arduino, o Driver com Transistor que havia antes, foi substituído pelo Módulo RS-485 "receptor".  Na saída desse módulo (o sinal "RO"), apenas um simples Filtro de Sinal é necessário, composto de dois Resistores e um Capacitor. Este filtro é o mesmo usado no post inicial. Mas neste caso, aumentei para 1 kΩ  o Resistor que vai ao pino de Entrada Digital do Arduino,  e com isso eliminei o Diodo "BAT85" que havia anteriormente, simplificando o circuito. Dessa forma, o mesmo circuito pode ser usado tanto para o Arduino convencional a 5V (UNO, Mega, etc), como para Arduinos com Processador alimentado a 3.3V (como ESP8266, ESP32, Due, STM32, etc). Importante: o Capacitor do Filtro de Sinal deve ser  obrigatoriamente  do tipo "Cerâmico".

      Qualquer dúvida sobre esta Implementação com Módulos RS-485, não deixe de perguntar.

 

 

      Como de costume, quando possível implemento também uma simulação, o que permite que aqueles que não tem o Hardware em mãos, possam testar, fazer experimentações, e aprender com isso. O arquivo para simulação no Proteus está anexado no final do post.

      Mas como no Proteus não há modelo para o ESP8266, fiz a simulação usando um Arduino UNO, mas o código foi escrito de forma que possa ser também usado no ESP8266 e em outros Arduinos.

      Para a simulação, utilizei o mesmo circuito com Driver a Transistor que publiquei no post inicial. Já para o Sensor de Proximidade E18-D80NK, utilizei um circuito que gera de forma cíclica o sinal de objeto detectado. Conectei o Display LCD 20x4 usando a interface paralela, devido à grande lentidão da simulação da Interface I2C (no final do post falo mais sobre isso). Por isso, no código é possível selecionar qual a Interface será usada com o LCD (paralela ou I2C), sendo esta seleção muito simples (mostro mais adiante). O circuito usado na simulação é mostrado na figura a seguir:

 (clique na figura para "zoom")

 

 

       Na simulação (e no código), algumas informações são "printadas" na Serial do Arduino, e portanto podem ser vistas no Terminal do Arduino no PC. Caso isso não seja desejado, basta comentar as linhas no código referentes a esta "printagem" (o que será mais fácil de fazer no "loop" do Arduino, como pode ser notado mais no final do post).

 

      Notar que a saída do circuito equivalente ao Sensor, é do tipo "Open Collector" (via Transistor "Q50"), pois o sensor real E18-D80NK tem uma saída deste tipo.

      E junto ao circuito equivalente ao Sensor de Proximidade, há um contador (o "COUNT1"), o qual conta todos os pulsos ali gerados. Isto nos permite comparar o valor mostrado nesse Contador, com o valor de contagem de objetos mostrado no Display LCD. Neste circuito do Sensor, há também a chave "SW1", que atua como se fosse um "liga/desliga" da esteira que transporta os objetos (ou "peças") a serem contados. Uma coisa a lembrar, é que quando o Sistema inicia (após ser ligado ou após um Reset), uma mensagem inicial é exibida no LCD por 2 segundos, e se a chave "SW1" já estiver fechada, o contador "COUNT1" iniciará a contagem antes do código executando no Arduino, sendo isso algo equivalente a ligar a esteira 2 segundos antes do Arduino iniciar a contagem de objetos.

 

      Há também um circuito para "emular" uma interferência (ou perturbação) no sinal do Sensor de Proximidade. Neste circuito, ao pressionarmos o Botão de nome "Interferência", será gerada uma forte perturbação no sinal do Sensor, o que nos permite verificar a imunidade do Sistema, já que a perturbação não afeta o contador "COUNT1" (então por comparação podemos verificar visualmente a integridade da contagem no Arduino).

 

 

      A figura a seguir, mostra o resultado da simulação após cerca de 1 minuto dela ter sido iniciada (fechei a chave "SW1" logo que a mensagem "iniciou o Monitoramento!" apareceu no Terminal do Arduino):

(clique na figura para "zoom")

 

 

       No Osciloscópio virtual, podemos ver dois sinais: em "amarelo" é o sinal de saída do Sensor de Proximidade, e em "azul" o sinal na saída do circuito Driver+Filtro  que vai ao pino de Entrada Digital "3" do UNO. Notar que estes sinais são complementares (conforme já dito no post inicial que fiz neste tópico).

      Pelos sinais no Osciloscópio virtual, é possível ver que cada objeto fica "na frente" do Sensor por cerca de 100 ms (0,1 segundo). E a taxa de objetos (ou seja, a velocidade que os objetos passam na frente do Sensor), está em 1 objeto por segundo. Na simulação, estas duas características estão definidas no gerador de sinal usado no circuito que equivale ao Sensor (sendo possível alterar as mesmas nas propriedades desse gerador). Conforme explico mais adiante, o conhecimento do tempo mínimo  que os objetos ficam "na frente" do sensor, e o conhecimento da taxa máxima de objetos por segundo, é fundamental para o funcionamento correto do mecanismo que permite aumentar a imunidade da detecção dos objetos em relação a perturbações no sinal do Sensor.

 

      Alguns segundos após a captura do resultado da simulação mostrado na figura anterior, acionei repetidas vezes o Botão de "Interferência", para gerar uma perturbação no sinal do Sensor de Proximidade. O resultado disso pode ser visto na figura a seguir, notadamente no Osciloscópio virtual:

 (clique na figura para "zoom")

 

 

      Dois pontos chamam a atenção na figura. Primeiro, a contagem no LCD continua igual à contagem mostrada no contador "COUNT1", mostrando que nenhuma contagem deixou de ser computada. Segundo, o sinal do Sensor em "amarelo" no Osciloscópio, mostra as interferências geradas, enquanto que em "azul" o sinal presente na Entrada Digital do Arduino tem alguns mínimos ruídos mas mantém o "shape" característico do sinal original. O "grosso" da perturbação foi removido pelo Filtro de Sinal composto por R5 e C4 no circuito. No entanto, mesmo que ruídos de grande amplitude ainda estivessem presentes no sinal "azul", ainda assim o código conseguiria ignorá-los, devido ao mecanismo implementado para identificar o sinal de detecção de objetos  vindo do Sensor de Proximidade. Uma forma de comprovar isso, é remover o Filtro de Sinal (curto-circuitar R5 e desconectar C4) e abrir a chave "SW1", e então acionar o Botão "Interferência" de forma intermitente ou contínua, e verificar que nenhum objeto é contado. Claro que eu fiz isso e comprovei, mas ao invés de postar uma figura mostrando isso aqui, acho interessante que cada um faça a experiência.

 

 

      Agora falando sobre o código. As funções implementadas são extremamente simples (se vc achar que não, pode ter certeza: sua visão e seus pensamentos estão te enganando), e praticamente não há muito o que dizer sobre elas. O código também está documentado com comentários funcionais, e qualquer um que entenda um mínimo de programação (mas entenda mesmo, sem enganação que alguns insistem em praticar) irá também entender o funcionamento com relativa facilidade.

      Assim inicio a seguir, a descrição das configurações mais significativas das funcionalidades no código.

 

      A figura a seguir, mostra a especificação do pino do Arduino a ser usado para a leitura do sinal do Sensor de Proximidade, e que portanto será configurado como uma Entrada Digital:

(clique na figura para "zoom") 

 

      Na simulação foi usado um Arduino UNO, e o pino usado está definido como sendo o "3". Mas qualquer outro pino disponível pode ser usado. Mas é melhor evitar pinos usados para a Serial "padrão" do Arduino, pelos motivos que apresentei em post anterior neste tópico. E pinos usados para o "LED_BUILTIN" (no UNO é o pino "13"), também devem ser evitados, uma vez que no "boot" são configurados como saídas digitais (mas esse problema pode ser desconsiderado se no pino for usado o circuito com Filtro de Sinal  mostrado anteriormente).

 

      Também é preciso especificar qual o Nível Lógico presente no pino, quando um objeto é detectado pelo Sensor. Quando um objeto está "na frente" do Sensor  E18-D80NK, o Nível Lógico presente na saída deste é "LOW". Mas observar que estamos falando do Nível Lógico presente no pino do Arduino, e portanto o Nível a ser especificado no código irá depender dos circuitos existentes entre a saída do Sensor e o pino do Arduino. No caso do circuito com Driver+Filtro mostrado na área em "azul claro" da primeira figura neste post (e também usado na simulação), o Nível Lógico será "HIGH" pois o circuito do Driver inverte  o sinal vindo do Sensor, e esta especificação pode ser vista na figura a seguir:

(clique na figura para "zoom")

 

 

      Caso seja usado o circuito mostrado no início do post com módulos RS-485, então o Nível Lógico a ser especificado é "LOW", pois aquele circuito não inverte o sinal vindo do Sensor. E claro:  se o sinal do Sensor for conectado diretamente ao pino do Arduino, o Nível Lógico a ser especificado também será "LOW".

 

      Ainda sobre o pino usado para a leitura do Sensor, este pino só deve ser configurado como "Pullup"  se  o Sensor estiver conectado diretamente ao respectivo pino do Arduino. E como a saída do Sensor é do tipo "Open Collector", mesmo que em alguns Processadores (ESP8266, ESP32, etc) exista a opção de ligar um "Pulldown", isto não tem sentido.e não deve ser feito.

      Mas se forem ligados os circuitos mostrados anteriormente neste post, que terminam com o Filtro de Sinal, então o pino deve ser configurado obrigatoriamente com "INPUT". Isto porque um Resistor de Pullup "pendurado" ali, irá alterar o funcionamento do Filtro, principalmente em termos da tensão presente no pino, o que impossibilitará detectar corretamente o sinal do Sensor de Proximidade.

      Esta configuração pode ser vista na figura a seguir, onde o pino é configurado apenas como "INPUT", uma vez que o Filtro de Sinal está presente no circuito:

(clique na figura para "zoom")

 

 

      Na figura anterior, é mostrada a função que configura o pino, neste caso como "INPUT", ressaltado na cor "verde claro" na figura. Mas se o Sensor for conectado diretamente ao pino do Arduino, então deve-se mudar a configuração para "INPUT_PULLUP".

 

Notaa página do post não comporta o restante do texto, então estou continuando logo a seguir:

Nota: esta é a continuação do post (Link) :

 

      Sobre o mecanismo implementado no código para detecção de um objeto via Sensor de Proximidade, há três parâmetros importantes a serem configurados, os quais são mostrados na figura a seguir:

(clique na figura para "zoom")

 

 

      Logo que o Sistema percebe que sinal do Sensor de Proximidade teve alguma mudança, inicia-se a contagem do tempo de "debouncing". Esse período de tempo, permite ignorar eventuais instabilidades ou ruídos presentes justamente na transição do sinal do Sensor. Portanto esse tempo tem efeito tanto quando o sinal do Sensor está passando de "OFF" para "ON", quanto de "ON" para "OFF" (ou seja: quando um objeto está "entrando na frente" do Sensor e quando ele está "saindo da frente"). No código, o tempo de "debouncing" é especificado pelo parâmetro "debouncing_Prox_ms",  em mili-segundos.  Mas caso se deseje que o tempo de "debouncing" não tenha efeito, basta especificá-lo como "0" (zero).

 

      E quando o sinal do Sensor está "ON" indicando que um objeto está sendo detectado pelo Sensor, logo após o período de "debouncing" o Sistema verifica se o sinal continua "ON" por um período mínimo de tempo. Isto confirma que o sinal do Sensor está de fato detectando um objeto (ou seja, garante-se que não foi um acionamento espúrio que durou um tempo maior que o "debouncing"). No código este tempo é especificado pelo parâmetro "tempo_min_Prox_ON_ms", em mili-segundos. Normalmente esse tempo dependente da velocidade da esteira que movimenta os objetos, sendo bem maior que o tempo de "debouncing".

 

      Depois que o objeto "sai da frente" do Sensor e o sinal deste vai a "OFF", após o período de "debouncing" o Sistema verifica se o sinal continua "OFF" também por um período mínimo de tempo, garantindo-se assim que o desacionamento do Sensor  não foi um evento espúrio. No código este tempo é especificado pelo parâmetro "tempo_min_Prox_OFF_ms", em mili-segundos. Esse tempo também dependente da velocidade da esteira que movimenta os objetos, mas também da distância física entre os objetos na esteira, e normalmente é bem maior que o tempo "ON".

 

      Observar que os valores dos tempos de "debouncing", "ON", e "OFF" usados na simulação, são valores hipotéticos, não necessariamente correspondendo a condições reais. Cada implementação deve especificar estes três parâmetros conforme o maquinário usado para a detecção de objetos, além das dimensões físicas dos próprios objetos.

      Para o caso do seu Sistema Renan, onde vc informou que a velocidade é baixa (3 a 10 peças por minuto), e cada peça (objeto) fica entre 2,5 a 3,5 segundos sob o Sensor, eu usaria os seguintes settings para os três parâmetros:  tempo de "debouncing" = 200ms,  tempo mínimo "ON" = 1000 ms,  e  tempo mínimo "OFF" = 2000 ms. Com estes valores, acredito que funcionará muito bem. Para outros Sistemas não será difícil escolher valores adequados e confiáveis. Lembre-se que no código os valores estão especificados em mili-segundos, conforme mostrado na figura anterior.

 

      Assim, para a detecção robusta de um objeto usando os três parâmetros anteriores, o código executa um processo sistemático. Primeiro é esperado que o objeto "entre na frente" do Sensor e logo que isso ocorre é aguardado o tempo de "debouncing", e após isso o código confirma que o objeto está de fato "na frente" do Sensor (usando o tempo "ON"). Então o código passa a aguardar que o objeto "saia da frente" do Sensor e logo que isso ocorre é aguardado novamente o tempo de "debouncing". Por fim, o código confirma que o objeto não está mais sendo detectado (usando o tempo "OFF"),  para então iniciar o processo de detecção do próximo objeto.

      Observar que independente do ponto que o código esteja no processo descrito, ele sempre conseguirá sozinho reiniciar este processo, assim garantindo sua estabilidade e autonomia.

      O processo pode ser melhor entendido através da figura a seguir, onde mostro também o comportamento do sinal na saída do Sensor nas várias etapas:

 (clique na figura para "zoom") 

 

 

      Para facilitar ver detalhes da figura anterior, o respectivo arquivo PDF está aqui disponível:   "temporizacao_Sinal_Prox_01.pdf"

 

      Mas como implementar este processo de uma forma simples e confiável?  Uma Máquina de Estados  faz isso com "o pé nas costas". Se seguirmos o processo que foi descrito, iremos facilmente obter os 6 estados para detectar um objeto, e que são definidos no código conforme mostrado na figura a seguir:

(clique na figura para "zoom")

 

 

       A implementação da Máquina de Estados que controla o processo de detecção, deve ser simples, sem lógicas bizarras, ou seja, uma implementação clássica conforme mostrado na figura a seguir:

(clique na figura para "zoom")

 

 

       Ao seguir a execução do código mostrado na figura anterior, percebe-se quanto é simples a implementação da Máquina de Estados, e que isso resulta em um funcionamento totalmente confiável.

      Claro, a Máquina de Estados deve ser mantida funcionando ciclicamente, e por isso mesmo a função que implementa a mesma (a "exec_MAQ_Sensor_Prox") é chamada a partir do "loop" do Arduino. Isso implica que no "loop" do Arduino  não se deve usar códigos "bloqueantes", ou seja, não usar loops quase eternos nem a função "delay", assim como ter cuidado com Bibliotecas escritas sem esses cuidados. Aqui fica um ponto importante:  sempre  é possível escrever uma Biblioteca que não seja "bloqueante". Então quando vc encontrar uma que é "bloqueante", é porque quem a escreveu ou não sabia como fazer, ou não estava interessado em fazer isso, ou então teve uma preguicinha de fazer. Mas é estranho que não se saiba como escrever um código "não bloqueante", uma vez que fazer isso é extremamente simples (e como eu disse, sempre isso é possível de ser feito, e nos meus mais de 35 anos de experiência em Projetos, eu nunca encontrei um caso que não tivesse solução).

 

 

       Como dito anteriormente, é possível selecionar no código, qual Interface será usada para o Display LCD:  Paralela ou I2C.  Esta definição pode ser vista na figura a seguir:

(clique na figura para "zoom")

 

 

      Deve ser especificado o "tamanho" do LCD, ou seja o número de colunas e linhas, e caso se esteja usando a Interface I2C deve-se também especificar o endereço I2C do LCD, conforme é mostrado na figura a seguir:

(clique na figura para "zoom")

 

 

      Mas se a Interface especificada for a Paralela, então o endereço I2C definido na figura anterior não será usado no código (mas também não é necessário deletar nem comentar a linha onde esta definição é feita).

 

      Outros parâmetros devem ser definidos para a Interface de Hardware do LCD, e as duas figuras a seguir mostram isto respectivamente para a Interface Paralela  e para I2C:

(clique na figura para "zoom")

  

(clique na figura para "zoom")

 

 

      Observar que para a Interface I2C, quando se utiliza o módulo I2C com chip PCF8574, normalmente não é necessário se preocupar com os pinos do módulo que são ligados ao LCD, pois estes pinos coincidem com aqueles mostrados na figura anterior.

      Também não é necessário deletar ou comentar a especificação de Hardware que não corresponda a opção feita para a Interface com o LCD, pois conforme pode ser visto nas duas figuras anteriores, o código só utiliza a especificação que foi selecionada.

 

 

       O "setup" do Arduino pode ser visto na figura a seguir:

(clique na figura para "zoom")

 

 

      Novamente, no "setup" do Arduino não há nenhuma novidade, mas é sempre bom refrescar a cabeça com alguns pontos, como a importância de observar a sequência em que as coisas vão sendo inicializadas para preparar o Sistema para o pleno funcionamento. Também deve-se notar a "limpeza" do processo executado no "setup", evitando-se deixar ali linhas e linhas de código detalhado (ou talvez melhor dizer "espalhado"). Para conseguir isto, as inicializações são feitas em funções específicas para cada elemento que precisa ser inicializado, deixando claro o que está sendo feito e a sequência em que isto é feito. Isto também facilita futuras alterações no funcionamento do Sistema, devido à melhor organização.

 

      Notar que no final do "setup", a variável "ref_minuto" é setada com o valor do "millis" naquele momento. Esta variável é a referência para a contagem dos minutos, e setando-a ali faz com que a contagem de minutos praticamente se inicie do zero no "loop" do Arduino, fazendo com que qualquer "delay" no "setup" não tenha efeito sobre o primeiro minuto. Particularmente, eu faria isso localmente no próprio "loop" do Arduino (pois isto seria mais "técnico/profissional", evitando que todos se lembrem do caso do "bit assassino" da Toyota), mas para deixar o código mais simples, fiz no "setup" conforme mostrado na figura anterior.

 

 

      E finalmente, novamente no "loop" do Arduino graças a toda a metodologia que foi usada na implementação do restante do código, podemos ver facilmente todos os processos que são continuamente executados no Sistema e que o mantém funcionando de forma simples e robusta. Isto pode ser visto na figura a seguir, que mostra quatro processos sendo executados no "loop" do Arduino:

(clique na figura para "zoom")

 

 

      Primeiro, é executada a Máquina de Estados (função "exec_MAQ_Sensor_Prox") que gerencia a detecção de objetos via Sensor de Proximidade.

      Em seguida é executado o processo que gerencia a exibição de informações no Display LCD (função "gerencia_Display"). Observar que o Display só é atualizado quando necessário. Esta atualização é requisitada através de uma flag (a "Display_update").

      O terceiro processo, verifica se um objeto foi detectado, e caso sim, é atualizado a contagem total de objetos e a contagem parcial (que é a contagem em progresso no minuto atual), sendo então requisitado que o Display seja atualizado. Adicionalmente, a contagem total  também é "printada" via Serial do Arduino. Então as operações neste terceiro processosão executadas apenas quando um objeto é de fato detectado.

      O quarto processo, verifica se foi completado um minuto desde a conclusão do minuto anterior, e caso sim, então é iniciada a contagem de mais um minuto (variável "ref_minuto") e atualizado o total de minutos decorridos. Também é registrado o total de objetos neste último minuto concluído (sendo então zerada a contagem parcial), e então calculada a Média de objetos por minuto. Finalizando o processo, as informações sobre a quantidade por minuto são "printadas" via Serial do Arduino, e é requisitado que o Display seja atualizado. Notar que todas as operações neste quarto processo,  são executadas apenas uma vez a cada minuto.

 

      É interessante notar que mesmo que se altere a sequência de execução dos processos no "loop" do Arduino, ainda assim o Sistema funcionará corretamente. Isto é devido à toda a técnica usada na implementação (como uso de Flags de sinalização, Flags de requisição, Processos "fechados", etc, além da própria Máquina de Estados que gerencia a detecção de objetos). Mas obviamente, há uma sequência lógica que pode ser percebida, e o bom senso nos diz que é melhor deixar a execução seguir conforme esta sequência lógica, pois isto irá facilitar o entendimento do funcionamento do Sistema, o que por sua vez facilitará o nosso trabalho.

 

 

      Algumas considerações finais:

 

      1)  nesta implementação, observar que apenas no "setup" do Arduino  e eventualmente em alguma função de inicialização (chamada no próprio "setup"), é que se utiliza a função "delay" do Arduino. Então não utilize "delay" fora destas áreas. E cuidado com a enorme quantidade disponível na Internet, de Bibliotecas "mal-escritas", e que fazem uso deliberado do "delay", provocando "travamento" da execução de todo o Sistema (como já mencionei anteriormente quando falei de códigos "bloqueantes").

 

      2)  sobre a simulação no Proteus, sempre é bom lembrar que dependendo do Computador, o I2C do PCF8574 pode "travar" com mais frequência. Pelas minhas investigações, o problema se restringe realmente ao PCF8574, pois com outros dispositivos I2C isto não ocorre. A performance da simulação no Proteus também cai sensivelmente quando se acessa o PCF8574, e isto afeta a simulação de outros circuitos que não tem relação alguma com o I2C. Assim a simulação do LCD via I2C no Proteus pode exigir uma certa dose de paciência. Então para promover a performance da simulação, usei na mesma o LCD via Interface Paralela. Mas caso a I2C seja desejada, basta compilar o código com essa opção (que é a default), gerar o arquivo "HEX" correspondente e especificar este arquivo nas propriedades do Arduino no Proteus (além é claro de alterar o circuito da Interface para usar o I2C via chip PCF8574 conforme mostro neste outro post: "Interface I2C no Proteus" ).

 

      3)  sobre usar junto ao código aqui implementado um Teclado Matricial (seja 4x3, 4x4, ou com qualquer outra configuração), é algo bem simples, mas precisa ser feito de forma a não ser um código "bloqueante". Para isto o Sistema deve ter dois processos associados:  um que executa ciclicamente (e de forma temporizada) fazendo a varredura e decodificação do Teclado, e outro que simplesmente verifica se uma Tecla foi acionada e caso sim então retorna um código correspondente a essa Tecla. Ou seja, é um mecanismo muito semelhante ao implementado para o Sensor de Proximidade. E este mecanismo pode ser aplicado para o uso de uma enormidade de Sensores e dispositivos.

 

 

      O download do código para o Arduino,  além dos arquivos para simulação estão disponíveis aqui:  "Cont_Sens_E18_02.zip"

 

 

      Espero ter ajudado.

 

      Abrçs,

      Elcids

Boa tarde Elcids, muito grato pelo retorno, a noite estarei estudando sua resposta.

Novamente, muito obrigado!

Ok.

      O código pode ser usado com o Wemos.

      Não esqueça de especificar o pino que vc está usando para o Sensor, e os parâmetros relacionados à temporização para detectar um objeto (ou "Peça"). Mas há diversos parâmetros que vc pode especificar e estão descritos no post.

 Abrçs

Elcids

olá Renan.

      Há algum retorno que vc possa compartilhar aqui no LDG?

      (especificamente sobre se vc conseguiu um bom resultado com a contagem de objetos)

      Sempre é bom compartilhar resultados, pois certamente isso ajuda outras pessoas que aqui no LDG (assim com vc)  procuram ajuda.

      Abrçs

      Elcids

Boa tarde Elcids, 

Sim, optei inicialmente por aplicar debounce via código mantendo o mesmo hardware e até o momento não tive mais problemas com interferências, fiz algo parecido que a sua maquina de estados filtrando acionamentos inferiores a 100ms. Quero agora fazer isolamento optoacoplado para aumentar a segurança na entradas.

ola, posso sugerir algumas alterações no seu codigo, e no hardware.

no codigo, faça uma rotina que pega somente uma borda de subida ou descida do sensor e coloque um filtro de tempo sem delay, apenas usando ciclos do processamento.

exemplo

boolean FlagCount  = false;

void ContaPeca()
{
//Contagem de peça
if (digitalRead(IO_Input) == HIGH)
{
// Sensor de Conta peça
if (!FlagCount)
{
FlagCount = true; // Pega a borda de Subida do sensor para incrementar o conta peça.
CountProduction++;
}
FiltroSensorPeca = millis();
}
else
{
if (millis() - FiltroSensorPeca > filtroPeca)
{ // Colocar um poteciometro depois para ajustar de acordo com a maquina
// Filtro para não ter problemas com pequenas bordas de descida
FlagCount = false; // Somente apos uma borda de Descida eu retiro a flag.
}
}
}

para o hardware tente usar circuito com debounce de 5 a 6 millis .

Ola Mendigo Rasteiro, 

Apliquei o debounce via software e até o momento solucionou o meu problema. 

Pretendo agora isolar opticamente as entradas.

Grato.

RSS

© 2024   Criado por Marcelo Rodrigues.   Ativado por

Badges  |  Relatar um incidente  |  Termos de serviço