Algunos consejos para usar TFT´s

Perdón si te pareció fuera de lugar, sólo quería saber para el uso que iba a darle yo que pantallas de recomendaban. Pero ya he decidido, me he comprado una nextion y probaré a ver qué tal. Mi intención no era comprarme la mejor pantalla del mercado que es de lo que hablan la mayoría de hilos, ni de pantallas súper hd con buenas velocidades si no cogerme algo bueno, bonito y barato sin llegar a llenarme de papeles. Aumente volví a postear por hacer un Up al hilo que ya había cambiado a la página 2.

Ojalá y que cuando te llegue la pantalla que has optado por usar en tus proyectos, nos des a conocer tus impresiones, ya sea en este hilo o bien en un nuevo post en el foro; ya que a mas de un forero he visto que le interesan ese tipo de pantallas.

La idea es que sea más fácil para todos programar otro tipo de pantallas, nos ayudaría bastante a conocer otras alternativas; ya que igual he menospreciado la capacidad de esos TFT.

No dudes que lo haré TFTLCDyg, tus comentarios los he leído todos pero voy a muchos años luz de tus experimentos con TFT's. Espero que para lo que yo necesito que es muuuuy simple esta pantalla de el pego, estaba por pillarme una china de esas de 4€ hasta que leí todos los comentarios de líos de librerías y montones de fallos. Creo que eso es lo importante de esta comunidad, la experiencia conjunta y el no repetir errores.

arkarash:
hasta que leí todos los comentarios de líos de librerías y montones de fallos. Creo que eso es lo importante de esta comunidad, la experiencia conjunta y el no repetir errores.

Por ello hemos escrito, para que no repetir errores.
A estos errores, hemos invertido mucho dinero para daros a conocer otros horizontes.

Por cierto, yo tengo una Nextion de 7 pulgadas, y de momento la tengo en el cajón(no para abandonarla) pero es una HMI sin futuro y ademas mas complicada de programar que una FT81x. te lo escribo, por que tengo de ambos tipos, y donde esten las FTDI, que guarden cola las demas para hacerles sombra

Ya tengo la Nextion, de momento la experiencia es buena, con el software de Nextion he conseguido fácilmente crear una interfaz para mi botonera a base de imagenes PNG y sustitución de partes de la imagen al pulsar. Gracias a todos por los consejos, me han servido para encontrar una buena opción.

Sobre las pantallas FTDI, se por vuestros comentarios que son mucho mejores que las Nextion pero como ya dije necesitaba una pantalla simple y barata para hacer simplemente un teclado de clave de acceso. Vamos que no lo iba a sacar el jugo con gráfricas ni nada que mereciese la pena el gasto. Sin duda me las miraré para proyectos de más envergadura que tengan más interfaz gráfico.

Hola.

Antes de nada daros las gracias por compartir vuestra gran afición y horas invertidas en aclarar estos temas.

Soy Informático, desde hace muchos años, y al final el tiempo te enseña que lo mejor es utilizar estándares que utilice una mayoría para desarrollar productos y no morir en el intento.

Ahora tengo que hacer un proyecto con arduino, donde soy novato, para controlar emisiones de luz RGB parametrizando valores sencillos desde una pantalla TFT, en principio con controles estándar como botones, "slider-bar", cajas de texto, "scroll-bar", "progress-bar", etc.

La pregunta es, qué TFT táctil me aconsejáis que utilice en torno a 3" o mayor, dado que el tamaño no es problema, pero que me complique lo mínimo, que sea si es posible un shield, de arduino uno en principio, que tenga librerías de programación lo más extendidas y sencillas posible aunque potentes y que no de problemas.

Gracias

Hola , muy bueno tu aporte. estoy teniendo problemas por que la pantalla está en blanco. EL programa es el siguiente, lo tomé de tu ejemplo TFT_Menu. El driver al parecer es ILI9341. ya no se que hacer he intentado de todo. es una pantalla tft con sd de 2.2" de 240x320.

#include "Adafruit_GFX.h"  
#include "Adafruit_TFTLCD.h" 
#include "SD.h"              
#include "SPI.h"             
#include "TouchScreen.h"     

#define YP A1 
#define XM A2 
#define YM 7 
#define XP 6 

//Rotacion 3
short TS_MINX = 68; // Controla el final de eje X del lado derecho en rotacion 3
#define TS_MAXX 950  //Controla el inicio de eje X del lado izquierdo en rotacion 3  // no contenpla los botones prediseñados 1-318
short TS_MINY = 170; // inicio Eje  Y
#define TS_MAXY 890  //   fin Eje Y  
//Rotacion 3

#define MINPRESSURE 1
#define MAXPRESSURE 1000
// Instancia del panel tactil (Pin XP, YP, XM, YM, Resistencia del panel) 
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 364); 

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

#if defined __AVR_ATmega2560__ 
#define SD_SCK 13              
#define SD_MISO 12  
#define SD_MOSI 11
#endif

#define SD_CS 10  
Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, 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
uint16_t  color;

int X, Y, Z; 
int deltaTactil = 10 ; //ajuste tactil-x en botones de diseño, por el uso de iconos prediseñados la tactil es unos 10/12 px mas grande que el TFT

char imagesOnSDCard1[8][30]={"Foff.bmp","Fon.bmp","6oB.bmp","6oH.bmp","6oI.bmp","ico9.bmp","ico7.bmp","La1.bmp"};
unsigned char imagenSD1 = 1;
char TX[50];

//iconos prediseñados
///////acá yo los saque a propósito por que no los uso. aparte me daba error por que me decía que el programa era muy largo y me excedía de la capacidad, estoy usando Android 1.8.7

void setup()
{
tft.reset();
tft.begin(0x9325);
tft.fillScreen(0);
Serial.begin(9600);

#if defined __AVR_ATmega2560__               
if (!SD.begin(SD_CS, SD_MOSI, SD_MISO, SD_SCK )) 
{
  tft.println(F("failed!"));   
  return;
}
#else
if (!SD.begin(SD_CS)) {
  tft.println(F("failed!"));
  return;
}
#endif
tft.setRotation(3); 
//MenuP();
}

void loop(){
delay(1000);
 bmpDraw("6oB.bmp",140,220);        
  delay(2000);
  bmpDraw("6oH.bmp",170,220);   }

emilts:
Hola.

Antes de nada daros las gracias por compartir vuestra gran afición y horas invertidas en aclarar estos temas.

Soy Informático, desde hace muchos años, y al final el tiempo te enseña que lo mejor es utilizar estándares que utilice una mayoría para desarrollar productos y no morir en el intento.

Ahora tengo que hacer un proyecto con arduino, donde soy novato, para controlar emisiones de luz RGB parametrizando valores sencillos desde una pantalla TFT, en principio con controles estándar como botones, "slider-bar", cajas de texto, "scroll-bar", "progress-bar", etc.

La pregunta es, qué TFT táctil me aconsejáis que utilice en torno a 3" o mayor, dado que el tamaño no es problema, pero que me complique lo mínimo, que sea si es posible un shield, de arduino uno en principio, que tenga librerías de programación lo más extendidas y sencillas posible aunque potentes y que no de problemas.

Gracias

Hace un tiempo que no pasaba por el post, espero que mi respuesta no llegue demasiado tarde.

Recientemente he visto una versión de 3.2" de pantallas SPI ILI9341 (320x248 px), es el tope en tamaño para ese controlador. Es de lo mejor en cuanto a si necesitas buena respuesta gráfica al manejar múltiples instrucciones.

Desafortunadamente la parte táctil deja mucho que desear ya que el chip no ha sido actualizado, se sigue empleando el XPT2046 o equivalente. Quizás por mantener el costo final del producto bajo o bien por un elevado stock de ese chip en las empresas que fabrican el TFT.

Existen pantallas un poco más grandes con chips ILI9488 de 3.5" (480x320 px), el formato es idéntico al de las ILI9341, usan el chip táctil XPT2046, sin embargo el controlador de pantalla es la actualización directa del chip ILI9341.

Ambas versiones son TFT´s relativamente grandes.

Si tu presupuesto te lo permite te recomendaría pantallas FT813 de 3.5" o de 4.3", NHD tiene pantallas de este tipo con doble conector: un cabezal de 20 pines y un zócalo para cable plano de 20 pines.

danielpaz88:
Hola , muy bueno tu aporte. estoy teniendo problemas por que la pantalla está en blanco. EL programa es el siguiente, lo tomé de tu ejemplo TFT_Menu. El driver al parecer es ILI9341. ya no se que hacer he intentado de todo. es una pantalla tft con sd de 2.2" de 240x320...

Bueno primero que nada felicidades por intentar un proyecto diferente. Te prevengo: habrá varias conexiones fallidas, pero ya diste el primer paso.

Veo en la foto que has compartido, que usas un cableado bastante largo, procura que el tamaño total de cada hilo no supere los 15 cm.

Las resistencias deben estar conectadas en forma de divisor de voltaje 5V/3.3V para cada línea de control de la pantalla, excepto para VCC y GND. Si te es posible consigue un chip CD4050BE, te ahorrará dolores de cabeza.

La mejor librería que puedes usar es esta

Hola, soy jose y soy nievo en esto de las pantallas tft, a ver si podeis ayudarme porque ando muy perdido y nadie me hecha un cable, queria empezar por algo sencillo, encender y apagar un rele desde un icono el la pantalla tft. No se por donde empezar, os agradezco de antemano vuestra ayuda.

JOSEBERMUDEZ:
Hola, soy jose y soy nievo en esto de las pantallas tft, a ver si podeis ayudarme porque ando muy perdido y nadie me hecha un cable, queria empezar por algo sencillo, encender y apagar un rele desde un icono el la pantalla tft. No se por donde empezar, os agradezco de antemano vuestra ayuda.

Esto del hobby con arduino implica que inviertas parte de tus ahorros en las piezas que quieres usar y antes que nada soy muy respetuoso con ese tema. Para empezar, te podría recomendar 6 o 7 opciones de TFT, pero quizás terminarás por sustituir por algo mucho mejor, por eso antes de opinar al respecto, me gustaría precisar algunas ideas.

Como siempre he dicho, mis opiniones son imparciales respecto a los fabricantes: si me sirve un TFT lo usaré en el proyecto, sino, irá directo al cajón de cosas sin usar y no lo recomendaré más, simplemente para evitar dolores de cabeza.

Bajo esta premisa, me he topado con piezas que han resultado algo costosas, pero que no he vuelto a usar, porque el TFT luego de un tiempo de uso muestra alguno que otro defecto. Sin olvidar el tiempo invertido en la curva de aprendizaje de la librería de control; que en varias ocasiones me ha retrasado el proyecto principal.

Ahora bien, en tu comentario veo que quieres un TFT con panel táctil con capacidad para gestionar imágenes. En ese sentido es mejor que te alejes de los TFT con táctil resistivo, el tema de cableado, calibración y sensibilidad dan paso a muchos problemas.

Los TFT con táctil capacitivo son de lejos la mejor opción.

Desafortunadamente la tecnología capacitiva está poco documentada en arduino y el universo de pantallas está muy reducido. Además el costo de este tipo de pantallas supera com mucho los 3 o 4 USD de las pantallas resistivas.

El complemento al TFT que quieres es el manejo de imágenes. Aquí necesitarás un lector micro SD para el manejo de archivos; esto ayudará que tu código consuma poca memoria en la placa de control o MCU

Otro aspecto a considerar es un buen MCU: muchos pines y capacidad para gestionar con librerías todo el hardware que quieres en tu proyecto.

Verás en internet demasiados proyectos muy bien logrados, pero no todo lo que dicen está documentado, el trasfondo implica que el dueño del proyecto pasó infinidad de horas creando sus propias librerías y que no siempre están dispuestos a compartir, quizás porque tienen un negocio detrás que deben cuidar...

El formato de la pantalla es importante: es mejor usar pantallas con pocos hilos de control y con cableado corto hacia el MCU.

Por varias razones y proyectos de trabajo me he alejado algún tiempo. Sin embargo he retomado algunos pendientes que dejé por falta de tiempo. No creo conveniente abrir un nuevo hilo, con la idea de que lo ya avanzado le sirva a los nuevos exploradores.

Menu simple en el TFT ILI9488 conectado a un teensy 4.x

En esta ocasión me centraré en la pantalla ILI9488 de 3.5" y su manejo con el teensy 4 o 4.1. La versión de pantalla será la SPI, por la comodidad de usar poco cableado; es similar físicamente a la versión SPI del chip ILI9341.

Para fines prácticos quiero usar la libreria ILI9488_t3, la libreria XPT2046_Touchscreen para el manejo del chip XPT2046, y para el manejo de imagenes BMP, me inclino por la libreria SdFat beta2, ya que con ella podemos usar el lector SDIO del teensy 4.x. No he visto ejemplos en la red con esta configuración; por lo aprendido en este tiempo con la librería SdFat beta, creo que es muy factible conseguir con algunos ajustes dentro del sketch acceder a la carga de imagenes BMP desde el lector SDIO. Tengo curiosidad por ver como se desmpeña.

Hasta ahora la libreria URTouch solo ha funcionado en el teensy 3.6, pero en el teensy 4.x no muestra progresos. He intentado varios ajustes pero sin resultados.

Componentes

  • TFT ILI9488 3.5", SPI
  • Teensy 4
  • Lector de 4 bits externo conectado a los pads SDIO del teensy 4.
  • MicroSD de 32 Gb
  • PCB de doble cara de 15x10 cm
  • Cabezales de 40 pines hembra
  • Hilos provenientes de un cable plano de 40 pines, de aquellas interfaces para dispositivos PC-IDE de hace algunos años

PD: por el momento le dejo aquí ya que tengo que ir a conectarlo todo, construir el lector externo con un adaptador microSD-SD Kingston que vi por algún cajón acumulando pelusas y tomar algunas fotos del resultado

Tras algunos intentos, por fin funciona el adaptador microSD-SD

El pinout es

Un acercamiento al teensy 4

Por fin he podido conectar la pantalla, se me fueron "los ojos" en la soldadura de cada pad del lector SDIO... toca hacer las primeras pruebas con la librería, pero ya es algo tarde en estos momentos, la dejaremos para mas tarde.

Hace unos meses hice las primeras pruebas, pero por alguna razón el adaptador previo daba algunos errores, posiblemente alguno de los pads del adaptador no estaba unido correctamente o quizás se dañó.

¿Cómo es que debemos configurar SdFat beta?

Greiman recientemente actualizó la librería SdFat beta, para darle soporte al teensy 4. En esta placa podemos instalar un lector externo microSD en SPI1.

También podemos instalar un lector externo mediante conexionado de 4 bits; en este caso, usaremos los ajustes con el segundo conexionado.

Primero debemos descargar la librería SdFat beta del repositorio oficial. Podemos instalarla en la carpeta de librerías del core teensy, en esta ruta:

C:\arduino-1.8.13\hardware\teensy\avr\libraries

De esta forma, cuando hagamos referencia a la librería SdFat beta con la placa teensy 4, la primer librería que va a consultar es la que tiene en la carpeta de librerías del core, aunque en el núcleo de librerías del IDE de arduino, exista otra versión.

Una vez instalada la memoria microSD en el adaptador, hay que verificar que funcione con SdFat beta.

Para ello podemos usar directamente los ejemplos: SdInfo o bech.

SdInfo

bench

Tomando como base cualquiera de los ejemplos, podemos extraer las lineas que nos permitirán usar el lector SDIO.

En el encabezado hacemos referencia a la librería SdFat. Debemos considerar dos aspectos: el constructor y el iniciador de la tarjeta.

Hay varios constructores para llamar a la tarjeta microSD:

#if SD_FAT_TYPE == 0
SdFat sd;
File file;
#elif SD_FAT_TYPE == 1
SdFat32 sd;
File32 file;
#elif SD_FAT_TYPE == 2
SdExFat sd;
ExFile file;
#elif SD_FAT_TYPE == 3
SdFs sd;
FsFile file;

Cada uno puede manejar diferentes características y clases dentro de la librería

1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT

En los documentos de referencia de la librería, se detallan estos aspectos con alcances y limitaciones para cada familia de placas y tipos de memorias SD.

En este caso podemos usar este constructor:

SdFat sd;

Respecto al iniciador, la librería SdFat beta considera 4 opciones, dos para lector en modo SDIO y dos para lector en modo SPI

sd.begin(SdioConfig(FIFO_SDIO))
sd.begin(SdioConfig(DMA_SDIO))
sd.begin(SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SD_SCK_MHZ(50)))
sd.begin(SdSpiConfig(SD_CS_PIN, SHARED_SPI, SD_SCK_MHZ(50)))

El ejemplo en el que podemos usar cada uno de estos iniciadores es: TeensySdioDemo. Estos son los resultados:

DMA_SDIO


totalMicros 43815939
yieldMicros 29389566

FIFO_SDIO


totalMicros 6623219
yieldMicros 335822

Entonces, el mejor iniciador que podemos usar es:

sd.begin(SdioConfig(FIFO_SDIO))

Combinando el constructor y el iniciador, podemos crear un ejemplo para verificar el funcionamiento de la tarjeta micro SD en el lector SDIO

#include "SdFat.h"

SdFat SD;

void setup() {
  Serial.begin(9600);
  while (!Serial){;}
  
  Serial.print("Initializing SDIO card...");
  if (!SD.begin(SdioConfig(FIFO_SDIO))) {
      Serial.println("failed!");
    return;
  }
  Serial.println("OK!");
}
void loop(){}

PD: toca el turno a la librería ILI9488_t3

La librería ILI9488_t3

Esta librería está pensada para las placas teensy 4.x, con algunos ajustes menores puede funcionar con las placas teensy 3.6/.35/3.2 y la librería URTouch. Es posible usar un lector microSD en paralelo al cableado SPI de la pantalla. En el caso de las placas 4.x, no se puede usar el panel táctil mediante la librería URTouch. En las 3.x señaladas, si se puede usar.

Los tres elementos (lector microSD, TFT y panel táctil) podrían instalarse en el bus SPI1, sin embargo solo pueden funcionar dos de ellos al mismo tiempo, inhabilitando el tercero.

Como ya es posible usar la memoria microSD conectada en modo SDIO, podemos conectar el panel táctil y la pantalla a SPI1, mediante el siguiente cableado

Teensy 4    ILI9488
3V3             VCC
GND             GND
10               CS
8             RESET
9             DC/RS
11        SDI(MOSI)
13              CLK
3V3             LED
12        SDO(MISO)
13            T_CLK
5              T_CS
11            T_DIN
12             T_DO
2             T_IRQ

Las librerías ILI9488 y XPT2046_Touchscreen, vienen en el teensyduino, en este caso usaremos el 1.53 en el IDE 1.8.13.

Toca verificar el cableado de la pantalla, usando hilos cortos no tendremos sobresaltos:


Una vez instalado el complemento para el IDE de arduino, localizamos la placa teensy 4 y ubicamos el ejemplo spitftbitmap, que modificaremos para que funcione con SDIO y SdFat beta.

Por defecto el ejemplo llama a la librería SD para la carga de imágenes en la tarjeta microSD desde el lector SPI. Lo renombraremos como T4_spitftbitmap_a_SdFat

Usando lo aprendido en el ejemplo T4x_SdFat_test, llamaremos a SdFat beta, tanto el constructor como el iniciador:

Crucemos los dedos para que no salte algún error por allí...

Al parecer es lo único que debemos modificar para usar SdFat beta en lugar de SD para el manejo del lector microSD.

¡Ha resultado!

Ahora las imágenes bmp las podemos cargar usando el lector SDIO.

Afinando algunos detalles en la carga de imagenes BMP desde el lector SDIO del teensy 4

Con algunos ajustes extra en la rutina de carga de imágenes, podemos enviar al TFT y sin inconvenientes, imágenes de hasta 480x320 pixeles.

Originalmente, la rutina fue diseñada para imágenes de 320x240 pixeles, por lo que la ubicación de alguna imagen en cualquier parte de la pantalla, generaba problemas sobre todo en los límites máximos inferior y derecho. Con los ajustes es posible colocar imagenes de hasta 480x320 px, en algún punto de la superficie del TFT, y lo mejor, respetando las dimensiones en cualquier rotación.

La condición es que la imagen bmp tenga orientación horizontal, para que la rutina de lectura de las lineas y columnas pueda coincidir con las dimensiones del TFT, incluso en los limites máximos 480 o 320.

Test de carga de imágenes desde el lector SDIO

T4x_ILI9488_BMP

ST7735 1.8" 160x128 touch

Hace unos días tratando de localizar un GPS neo7, vi publicación titulada:
"8/10/12pin 1,8 pulgadas MÓDULO DE PANTALLA LCD 1,8 pulgadas TFT LCD puerto serial SPI módulo TFT pantalla a color"

Una de las imágenes que refiere al TFT de 12 pines, me llamó la atención:


Pedí un par de pantallas para experimentar con ellas. La librería de control que se puede usar es la ST7735_t3 que viene en el teensyduino, lo mejor es que puede funcionar en el teensy 4 o en el teensy 4.1. La librería de control para el panel táctil es la XPT2046_Touchscreen.

El pinout de la pantalla une el bus SPI del TFT con el panel táctil, para la pantalla bastan estas líneas:

VCC   3.3V
GND
CS1   10  
DC    9  
RES   8  
BLK   3.3V
MOS   11
CLK   13


Para agregar la funcionalidad del panel táctil, se deben conectar estos pines:

MIS   13
CS2    5
PEN    2

Este es el mapeo que permite usar la superficie del panel táctil:

x = map (p.x, 201, 3950, 0, 160);
y = map (p.y, 3850, 340, 0, 128);

Este es el constructor:

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

Para activar el llamado del lector SDIO hay que definir:

#define SD_CS BUILTIN_SDCARD

O bien en algunos casos:

SD.begin(BUILTIN_SDCARD)

Los últimos ajustes de la librería SD para el teensy, permiten extender su alcance a la librería SDFat beta, por lo que ambas librerías puede usarse para la gestión de imágenes bmp o jpg. Lo que abre la posibilidad de usar el lector SDIO que viene en el teensy 4.1 o 3.6, o el SDIO externo en el teensy 4. Podría también ser factible usar el lector SDIO del teensy 3.5.

Las imágenes BMP se pueden gestionar con el ejemplo que proporcionó Adafruit desde las primeras versiones de la librería GFX: spitftbitmap, con algunos ajustes similares a los que se realizaron en la librería ILI9488_t3 para poder habilitar el uso de la librería SdFat beta y el lector SDIO.

Las imágenes jpg pueden ser gestionadas con la librería JPEGDEC, capaz de administrar la carga de imágenes de mayor formato que el de la pantalla:


Eliminando el cableado provisional y evitar aluno que otro fallo por falso contacto...


En conclusión, es el TFT con funcionalidad táctil más pequeño que podemos usar en nuestros proyectos, tiene apenas una resolución de 160x128 pixeles

Grafica deslizante para presentar datos en el TFT

Aprovechando la velocidad del teensy 4 (nada menos que 600 mHz!!! en condiciones normales, con posibilidad de 1 GHz con un disipador y un ventilador adecuado)

Visualizar datos en un TFT en el entorno arduino resulta algo complejo de conseguir con las pantallas basadas en librerías estilo Adafruit/GFX: ILI9341, ILI9488, ILI9325, ST7735, etc. Como no disponen de memoria dedicada, todo el trabajo lo realiza el MCU. Es posible agregar algún shield basado en chips F103X, con la idea de que gestione los gráficos, pero la electrónica requerida nos queda fuera de alcance. Existen algunos ejemplos en la red pero es tal la cantidad de subrutinas y de código C rebuscado, que tan solo tratar de aislar el marco de la gráfica es todo un triunfo.

Después de muchos intentos y luego de la llegada de estas diminutas ST7735 de 1.8" táctiles (sigo sin salir del asombro!), decidí retomar el tema.

La aproximación la conseguí con la primitiva más simple: borrar y luego dibujar un pixel. Para borrar un pixel en una determinada posición en el TFT, lo podemos conseguir colocando en esa posición un pixel con el color del fondo.

Otro concepto tiene que ver con los arrays de datos. Podemos usar un array para almacenar los datos actuales de algún sensor y en otro array podemos almacenar los datos previos de ese sensor. Aquí está la clave: los datos previos serán el conjunto de pixeles que al dibujarlos con el color del fondo, nos ayudarán a borrar los pixeles. Aquí todo muy bien como concepto, pero escribirlo en el código podría parecer complejo...

Al escribir el código traté de mantenerlo de forma modular, lo mas simple posible.

Primero debemos dibujar el marco para graficar. Esta función es fija

//posición X, posición Y, número de marcadores en X, número de marcadores en Y, color del marco
void MarcoG(int XM, int YM, int NDX, int NDY, uint16_t color)
{ 
  int Pitch = 10;  //espaciado fijo de 10 pixeles
    //Marco
  tft.drawRect(XM, YM, Pitch*NDX+1, Pitch*NDY+1, color);

    //Divisores eje X
  int altoMarcaX = 4;  //Número de pixeles de cada marcador
  for (int i=XM; i<=XM+Pitch*NDX; i+=Pitch)
  tft.drawLine(i, YM+Pitch*NDY, i, YM+Pitch*NDY+altoMarcaX, color);

    // Divisores eje Y
  int largoMarcaY = altoMarcaX;
  for (int i=YM; i<=YM+Pitch*NDY+1; i+=Pitch)
  tft.drawLine((XM-largoMarcaY), i, (XM-1), i, color);
}

Para fines prácticos, el marco estará formado por arreglos cuadrados de 10 pixeles por lado, por lo que cada celda representa 10 unidades en el eje X y 10 en el eje Y.

En el eje X se representa el número de datos y el en eje Y los datos del sensor, normalizados a marcadores de 10 unidades

Antes de dibujar algún pixel, debemos tener datos como línea base. Esta función es fija

void lineabaseG1(int BaseD)
{
  for (int i=0; i<maxlecturas; i++)
    {
       //AdquiereDatosG1();
       lecturaG1[i] = BaseD;   
    }     
}

Para efectos prácticos, el array principal lo designé como lecturaG1[], almacenará los datos actuales y los datos previos estarán en lecturapreviaG1[], la línea base llena el array de datos actuales con algún valor dentro del rango de los datos del sensor.

Los datos los obtendremos con la función AdquiereDatosG1. En ella podemos colocar la rutina con la que adquirimos datos del sensor, en este caso coloqué alguna función simple para simular un termómetro con escala Celcius, con lecturas en el rango de 1 a 25. Cabe señalar que se debe agregar una operación de mapeo, escalado o factorización, con la finalidad de obtener valores que se puedan dibujar en el espacio de pixeles del TFT.

Si el sensor arroja valores en un rango de 0 a 10000, podemos dividir los datos del sensor entre 100, para que la lectura se adapte a la escala de la pantalla. En este ejemplo los valores corresponden 1 a 1. Esta función puede ser adaptada por el usuario

float velTCG1 = 1;
void AdquiereDatosG1()
{
   //TempCG1=random(20,30);

   TempCG1= TempCG1 + velTCG1;
   if (TempCG1>=25){velTCG1=-1;}
   if (TempCG1<=1){velTCG1=1;}
   
   if (TempCG1<=0){TempCG1=0;}
   LecturaTAG1 = TempCG1;
   
// Truco para conservar 2 decimales en la presentación de la temperatura
   //TAG1=TempCG1*100;
   TAG1=TempCG1*1; 
}

Para efectos prácticos, TempCG1 es el dato actual del sensor, LecturaTAG1 y TAG1, son valores de respaldo que podemos manipular para efectos de presentación en pantalla, como señalamos previamente, nos permitirán escalar los valores del sensor para poder manejarlos dentro del marco de la gráfica, además nos permitirán conservar valores decimales por ejemplo para la impresión de datos en pantalla.

La rutina que da vida a la gráfica continua de datos es esta (función fija)

long previousMillisG1 = 0;
long intervalG1 = 100;   //7000

int jG1;  // contador para recorrer los datos de la lista actual
void LineaDatosG1(int xinicial, int ybase, int NDX, int NDY, const int maxlecturas, uint16_t color) //permite ajustar el numero máximo de datos de las bases lecturaprevia y lectura
{
  int escala = 1;
  int yDatoTXT = ybase;
  ybase = ybase + 10*NDY;
  
  unsigned long currentMillisG1= micros();        
  if(currentMillisG1 - previousMillisG1 > intervalG1)
  {
    previousMillisG1 = currentMillisG1;
  
    lecturapreviaG1[jG1]=lecturaG1[jG1];  // almacena el dato actual
  // Recorre una posición. Los datos de la lista se recorren de adelante hacia atrás, para dejar libre el último espacio de la lista

     lecturaG1[jG1] = lecturaG1[jG1+1];  
     tft.drawPixel(jG1+xinicial, ybase-escala*lecturapreviaG1[jG1], ST77XX_BLUE); //borra el pixel previo
     tft.drawPixel(jG1+xinicial, ybase-escala*lecturaG1[jG1], color); //gráfica el pixel nuevo
     jG1++;

// Continua recorriendo los datos hasta llegar al último de la lista, en el que se colocará la nueva lectura de datos
      if (jG1==maxlecturas-1)
       {
         AdquiereDatosG1();
         lecturapreviaG1[jG1]=lecturaG1[jG1];         
         lecturaG1[jG1] = TempCG1;  
                 
         tft.drawPixel(jG1+xinicial, ybase-escala*lecturapreviaG1[jG1], ST77XX_BLUE); //borra el pixel previo
         tft.drawPixel(jG1+xinicial, ybase-escala*lecturaG1[jG1], color); //gráfica el pixel nuevo
         tft.setCursor(xinicial+1, yDatoTXT+2); tft.setTextColor(color, ST77XX_BLUE); sprintf(TXP,"%2d", TAG1); tft.println(TXP);
         jG1=0;
       }
  }  
}

Se aceptan sugerencias de mejora.

Solo falta: lo que va en el encabezado, la parte modificable por el usuario de la gráfica dentro del sketch y la parte de presentación de la gráfica en el TFT.

Encabezado del sketch

En el encabezado para cada sensor debemos agregar estas líneas, el ejemplo muestra como se pueden manejar dos sensores de temperatura

char TXP[50];
const int maxlecturas = 139; // 139   // Variable que permite manipular el tamaño de todos los arrays de datos, esta relacinado con el largo del eje X, provisional

//sensor 1
float TempCG1 =20;        // dato decimal
int TAG1, LecturaTAG1;    // para manejar los decimales (experimental no usado aún
float lecturaG1[maxlecturas];  // base de datos actual
float lecturapreviaG1[maxlecturas]; // base de datos previa
//sensor 1

//sensor 2
float TempCG2 =20;        // dato decimal
int TAG2, LecturaTAG2;    // para manejar los decimales (experimental no usado aún
float lecturaG2[maxlecturas];  // base de datos actual
float lecturapreviaG2[maxlecturas]; // base de datos previa
//sensor 2

Para agregar un tercer sensor bastaría agregar estas líneas:

//sensor 3
float TempCG3 =20;        // dato decimal
int TAG3, LecturaTAG3;    // para manejar los decimales (experimental no usado aún
float lecturaG3[maxlecturas];  // base de datos actual
float lecturapreviaG3[maxlecturas]; // base de datos previa
//sensor 3

Las funciones que vimos:

void LineaDatosG1()
void lineabaseG1()
void AdquiereDatosG1()

Deben copiarse y modificarse para cada sensor que agreguemos, solo hay que sustituir el índice al final del nombre. En el interior de las funciones también se debe modificar el índice en cada variable.

Mas adelante podría ser factible simplificar a solo tres funciones para n sensores, sin tener que copiar, pero aun es un trabajo en progreso, posiblemente involucrará un array para el ID de los sensores.

Configuración en el sketch

Normalmente no uso void loop() en los sketchs, esto permite crear presentaciones con menús completamente independientes unos de otros, lo que permite crear un sistema modular con el que podemos agregar nuevos elementos al menú principal sin afectar a los que ya funcionan. Además cada módulo puede funcionar si lo aislamos del resto para efectos de depuración. Este es el menu principal de trabajo, en este caso será lo que mostraremos en pantalla:

void MP()
{
 
 tft.setRotation(Rotacion); 
 tft.fillScreen(ST77XX_BLUE);
 tft.setTextSize(1);
 tft.setCursor(10, 3); tft.setTextColor(ST77XX_WHITE);  tft.println("Grafica deslizante");

 lineabaseG1(10);
 int xbaseG1 = 30; //origen en X del TFT
 int ybaseG1 = 13; //origen en Y del TFT
 int NDXG1 = 10;   //mínimo 2, máximo 14, marcadores horizontales
 int NDYG1 = 5;    //minimo 4, máximo 10, marcadores verticales
 MarcoG(xbaseG1, ybaseG1, NDXG1, NDYG1, ST77XX_RED);

 lineabaseG2(1);
 int xbaseG2 = 30; //origen en X del TFT
 int ybaseG2 = 17+5+5*10; //origen en Y del TFT
 int NDXG2 = 10;   //mínimo 2, máximo 14, marcadores horizontales
 int NDYG2 = 5;    //minimo 4, máximo 10, marcadores verticales
 MarcoG(xbaseG2, ybaseG2, NDXG2, NDYG2, ST77XX_RED);
 
 while(1)
  {
   //Datos del sensor G1
   LineaDatosG1(xbaseG1+1, ybaseG1, NDXG1, NDYG1, (NDXG1*10)-1, ST77XX_GREEN); 
   //Datos del sensor G2
   LineaDatosG2(xbaseG2+1, ybaseG2, NDXG2, NDYG2, (NDXG2*10)-1, ST77XX_YELLOW); 
  }
}

El menú principal lo podemos llamar desde el setup del sketch.

La parte en la que podemos configurar la posición del marco, dimensiones y el número de marcadores en cada eje
se consigue con estas líneas:

lineabaseG1(10);
 int xbaseG1 = 30; //origen en X del TFT
 int ybaseG1 = 13; //origen en Y del TFT
 int NDXG1 = 10;   //mínimo 2, máximo 14, marcadores horizontales
 int NDYG1 = 5;    //mínimo 4, máximo 10, marcadores verticales
 MarcoG(xbaseG1, ybaseG1, NDXG1, NDYG1, ST77XX_RED);

Para agregar un nuevo sensor basta con copiar las líneas y modificar el índice. en el ejemplo, esto configura el marco del segundo sensor:

lineabaseG2(1);
 int xbaseG2 = 30; //origen en X del TFT
 int ybaseG2 = 17+5+5*10; //origen en Y del TFT
 int NDXG2 = 10;   //mínimo 2, máximo 14, marcadores horizontales
 int NDYG2 = 5;    //minimo 4, máximo 10, marcadores verticales
 MarcoG(xbaseG2, ybaseG2, NDXG2, NDYG2, ST77XX_RED);

Dado que estos parámetros son fijos en el skech, van en la parte inicial, después del setup.

Gráfica continua dentro de la sección ejecutable del sketch

Para el sensor 1:

   //Datos del sensor G1
   LineaDatosG1(xbaseG1+1, ybaseG1, NDXG1, NDYG1, (NDXG1*10)-1, ST77XX_GREEN);

Nuevamente para el sensor 2, basta con copiar la línea anterior, modificando el índice respectivo:

   //Datos del sensor G2
   LineaDatosG2(xbaseG2+1, ybaseG2, NDXG2, NDYG2, (NDXG2*10)-1, ST77XX_YELLOW);

La primer gráfica presenta datos en base a una función que oscila linealmente entre 1 y 25, cada 100 microsegundos, la segunda gráfica presenta valores aleatorios entre 20 y 30 cada 4000 microsegundos

Video del skecth Gráfica deslizante en ST7735 touch

Conectando dos ILI9341 en un Teensy .6

El comportamiento del puerto SPI a veces nos puede dar dolores de cabeza, si no exploramos el comportamiento de los pines alternos a los clásicos 11-12-13 con los que estamos familiarizados en el entorno arduino. Es posible conectar dos pantallas SPI en una misma placa con la capacidad de controlarse de forma independiente.

En este caso exploraremos esta posibilidad en una placa Teensy 3.6. En ella los pines que acceden al bus SPI1, están identificados con el número 0 al final de su asignación; por ejemplo CS0, MISO0, MOSI0 y SCK0. Para el bus SPI12 el número al final es el 1. Hay que cuidar esta nomenclatura para no perdernos en el cableado de las pantallas. Algunos de estos pines SPI pueden funcionar en los dos buses SPI1 o SPI2, pero debo aclarar que no todos. Suena algo confuso, pero en la practica, hay que pasar un buen rato de prueba y error para dar con la combinación correcta de pines para la segunda pantalla.

Lo mejor es conectar la primer pantalla en un cabezal para evitarnos algún susto. En ella el cableado SPI es el de siempre: 8-9-10-11-13 (RESET-DC-CS-MOSI-SCK). Confirmamos quela pantalla va como debe, subiendo algún sketch de la librería ILI9341_t3. Con este paso verificado, ya podemos avanzar al siguiente nivel: conectar la segunda pantalla a SPI1.

Ahora viene lo interesante. No todos los pines PWM nos pueden servir para conectar la segunda pantalla. Dado que el MCU es muy compacto, pensé que seria solo cuestión de conectar en los pines alternos, pero para mi sorpresa no todos funcionan.

Luego de algunas horas de prueba y error, encontré la combinación correcta para CS-DC-RESET de la segunda pantalla. MOSI y SCK van a 11 y 13 respectivamente, para el bus SPI1.

Estos son los dos constructores que podemos usar:

#define TFT_RST  8
#define TFT_DC   9
#define TFT_CS  10
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC, TFT_RST);

#define TFT_RST2 21 
#define TFT_DC2  20
#define TFT_CS2  15
ILI9341_t3 tft2 = ILI9341_t3(TFT_CS2, TFT_DC2, TFT_RST2);

Se crean dos instancias para poder usar la misma librería ILI9341_t3: tft y tft2

En el setup debemos iniciar por separado cada tft.

 tft.begin();
  tft.setRotation(3); 
  tft.fillScreen(ILI9341_BLUE);
  tft.setTextColor(ILI9341_WHITE);
  tft.setTextSize(1);
  tft.setCursor(320-80,10);
  tft.print("First TFT");
  
  tft2.begin();
  tft2.setRotation(3);
  tft2.fillScreen(ILI9341_RED);
  tft2.setTextColor(ILI9341_WHITE);
  tft2.setTextSize(1);
  tft2.setCursor(320-80,10);
  tft2.print("Second TFT");

Esto nos permitirá controlar de forma independiente cada pantalla:

Luego de un rato de meditarlo, me gustaría usar el lector SDIO del teensy 3.6, para, poder acceder a las imagenes de un lector microSD, con apoyo de la librería SdFat beta: ¿será posible enviar imágenes independientes bmp o jpg a cada pantalla?...