Ir para conteúdo
  • Cadastre-se

dúvida Leitura de display LCD.

Avalie este tópico:


Posts em destaque

Olá, já estou a algum tempo em um projeto que não está andando.
Preciso ler a informação que chega em um display lcd 20x4 (barramento paralelo 8 pinos de comunicação) e envia-la para um planilha google.

o display lcd recebe os dados de um PLC de uma maquina injetora de plástico. Porem não consegui informações do PLC para retirar esses dados diretamente del, pois o PLC e de fabricação propria da empresa que fez a maquina, e não disponibiliza esses dados. Empresa que já não existe mais.

Atualmente estou tentando fazer isso ligando os pinos de comunicação do lcd nas portas de um esp32, que enviaria esses dados para a planilha. O código que estou usando para isso está a baixo, porem não funciona.

Gostaria de sugestões de como prosseguir, se existe uma forma mais simples de ter as informações que a máquina plota no display, como algum analisador logico que funcione como um display lcd que não plota os dados, mas mande ele via serial ou algo assim.

Não e possível fazer muitos testes na máquina, pois ela roda 24 por 7, só posso testar em paradas para manutenção.

 

Se alguém puder me dar uma luz eu agradeço.

 

 

/* Ativa debug pela porta serial, para ser utlizado com serial monitor */
#define DEBUG 1    

/* Tamanho do buffer para armazenamento dos bytes lidos do LCD */
#define BUFFER_LEN 250

/* Pinos do LCD */
#define PINO_EN   21 //Ativo em HIGH
#define PINO_RS   22 //LOW comando, HIGH Caractere
#define PINO_RW   23 //LOW write, HIGH read
#define PINO_BIT7 19 //Bit de dados 
#define PINO_BIT6 18 //Bit de dados 
#define PINO_BIT5 25 //Bit de dados 
#define PINO_BIT4 26 //Bit de dados 
#define PINO_BIT3 27 //Bit de dados 
#define PINO_BIT2 14 //Bit de dados 
#define PINO_BIT1 12 //Bit de dados 
#define PINO_BIT0 13 //Bit de dados 

/* Ativa modo de comunicação seria utlizando apenas 4 pinos/bits de dados, 
 se estiver comentado ativa modo 8pinos bits de dados */
#define BITS_8

/* Variável que contem os pinos do LCD a serem lidos */
#ifdef BITS_4
  #define ULTIMO_BIT 3
  uint8_t pinosPorta[4] = {PINO_BIT7, PINO_BIT6, PINO_BIT5, PINO_BIT4};
#else
  #define ULTIMO_BIT 7
  uint8_t pinosPorta[8] = {PINO_BIT7, PINO_BIT6, PINO_BIT5, PINO_BIT4, PINO_BIT3, PINO_BIT2, PINO_BIT1, PINO_BIT0};
#endif  

void IRAM_ATTR isr();

/* Variável que contem os bytes lidos */
uint8_t bytesLidos[BUFFER_LEN];

/* Variável que contem se o byte é um comando ou caractere */
uint8_t comandosLidos[BUFFER_LEN];
uint8_t RW_Lidos[BUFFER_LEN];

/* Variável para controle da posição atual do byte no buffer rotativo */
uint8_t posicaoByteLido = 0;

/* Variável para controle da quantidade de bytes lidos e disponiveis */
uint8_t BytesDisponiveis = 0;

/* Variável para quebra de linha do debug */
#ifdef DEBUG
  int cc = 0;
#endif 

/* Função setup, configuração do dispositivo, executa apenas uma vez quando ligado */
void setup() {

  /* Inicia portas */
  pinMode(PINO_EN, INPUT);
  pinMode(PINO_RS, INPUT);
  pinMode(PINO_RW, INPUT);
  for ( uint8_t i = 0; i < ULTIMO_BIT+1; i++ ) {
    pinMode( pinosPorta[i], INPUT );    
    digitalRead(pinosPorta[i]);
  }

  /* Ativa interrupção externa no PINO_EN */
  //attachInterrupt(PINO_EN, isr, FALLING); //HIGH para LOW
  attachInterrupt(PINO_EN, isr, RISING); //LOW para HIGH   

  /* Inicia comunicação serial para debug */
  #ifdef DEBUG
    Serial.begin(115200);
    delay(300);
    Serial.flush();
    Serial.println();
    Serial.println("Iniciando leitura");
  #endif  
}

/* Função loop, executa continuamente enquanto ligado */
void loop() {
  if (BytesDisponiveis > 0 ) {
    
    /* Pega um byte lido */
    uint8_t cbyte = bytesLidos[posicaoByteLido];
    
    /* Paga informação se é comando ou não */
    uint8_t ccomm = comandosLidos[posicaoByteLido];    
    uint8_t cRW = RW_Lidos[posicaoByteLido];

    /* Decrementa quantidade de bytes disponiveis */
    BytesDisponiveis--;            
    
    /* Incrementa posição atual no buffer rotativo */
    posicaoByteLido++;
    
    /* Se chegou no final do buffer volta para o inicio */
    if ( posicaoByteLido >= BUFFER_LEN ) {
      posicaoByteLido = 0;
    }
    
    /* Envia dados lidos para debug serial monitor */
    #ifdef DEBUG
      if (ccomm) {
        Serial.print( " " );
      } else {
        Serial.print( "*" );
      }
      if (cRW) {
        Serial.print( " " );
      } else {
        Serial.print( "W" );
      }
      
      if ( cbyte < 16 )
        Serial.print( "0" );
      Serial.print( cbyte, HEX );    
      cc++;
      if ( cc > 20 ) {
        cc = 0;
        Serial.println();
      } else {
        Serial.print( " " );
      }
    #endif
  }  
}

/* Função que efetura a leitura digital da porta/pino que corresponde a 1bit */
uint8_t lerPorta( uint8_t p ) {
  return ((GPIO.in >> p) & 0x1);
}

/* Função ativada pelo interruptor externo, FALLING = HIGH para LOW */
void IRAM_ATTR isr() {
  static uint8_t posicaoByte = 0;

  /* Efetua leitura a porta RS que indica se o byte a ser lido é comando ou caractere */
  comandosLidos[posicaoByte] = lerPorta(PINO_RS);
  RW_Lidos[posicaoByte] = lerPorta(PINO_RW);

  /* Efetua leitura dos bits disponiveis e converte em um byte "byteLido" */
  uint8_t byteLido = 0;  
  for ( uint8_t i = 0; i < ULTIMO_BIT; i++ ) {
    byteLido += lerPorta(pinosPorta[i]);
    byteLido = byteLido << 1;
  }
  byteLido += lerPorta(pinosPorta[ULTIMO_BIT]);

  /* Adiciona o byte lido ao buffer */
  bytesLidos[posicaoByte] = byteLido;
  
  /* Incrementa a quantidade de bytes lidos disponiveis */
  BytesDisponiveis++;
  
  /* Incrementa a posição no buffer rotativo */
  posicaoByte++;
  if ( posicaoByte >= BUFFER_LEN ) {
    posicaoByte = 0;
  }
}

 

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

Buenas,

 

o que exatamente não está funcionando? 

 

Não conheço ESP32, mas pelo código que você postou, a linguagem parece ser semelhante à do arduino. Não notei nada errado, apenas alguns detalhes, tipo:

 - Se uma variável global é manipulada dentro de uma rotina de interrupção, declare ela com o atributo volatile. Isso vale para o buffer e para os ponteiros de entrada e saída. 

 - O pino RW é usado? Mesmo que seja (provavelmente apenas para ler a busy flag), não há a necessidade de ler os dados vindos do display, pois todo e qualquer dado que estiver nele foi enviado para ele antes. Pode fazer com que a interrupção seja abortada quando o pino RW estiver em 1.

 

Dá pra fazer com que o buffer seja um FIFO, como você fez, ou que seja uma cópia do que estiver sendo exibido no display. No segundo caso, o código deve interpretar os comandos de movimentação do cursor. Dá inclusive para fazer com que ele traduza o comando numa sequencia de escape para movimentar o cursor no terminal que você conectar na serial.. nesse caso, o que aparecer no terminal será uma cópia exata do display.

 

Vou escrever como eu faria caso usasse um ATMega88, pois nunca mexi com ESP32, mas dá pra ter uma idéia:


#define DISP_EN _BV(PD2)

#define DISP_RW _BV(PD3)

#define DISP_RW _BV(PD4)

 

volatile uint8_t buffer[256]; // dados formatados, enviados para o host

volatile uint8_t ptr_entrada, ptr_saida; // ponteiros de entrada e saída do buffer;

 

void inicializa() {

 DDRB = 0x00; // PORTB será ligada direto no barramento;

 DDRD = _BV(PD1); // PD1 = TX

/// código de inicialização da porta serial aqui

// habilitar interrupção na borda de subida do PD2

}

 

ISR(INT0_vect) { // int que será chamada na borda de subida do DISP_EN

 uint8_t dado = PORTB;

 if (PORTD & DISP_RW) return; // não queremos ler nada vindo do display

 if (PORTD & DISP_RS) { // se for dado

  push_buffer(dado);

 } else if ( // se for comando de movimentação de cursor

  if (!(comando & 0x80)) return; // se não for comando de mover cursor, descarta

  push_buffer(27); // código de escape vt100

  push_buffer('['); 

  push_buffer ((dado & 0x60) - 0x60); // converte número da linha

  push_buffer(';'); 

  push_buffer (dado & 0x3F);  // mascara numero da coluna

  push_buffer('H');  // finaliza sequencia de escape

 }

}

 

void push_buffer(uint8_t dado) { // coloca um byte no buffer

 buffer[ptr_entrada] = dado;

 ptr_entrada++;

}

 

uint8_t buffer_vazio () { // retorna se tem dados no buffer;

 return (ptr_entrada == ptr_saida);

}

uint8_t  pop_buffer() { // pega um byte no buffer

 ptr_saida++;

 return buffer[ptr_saida];

}

 

main () {

 inicializa();

 while(1) {

  if (!buffer_vazio()) {

   enviapelaserial(pop_buffer);

   }

 }

}

 

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

Esse código não vai mostrar uma imagem igual a do display na tela do terminal.. vai mostrar como se fosse um lcd 80x2. Não incluí a parte que decodifica os números de linha porque esses displays 20x4 tem um mapeamento de memória meio incomum: A linha 0 começa no endereço 0, a 1 no endereço 0x40, a 2 no 0x14 e a 3 no 0x54. Se quiser que ele mostre exatamente igual, vai precisar adicionar umas instruções a mais para decodificar o número da linha e coluna. 

 

A sequência de escape que pus na rotina de interrupção (ESC[_linha_;_coluna_H) corresponde ao comando de movimentação do cursor no padrão de terminal VT100. Com ela, os dados devem aparecer como no display, em vez de ficar rolando continuamente pela tela. 

 

Fale mais sobre a máquina. Por acaso é uma ROMI?

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

@zazulak Muito obrigado pelo interesse no meu projeto.

 

Na verdade esse código não e meu. eu havia pago para um freelance desenvolver essa solução para mim, porem o código ou o hardware não funcionou como devia. ele não retornava os valores esperados. em anexo vou colocar as saídas.

o esp32 pode ser compilado pela ide do arduíno, então e praticamente o mesmo código.

Eu não sou especializado em programação de micros, então tenho um pouco de dificuldade em entender as modificações que fez no código, entendo que escreveu parte do código para que eu modifique no código completo.

Vou testar com as suas modificações no código.  

A maquina e uma pavan zanetti unijet 250V. porem e uma maquina reformada pela empresa maquinjet, ou seja, não preserva nada de seu esquema elétrico de fabrica. não e nem o mesmo plc.

 

agradeço muito pela sua ajuda.

 

Captura de tela 2021-06-14 083902.png

Captura de tela 2021-06-14 083927.png

Link para o comentário
Compartilhar em outros sites

Participe agora da conversa!

Você pode postar agora e se cadastrar mais tarde. Se você tiver uma conta, faça login para postar com sua conta.

Visitante
Responder

×   Você colou conteúdo com formatação.   Restaurar formatação

  Apenas 75 emoticons máximos são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir apenas como um link

×   Seu conteúdo anterior foi restaurado.   Limpar o editor

×   Você não pode colar imagens diretamente. Envie ou insira imagens do URL.

SOBRE O ELETRÔNICABR

EletrônicaBR é o melhor fórum técnico online, temos o maior e mais atualizado acervo de Esquemas, Bios e Firmwares da internet. Através de nosso sistema de créditos, usuários participativos têm acesso totalmente gratuito. Os melhores técnicos do mundo estão aqui!
Técnico sem o EletrônicaBR não é um técnico completo! Leia Mais...
×
×
  • Criar Novo...