Problemas con LCD (Arduino)

Hola.
Tengo problemas al momento de imprimir números en el display lcd, ya que cuando pongo un número grande, por ejemplo el 10000 y después imprimo otro, por ejemplo 253, los ceros del otro número se quedan y me imprime 25300
Ya lo intenté borrar con el comando lcd.clear() y solo provoca que el lcd parpadeé y no muestra ningún dato.
¿Cual será el error?
 
Última edición por un moderador:
Hola.
Tengo problemas al momento de imprimir números en el display lcd, ya que cuando pongo un número grande, por ejemplo el 10000 y después imprimo otro, por ejemplo 253, los ceros del otro número se quedan y me imprime 25300
Ya lo intenté borrar con el comando lcd.clear() y solo provoca que el lcd parpadeé y no muestra ningún dato.
¿Cual será el error?
Ese problema es muy común al mostrar cantidades sin formato en la pantalla.
No sé de programación en Arduino, pero para que eso no suceda debes asignar cuantos dígitos se deben mostrar conforme al tamaño del tipo de variable que estés usando.

Es decir, si usas una variable del tipo Byte (255) debes mostrar 3 dígitos (000)
Por lo tanto, si el resultado es 12, se verá en pantalla 012 y así no tendrás problemas con los números que hayan sido escritos anteriormente en la pantalla.
Lo mismo se debe hacer para otro tipo de tamaño de variables.
Por ejemplo, una variable de 16 Bits (0 a 65535) que tiene 5 dígitos, el número 12 se mostrará como 00012

En C de CCS para hacer lo que te menciono sería de esta forma:
printf(lcd_putc,"Resultado: %05LU",Mi_Variable);

Donde 05 son los ceros a mostrar como formato en pantalla y LU es Long Unsigned Integer. (Tipo de variable)

De esta forma ya no tienes por qué estar borrando la pantalla y evitas el parpadeo.

Suerte.
 
Última edición:
Proba escribiendo una logica que haga que el LCD se limpie solo si el dato nuevo es distinto del anterior.

Si el LCD todavia parpadea mucho, podes limpiar el display solo si el dato nuevo es distinto del anterior en algun porcentaje que te resulte comodo para tu aplicacion.
 
Es raro que no te funcione el LCD clear, a mí nunca me ha dado ningún problema. Igual poniendo algún delay entre dato y dato...

Si no, prueba a poner lcd.write("\f Palabra"), es lo que usamos en el CCS también para limpiar la pantalla completa, he probado en el arduino y no lo he puesto en la lcd, pero compila bien.
 
Hola intenta con un "if" que cuando el valor sea menor que un numero de 4 o 5 digitos te imprima en el lugar o posicion de los "0" te imprima " " (nada). No se si me entendiste.
 
Hola gente, les comento que estoy haciendo un programita con un arduino uno porque se quemo el micro de mi estación de soldado, ya pude hacer andar todo, pero tengo un problema con el lcd.
Como la bomba de aire es de 220 tengo que hacer un pwm sincronizado con la fase para que ande bien, pero mi problema es que cuando refresco el lcd demora mucho y me hace saltos en el pwm, mi consulta es si se puede hacer algo para que el print de la librería del lcd no me demore tanto tiempo.

Desde ya muchas gracias
 
Hola gente, les comento que estoy haciendo un programita con un arduino uno porque se quemo el micro de mi estación de soldado, ya pude hacer andar todo, pero tengo un problema con el lcd.
Como la bomba de aire es de 220 tengo que hacer un pwm sincronizado con la fase para que ande bien, pero mi problema es que cuando refresco el lcd demora mucho y me hace saltos en el pwm, mi consulta es si se puede hacer algo para que el print de la librería del lcd no me demore tanto tiempo.

Desde ya muchas gracias

No depende tanto del LCD sino de tu esquema de ejecución de código (me lo anoto como tema para un próximo video :D).

En este caso hay una tarea de alta prioridad (pwm sincronizado) y una de baja prioridad (actualizar el LCD).
Hablo de tareas pero no hace falta matar el mosquito con un cañon como usar un RTOS ni nada de eso.

Una posibilidad es ejecutar tu tarea de alta prioridad en una rutina de interrupción, por ejemplo, la interrupción de un timer o el cruce por cero de la tensión a sincronizar vía interrupción de puerto.

Si lo planteamos en código:

PHP:
void main (void) {
    //Inicialización etc etc, activar la interrupción de tarea prioritaria

    while(1) {
        //Tarea de baja prioridad:
        LcdPrintf("bla bla bla");
    }
}

//Funcion llamada por interrupción o directamente copiar el cuerpo a la ISR
void TareaPrioritaria(void) {
    cicloTrabajo = algunaCuentaMuyComplicadaQueDesconozco;
    SetearPWM(cicloTrabajo);
}

Si es posible o no hacer algo así, no podría decirlo sin más información, ¿te puede servir algo así?
 
si, claro me recontra sirve, yo de hecho estaba haciendo todo lo contrario, por lo que entiendo lo ideal seria usar la interrupcion en la pata que tengo para detectar el cruce por 0 y en esa interrupcion hacer lo de el pwm y el resto en el eje central del programa, no?.
porque yo estaba poniendo lo del cruce en el eje del programa y un timer con el refresco del lcd.
ahora hago lo que me decis y lo subo, igualmente aca te paso el programa que me trae problemas, esta un poco complicado porque no lo comentarie

PHP:
#include <LiquidCrystal.h>
#include <TimerOne.h>
#include <Wire.h>
#include <PID_v1.h>
#include <string.h>

#define boton_down 2
#define boton_up 1
#define boton_set 16
#define face 3
#define FanHotGun 4
#define Rele 5
#define HotGun 6
#define Lapiz 7
#define tiempo2 1
#define rebotes 10

int cantidad_rebotes_up=0;
int cantidad_rebotes_down=0;
int cantidad_rebotes_set=0;
int estado_actual = 0;
int estado_anterior = 0;
int estado_set =0;
int estado_up = 0;
int estado_down = 0;
int estado_set_a =0;
int estado_up_a = 0;
int estado_down_a = 0;
int estado = 0;
int tiempo1 = 00;
int periodo = 0;
float multiplo= 0.828;
float suma= 0;
float porse =0;
int temp1=0;
int temp2=0;
int flag_set_a=0;
int flag_up_a=0;
int flag_down_a=0;
int flag_set=0;
int flag_up=0;
int flag_down=0;
int conteo_timer =0;
int modo_set =0;
int conteo_modo=0;
int pistola_on =0;
int temperatura_p =350;
int temperatura_s =300;
LiquidCrystal  lcd(8, 9, 10, 11, 12, 13);
int barrido=1;
int boton_a=0;
int boton_b=0;
int fun_on=1;


void setup() 
{
        pinMode(face, INPUT);
        pinMode(boton_down, INPUT);
        pinMode(boton_up, INPUT);
        pinMode(boton_set, INPUT);
        pinMode(FanHotGun, OUTPUT);    //FanHotGun
        pinMode(HotGun, OUTPUT);    //FanHotGun
        periodo = pulseIn(face, LOW);
        periodo = periodo / 2;
        lcd.begin(16, 2);
        digitalWrite(HotGun, HIGH);
        delay(500);
        tiempo1 = periodo;
        Timer1.initialize(10000);
        Timer1.attachInterrupt(pantalla);
}

void pantalla ()
{   
        
        
        String temperatura1 = String (temp1);
        String temperatura2 = String (temp2);
        String temperaturaSoldador = String (temperatura_s);
        String temperaturaPistola = String (temperatura_p);
        String aire = String((tiempo1-periodo)/200);
        
        
        
        switch(modo_set)
        {
          case 0:
          {
             String renglon1 = String("S C:" + temperatura1);
             String renglon2 = String("P C:" + temperatura2 + "AIRE:" + aire);
             
             lcd.setCursor(0, 0);
             lcd.print(renglon1);
             lcd.setCursor(0, 1);
             lcd.print(renglon2);
             break;
          }
          case 1:
          {
             String renglon1 = String("Soldador");
             String renglon2 = String("C:" + temperaturaSoldador);
              
             lcd.setCursor(0, 0);
             lcd.print(renglon1);
             lcd.setCursor(0, 1);
             lcd.print(renglon2);
 
             break;
          }
          case 2:
          {
             String renglon1 = String("Pistola");
             String renglon2 = String("C:" + temperaturaPistola);
              
             lcd.setCursor(0, 0);
             lcd.print(renglon1);
             lcd.setCursor(0, 1);
             lcd.print(renglon2);
             break;
          }
          case 3:
          {
             String renglon1 = String("Aire");
             String renglon2 = String("N:" + aire);
              
             lcd.setCursor(0, 0);
             lcd.print(renglon1);
             lcd.setCursor(0, 1);
             lcd.print(renglon2);
             break;
          }
        }

             
}

void teclado ()
{ 
              estado_up = digitalRead(boton_up);
              if (estado_up == 1 && estado_up_a == 1)
              {
                  cantidad_rebotes_up++;
                  if (cantidad_rebotes_up>=rebotes)
                   flag_up_a=1;
                   
              }
              else
              {
                if (flag_up_a == 1)
                {
                  flag_up_a=0;
                  flag_up=1;
                }
                cantidad_rebotes_up=0;
              }
              estado_up_a=estado_up;

              estado_down = digitalRead(boton_down);
              if (estado_down == 1 && estado_down_a == 1)
              {
                  cantidad_rebotes_down++;
                  if (cantidad_rebotes_down>=rebotes)
                    flag_down_a=1;
              }
              else
              {
                if (flag_down_a == 1)
                {
                  flag_down_a=0;
                  flag_down=1;
                }
                cantidad_rebotes_down=0;
              }
              estado_down_a = estado_down;

              estado_set = digitalRead(boton_set);
              if (estado_set == 1 && estado_set_a == 1)
              {
                  cantidad_rebotes_set++;
                  if (cantidad_rebotes_set>=rebotes)
                    flag_set_a=1;
              }
              else
              {
                if (flag_set_a == 1)
                {
                  flag_set_a=0;
                  flag_set=1;
                }
                cantidad_rebotes_set=0;   
              }
              estado_set_a = estado_set;  


              estado_anterior = estado_actual;
              estado_actual = digitalRead(face);
              temp1=analogRead(1);
              temp2=multiplo*analogRead(0)+suma;
}

int leer_teclado ()
{
  int return_tecla=0;
  if (flag_up==1)
  {
    return_tecla=1;
    flag_up=0;
  }
  if (flag_down==1)
  {
    return_tecla=2;
    flag_down=0;
  }
  if (flag_set==1)
  {
    return_tecla=3;
    flag_set=0;
  }
  return (return_tecla);
}



void loop() 
{
  teclado();
  
        if (estado == 0)
        {
            if (estado_actual == 1 && estado_anterior == 0)
            {
                estado_anterior = estado_actual;
                estado = 1;
            }
            if (fun_on==0)
              estado=4;
        }
      
        if (estado == 1)
        {
          noInterrupts();
            delayMicroseconds (tiempo1);
            digitalWrite(FanHotGun, LOW);
            delayMicroseconds (tiempo2);
            digitalWrite(FanHotGun, HIGH);
          
            estado = 2;
        }
        if (estado == 2)
        {
            if (estado_actual == 0 && estado_anterior == 1)
            {
                estado_anterior = estado_actual;
                estado = 3;
            }
            estado_anterior = digitalRead(face);
        }
        if (estado == 3)
        {
           
            delayMicroseconds (tiempo1);
            digitalWrite(FanHotGun, LOW);
            delayMicroseconds (tiempo2);
            digitalWrite(FanHotGun, HIGH);
           interrupts();
            estado = 4;
        }
        if (estado == 4)
        {
          if (pistola_on==1)
          {
              fun_on=1;
              if  (temp2<temperatura_p )
               digitalWrite(HotGun, LOW);
              if  (temp2>temperatura_p)
               digitalWrite(HotGun, HIGH);
          }
          else
          {
              if  (temp2 <= 100)
                fun_on=0;
              tiempo1 = periodo;
              digitalWrite(HotGun, HIGH);
          }
          estado = 5;
        }
        //****************************************************************************botones//
        
        if (estado == 5)
        {
          
          
        
            
         estado = 6;
        }
        if (estado == 6)
        {
          switch (leer_teclado())
          {
              case 1:
                  if (modo_set == 1)
                      temperatura_s = temperatura_s + 10;
                  if (modo_set == 2)
                      temperatura_p = temperatura_p + 10;
                  if (modo_set == 3)
                     tiempo1 = tiempo1 + 200;
                  if (modo_set == 0)
                  {
                    if (pistola_on == 0)
                      pistola_on = 1;
                    else
                      pistola_on = 0;
                  }
                    
               break;
    
               case 2:
                  if (modo_set == 1)
                      temperatura_s = temperatura_s - 10;
                  if (modo_set == 2)
                      temperatura_p = temperatura_p - 10;
                  if (modo_set == 3)
                     tiempo1 = tiempo1 - 200;
               break;
    
               case 3:
                    
                      if (modo_set >= 3)
                        modo_set = 0;
                      else
                        modo_set++;
                    
               break;
          }
          estado = 0;
        }      
}
 
si, claro me recontra sirve, yo de hecho estaba haciendo todo lo contrario, por lo que entiendo lo ideal seria usar la interrupcion en la pata que tengo para detectar el cruce por 0 y en esa interrupcion hacer lo de el pwm y el resto en el eje central del programa, no?.
porque yo estaba poniendo lo del cruce en el eje del programa y un timer con el refresco del lcd.

Claaaaro :D, lo que pasa es que la interrupción siempre tiene prioridad sobre el programa principal. El código viene ejecutando el while(1) del main lo más tranquilo, hasta que llega una interrupción, deja todo lo que está haciendo, y se dedica de lleno a la interrupción.

Es como cuando estás trabajando y te llaman porque tu madre tuvo un accidente... interrumpís/largás todo y vas a ver que pasó hasta saber que está atendida.
Vos lo estabas haciendo como cuando estás mirando el partido del Domingo y la bienamada esposa se poner a contarnos que a fulanito le pasó esto o aquello... a esa interrupción la ignoramos sin problema :LOL:.

Pero no, tu caso es el accidente de mamá, no el anterior.
Eso siempre y cuando las interrupciones estén habilitadas.
Le damos más importancia a setear el pwm porque la línea de 220V no espera a nadie. 50 Hz no parece mucho, pero es un ciclo cada 20ms, no lo hagamos esperar más de algún que otro milisegundo, no?.
En cambio el mensaje en la pantallita... ni vamos a notar si tarda 10, 50, o 100 milisegundos en presentar el mensaje.

... leo el código sin entrar en mucho detalle ...

Aja... bueno, tiene sabor a Arduino no?. No estoy familiarizado con las cosas internas de la librería LCD y PID, pero creo que no es mucho suponer que es todo programación secuencial (que internamente no usan interrupciones y que las funciones retornan solo cuando se completo la función, es decir, no hay llamadas asíncronas).

Me gusta que hayas hecho algo en base a estados :).

Agrego tarea de teclado:

  1. Actualizar PWM con detección de cruce por cero: prioridad más alta.
  2. Leer teclado: que nos gustaría que se ejecute en un intervalo T para no perdernos una pulsación del usuario. Prioridad media
  3. Mostrar el mensaje en pantalla LCD: prioridad baja.
Pero diría que conviene tener solo 2 tareas, teclado y pantalla en el loop(), y seteo de pwm en la interrupción.

Es más, también podría disparar la actualización de teclado y pantalla por interrupción, pero en la rutina de interrupción de actualización de pantalla y teclado seteamos un flag y volvemos bien rápido. De esa forma también podés configurar para que la actualización se haga 10 veces por segundo, o 20 veces por segundo para el teclado y 5 veces por segundo para la pantalla... pero eso último sería agregar un poco de complejidad, por ahora digamos que teclado y pantalla se actualizan 10 veces por segundo al unísono.



La estructura del código podría ser algo como:


PHP:
void setup() {

    //...
    //configurar interrupción de pwm -> puerto de I/O
    //configurar interrupción de teclado y pantalla -> timer

    HabilitarInterrupciones();
}

volatile unsigned int actualizarTecladoPantalla = 0;

void loop (void) {
    if (actualizarTecladoPantalla) {
        actualizarTecladoPantalla = 0;
        teclado(); //lee puertos, actualiza variables de entrada al pid
        
        if(sePresionoAlgunaTecla) {
            RecalcularPID();    //los valores calculados los utiliza la rutina de interrupción de seteo de pwm
        }

        pantalla(); //se imprimen los valores de pantalla
    }

}

void RecalcularPID(void) {
    cicloPWM = cuentaQueLeeValoresSeteadosPorTeclado();
}

void InterrupcionCrucePorCero(void) {
    timerSetearCicloDeTrabajo(cicloPWM);
}

void InterrupcionPorTimerActualizacionTecladoPantalla(void) {
    actualizarTecladoPantalla = 1;
}


No sé si se entiende la idea.
 
Muchas gracias, si es con arduino, porque no me quería poner a fabricar las librerías de un micro, y las librerías que tengo es de un lpc 1769 que es demasiado para esto jaja. Si, gracias a un profesor de la facultad que prácticamente nos pegaba cuando usábamos un while o alguna función bloqueante, me acostumbre a los estados, y la verdad que me encanta. te comento que ya esta andando perfecto y cuando me haga un tiempito junto toda la info y lo subo, porque estuve como 1 semana con un montón de trabajos atascados y tengo que librarme de eso primero.

Muchísimas gracias
 
Atrás
Arriba