ayuda con tft y visualizar distintos menus

Hola, tengo una pantalla tft que funciona muy bien, el tema es que quiero utilizar 3 menus distintos que los habilito mediante un pulsador hasta ahi todo bien. El tema es que al pasar de un menú a otro es como si no actualizara bien los datos y ademas no deja de repetirlos por ej si en el menu2 uso tft.print("hola") ese hola lo repite sobre la pantalla infinitas veces:

 if (n != contador)
  {
    Serial.println(contador);
    n = contador;
  }
  if (contador == 3)
  {
    contador = 0;
  }

switch (contador)
{
  case 0:
         menu1();
         break;
  case 1:
         menu2();
         break;
  case 2:
         menu3();
         break;
}
delay(200);
}

void ServicioBoton()
{
  if (millis() > T0 + 250)
  {
    contador ++;
    T0 = millis();
  }
}

Es decir cuando pasa de menú no deja de repetir por pantalla lo que contenga ese menú, no se si me explico.. :confused:

Y hay que responder con ese extracto de código? Normalmente las impresiones en un tft requieren indicar la posición donde se va a imprimir, en tu código parcial no se ve nada de eso. asi que no puedo resonder Tampoco se que librería estas usando.

Aca subo el código completo, tengo un video en caso de q no se entienda, el tema es que ahora puedo cambiar de menu en menu con un pulsador, pero parpadea la pantalla en cada menú, es como q se actualiza completamente la pantalla como un refresco bastante molesto. ayuda por favor :confused:

#include <SPI.h>
#include <Adafruit_TFTLCD.h>
#include <pin_magic_MEGA.h>
#include <pin_magic_UNO.h>
#include <registers.h>
#include <Adafruit_GFX.h>

#define LCD_CS A3
#define LCD_CD A2
#define LCD_WR A1
#define LCD_RD A0
#define LCD_RESET A4

#define	BLACK   0x0000
#define	BLUE    0x001F
#define	RED     0xF800
#define	GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);

byte dato1,dato2,dato3;
char digitos;
char TX[50];
volatile int contador = 0;
int n = contador;
long T0 = 0;

void setup(){
  
  Serial.begin(9600);
  Serial1.begin(9600);
  pinMode(20,INPUT);
  attachInterrupt(3, ServicioBoton, RISING);
  iniciando();
}  

void loop(){
  
  if(Serial1.available()){
    delay(10);
    digitos = Serial1.read();
  }
  if (digitos == '

){
   
   dato1 = Serial1.parseInt();
   dato2 = Serial1.parseInt();
   dato3 = Serial1.parseInt();
   
 }
 delay(2000); //este delay si lo hago mas chico mas parpadea la pantalla
 if (n != contador)
 {
   Serial.println(contador);
   n = contador;
 }
 if (contador == 3)
 {
   contador = 0;
 }

switch (contador)
{
 case 0:
        valorsensor();
        break;
 case 1:
        valorsensor2();
        break;
 case 2:
        valorsensor3();
        break;
}

}

void iniciando(){
 tft.begin(0x9341);
 tft.fillScreen(BLACK);
 tft.setRotation(3);
 tft.fillRect(0,120,320,20,BLUE);
 tft.fillRect(160,140,20,140,BLUE);
}

void ServicioBoton()
{
 if (millis() > T0 + 250)
 {
   contador ++;
   T0 = millis();
 }
}

void valorsensor()

{
   tft.fillScreen(BLACK);
   tft.setRotation(3);
   tft.fillRect(0,120,320,20,BLUE);
   tft.fillRect(160,140,20,140,BLUE);
   tft.setCursor(10,160);
   tft.setTextSize(2);
   tft.setTextColor(WHITE);
   tft.print(“temperatura”);
   tft.setTextSize(4);
   tft.setTextColor(YELLOW);
   tft.setCursor(120,190);
   tft.drawCircle(110,190,5,YELLOW);
   tft.print(“C”);
   sprintf(TX,"%3d",dato1);  //aca se le da formato a los datos y se almacena en la variable temporal TX
   tft.setCursor(10,190);
   tft.setTextSize(4);
   tft.setTextColor(YELLOW,BLACK);  //En una sola instrucción le das todos los colores a tu presentación: el primero es el color de la fuente y el segundo es el color del fondo de la fuente
   tft.println(TX);
   
   tft.setCursor(200,160);
   tft.setTextSize(2);
   tft.setTextColor(WHITE);
   tft.print(“aceite”);
   tft.setCursor(280,190);
   tft.setTextSize(2);
   tft.print(“psi”);  
   sprintf(TX,"%3d",dato2);
   tft.setCursor(180,190);
   tft.setTextSize(4);
   tft.setTextColor(WHITE,BLACK);
   tft.println(TX);
 
   tft.setCursor(240,60);
   tft.setTextSize(3);
   tft.setTextColor(RED);
   tft.print(“RPM”);
   sprintf(TX,"%3d",dato3);  
   tft.setCursor(30,30);
   tft.setTextSize(7);
   tft.setTextColor(RED,BLACK);  
   tft.println(TX);  
 
}

void valorsensor2()
{
   tft.fillScreen(BLACK);
   tft.setRotation(3);
   tft.setCursor(10,30);
   tft.setTextSize(4);
   tft.setTextColor(YELLOW,BLACK);
   tft.print(“temperatura”);
   tft.setTextSize(6);
   tft.setTextColor(YELLOW,BLACK);
   tft.setCursor(190,120);
   tft.drawCircle(180,120,5,YELLOW);
   tft.print(“C”);
   sprintf(TX,"%3d",dato1);  //aca se le da formato a los datos y se almacena en la variable temporal TX
   tft.setCursor(50,120);
   tft.setTextSize(6);
   tft.setTextColor(YELLOW,BLACK);  //En una sola instrucción le das todos los colores a tu presentación: el primero es el color de la fuente y el segundo es el color del fondo de la fuente
   tft.println(TX);
   
 
}

void valorsensor3()
{
 
 tft.fillScreen(BLACK);
 tft.setCursor(100,100);
 tft.setTextColor(BLUE,BLACK);
 tft.print(“fin”);
}

perdon la desprolijidad del video, pero estaba apurado.

Video.mpg (612 KB)

Modifiqué tu sketch para simular el cambio del botón mecánico que tienes, con el icono-libro que tiene prediseñado la pantalla TFT que tengo, es una ILI9325, (de hecho se puede usar toda la pantalla tactil o cualquier otro de los iconos prediseñados, solo fué un experimento). Me tomó un rato calibrar los parametros de la táctil para ajustarlos a las dimensiones de la pantalla. La calibración funciona la para la rotacion 3, para otras rotaciones hay que ajustar estas lineas:

   X = map(p.y, TS_MINX, TS_MAXX, tft.width(), 0);
    Y = map(p.x, TS_MAXY, TS_MINY, tft.height(), 0);

y por prueba y error ajustar estos parámetros:

short TS_MINX = 68; 
#define TS_MAXX 950  
short TS_MINY = 170; 
#define TS_MAXY 890

Volviendo al tema: cuando la variable contador cambia, debes detectar ese cambio y cargar un refresco de pantalla cuando eso ocurra, antes de pasar al menu siguiente. Mientras contador no se modifique, la pantalla no se refrescará y mantendrá estable la ventana en uso.

Quité el acceso al hardware que estás monitoreando por el puerto serie1 del MEGA. En su lugar los datos se generan de forma aleatoria y el icono-casa lo uso como selector tactil.

Programa modificado

|500x298 Las bandas oscuras que se observan sobre el marco azul provienen de un defecto en la pantalla que tengo, algunos colores no se muestran correctamente.

Este es el video para que veas que no se produce el refresco frecuente de la pantalla

PD:

Si no me equivoco estás usando la libreria modificada Adafruit TFTLCD, para que el shield funcione en el MEGA directamente.

Si no es así, te recomiendo que desinstales estas librerias: SD, Adafruit TFTLCD, TouchScreen, e instales las que están en la página del link.

Quería ver porque casi nadie usa la pantalla táctil de este tipo de shields-TFT, incluso para mí es algo nuevo, pensé que mi TFT era completamente inservible XD. Creo que subiré al post información de como crear menus con este tipo de pantallas

q laburo te mandaste TFTLCDCyg la verdad felicitaciones! ahora voy a probar algunos consejos q me diste el tema es que la libreria SD por ejemplo la necesito porque hago captura de datos y los vuelco a una memoria, no uso el panel táctil (aunque tu ejemplo me va a servir para futuros proyectos gracias) utilizo un boton para desplazarme por los menús, voy a ver que puedo hacer y te comento!! una vez mas gracias. :)

Agregue las lineas q me sugeriste para que cuando cambie de menu haga un "refresco" de pantalla con la funcion fillScreen(BLACK) y sin embargo no sirve para mi ejemplo sigue parpadeando...para mi viene por otro lado pero no se me ocurre todavia.

Estoy seguro que viene mas por el lado del codigo en si y no de las librerias, ya que antes no me parpadeaba la pantalla, todo empezo cdo agregue las lineas del swich-case para los distintos menúes.

en esta parte del codigo:

void loop(){
  
  if(Serial1.available()){
    delay(10);
    digitos = Serial1.read();
  }
  if (digitos == '

ahi me parece q esta mi problema porque recibo datos por el puerto serie1 todo el tiempo, y el delay ese que figura si no lo uso me parpadea mucho mas rapido la pantalla... >:(){         dato1 = Serial1.parseInt();     dato2 = Serial1.parseInt();     dato3 = Serial1.parseInt();    
  }   delay(1000); //este delay si lo hago mas chico mas parpadea la pantalla ```

ahi me parece q esta mi problema porque recibo datos por el puerto serie1 todo el tiempo, y el delay ese que figura si no lo uso me parpadea mucho mas rapido la pantalla... >:(

Hola. No he mirado muy a fondo tu problema pero prueba a ver moviendo la llave de cierre del if(Serial1.available()){ hasta justo antes del delay (que englobe al propio switch/case, vamos).

Noter acabo de probar tu sugerencia de mover la llave del if(Serial1.available()) englobando al switch-case y sigue aun el problema del parpadeo :confused:

Pon el código actual completo, a ver si vemos algo.

Es el mismo que subi mas arriba, igual lo vuelvo a subir:

#include <SPI.h>
#include <Adafruit_TFTLCD.h>
#include <Adafruit_GFX.h>

#define LCD_CS A3
#define LCD_CD A2
#define LCD_WR A1
#define LCD_RD A0
#define LCD_RESET A4

#define	BLACK   0x0000
#define	BLUE    0x001F
#define	RED     0xF800
#define	GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);

byte dato1,dato2,dato3;
char digitos;
char TX[50];
volatile int contador = 0;
int n = contador;
long T0 = 0;

void setup(){
  
  Serial.begin(9600);
  Serial1.begin(9600);
  pinMode(20,INPUT);
  attachInterrupt(3, ServicioBoton, RISING);
  iniciando();
}  

void loop(){
  
  if(Serial1.available()){
    delay(10);
    digitos = Serial1.read();
  }
  if (digitos == '

){
   
    dato1 = Serial1.parseInt();
    dato2 = Serial1.parseInt();
    dato3 = Serial1.parseInt();
   
  }
  delay(2000); //este delay si lo hago mas chico mas parpadea la pantalla
  if (n != contador)
  {
    Serial.println(contador);
    n = contador;
  }
  if (contador == 3)
  {
    contador = 0;
  }

switch (contador)
{
  case 0:
        valorsensor();
        break;
  case 1:
        valorsensor2();
        break;
  case 2:
        valorsensor3();
        break;
}

}

void iniciando(){
  tft.begin(0x9341);
  tft.fillScreen(BLACK);
  tft.setRotation(3);
  tft.fillRect(0,120,320,20,BLUE);
  tft.fillRect(160,140,20,140,BLUE);
}

void ServicioBoton()
{
  if (millis() > T0 + 250)
  {
    contador ++;
    T0 = millis();
  }
}

void valorsensor()

{
    tft.fillScreen(BLACK);
    tft.setRotation(3);
    tft.fillRect(0,120,320,20,BLUE);
    tft.fillRect(160,140,20,140,BLUE);
    tft.setCursor(10,160);
    tft.setTextSize(2);
    tft.setTextColor(WHITE);
    tft.print(“temperatura”);
    tft.setTextSize(4);
    tft.setTextColor(YELLOW);
    tft.setCursor(120,190);
    tft.drawCircle(110,190,5,YELLOW);
    tft.print(“C”);
    sprintf(TX,"%3d",dato1);  //aca se le da formato a los datos y se almacena en la variable temporal TX
    tft.setCursor(10,190);
    tft.setTextSize(4);
    tft.setTextColor(YELLOW,BLACK);  //En una sola instrucción le das todos los colores a tu presentación: el primero es el color de la fuente y el segundo es el color del fondo de la fuente
    tft.println(TX);
   
    tft.setCursor(200,160);
    tft.setTextSize(2);
    tft.setTextColor(WHITE);
    tft.print(“aceite”);
    tft.setCursor(280,190);
    tft.setTextSize(2);
    tft.print(“psi”); 
    sprintf(TX,"%3d",dato2);
    tft.setCursor(180,190);
    tft.setTextSize(4);
    tft.setTextColor(WHITE,BLACK);
    tft.println(TX);
 
    tft.setCursor(240,60);
    tft.setTextSize(3);
    tft.setTextColor(RED);
    tft.print(“RPM”);
    sprintf(TX,"%3d",dato3); 
    tft.setCursor(30,30);
    tft.setTextSize(7);
    tft.setTextColor(RED,BLACK); 
    tft.println(TX); 
 
}

void valorsensor2()
{
    tft.fillScreen(BLACK);
    tft.setRotation(3);
    tft.setCursor(10,30);
    tft.setTextSize(4);
    tft.setTextColor(YELLOW,BLACK);
    tft.print(“temperatura”);
    tft.setTextSize(6);
    tft.setTextColor(YELLOW,BLACK);
    tft.setCursor(190,120);
    tft.drawCircle(180,120,5,YELLOW);
    tft.print(“C”);
    sprintf(TX,"%3d",dato1);  //aca se le da formato a los datos y se almacena en la variable temporal TX
    tft.setCursor(50,120);
    tft.setTextSize(6);
    tft.setTextColor(YELLOW,BLACK);  //En una sola instrucción le das todos los colores a tu presentación: el primero es el color de la fuente y el segundo es el color del fondo de la fuente
    tft.println(TX);
   
 
}

void valorsensor3()
{
 
  tft.fillScreen(BLACK);
  tft.setCursor(100,100);
  tft.setTextColor(BLUE,BLACK);
  tft.print(“fin”);
}

¿Has probado tu loop así?

void loop(){

  if(Serial1.available()){
    delay(10);
    digitos = Serial1.read();
    if (digitos == '

){

      dato1 = Serial1.parseInt();       dato2 = Serial1.parseInt();       dato3 = Serial1.parseInt();          }     delay(2000); //este delay si lo hago mas chico mas parpadea la pantalla     if (n != contador)     {       Serial.println(contador);       n = contador;     }     if (contador == 3)     {       contador = 0;     }

    switch (contador)     {       case 0:       valorsensor();       break;       case 1:       valorsensor2();       break;       case 2:       valorsensor3();       break;     }   } } ```

Si noter ya lo probé de esa forma y sigue el flickeo...

encontre un error, en cada funcion de los distintos menú yo encabezaba con un tft.fillScreen() entonces refrescaba continuamente, ya lo elimine de cada menú y funciona.

agregue en esta línea (como me sugeria TFTLCDCyg) agregar el refresco cuando cambia la variable contador me quedo asi esa parte:

if (n != contador)
    {
      Serial.println(contador);
      n = contador;
      tft.fillScreen(BLACK);
    }

y funciona bien pero a veces se me superponen los menu y eso si q no se porque será..

Tu programa tiene un eje, y ese es un número que solo tiene 4 valores 0,1, 2 y 3

0 da como resultado el menu 1 1 da como resultado el menu 2 2 da como resultado el menu 3 3 debe regresar a 0 y da como resultado el menu 1

Debes considerar que la impieza general de pantalla solo ocurre cuando el número cambia su valor, mientras se mantenga constante, la limpieza no debe ocurrir.

En tu caso cada menu tiene como primer acción la limpieza de la pantalla, esto hace que aunque el número se mantenga constante, la pantalla sufra una limpeza general cada vez que compara el valor con el switch case

En mi opinión tu problema lo puedes resolver con el ejemplo arduino blink without delay

Debes tener una variable que almacene el tanto valor actual como el valor previo del contador, si la diferencia entre ambos es mayor a cero, debe ocurrir una limpieza general de pantalla, si la diferencia es igual a cero la limpieza no debe ocurrir.

PD: te sugiero que dibujes un arbol lógico que represente tu programa. Con eso no necesitaras de un experto y nosotros, los humildes aficionados, te pediremos consejos XD