Ir ao conteúdo
  • Cadastre-se

Arduino comando lcd.print trava arduino


Posts recomendados

Boa noite pessoal.

Estou ficando louco.

Há 3 dias que estou enfrentando problemas para trabalhar com display lcd I2C 20x4. O problema é o seguinte:

tenho um skecht que funciona perfeito e estou querendo implementar um display, porém ao enviar o comando lcd.print() o arduino trava.

Já testei um exemplo e funciona normal, mas quando passo para o meu skecht ele trava quando a condição é satisfeita. Já experimentei um monte de bibliotecas, até formatei o PC e nada.

 

 

Um exemplo que funciona:

 

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// Inicializa o display no endereco 0x27
LiquidCrystal_I2C lcd(0x3F,2,1,0,4,5,6,7,3, POSITIVE);
 
void setup()
{
 lcd.begin (20,4);
}
 
void loop()
{
  lcd.setBacklight(HIGH);
  lcd.setCursor(0,0);
  lcd.print("Arduino e Cia !!");
  lcd.setCursor(0,1);
  lcd.print("LCD e modulo I2C");
  delay(1000);
  lcd.setBacklight(LOW);
  delay(1000);
}



O meu exemplo que trava: )só estou testando com um comando lcd.print)





#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F,2,1,0,4,5,6,7,3, POSITIVE);
const int bomba = 3;
const int sensor1 = 4;
const int sensor2 = 5;
const int reset = 6;
const int liga = 7;
const int ledbomba =  8;
const int ledalarme = 9;
int estadobomba = LOW;
int trava = 0;
int i=0;
int contaPulso;
float vazao;
float media=0;


void setup() {
  lcd.begin (20,4);
  lcd.setBacklight(HIGH);
  pinMode(bomba, OUTPUT);
  pinMode(ledbomba, OUTPUT);
  pinMode(ledalarme, OUTPUT);
  pinMode(sensor1, INPUT);
  pinMode(sensor2, INPUT);
  pinMode(reset, INPUT);
  pinMode(liga, INPUT);
  pinMode(2, INPUT);
  attachInterrupt(0, incpulso, RISING);
}

void loop() {

if (estadobomba == HIGH) {
    digitalWrite(bomba, HIGH);
    digitalWrite(ledbomba, HIGH);
    digitalWrite(ledalarme, LOW);
    lcd.print(" ligada!");

      }
  if (estadobomba == LOW) {
    digitalWrite(bomba, LOW);
    digitalWrite(ledbomba, LOW);
  }

  if ((digitalRead(sensor1) == LOW) && (digitalRead(sensor2) == LOW) && trava == 0) {
     estadobomba=HIGH;
  }
  if ((digitalRead(sensor1) == HIGH) && (digitalRead(sensor2) == HIGH)) {
    estadobomba=LOW;
    i = 0;
  }

  if (estadobomba == HIGH) {
  contaPulso = 0;
  sei();
  delay (1000);
  cli();
 
  vazao = contaPulso / 5.5;
  media=media+vazao;
  i++;

  if(i==30)
  {
    media = media/30;
    media = 0;
    i=0;
  }
  }
 
  if ((estadobomba == HIGH) && (contaPulso <= 10) && (i >= 10)){
    estadobomba = LOW;
    digitalWrite(ledalarme, HIGH);
    trava = 1;
  }

 if (digitalRead(reset) == HIGH) {
  trava = 0;
  i = 0;
  digitalWrite(ledalarme, LOW);
 }

 if ((digitalRead(liga) == HIGH) && (trava == 0)) {
  estadobomba = HIGH;
 }
 
}

void incpulso ()
{
  contaPulso++;
}

 

Link para o comentário
Compartilhar em outros sites

@Isadora Ferraz, abrigado pela resposta.

mas não é ruído, suspeito que seja a interrupção.

no novo sketch estou acionando um relé. deixa eu atualizar:

montei um novo sketch, porém sem esta parte:

 

 if (estadobomba == HIGH) {
    contaPulso = 0;
    sei();
    delay (1000);
    cli();
    vazao = contaPulso / 5.5;
    media=media+vazao;
    i++;

   if (i==30) {
     media = media/30;
     media = 0;
     i=0;
   }
  }

 

e está quase funcionando, percebi um detalhe, o comando print.lcd() não manda um comando e pára, ele continua atualizando a tela sempre, dá pra ver as letras piscando.

agora me vem outra dúvida, tem como usar outra coisa sem ser a interrupção?

adicionado 43 minutos depois

Mais uma atualização:

quase tudo resolvido, só um detalhe:

a causa do travamento é a interrupção, só foi desabilitar que o lcd funcionou, porém sem ela não sei contar pulos.

alguém me ajuda.

Link para o comentário
Compartilhar em outros sites

  • Membro VIP
18 minutos atrás, caolne disse:

555 serve pra isto?

Não amigo. Por gentileza pesquise por atmega168 counter p.ex. . P. ex.:

Counter1%20-%20ATmega8.JPG

A ideia por trás da ideia é configurar Tn como a entrada do contador - seu sinal do contapulso() - e manipular TCNTn ao seu bel prazer.

 

Mas sei que o tal arduíno dá tudo mastigado mas infelizmente mesmo assim eu (eu) não consigo engolir. Alguém do ramo poderá te ajudar mais efetivamente se achar que deve...

Mas acho que falta pouco... sua interrupção pode estar demorando muito pra sair dela ou alguma coisa no circuito pode estar a provocando e ela fica com raiva...

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

  • 4 semanas depois...
  • Membro VIP

Então apontemos os holofotes para o ldc...

Ele funciona de 2 formas: você envia o controle e espera ele retornar que está pronto para o próximo analisando   sinal busy. Outra... você envia o controle e espera um pouquinho antes de enviar o próximo. No caso do 1º pode ser que há alguma falha nesta comunicação. No 2º, pode estar raṕido d+. Se fosse você no controle ficaria fácil interpretar/adaptar algo. Mas como preferes os mastigados do arduíno, ... fizeste tua escolha.

Portanto a dica: aprofunde + nas rotinas mastigadas do arduino pra ver que método ele usa.

abç

Link para o comentário
Compartilhar em outros sites

@Isadora Ferraz, @vnszava

desconfio que seja falha do Arduino mesmo, pois como comentado mais acima funciona normalmente quando uso o serial.print no lugar do lcd.print, acompanho todas as informações no serial.

e quanto ao lcd já testei com outros sketchs que não usam interrupção, suspeito que o protocolo I2C usa a mesma interrupção que usei para contar os pulsos.

 

tava pensando e tive outra ideia, comprei vários Arduino unos, e pensei em usar um só para contar os pulsos com interrupçao e passar a informação para o outro que roda o sketch, será que funciona?

Link para o comentário
Compartilhar em outros sites

  • 1 ano depois...

Amigo, estou passando por este mesmo problema.

Estou fazendo um circuito dosador de água. Todo o programa funciona normalmente, com teclado, LCD, buzzer, led´s e tudo mais, porém, quando incluo a interrupção via hardware para contar os pulsos do sensor, o programa faz a contagem e quando sai do circuito, o buzzer para de funcionar e o lcd também.

Coloquei um led para depurar o programa, porém é realmente uma falha de hardware.

Todos os exemplos que olhei funcionam com interrupção, porém a interrupção está travando o arduino.

Cheguei até a colocar uma fonte externa de alimentação , porém meu circuito está consumindo muito pouco e mesmo assim não resolveu.

Você conseguiu chegar à alguma conclusão?

Obrigado.

Link para o comentário
Compartilhar em outros sites

  • Membro VIP
1 hora atrás, eduardomoraes disse:

este mesmo problema

Amigo pode ser que seu problema não seja necessariamente o mesmo. Dica: publique o seu esquema e seu fonte.

1 hora atrás, eduardomoraes disse:

quando sai do circuito, o buzzer para de funcionar e o lcd também.

Você quer dizer, sai da interrupção né? Nestes casos usa ser alguma variável que é compartilhada indevidamente ou de forma errada entre loop e rotina de interrupção ou algo do gênero. Mas sem as informações que pedi... sem chance de chutar mais...

Ou aguarde o autor do tópico.. caso ele ainda esteja entre nós...

abç

Link para o comentário
Compartilhar em outros sites

O programa que estou usando é esse:

 

// OBS: Para fins de analise, omiti as informações de teclado (configurações de teclas, pinos e etc)

#define PortaRele 13    // Pino onde o acionamento do rele
#define PortaBuzzer 7   // Pino onde o acionamento do Buzzer
#define PortaAgua 2  // Pino do Sensor de Fluxo

// Codigo das mensagens do Buzzer
#define ERRO 0
#define TECLA 1
#define CONFIRMA 2
#define FIM 3

volatile int contaPulso;   // Inicializa a variavel para contagem do Fluxo de Água

 

// Função para incrementar o contador de pulsos do sensor de vazão
void Pulso() {
  contaPulso++;
}

 

// Setup Arduino
void setup() {
  pinMode(PortaRele,OUTPUT);    // Inicializada o RELE
  pinMode(PortaBuzzer,OUTPUT);      // Inicializada o Buzzer
  pinMode(PortaAgua,INPUT);    // Inicializa o Sensor de Fluxo
  Serial.begin(9600);    //INICIALIZA A SERIAL  
  MenuPrincipal();     //Exibe o menu principal
}

 

void loop() {
  // Verifica se alguma tecla foi pressionada
  char tecla_pressionada = meuteclado.getKey(); //VERIFICA SE ALGUMA DAS TECLAS FOI PRESSIONADA
  if (tecla_pressionada){
    switch(tecla_pressionada){
     case 'A':
        {
        // Emite um "clique" padrão
        Buzzer(TECLA);
        // Entra em uma função que permite digitar o numero de litros que será contato     
        SelecionaLitros();
        break;
        }
     case 'B':
        {

//  ... Continua o case das demais funções (configurações, e etc).

// Não é importante para o problema em questão
         }
    }
    MenuPrincipal();    // Após varrer as opções, exibe o menu novamente
  }
}

 

// Função para aguardar o usuario pressionar quantos litros serão contados

void SelecionaLitros(){
// Inicializa as variáveis  
int nLitros, i = 0;
boolean sair = false;
String cLitros = "";
// Verifica se alguma tecla foi pressionada
char tecla_pressionada = meuteclado.getKey();
// Exibe o menu secundario do sistema
MenuLitros();
// Fica rodando neste menu até sair ou confirmar
while (!sair) {
   // Verifica se alguma tecla foi pressionada
   tecla_pressionada = meuteclado.getKey();
   // Se foi pressionada uma tecla
   if (tecla_pressionada) {
      switch (tecla_pressionada){
        // Tecla CONFIRMA foi pressionada
        case 'A': 
           {
           if (cLitros != "")
              {                
              // converte de array para int
              nLitros = cLitros.toInt();
              // Exibe a quant.de litros 
              Serial.println(cLitros);
              // Dispara a função de contagem de litros
              AcionaContadorLitros(nLitros);
              // Limpa as variáveis
              nLitros = 0;
              cLitros = "";
              // Encerrou, sai do loop e retorna ao menu principal              
              sair = true;

              break;
           }
           Serial.println("Quant.incorreta");
           delay(500);            // Aguarda 1/2 segundo
           }

 // Restante das opções são tratamento das teclas digitadas
     }
     // Aguarda 1/10 de segundo para ler as teclas novamente 
     delay(100);
   }  
}

}

 

// Função para contar os litros selecionados

void AcionaContadorLitros(int Litros){
  // Inicializa as variaveis
  float FatorC = 7.5;
  boolean _sair = false;
  unsigned long OldMillis;
  float vazao=0; //Variável para armazenar o valor em L/min

 ===>>>>>>>>>>>>>> Inicio do problema
  // Habilita a interrupção de hardware
  attachInterrupt(digitalPinToInterrupt(PortaAgua), Pulso, RISING);   
  // abre a valvula eletromagnetica
  digitalWrite(PortaRele,HIGH);
  // vamos executar este loop até atingirmos Litros
 while (!_sair){
   // zera a variavel de contagem de pulsos do sensor de vazao
   contaPulso=0; 
   sei();      //Habilita interrupção

   delay(1000);
   cli();      //Desabilita interrupção
    vazao += (contaPulso / FatorC / 60); //Converte para L/seg
     //verificamos se a quant.de litros esperada já foi alcançada   
    if (vazao >= Litros){
         _sair = true;
         }
  {
 }
 // Desabilita a interrupção de hardware
 detachInterrupt(digitalPinToInterrupt(PortaAgua));

=====>>>>>>>> Fim do problema
 digitalWrite(PortaRele,LOW); 
 // Quando encerra a contagem, exibe uma mensagem no display
 Serial.println("Contagem Encerrada");
}

 

Se o circuito Início / Fim do problema for substituído por qualquer outro, não apresenta nenhum inconveniente, porém, da maneira que está, para de funcionar outras funções auxiliares (que não utilizam qualquer variável)  como Buzzer(MSG) que toca um som diferente de acordo com o programa (confirma, digitação, erro e etc), até mesmo a porta serial para de funcionar.

Eu coloquei um led em diversos pontos do programa para ver até onde a execução ia, e ela chega até a função loop(), porém TODAS as chamadas de funções digitalWrite(), Serial.print() e Serial.println() param de responder, até que o controlador congela.

Uma coisa que observei é que o led utilizado para checar o ponto de excução, quando congelava o controlador, ele ficava com um brilho menor. Pensei que poderia ser um problema de alimentação. Coloquei toda a alimentação dos relês, sensores e etc em uma fonte auxiliar e mesmo assim o problema persiste.

Cheguei a fazer um teste utilizando um loop de contagem de tempo com millis(), pegando o tempo antes de chamar a  interrupção (i.e. sei() ) e depois de encerrar a interrupção (i.e. cli() ) e mesmo assim o problema persiste.

O ideal seria se tivesse uma outra maneira de contar os pulsos do sensor, mas ainda não sei como fazê-lo. Se alguém tiver uma ideia diferente...

Link para o comentário
Compartilhar em outros sites

qual a placa que está usando? Não sobrou nenhum timer nela? Além de tempo esse periférico tb pode ser utilizado para contagem de eventos (seus pulsos). Possui internamente a função compare que dispara uma interrupção interna (se setada) quando o a contagem atingir o valor desejado.

Não entendi aquele delay agindo junto com a interrupção. Possível fonte de bugs.

Pense no seguinte fluxo utilizando o contador de 16 bits:

 

- seu pino de pulso habilitado como clock do contador, prescaler = 1

zera o timer

calcula a quantidade de pulsos equivalentes aos litros desejados

carrega o comparador com a quantidade de pulsos (máx 64k)

habilita o timer

reseta a flag do comparador

habilita o comparador

liga a válvula

while comparador == false(

   // durante a espera até dá para atualizar o display com a

   contagem

   faz leitura do timer (pulsos contados)

   converte pulsos para litros

   print litros

)

desliga válvula

 

o código fica mais simples e confiável

 

Boa sorte

 

 

adicionado 9 minutos depois

Como não foi criada uma função a ser disparada por interrupção do compare não é necessário setar a interrupção por compare.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

  • Membro VIP

Serjão tem razão. É melhor o próprio hw do mc pra esta função. Algo como o pseudocodigo

-pulsos na entrada do contador

-a cada segundo capture os registros e guarde numa variável

-zere os registros pra próxima captura

 

-Só isso

-Simples d+

-Não complique

-Adote o minimalismo

-tmj

 

Se usar uma interrupção a cada 1 segundo pra fazer isso, seu loop principal fica livre pra fazer o que quiser. Nele (e não na interrupt) faça as contas necessárias, escreva no display, acione/leia portas e etc.

 

Link para o comentário
Compartilhar em outros sites

Fiz as seguintes alterações e funcionou. agora sem travamentos:

 

/*
 * Funçao Setup
 * Inicializa as variáveis e prepara o ambiente do programa
*/
void setup(){
    // Inicializa o RELE   *#*
    // Inicializa o Buzzer   *#*
   
    // Inicializa o Sensor de Fluxo
    pinMode(PortaAgua,INPUT);
    digitalWrite(PortaAgua,HIGH);
    contaPulso = 0;
    attachInterrupt(digitalPinToInterrupt(PortaAgua), Pulso, RISING);     // atribui a interrupção por hardware
    sei();      // liga a interrupção

 

    // Inicializa a interface I2c *#*
    // Inicializa o LCD  *#*
     //INICIALIZA A SERIAL  *#*
  
    //Exibe o menu principal
    MenuPrincipal();
}

 

As linhas com *#* foram omitidas pois não interferem no código do sensor

 

/*
 * Programa para contar os litros selecionados
 */
void AcionaContadorLitros(int Litros){
 // Inicializa as variaveis

  // Fator de conversao (frequencia/vazao) do sensor

  // Coloquei em uma variavel pois caso seja um sensor de 3/4" o valor será 5.5
  float FatorC = 7.5;   

  boolean _sair = false;   // Controle do loop
  unsigned long OldMillis;   // variável contador de tempo1
  unsigned long NewMillis;   // variável contador de tempo2
  float vazao=0; //Variável para armazenar o valor em L

  contaPulso = 0;   // zera a variável de contagem de pulsos do sensor
 OldMillis = millis();   // Pega o contador de tempo atual
 digitalWrite(PortaRele,HIGH);    // abre a valvula eletromagnetica

 // Inicia o loop
 while (!_sair){
   NewMillis = millis();   // Pega o novo contador de tempo
   if (NewMillis >= (OldMillis + 1000)){   // Se já passou 1 segundo
      Serial.println(NewMillis);      // Exibe o novo contador de tempo
      OldMillis = NewMillis;     // Atualiza o contador de tempo anterior = atual

      vazao += (contaPulso / FatorC / 60);    //Converte para L/seg 
      contaPulso = 0;            // zera a variável de contagem de pulsos do sensor
      Serial.print(vazao);      // Exibe a quantidade de litros já contada
   }
   if (vazao >= Litros){          //verificamos se a quant.de litros esperada já foi alcançada
       _sair = true;    // Sai do loop
   }
 }
 digitalWrite(PortaRele,LOW);    // Desliga o relê
 Serial.println("Contagem Encerrada");  // Quando encerra a contagem, exibe uma mensagem no display
 Buzzer(FIM);    // Toca um alerta sonoro para avisar que acabou a contagem
 delay(3000);   // Aguarda 3 segundos
}

 

 

Obs: Como é um programa dedicado, NUNCA encerramos a interrupção por hardware (i.e. função cli()   ).

Não acredito que isso vá causar algum problema, mas, por enquanto o programa está funcional.

Só falta fazer os testes de vazão / volume para criar uma rotina de compensação pois quero reduzir ao máximo o erro na medida de volume.

Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

Ebook grátis: Aprenda a ler resistores e capacitores!

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!