Conflito entre DISPLAY LDC com I2C,TIMER1, RT1307, DS18B20 ,ARDUINO UNO

Busco  respostas para corrigir um erro de programação 

Quando utilizo a biblioteca simples de LiquidCrystal  com o TIMER1 , RT1307, DS18B20  funciona normalmente.

Mas quando utilizo a biblioteca LiquidCrystal-I2C   com o TIMER1 , RT1307, o display inicia normalmente e após a varredura inicial para de funcionar .

Estou utilizando o TIMER1 devido  a necessidade de interromper o ciclo  para atualizar a tela do display  de  indicação das horas , temperatura, que ocorre  de 1 em 1 segundos para o ciclo de funcionamento de indicação no display .

Em anexo coloco a disposição de todos que puderem me auxiliara a encontrar  uma maneira mais simples de solucionar este problema.

Obrigado por poder compartilhar  minhas dificuldades  com vocês.

Meu conhecimento é na área de automação industrial , mas sinto necessidade de entender o que se passa de errado no programa . 

Alguns trechos foram retirados de sketch já produzidas .

Teimosia minha,  mas pretendo  se possível com auxilio de vocês solucionar o que se passa nesta sketch

Obrigado. 

JÁ EH !!!!

Exibições: 683

Anexos

Responder esta

Respostas a este tópico

Bom dia, 

Primeira pergunta para saber se a interface I2C foi montada adequadamente. 

Você esta usando resistores de pullup na interface I2C? São essenciais.

Qual valor e onde esta usando? Sabendo-se que não pode usar mais de um para cada linha SCL e SDA. 

Mostre o diagrama das ligações, por favor. 

Bom dia José!

Obrigado pelo retorno!

Sobre a interface I2C foi montada correta ,porque em outra programas está funcionando sem o TIMER1.

Sobre o uso de resistores não estou usando nenhum , utilizo somente os PULLUP internos do arduino.

Sobre utilizar os SDA E SCL está funcionando no mesmo  . A4 , A5 , (SDA , SCL)  porém pontos diferentes.

Sobre o diagrama estarei  enviando a foto da montagem , mais rápido  .  KKK

olá Marlén.

      Analisei todo o seu código, e tenho que ser direto com vc sobre istohá uma enormidade de problemas  nele,  desde os mais "bobos" e sem muita importância, até os graves, chegando aos "gravíssimos".

      Mas fazer ele funcionar da forma que vc deseja, é simples.  E se vc estiver com muita pressa, faça apenas os ajustes simples que descrevo a seguir:

      1)  primeiro,  defina  a variável  "diplay_FLAG"  e  altere  a  função  "ISR(TIMER1_OVF_vect)"  conforme mostrado na figura a seguir:

(clique na figura para "zoom")

      2)  segundo,  acrescente na sua função "loop",  o trecho de código marcado na cor verde na figura a seguir:

(clique na figura para "zoom")

      Com estes dois "ajustes", seu código deve funcionar como vc espera.

      Mas vejaainda existem muitos problemas graves na sua implementação.  E caso vc deseje resolver estes "outros" problemas, avise aqui, que eu te ajudarei neste processo.

      Abrçs,

      Elcids

Bom dia  Elcids !

Como vai ? 

Obrigado pela atenção ! Fico grato !

Então , falando sobre os erros , isso para min é muito importante .

Através do conhecimento  de vocês estarei aprendendo aquilo que para min seria uma enorme dificuldade.

Gostaria de saber de sua parte se você poderia informar todos os erro possível , destes os mais simples que seja até aqueles que eu jamais saberia identificar.Como você avaliou o programa , deu para notar que eu programei da maneira que eu pensava que iria funcionar, sabe como é né?

Para min , o TIMER1 seria o erro que estaria com conflito com o I2C do LCD , porque sem ele o programa roda da maneira prática. 

Por motivo de aprendizagem .

Aprender com aqueles que mostram interesse de ajudar é muito gratificante. 

Isso serve para min e para todos  aqueles que algum dia passaram pelo mesmo ocorrido.

Mais uma vez agradeço a todos a imensa ajuda pelo meus erro .

Estarei disposto a aprender com meus erros. 

Assim que você poder estarei disposto.

ok Marlén.

      Vamos primeiro falar da questão I2C e TIMER1, onde inclusive está o problema de ordem "gravíssimo".

      Vc estava usando a ISR (Interrupt Service Routine) do Overflow do TIMER1, apenas para cadenciar a exibição no Display.  Ok, não há nada de errado com isso. Mas é praticamente um desperdício de recurso, e neste caso o recurso é a ISR do Overflow do TIMER1.  Você pode conseguir a mesma coisa sem usar esse recurso, e de forma extremamente simples e funcional (como já demonstrei em inúmeros posts aqui no LDG).

      O problema "gravíssimo" a que me refiro, é o fato de vc acessar a I2C dentro da ISR.  Devido à forma como as Interrupções funcionam no ATMega328 (a CPU do Arduino UNO), habilitar Interrupções  dentro de uma ISR, exige extremo cuidado com a temporização (apenas especialistas irão fazê-lo da forma adequada, pois isto é extremamente técnico), do contrário,  a chance do seu código "travar" é imensa (isto pode acontecer devido a alguma espera de que outras ISRs sejam concluídas quando nunca serão concluídas,  ou então por overflow do "Stack", do "Heap", ou de ambos).  Então, ocorre que quando vc acessa funções da I2C,  algumas dessas funções reabilitam as Interrupções, podendo causar o problema que mencionei.  E estas funções também ficam esperando que a ISR da I2C seja concluída, e caso estas próprias funções não habilitem as Interrupções,  a ISR da I2C  jamais será executada,  uma vez que a ISR do TIMER1  automaticamente desabilita as Interrupções  assim que esta ISR é executada (o mesmo ocorre com qualquer outra ISR).

      Resumindo:  acessar dentro de uma ISR,  funções que habilitam Interrupções ou que necessitam que as Interrupções estejam habilitadas,  é certamente dar um tiro no pé, pois estará automaticamente gerando conflitos entre recursos de Hardware e Firmware.  Então isto não deve ser feito.

      Então como se faz, caso vc realmente queira usar Interrupções?  Simples:  use uma Flag para sinalizar a ocorrência de um evento, e processe este evento fora da ISR, detectando tal evento pelo teste do estado da Flag. Foi exatamente isso que fiz na sugestão inicial que postei.

      No entanto Marlén, se vc testou os ajustes que mostrei,  vc deve ter percebido que o Display não ficou mais "travado",  mas também não atualizou as informações exatamente como vc esperava.  Isto ocorre, por causa dos "outros" problemas no seu código, que mencionei antes. Neste caso estes  não são  os "graves" nem os "bobos",  mas são problemas da implementação lógica do seu código, que irei explicar adiante.  Mas lembre-se: ainda há problemas "graves",  que não tem  a ver com lógica,  mas são facilmente corrigíveis, e te mostrarei posteriormente.

      Para resolver seu problema de implementação lógica,  é preciso primeiro conhecer a sequência de execução funcional do seu Sistema. Vou explicar.  Na função "setup" vc inicializa tudo e deixa tudo "pronto" pra funcionar.  Esse funcionamento,  será então na função "loop", que é executada ciclicamente.

      Então a primeira questão é:  qual a primeira coisa que deve ocorrer no seu Sistema, dentro da função "loop"?  Veja,  a pergunta aqui é "temporal",  ou seja,  conforme o tempo passa,  qual a primeira coisa deve ocorrer?  Vou tentar responder parcialmente essa pergunta:

      Se olhamos seu código original,  percebe-se que o Sistema começa com tudo "deligado".  Então, após um tempo de 3 segundos, é ligada a "Válvula de Sopro de Ar", que ficará ligada por um tempo "X", após o qual...  etc, etc, etc.

      Nota-se também que há um mecanismo que impede o acionamento de tudo, a qualquer instante, neste caso claramente determinado pelo Botão "pEmerg", e Sensor "pSiloCheio".  Ou seja, se um desses é acionado,  aparentemente o Sistema deve desligar tudo. Confirme se é isso mesmo, e os detalhes que eu possa não ter descrito aqui.

      Então Marlén, minha sugestão:  descreva claramente, qual a primeira coisa deve ser feita no seu Sistema, e qual a informação deve aparecer no Display.  Em seguida, descreva a sequência de coisas que deve acontecer, e como cada uma deve ser tratada.  Veja, eu poderia "levantar" esses dados analisando os "eventos lineares" no seu código, mas acho que seria mais efetivo se vc mesmo os descrevesse aqui.

      E não se preocupe: a lógica de atualização do Display que vc implementou na função "tela1", pode ser totalmente preservada. Mas certamente alguns problemas tem que ser resolvidos ali também (sem contar que vc "inseriu" ali alguns problemas "graves", que irei descrever logo).

      Fico no aguardo para prosseguir.

      Abrçs,

      Elcids

Ok, Elcids !

Primeiramente seria a leitura inicial do LCD , void inicializaLCD(), porque dentro dela contém informações iniciais .

Após sempre atualizando a void tela1(),

dentro da tela1() o void loop estará acontecendo., mas como assim??

Quando uma entrada for habilitada no arduino , o display atualizará a escrita informando o que estará acontecendo.

No caso da temperatura e da horas poderia ocorrer a cada 10 segundos , sempre voltando para  void tela1(),

Como você interpretou o programa aceito sugestões  também !

Veja o que você escreveu :

     Se olhamos seu código original,  percebe-se que o Sistema começa com tudo "deligado".  Então, após um tempo de 3 segundos, é ligada a "Válvula de Sopro de Ar", que ficará ligada por um tempo "X", após o qual...  etc, etc, etc.

      Nota-se também que há um mecanismo que impede o acionamento de tudo, a qualquer instante, neste caso claramente determinado pelo Botão "pEmerg", e Sensor "pSiloCheio".  Ou seja, se um desses é acionado,  aparentemente o Sistema deve desligar tudo.

ESTÁ CORRETO  SUA INTERPRETAÇÃO (CONFIRMO SIM)

Só que quando o Botão "pEmerg" for acionado o programa só está parando após concluir tudo ( que estaria errado ) deveria para na hora .(como foi acionado a EMERGÊNCIA.  Que pode sim ser corrigido.

Uma coisa que estou lhe informando que o programa não está terminado por motivo que como apresentou estes erros não atualizei o restante .

Tudo que você viu no programa está funcionado COM ERROS num lcd 40x4  e no arduino Mega  .Digo que escrita de lcd com o endereçamento de posição e colunas . 

Caso queira postarei no Post (Blog)

Fico a disposição para mais esclarecimento  par você me ajudar.

Grato

Marlén C.

 

   

PS: 

Outra coisa que pode ser comentado:

Se você retirar o  #include <LiquidCrystal_I2C.h>  e adicionar  #include <LiquidCrystal.h> e refazer todas a coisa abaixo para esta biblioteca , perceberá no  Monitor  Serial  que o programa funciona bem e atualiza tudo pelo TIMER1  (mesmo contendo erros.) DE 1 EM 1 SEGUNDOS.

ok Marlen.

     Eu já havia concluído sobre isto, uma vez que a Interface Paralela para o controle do LCD  não utiliza Interrupção. Já a Interface I2C utiliza, e isto causa os problemas "gravíssimos" que descrevi antes.

     Mas a questão é exatamente outra.  Da forma que está seu código, vc não vai conseguir evoluir muito com ele. Vc ficará escravo de um código travado, difícil de mexer, e ficará a mercê de Bugs sempre que vc mexer nesse código.

      Para sair dessa,  vc precisa mudar a lógica, e isto é muito simples.  Vou tentar te ajudar. Acredito que assim que vc perceber como a coisa evolui,  irá se entusiasmar e conseguirá prosseguir com novas implementações.

      Uma coisa muito importante:  neste momento esqueça toda a parte do Display.  Ela será consequência da sua implementação. Então não é nela que vc precisa ter atenção neste momento.

      Então vamos iniciar listando os elementos no seu Sistema.

      Vc tem 5 elementos de entrada digital:  dois Botões (o "pHabTransp" e o "pEmerg"), dois Sensores ("pPress" e "pSiloCheio"), e uma Chave (a "pHabAquecimento").

      E vc tem 4 elementos de saída digital:  três controles (o "pSoproAr", o "pAbreCarga", e "temperatura_areia"),  e uma sinalização (o "pAvisoFalha").

      Então aqui vai o primeiro ponto.  Analisando seu código, vi que tudo só ocorre se o Botão "pEmerg" e o Sensor "pSiloCheio"   não  estiverem acionados.  Ok.  Então eu pergunto:  se qualquer um deles for acionado a qualquer momento, o que deve ocorrer no Sistema?   Atenção:  responda sempre relatando o que deve ocorrer com os elementos de saída digital. E responda apenas a questão, ou seja, não acrescente nenhuma outra informação que não esteja relacionada.

      Eu irei colocando novas perguntas conforme vc for respondendo.  E irei postando o código e explicando o mesmo, conforme for evoluindo. Se sua primeira resposta (à minha questão acima) for suficiente para eu postar um código inicial, então eu o farei.

      Fico no aguardo.

      Abrçs,

      Elcids

Vamos lá então!

VOCÊ ( tudo só ocorre se o Botão "pEmerg" e o Sensor "pSiloCheio"   não  estiverem acionados.  Ok.)

CORRETO.

 Se o Botão "pEmerg" for acionado para tudo .

Aciona somente saída  da sinalização ( "pAvisoFalha")..

Se Sensor "pSiloCheio foi acionado termina o tempo de sopro .e para este processo , não faz mais nada.

Caso a entrada pSiloCheio for desabilitada  entra a saída   pSoproAr e após  tempo vencido  aciona pAbreCarga .

Se durante a saída pSoproAr estiver ligada a pressão subir  irá,habilitar pPress , que ficará acionada até a pressão abaixar , caso não abaixa a pressão haverá um tempo limite que após atingir esse tempo para tudo e aciona  ( "pAvisoFalha")..

Esse ciclo fica sempre repetido tudo acima.

Espero ter ti explicado  conforme solicitado

Grato

Marlén

Ok Marlen.

      Mas vc ainda não entendeu como se implementa isso. E é isto que estou tentando te mostrar. Então vc precisa ficar atento exclusivamente aos pontos que eu colocar.  Veja:  não acrescente nenhuma outra informação, ou seja:  só coloque estritamente o que eu te perguntar. Em Programação, tudo consiste em manipular informações,  então se vc misturar tudo, também vai obter um resultado misturado e bagunçado. Então fique atento a isso.

      Vamos tentar novamente.

      Primeiro de tudo:  esqueça em que estados estão os controles das saídas digitais. Ou seja: não importa se o "pSoproAr" está ligado ou desligado. O mesmo vale para o "pAbreCarga", para o "pAvisoFalha", e para o "temperatura_areia". Eles podem estar ligados ou desligados. E estou falando isso em um momento qualquer da execução do código, um momento qualquer.

      Segundo:  se o Botão "pEmerg" for acionado,  ESCREVA qual deve ser o estado das saídas digitais.  Escreva todas elas.  Veja um exemplo (é apenas um exemplo!!!):

              se o Botão "pEmerg" foi acionado, então:

                    - desliga "pSoproAr"

                    - desliga "pAbreCarga"

                    - desliga "temperatura_areia"

                    - liga "pAvisoFalha"

      Atenção: responda apenas para o Botão "pEmergacionado !!!

      Abrçs,

      Elcids

 se o Botão "pEmerg" foi acionado, então:

                    - desliga "pSoproAr"

                    - desliga "pAbreCarga"

                    - desliga "temperatura_areia"

                    - liga "pAvisoFalha"

Correto.

 se o Sensor "pSiloCheio "" foi acionado, então:

  se durante  "pSoproAr"  estiver ligado manter até acabar tempo

                    - desliga "pAbreCarga"

                

olá novamente Marlen.

      Acho que encontrei uma forma que poderá facilitar a descrição e o entendimento do funcionamento do seu Sistema.

      Veja, eu analisei o funcionamento e consegui entender o mesmo. Porém a questão é que vc disse que há erros no funcionamento do mesmo. Então não adianta fazer a implementação em cima de algo que está funcionando de forma errada.

      Assim, vamos tentar analisar os pontos mais duvidosos que eu encontrei,  e com isso eliminar essas dúvidas e então fazer a implementação do Sistema (a implementação é a parte mais fácil).

      E como eu disse, acho que encontrei uma forma de fazer isso. Mas preciso que vc colabore, e não acrescente (por favor)  nenhuma informação além da que foi questionada (porque isso atrapalha muito o entendimento da lógica).

      Então vamos tentar.

      Toda a parte mais importante do funcionamento do seu Sistema, está na função "loop".  Então eu a organizei de uma forma mais fácil de visualizar as diversas estruturas de comando ali existentes. Veja: eu não alterei nada no funcionamento, apenas eu organizei o código dentro da função "loop".  Na figura a seguir vc pode ver o resultado disso:

(clique na figura para "zoom")

      Se vc preferir, também imprimi em PDF,  nesse arquivo:   "loop_view_01.pdf"

      Observe que marquei na figura,  uma região na cor verde.  Essa região inicia na linha 738 e vai até a linha 829,  e essencialmente é todo o código dentro da função "loop".

      Na linha 738,  há o teste "if",  que testa as condições para iniciar o controle de todo o Sistema. Vamos por enquanto esquecer o que está sendo testado ali, porque uma vez que o resultado do teste seja "verdadeiro" (ou "true" em C/C++),  o código irá "entrar" ali e iniciar todo o controle,  e é isso que é o mais importante em termos de lógica.

      Mas em algum momento este controle chega ao "fim",  na linha 829.  Quando isso ocorre,  a função "loop" termina sua execução.  Mas após isso,  a função "loop" é reexecutada,  ou seja, inicia novamente, como é o padrão no Arduino (já que o "loop" executa ciclicamente).

      Então vamos à primeira questão:  quando o teste resulta verdadeiro na linha 738  e a execução prossegue na linha 739,  a partir desse ponto como devem estar as saídas digitais  listadas a seguir:

                    - saída  "pSoproAr"  =  ?

                    - saída  "pAbreCarga"  =  ?

                    - saída  "temperatura_areia"  =  ?

                    - saída  "pAvisoFalha"  =  ?

      Elas devem estar ligadas ou desligadas?

      Por favor, só responda "ligada"  ou "desligada".  NÃO  acrescente nenhuma outra informação (ou vc irá me fazer desistir do tópico).

      Assim que vc responder,  irei questionar um outro ponto bem simples relacionado com isso, mas que aparentemente está em contradição no seu código.

      Elcids

RSS

© 2024   Criado por Marcelo Rodrigues.   Ativado por

Badges  |  Relatar um incidente  |  Termos de serviço