No logro "limpiar" el display TFT

Pues estoy fabricando una pantalla de leds para un acuario de 500 litros, que controlando 3 circuitos de leds de alta potencia haga el efecto de amanecer y anochecer, por la noche el efecto luz de luna, registre la temperatura ambiente, la temperatura del agua y la temperatura de los leds para activar un grupo de ventiladores de 12v (mantener la temperatura de los leds por debajo de los 35 o 40 grados), y a través de una pantalla TFT muestre el estado de los diferentes mecanismos, pero con un interruptor con resistencia pull down pueda apagar la pantalla de datos para mostrar solo una pantalla negra con un reloj digital.

El problema es que al pasar de una pantalla a otra no logro borrar la pantalla previa, y al hacer el cambio se sobreescribe una pantalla sobre la anterior.

He intentado diferentes maneras, con condicionales if, con while, no logro que se borre el display antes de dibujar el otro.

El sketch (que aún no he terminado porque me falta el control de temperaturas y ventiladores) es ahora mismo bastante extenso, voy a poner dos fragmentos, espero que me puedan ayudar. En caso necesario pongo todo el sketch.

El siguiente (al principio del loop) es el condicional que según el estado del interruptor dibuja una pantalla u otra, y no logro que borre la pantalla una vez, sino que borra intermitentemente la pantalla un par de veces por segundo (y la redibuja):

 if (digitalRead(InterruptorTFT) == HIGH)       //Interruptor pull down cerrado 
    {
      if (x == 0)                                            //La variable viene declarada desde el inicio con valor cero
       {tft.fillScreen(TFT_NEGRO);   x = 1;}     //Para que limpie la pantalla una sola vez
        DibujarTFT("Datos", TFT_NEGRO);        //Dibuja los datos de funcionamiento
    }
  else                                         //Interruptor pull down abierto 
    {
      if (y == 0) //La variable viene declarada desde el inicio con valor cero
       {tft.fillScreen(TFT_NEGRO);   y = 1;}     //Para que limpie la pantalla una sola vez
        DibujarTFT("Reloj", TFT_NEGRO);         //Dibuja un reloj analógico sobre fondo negro
    }

La variable invocada es la siguiente:

void DibujarTFT(int Pantalla, int ColorFondo)
{
  if (Pantalla == "Datos")                            //Dibuja la pantalla de datos generales de funcionamiento
 { tft.setTextColor(TFT_VIOLETA, TFT_NEGRO);              //Para dibujar la hora (centro superior del Display)
    tft.setTextSize(2); tft.setCursor(180,7);                      //Tamaño y posición de los dígitos de la hora
  if (RTC.hour < 10) {tft.print("0");}
    tft.print(RTC.hour);tft.print(":");
  if (RTC.minute < 10){tft.print("0");}
    tft.print(RTC.minute);tft.print(":");
  if (RTC.second < 10){tft.print("0");}
    tft.print(RTC.second);
    tft.setTextSize(1);                                                          //Volver al tamaño de texto normal.
    tft.drawLine(0,0,0,479, TFT_VERDE);                                //linea vertical izquierda
    tft.drawLine(479,0,479,479, TFT_VERDE);                         //linea vertical derecha
    tft.drawLine(0,0,479,0,TFT_VERDE);                                 //línea Horizontal superior
    tft.drawLine(0,28,479,28,TFT_VERDE);                             //línea Horizontal siguiente
    tft.drawLine(0,319,479,319,TFT_VERDE);                         //línea Horizontal inferior
    tft.setTextColor(TFT_VERDE, TFT_NEGRO); 
    tft.drawString("Temperatura  Ambiente : ", 5,33, 4);
    tft.drawString("Temperatura   del  Agua : ", 5,62, 4);
    tft.drawString("Temperatura de los Leds: ", 5,91, 4);
    tft.drawString("Alimentador  Derecho (12:00 / 18:00 Hs.)", 5,120, 4);
    tft.drawString("Alimentador Izquierdo (13:00 / 19:00 Hs.)", 5, 149, 4);
    tft.drawLine(0,177,479,177,TFT_VERDE);                          //línea Horizontal divisoria del Display
    tft.setTextColor(TFT_CYAN, TFT_NEGRO);
    tft.drawString("Mecanismos en Funcionamiento",60,183,4);
    tft.setTextColor(TFT_ROJO, TFT_NEGRO);
    if (RTC.hour >=22 || RTC.hour <10)                           //Desde las 10 de la noche a las 10 de la mañana 
     {//tft.fillRect(5,218,360,7,TFT_ROJO);
      tft.drawString("Leds Azules al  ",5,218,4);                         // "Luz de Luna"
      tft.setTextSize(2);    tft.setCursor(170,223);                    //Tamaño de texto similar al resto
      tft.print(EstadoLedsAzules * 100 / 255); tft.setTextSize(1);     //Calcula el porcentaje de intensidad luminosa
      tft.drawString("%  ",200,218,4);} 
    else 
     {tft.drawString("Intensidad de Leds al",5,218,4);                   //Fuera de ese horario nocturno
      tft.setTextSize(2);    tft.setCursor(250,223);                       //Tamaño de texto similar al resto
      tft.print(EstadoLedsBlancos * 100 / 255);                           //Porcentaje de intensidad de leds blancos
      tft.setTextSize(1);                                                              //Volver al tamaño de texto normal
      tft.drawString("%  ",280,218,4); }      
    tft.setTextColor(TFT_ROJO, TFT_NEGRO);
    tft.drawString("Ventiladores Apagados              ",5,252,4); 
    tft.setTextColor(TFT_ROJO, TFT_NEGRO);
    /*Lo siguiente son condicionales para escribir en el Display el estado de los Alimentadores Automáticos
    *(izquierdo y derecho) activado dos veces al día cada uno de manera automática y manualmente con dos 
    *pulsadores pull down:
    */
     if (digitalRead(PulsadorDcho) == HIGH)     {tft.drawString("Alimentador  Derecho  Encendido    ",5,284,4);}
    else if (digitalRead(PulsadorIzq) == HIGH) {tft.drawString("Alimentador  Izquierdo Encendido   ",5,284,4);}
    else                             {tft.drawString("Alimentadores Apagados                       ",5,284,4);}}
 else                                            //Dibuja una pantalla de fondo negro con un reloj digital
  {
    tft.setTextColor(TFT_VERDE, TFT_NEGRO);
    tft.setTextSize(9); tft.setCursor(80,120);
  if (RTC.hour < 10) {tft.print("0");}
    tft.print(RTC.hour);tft.print(":");
  if (RTC.minute < 10){tft.print("0");}
    tft.print(RTC.minute);tft.print(":");
  if (RTC.second < 10){tft.print("0");}
    tft.print(RTC.second);
    tft.setTextSize(1);
  }
}

El resultado que obtienes está causado por la forma en la que has programado tu proyecto. El manejo mediante todas las condicionantes desde el loop principal es muy complicado y a veces da resultados que no queremos.

Adicionalmente no es conveniente que trates de controlar todos los componentes en una sola pantalla. Mi sugerencia es que separes cada diseño de pantalla en funciones independientes, capaces de funcionar cada una por separado. Simplifica tu proyecto en acciones simples, por ejemplo:

  • encender/apagar iluminación principal
  • encender/apagar dosificador
  • encender/apagar sistema de limpieza

Cada acción puede convertirse en una pantalla independiente.

MP
Menu 1
Menu 2
Menu 3

El diseño de cada menú se puede crear en base a este esquema general, por ejemplo la función Menu X:

Menu X
{
  Instrucciones que se ejecutan sólo una vez al cargar la pantalla del menú

  while(1)
  {
    Instrucciones en ciclo relacionadas al menú actual

    Condición de salida a menú principal
    Condición para cambio de menú
    Condición de salida a menú secundario
  }
}

El uso de ciclos continuos no solo está controlado por la función void loop(){}, también los podemos obtener desde el setup, a través de funciones preparadas como Menu X

void setup() {
  MP();
}

void loop() {}  //puede quedarse así


void MP(){
  Instrucciones que se ejecutan sólo una vez al cargar la pantalla del menú

  while(1)
  {
    Instrucciones en ciclo relacionadas al menú actual

    Condición de salida a menú principal
    Condición para cambio de menú
    Condición de salida a menú secundario
  }
}

void Menu1(){
  Instrucciones que se ejecutan sólo una vez al cargar la pantalla del menú

  while(1)
  {
    Instrucciones en ciclo relacionadas al menú actual

    Condición de salida a menú principal
    Condición para cambio de menú
    Condición de salida a menú secundario
  }
}

void Menu2(){
  Instrucciones que se ejecutan sólo una vez al cargar la pantalla del menú

  while(1)
  {
    Instrucciones en ciclo relacionadas al menú actual

    Condición de salida a menú principal
    Condición para cambio de menú
    Condición de salida a menú secundario
  }
}

Ante todo gracias por responder. No sé si he entendido totalmente, pero llevo un rato meditando y he sacado alguna conclusión (lo mismo equivocada) y varias dudas.

Creo entender que el problema de no lograr borrar la pantalla al pasar de una a otra es que la función está en el void loop() y aunque pongo condicionales que se ejecutan una sola vez, el ciclo vuelve a repetirse contínuamente y esa es la causa que la pantalla se "limpie" y vuelva a redibujarse de manera indefinida.

Entonces, se trata de crear una función dentro del setup, en el cual por ejemplo en una primera pantalla se enseñe un menú con las dos o tres pantallas de datos que quiera mostrar, cada una será una función que también dibujará la pantalla con el dato seleccionado. ¿Si?

En mi caso como la TFT no es táctil tendría que colocar por ejemplo 2 o 3 pulsadores para seleccionar la pantalla que quiero observar.

Las dudas (y probablemente están explicadas en tu mensaje, lo que sucede es que seguramente no las he entendido) es que independientemente de la pantalla secundaria que elija, tiene datos que van cambiando como la temperatura de los leds, que vá subiendo en minutos y al llegar a un umbral se activarán los ventiladores para bajarla en los minutos siguientes, todo eso hay que "redibujarlo", ahora mismo no alcanzo a ver cómo (lo mismo hoy noche con la almohada me entero, jaja).

En el void loop() supongo que pondría todos lo procesos que se deben realizar de forma contínua, como los registros y cálculos de temperaturas, los cálculos para visualizar el reloj, el registro del estado de los pines de entrada (pulsadores, que iban a ser tres y ahora serían cuatro o cinco), pero digamos que son todos los procesos que se manejan en cualquier programa Arduino, mientras que los procesos que controlan el display ván "por otro lado".

Espero no aburrirte, tenme un poco de paciencia, jajaja

Y que librería usas y qué modelo de pantalla. Hubiese sido mejor que presentaras todo el código y no parcialmente.

surbyte:
Y que librería usas y qué modelo de pantalla.
Hubiese sido mejor que presentaras todo el código y no parcialmente.

Las librerías incluidas:

#include <TFT_HX8357.h>
TFT_HX8357 tft = TFT_HX8357();
#include <SoftwareSerial.h>
#include <Wire.h>
#include <DS1307new.h>
#include <TimeLib.h>

En cuanto a la pantalla:

Display TFT

En relación a poner todo el sketch, ahora mismo lo estoy cambiando siguiendo los consejos de TFTLCDCyg.

Pero pongo el sketch como está hasta ahora en archivos adjuntos.

A propósito siguiendo a TFTLCDCyg, supongo que será correcto utilizar pulsadores para moverrse por los menús?

Sketch Pantalla.doc (41.5 KB)

Pantalla_Inteligente_Acuario.ino (12.4 KB)

Estoy atascado, bloqueado.
He hecho un sketch de prueba (quitando los controles de luces, de temperaturas, etc…), solo con las opciones de mostrar la hora en un menú inicial (a modo de menú inicial).
La TFT no es táctil (320x480 y 3,2’), así que he colocado 4 pulsadores pull down para moverme por los menús.
No comprendo bien cómo moverme entre menús, cómo salir.
Pongo el sketch:

#include <TFT_HX8357.h>
TFT_HX8357 tft = TFT_HX8357();       // Invoke custom library
#include <SoftwareSerial.h>
#include <Wire.h>
#include <DS1307new.h>
#include <TimeLib.h>

SoftwareSerial mySerial(18, 19); //RX, TX
uint16_t startAddr = 0x0000;            // Start address to store in the NV-RAM
uint16_t lastAddr;                             // new address for storing in NV-RAM
uint16_t TimeIsSet = 0xaa55;            // Helper that time must not set again
//·························Los Pulsadores para las opciones del Menú·······························
const int Pulsador1 = 54;      const int Pulsador2 = 55;   
const int Pulsador3 = 56;     const int Pulsador4 = 57; 
 //···································Define los colores···················································
#define GRIS         0x5AEB           //MÁS COLORES EN:
#define NEGRO    0x0000        // http://www.barth-dev.de/online/rgb565-color-picker/
#define BLANCO 0xFFFF
#define AZUL       0x001F
#define ROJO       0xF800
#define VERDE    0x07E0
#define CYAN       0x07FF
#define MAGENTA 0xF81F
#define AMARILLO 0xFFE0
#define NARANJA 0xFC00
#define VIOLETA 0xFCFD
//······································Variables para no utilizar delay()····················
unsigned long MillisPrevias    = millis();
unsigned long MillisAnteriores = millis();
//****************************************************************************************
void setup() 
{  
  ConfigurarSetup(); 
  MenuPrincipal(); 
}
//****************************************************************************************
void loop() 
{ 
  RelojPuertoSerie();                        //Salida por puerto serie de la hora y la fecha
}
//****************************************************************************************
void RelojPuertoSerie()                   //Muestra la hora en el puerto serie
{ unsigned long MillisActuales = millis();
  if ((MillisActuales - MillisPrevias) >= 950)  //Espera un poco menos de 1 segundo
  {MillisPrevias = MillisActuales;  
  RTC.getTime();     
  if (RTC.hour < 10)    {Serial.print("0");   Serial.print(RTC.hour, DEC);} 
  else    {Serial.print(RTC.hour, DEC); }
  Serial.print(":");
  if (RTC.minute < 10)  {Serial.print("0"); Serial.print(RTC.minute, DEC); }
  else    {Serial.print(RTC.minute, DEC);  }
  Serial.print(":");
  if (RTC.second < 10)  {Serial.print("0");  Serial.print(RTC.second, DEC); }
  else    {Serial.print(RTC.second, DEC);}
  Serial.print(" ");
  if (RTC.day < 10)     {Serial.print("0"); Serial.print(RTC.day, DEC);}
  else    {Serial.print(RTC.day, DEC); }
  Serial.print("-");
  if (RTC.month < 10)   {Serial.print("0"); Serial.print(RTC.month, DEC); }
  else    {Serial.print(RTC.month, DEC);}
  Serial.print("-");     Serial.print(RTC.year, DEC);     Serial.println(" ");}}
//****************************************************************************************
void ConfigurarSetup()
{ Serial.begin(115200);  mySerial.begin(115200);
   pinMode(Pulsador1, INPUT);          pinMode(Pulsador2, INPUT);          
   pinMode(Pulsador3, INPUT);          pinMode(Pulsador4, INPUT);
   digitalWrite(Pulsador1, LOW);       digitalWrite(Pulsador2, LOW);    
   digitalWrite(Pulsador3, LOW);       digitalWrite(Pulsador4, LOW);  
   if (mySerial.available()) {Serial.write(mySerial.read());}
   if (Serial.available())   {mySerial.write(Serial.read());}
   tft.init(); tft.setRotation(1);     tft.fillScreen(NEGRO);
}
//****************************************************************************************
void MenuPrincipal()                               //Display Negro con reloj digital en el centro de la pantalla
 { tft.fillRect(0,0,480,360,NEGRO);       //Rectángulo de toda la pantalla
   tft.setTextColor(VIOLETA, NEGRO);
   tft.setTextSize(2); tft.setCursor(180,7); 
  while(1)
 { 
  unsigned long MillisActuales = millis();
  if ((MillisActuales - MillisAnteriores) >= 950)  //Espera un poco menos de 1 segundo
  {MillisAnteriores = MillisActuales;  }
   RTC.getTime();
//························Dibuja el marco de Pantalla·························   
    tft.setTextSize(1);
    tft.drawLine(0,0,0,479, VERDE);     //linea vertical izquierda
    tft.drawLine(479,0,479,479, VERDE); //linea vertical derecha
    tft.drawLine(0,0,479,0,VERDE);      //línea Horizontal superior
    //tft.drawLine(0,28,479,28,VERDE);    //línea Horizontal siguiente
    tft.drawLine(0,319,479,319,VERDE);  //línea Horizontal inferior
//························Dibuja el Reloj Digital en el centro·················    
    tft.setTextColor(VERDE, NEGRO);
    tft.setTextSize(8); tft.setCursor(80,120);
  if (RTC.hour < 10) {tft.print("0");}
    tft.print(RTC.hour);tft.print(":");
  if (RTC.minute < 10){tft.print("0");}
    tft.print(RTC.minute);tft.print(":");
  if (RTC.second < 10){tft.print("0");}
    tft.print(RTC.second);
    tft.setTextSize(1);
}}
//****************************************************************************************

Alguna guía para seguir, como decía más arriba, para salir del menú, moverme entre menús con los pulsadores…

Parece que este es tu comando para limpiar pantalla

tft.fillScreen(TFT_BLACK);

No, si el problema no es poner la pantalla en negro, mi dificultad es más en los comandos o sitios para salir de un menú determinado permitiendo al mismo tiempo que los procesos del loop() se sigan ejecutando. Por ejemplo he hecho menús cada uno correspondiendo a una función desde el setup() y entonces dentro de la función un condicional que cuando se cumple, por ejemplo: si un pulsador está en alto, con una orden return(MenuPrincipal) se vuelve al menú principal pero como los menús están fuera del loop() no logró ejecutar el código que está en el loop()

@Alberto perderas el tiempo.

Tu pantalla es ILI9341 ... mi debilidad. Esta son unas autenticas basura de pantallas (por no decir otro adjetivo calificativo). De lo contrario que te lo diga @TFTLCDCyg, donde vi que ha drede destrozo una.jejejeje

La libreria que estas usando para esa pantalla, por cierto la peor.

Usa la UTFT.

Si quieres no complicarte la vida, y no perder tiempo, cada uno sabe el oro que vale, y mas si te queda poco tiempo de vida (no mi caso) pero porque complcarse la vida cuando hay otras opciones?

Pantallas basadas en GPU FT81xxQ. La solución final. No hay otras.

Las pantallas "que GRAFICAN" usan por lo general un;

while(1) {
tu códdigo de menus}

o bien

do {
aqui tu código}
while(1);

Es la unica forma de representar menus, y salir de ellos (siempre que dispongas si la pantalla es tactil o a nivel de botones), y esto ya hace tiempo, precisamente @TFTLCDCyg me enseñó.

@TFTLCDCyg es muy grande, gran programador de pantallas, el mejor que he leido y te dió la pista.

Hechale un vistazo a un video mio con NODEMCU 1.0 y veras los códigos de como pasar de una pantalla a otra como si fuese un libro que vas pasando paginas.

Saludos. :)

La clave es que cada menú del sketch pueda funcionar de forma independiente: borrado de pantalla, ciclo continuo. Para convertirlo en interactivo solo hay que agregar una rutina de salto al menú siguiente en tiempo real.

Cuando no se cuenta con un TFT con pantalla táctil, el uso de pulsadores es buena idea, sin embargo a veces las “variables bandera” las podemos perder de visto, si no ponemos atención en la secuencia de uso, volviéndose en contra como parece que te está ocurriendo. Mi sugerencia es que mejor uses un encoder, es bastante simple de usar de forma directa, sin recurrir a librerías complicadas.

El ejemplo siguiente usa un encoder, un arduino Due y una pantalla ILI9341 de 2.2" sin táctil

#include <SPI.h>

#include "ILI9341_due_config.h"
#include "ILI9341_due.h"
#include "SystemFont5x7.h"
#include "fonts\Arial_bold_14.h"

// For the Adafruit shield, these are the default.
#define TFT_RST 8
#define TFT_DC 9
#define TFT_CS 10

ILI9341_due tft = ILI9341_due(TFT_CS, TFT_DC, TFT_RST);

// Color set
#define  BLACK           0x0000
#define RED             0xF800
#define GREEN           0x07E0
#define BLUE            0x102E
#define CYAN            0x07FF
#define MAGENTA         0xF81F
#define YELLOW          0xFFE0 
#define ORANGE          0xFD20
#define GREENYELLOW     0xAFE5 
#define DARKGREEN       0x03E0
#define WHITE           0xFFFF

uint16_t  color;
uint16_t  colorFONDO = BLACK;

// Pines de lectura del encoder
int a = 45;  //CLK
int b = 47;  //DT

// Valores de medida del encoder
int anterior = 1;
int contador;

int Cuenta=0, Cambio=1;

int Dial=0;
char TX[25];

void setup() {
     Serial.begin (9600);
     pinMode (a,INPUT);
     pinMode (b,INPUT);
  tft.begin();
  tft.setRotation(iliRotation180);
  tft.fillScreen(colorFONDO);
  //tft.setFont(SystemFont5x7);
  tft.setFont(Arial_bold_14);
  //tft.setTextLetterSpacing(4);
  MP();
}

void loop() {}



void MP()
{
  tft.fillRect(0, 0, 240, 320, RED);
  tft.setTextColor(WHITE, RED);
  tft.printAlignedOffseted(F("MP"), gTextAlignTopCenter, 0, 5);

  while(1)
  {
    LeeEncoder();
 
    sprintf(TX,"Encoder = %d", Dial);
    tft.setTextColor(WHITE, RED);
    tft.printAlignedOffseted(F(TX), gTextAlignTopCenter, 0, 75);
    //tft.printAt(TX,25,70);

    if(Dial==5){M1();}
    if(Dial==10){M2();}
    
    Cuenta=Cuenta + Cambio;
    if(Cuenta>=100){Cambio=-1;}
    if(Cuenta<=0)  {Cambio= 1;}
    tft.printAt("Cuenta =",25,150);
    sprintf(TX,"%4d", Cuenta);
    tft.setTextColor(WHITE, RED);
    tft.printAlignedOffseted(F(TX), gTextAlignTopCenter, 0, 150);
    
  }
}


void M1()
{
  tft.fillRect(0, 0, 240, 320, BLACK);
  tft.setTextColor(WHITE, BLACK);
  tft.printAlignedOffseted(F("M1"), gTextAlignTopCenter, 0, 12);

  while(1)
  {
    LeeEncoder();
 
    sprintf(TX,"Encoder = %d", Dial);
    tft.setTextColor(WHITE, BLACK);
    tft.printAlignedOffseted(F(TX), gTextAlignTopCenter, 0, 75);
    //tft.printAt(TX,25,70);

    if(Dial==10){M2();}

    Cuenta=Cuenta + Cambio;
    if(Cuenta>=100){Cambio=-1;}
    if(Cuenta<=0)  {Cambio= 1;}
    tft.printAt("Cuenta =",25,150);
    sprintf(TX,"%4d", Cuenta);
    tft.setTextColor(WHITE, BLACK);
    tft.printAlignedOffseted(F(TX), gTextAlignTopCenter, 0, 150);
  }
}

void M2()
{
  tft.fillRect(0, 0, 240, 320, BLUE);
  tft.setTextColor(WHITE, BLUE);
  tft.printAlignedOffseted(F("M2"), gTextAlignTopCenter, 0, 19);

  while(1)
  {
    LeeEncoder();
 
    sprintf(TX,"Encoder = %d", Dial);
    tft.setTextColor(WHITE, BLUE);
    tft.printAlignedOffseted(F(TX), gTextAlignTopCenter, 0, 75);
    //tft.printAt(TX,25,70);

    if(Dial==5){M1();}
    if(Dial==15){MP();}

    Cuenta=Cuenta + Cambio;
    if(Cuenta>=100){Cambio=-1;}
    if(Cuenta<=0)  {Cambio= 1;}
    tft.printAt("Cuenta =",25,150);
    sprintf(TX,"%4d", Cuenta);
    tft.setTextColor(WHITE, BLUE);
    tft.printAlignedOffseted(F(TX), gTextAlignTopCenter, 0, 150);
  }
}


int mul;

void LeeEncoder()
{
  int actual = digitalRead(a);
   if (actual != anterior){     
     if (digitalRead(b) != actual) { 
       contador ++;
     } else {
       contador --;
     }
     Serial.print("Position: ");
     Serial.println(contador);
     Dial=contador;
   } 
   anterior = actual;
}

Cada menú, tiene una sección de instrucciones que se ejecutan una vez, y una sección que se ejecuta de forma contínua, en ella se puede colocar la función que monitorea en tiempo real el movimiento del encoder. El salto al siguiente menu se consigue cuando el valor de salida del encoder es igual a un valor fijo predefinido.

En este caso los puntos de salto son:

5  Menú 1
10 Menú 2
15 Menú principal

Tu pantalla usa instrucciones similares a las del ejemplo, así que se puede convertir fácilmente. Afortunadamente estas usando una librería bastante optimizada como la ILI9341_due que usé, así que el refresco de pantallas entre cada menu debería ser muy rápido.

PD: ligthcalamar quizás te refieras a esta imagen XD…

TFTLCDCyg:
PD: ligthcalamar quizás te refieras a esta imagen XD…

Esa, esa, esa con dos cojones bien cortada el flexo para jamas volver a funcionar. jejejeje que asco de ILI9341.

Por cierto @Alberto localiza el foro del canguro, y veras que no tiene despedicios, el canguro y su tropa en hablar y rendir como santo de evoción la ILI9341.

Gracias a ambos (lightcalamar y TFTLCDCyg) por responder (y a surbyte que aproveche sus merecidas vacaciones, jeje).

Tu pantalla es ILI9341 ... mi debilidad. Esta son unas autenticas basura de pantallas (por no decir otro adjetivo calificativo). De lo contrario que te lo diga @TFTLCDCyg, donde vi que ha drede destrozo una.jejejeje

Ya, si me sucede muy frecuentemente, como comprando a los chinos a veces tardan hasta 2 meses en llegar la compra, y tienen esos precios imbatibles, pues COMPRÉ TRES, así que ahora a apechugar, espero no terminar guardándolas... en la basura.

Usa la UTFT.

No, si me espera "cambiar de caballo en mitad del río" varias veces antes de llegar, espero, a buen puerto.

Cuando no se cuenta con un TFT con pantalla táctil, el uso de pulsadores es buena idea, sin embargo a veces las "variables bandera" las podemos perder de vista, si no ponemos atención en la secuencia de uso, volviéndose en contra como parece que te está ocurriendo. Mi sugerencia es que mejor uses un encoder, es bastante simple de usar de forma directa, sin recurrir a librerías complicadas.

Pregunta: Supongo que la "variable bandera" será la que alude a la variable que según su valor abre un menú u otro.

En relación al encoder, como le respondía más arriba a lightcalamar, una imagen vale más que mil palabras:

Culpa de los chinos terminaré con un sindrome de Diógenes, acumulando basura...

Por cierto @Alberto localiza el foro del canguro, y veras que no tiene despedicios, el canguro y su tropa en hablar y rendir como santo de evoción la ILI9341.

Parece que lo han cerrado, están en facebook, pero no entro en facebook, buscaré más por google.

Una última pregunta, perdonar si es ridícula, pero ¿TODOS los procesos los hacen dentro del while de cada menú? ¿el loop() queda vacío?, en caso contrario ¿cómo "llamar al loop()"?

No hace falta para nada el loop @Alberto

Te descargastes el ejemplo de mi video? Como bien te dijo @TFTLCDCyg el uso de los pulsadores es buen opción para “parar” el loop "virtual " (el while). Aun así puedes crear una función a cada pulsador para salir del bucle.

En caso de las tactiles, lo hace un boton grafico y esto no tiene comparación. De hecho no se necesita nada, solo acoplar tus modulos I2C, serie etc …

A cada “pantalla” o función tiene su while, puedes navegar por las paginas a tu antojo, es una tecnica que aprendí de @TFTLCDCyg y desde luego es otro mundo, en C lei un comentario que dicen es programación “anidada” puedes crear tantas “pantallas” como te permita la capacidad de la flassh de la MCU.

Si te sirve de algo he aquí una 4,3 pulgadas 4.3 Graphical LCD Touchscreen, 480x272, SPI, FT800 [FT800CB-HY43B] - US $25.00 : HAOYU Electronics : Make Engineers Job Easier por unos 20€ y si quieres resolucion 800x600 en una hermosa pantalla de 5 pulgadas sería esta;

5 Graphical LCD capacitive touch screen, 800x480, SPI, FT811 [FT811CB-HY50HD] - US $38.00 : HAOYU Electronics : Make Engineers Job Easier por unos 30 y algo de €, sson caras, pero las mejores. No hay otras.

Ser propietario de una de estas pantallas es algo que no se experimenta hasta cuando la tienes en tus manos.

El loop principal queda sin uso. La ventaja de ello es que liberas a todos los menús para que funcionen de forma independiente entre sí, creando procesos continuos que no se enlazan o quedan anclados.

Las pantallas que hemos decidido usar algunos colegas y un servidor, no se programan como las pantallas que todo mundo usa en sus proyectos arduino: ILI, Oled, ST775, HX, etc. El chip que incluyen solo es un driver que permite controlar los pixeles de la pantalla a un nivel muy (pero muy) básico y requieren de genios en lenguaje C para poder usar mejoras como DMA, por ejemplo.

Son buenos puntos de partida para aprender el uso de TFT, pero ya te has dado cuenta por la cantidad de pulsadores que has conseguido; que este hobbie evoluciona muy rápido, empiezas con un led y una resistencia y después quieres tener un robot que te traiga el café :slight_smile:

Desafortunadamente en el camino van quedando componentes que por una u otra razón ya no los consideras relevantes y tendrás que reservar un cajón para almacenarlos.

No es complicado cambiar el paradigma de uso del IDE, solo es cuestión de que te familiarices con el manejo de funciones independientes, tal y como están diseñadas todas las librerías que podemos usar en Arduino.

El ejemplo tiene todos los elementos para que consigas adaptar tu proyecto, creo que será muy fácil de trasladar a las instrucciones de la librería que estás usando para tu pantalla.

Hablando de limpieza de pantalla al cambiar de menús; video: capacidades gráficas del FT800
Video: control de menús FT813+STM32
Video: apagadores en FT800

El sonido que se escucha en el último video, corresponde al procesador de audio simple que incluyen los chips FT8XX, solo hay que usar un amplificador y un parlante, incluso se puede conectar a la entrada de audio de la placa base de la PC.

PD: cómo te has podido dar cuenta, las pantallas que hemos decidido usar algunos aficionados, están basadas en los chips FT8XX e impulsadas por variantes de la librería gameduino 2/3, creada por el gurú: James Bowman

INCREIBLE!! FUNCIONA!!!! :) :) :) :) :) :) :) :) :)

Hasta ahora no hubiese imaginado un programa sin instrucciones en el loop(), JAJA!!

Bueno, he hecho un par de pantallas, cada una correspondiente a una función con su while(1). Por ahora los pulsadores funcionan bien.

Ya veo que en nada me volveré loco con las TFT, jajaja Culpa de TFTLCDyg y lightcalamar (es broma)

Ahora viene la inclusión de los procesos que hasta ahora colocaba dentro del loop(), entiendo que poniéndolos dentro de funciones que se invocarán dentro de los while(1) de cada menú, incluso supongo que se podrá crear una función "suma de funciones que se ejecutarían en el loop()" para invocarla dentro del bucle de cada menú o función gráfica.

Bueno, a currar el fin de semana...

PD: Cuando empecé con Arduino, hará un par de años, posteé un proyecto que aún lo tengo aparcado, para hacer un controlador de acuarios, y compré una TFT táctil de 7", lo mismo cuando tenga solventado este proyecto de iluminación de acuario, me pongo con esa pantalla, que la tengo guardadita, y cada tanto la miro con cierto respeto, como diciendo ¿y esto como se comerá?

|500x285

Otra pregunta: Es útil ir utilizar al mismo tiempo el puerto serie? Es decir, ir escribiendo mensajes con los eventos que se van produciendo? Tengo entendido que ralentiza los procesos. ¿Lo utilizan?

No afecta gran cosa, siempre y cuando no tengas alguna instrucción o condicional que esté vinculada al funcionamiento del monitor serie y desees independizar de la PC tu proyecto.

No hay consumo de recursos apreciables, estamos hablando de algunos valores intermedios que deseas conocer al realizar alguna acción con el hardware.

Si ya cuentas con un TFT, esos valores puedes omitirlos en el monitor serie y los puedes enviar a tu pantalla, incluso puedes eliminarlos por completo.

En la placa Core7XXI y una F429ZI-DISCO que estoy usando en el proyecto actual, no tengo salida al monitor serie, si tengo duda con algún valor intermedio de alguna variable bandera o variable de control, simplemente incluyo algunas instrucciones para mostrar dichos valores en pantalla.

Este es un ejemplo con una brújula digital, todos los parámetros pueden verse en pantalla sin usar el monitor serie:

Brújula digital

PD: una muestra más del poder gráfico de estas pantallas :), falta ajustar la orientación correcta del sensor y del dial de la carátula, me centré principalmente en las gráficas lineales continuas de los tres vectores, un par de correcciones matemáticas en el ángulo son suficientes

Llevo desde hace dos días arrastrando un problema que no sé resolver.

Al display TFT ese chungo chino (chino chungo, jaja) no táctil, le he puesto dos pulsadores pull down que son los que controlarán el encendido manual de los dos alimentadores del acuario, y un interruptor, también con una resistencia de 10K pull down que cuando está abierto (es decir el pin correspondiente que es el 54 o A0 en baja) muestre una pantalla negra con un reloj digital en el centro.
He comprobado con multímetro el pin del interruptor (A0) y vá bien.

Cuando el interrutor esté cerrado cambia a la segunda (y última pantalla) en la cual se muestran los estados de los distintos sistemas y mecanismos (por ahora solo los alimentadores automáticos que se conectan dos veces al día y pueden activarse manualmente mediante los dos pulsadores).

Pero no sé qué estoy haciendo mal que las pantallas se observan parpadeantes, es decir que se redibujan contínuamente, me tiene frito…

Pongo el sketch en archivo adjunto porque pone que excede los 9000 caracteres, lo mismo es una tontería pero no sé resolverlo.

Pantalla_Acuario.ino (8.83 KB)

Pues después de perder todo el fin de semana y un montón de horas ante el ordenador pude resolver la manera de salir de un menú y entrar en otro sin problema.

Como ponía en respuestas anteriores, con algunas alternativas salía de un menú pero al entrar en otro redibujaba contínuamente la pantalla con un efecto parpadeante o salía de un menú e inmediatamente volvía al anterior.

Por si a alguien puede serle de utilidad pongo el sketch que no me funcionaba, incluso por si alguien pueda explicarme porqué no funcionaba, porque yo no lo entiendo:

[code]
 MenuX   
 { 
      Procesos que se realizan una sola vez
      while(1)
     {
         Procesos que se tienen que repetir hasta que se cumpla la condición de salida
          if (estado del pin cumple la condición)
             {
                  MenuY(); (ó return MenuY;)     //Entra en el otro menú
              }
     }
 }

[/code]

Y finalmente de esta manera funciona:

[code]
 MenuX   
 {  
     Procesos que se realizan una sola vez
     int x = estado del pin 
     while(x cumple la condición)
     {
         Procesos que se tienen que repetir hasta que se cumpla la condición de salida
         x = estado del pin     //Colocado al final del bucle while antes de volver a comprobar la condición en el while
      } 
          MenuY(); (ó return MenuY;)      //Ya fuera del while. Entra en el otro menú
 }

[/code]