Algunos consejos para usar TFT´s

Las correcciones funcionan muy bien, es posible utilizar la memoria de 64 Gb y la de 128 Gb, tanto en el teensy 4 como en el teensy 4.1.

En el teensy 4.1, el lector SDIO o de 4 bits viene instalado en la propia placa del MCU. En el caso del teensy 4, hay que soldar algún elemento extra en la parte inferior del PCB, ya sea un grupo de hilos delgados o bien algún PCB extra. En mi caso opté por utilizar algunos hilos y soldarlos en un adaptador microSD-SD

La solución funciona, sin embargo, hay que cuidar de no mover demasiado el adaptador, ya que alguno de los hilos o se puede desoldar o se puede dañar. Una alternativa consiste en localizar algún lector microSD comercial, quizás con algún mecanismo de retención de la tarjeta de memoria.

Tengo en mente un lector que coindice con el orden del pinout del teensy 4, sin embargo el espaciado de los puntos de soldadura es de 2 mm

Localicé un lector microSD con conexionado directo, sin resistencias intermedias, lo que lo convierte en un excelente complemento de 3.3V para el teensy 4, además coincide pin a pin con el cabezal inferior SDIO del PCB del teensy.

Adicionalmente, pude localizar un adaptador de 2 mm a 2.54 mm, para poder usarlo en un cabezal normal.

IMG_20210509_152107

Para armar el adaptador 2-2.54 mm se puede usar una tira de pines macho, usando los pasadores individuales para soldarlos en la microSD y luego en la cara posterior del PCB-adaptador.

Finalmente, para el pinout de 2.54 mm, soldamos una tira de pines macho normal.

Me agrada bastante como ha quedado el módulo, es mas robusto y creo que tendrá buen desempeño con las pantallas FT1x/BT81x.

PD: por cierto hace unas semanas pedí a directamente a Riverdi, una pantalla EVE4 de 5", con el chip BT817. Hubo que esperar un mes aproximadamente, ya que el TFT se construye sobre pedido. Por fin ha llegado el jueves, hubo que pagar algún complemento por gastos de importación, pero ya lo tenía considerado.

Riverdi 6 Riverdi 7

Terminaré de instalar el lector microSD y seguiré con las correcciones en la librería para conseguir que funcione con microSD de mas de 32 Gb.

Seguiré con los datos de la tabla de registros específicos para esta pantalla y conseguir el constructor correcto dentro de la librería, pero para eso, hay que revisar a detalle el datasheet de la pantalla RVT50HQBNWC00-B.

Me gustaría afinar el detector de tipo de pantalla de la librería por puerto serie al iniciar el TFT; ya que por el momento, solo da números básicos como 0 para FT800/FT801 y 1 para FT813; creo que puedo conseguir leer el registro de inicio, para que muestre el chip correcto en hexadecimal: 13 para FT813 o 17 para FT817 por ejemplo.

He conseguido hacer funcionar la pantalla en la placa teensy 4. Hay varios aspectos a considerar dentro de la librería.

En esta cuarta familia de chips EVE, el pin PD debe ir conectado al MCU, recuerdo que el buen ligthcalamar encontró que las pantallas de HOTMCU necesitan de ese pin para poder resetearse correctamente tanto al subir algún sketch como al conectar el MCU a la fuente de alimentación.

El pin PD puede ir conectado a algún pin digital que tenga capacidades PWM; usé el pin 24 en el teensy 4.

Antes de iniciar la pantalla, debe implementarse una secuencia "power on reset" por software, antes aplicar cualquier otra instrucción de llamado al chip de la pantalla. La secuencia se implementó en el archivo wiring.h

pinMode(POR_PIN, OUTPUT);
digitalWrite(POR_PIN, HIGH);    
delay(100);
digitalWrite(POR_PIN, LOW);     //           |
delay(100);                     //           |
digitalWrite(POR_PIN, HIGH);    //           |
delay(100);

Luego, hay que fijar los parámetros de control específicos de la pantalla relacionados con la sincronización y relojes horizontal y vertical. De acuerdo con el datasheet del TFT. Los mejores parámetros de ajuste que han funcionado, son:

    GD.wr32(REG_HSIZE, 800);  //      Thd       visible horizontal line length 
    GD.wr32(REG_VSIZE, 480);  //      Tvd       number of visible lines 

    GD.wr32(REG_HCYCLE, 816); //808 816 896  816 Th        One Horizontal Line length (visible/invisible)
    GD.wr32(REG_HOFFSET, 8);  //4   8   48   8   Thb       HS Blanking            
    GD.wr32(REG_HSYNC0, 8);   //4   8   48   8   Thfp      HS front porch         
    GD.wr32(REG_HSYNC1, 4);   //2   4   8    4   Thpw/Thw  HS pulse width         
	
    GD.wr32(REG_VCYCLE, 496);  //488 496 504  504 Tv        VS period time         
    GD.wr32(REG_VOFFSET, 8);  //4   8   12   12   Tvb       VS Blanking            
    GD.wr32(REG_VSYNC0, 8);   //4   8   12   12   Tvfp      VS front porch         
    GD.wr32(REG_VSYNC1, 4);    //2   4   8    8   Tvpw/Tvw  VS pulse width         

    GD.wr32(REG_PCLK, 2);             //2, 1, 0       1:REG_PCLK_FREQ
	GD.wr32(REG_PCLK_FREQ, 0);        //0   
	GD.wr32(REG_PCLK_2X, 0);          //0,1
    GD.wr32(REG_SWIZZLE, 0);          //0 1  3
    GD.wr32(REG_PCLK_POL, 1);         //1, 0
    GD.wr32(REG_CSPREAD, 1);          //1,0
    GD.wr32(REG_DITHER, 1);           //1, 0

La frecuencia del bus SPI-1, la he fijado en 36 MHz. La frecuencia de la pantalla puede establecerse hasta 72 MHz, las pruebas que he realizado han dado como frecuencia óptima 64 MHz, es decir un 88.88% de la frecuencia máxima. Al acercar ese parámetro al máximo teórico la pantalla sigue respondiendo, pero el audio se acelera al reproducir video.

Finalmente, hay que leer varias veces el registro 0x0c0000, antes de iniciar el TFT, dentro del archivo wiring.h. Originalmente la libreria establece un valor de 0 para pantallas FT800/801, 1 para FT813, siguiendo esa premisa, correspondería el valor 2 para BT815/BT816 y el valor 3 sería para BT817/BT818.

Al almacenar la lectura sucesiva del valor del registro 0x0c0000 antes de subir las frecuencias de sincronización, es posible obtener el valor hexadecimal equivalente para cada familia de pantallas 0 para FT800, 1 para FT801, 13 para FT813, 15 para BT815 o 17 para BT817

    // So that FT800,801      FT810-3   FT815,6      FT817
    // model       0            1         2             3
    switch (__rd16(0x0c0000) >> 8) {
    case 0x00:
    case 0x01: ft8xx_model = 0;  BT8XX = __rd16(0x0c0000) >> 8; break;
    case 0x10: ft8xx_model = 1;  BT8XX = __rd16(0x0c0000) >> 8; break;
    case 0x11: ft8xx_model = 1;  BT8XX = __rd16(0x0c0000) >> 8; break;
    case 0x12: ft8xx_model = 1;  BT8XX = __rd16(0x0c0000) >> 8; break;
    case 0x13: ft8xx_model = 1;  BT8XX = __rd16(0x0c0000) >> 8; break;
    case 0x15: ft8xx_model = 2;  BT8XX = __rd16(0x0c0000) >> 8; break;
    case 0x16: ft8xx_model = 2;  BT8XX = __rd16(0x0c0000) >> 8; break;
	case 0x17: ft8xx_model = 3;  BT8XX = __rd16(0x0c0000) >> 8; break;
    default:   ft8xx_model = 3;  BT8XX = __rd16(0x0c0000) >> 8; break;

El monitor serie da este resultado de detección, reporta correctamente la familia del chip del TFT, la velocidad del bus SPI, dimensiones en pixeles y frecuencia del reloj del TFT:

Los leds de retroiluminación dan un tono cálido, posiblemente el tipo de chip no tiene tonos fríos por completo.

Tras algún tiempo de mantener la pantalla conectada al teensy 4, para verificar la estabilidad de la conexión del lector SDIO, manteniendo la pantalla en el bus SPI-1, por fin he podido afinar algunos detalles.

Para asegurar la estabilidad del panel táctil, es necesario instalar resistencias de 10K en modo pullup en las líneas MISO, MOSI y SCK. Sin ellas, las entradas táctiles se activan de forma aleatoria sin tocarlas. Este comportamiento ya lo había notado en las primeras placas Nucleo STM32 que se utilizaron para conectar pantallas FT813: F429ZI-DISCO1, M4DEMO (F407) y Core7XX (F746).

Con estas tres resistencias en el bus SPI1, la pantalla funciona sin problemas. Verificaré el funcionamiento de la microSD de 128 Gb, para comprobar si los ajustes para exFat, que sugiere la libreria SdFat beta2, pueden servir para usar este tipo de memorias de gran capacidad.

GDT4Xv134: librería para gameduino 23x compatible con SdFat

Aunque hay algunos puntos por revisar, creo la librería ya es operativa en la mayoría de funciones principales o widgets. Acá está el repositorio:

https://github.com/FT81xMania/GDT4Xv134

MCU: teensy 4, teensy 4.1, teensy 3.6 y probablemente teensy 3.5
TFT: las pantallas en las que me ha sido posible experimentar la librería son:
EVE: Riverdi FT801
EVE2: Riverdi: FT813 5", 7", NHD: 3.5", 4.3", 5" y 7", MO: FT813 5" (por configurar el panel táctil)
EVE3: MO: BT815 5" (inestable), 38G (por configurar el panel táctil)
EVE4: Riverdi: BT817 5"

Para el manejo de elementos multimedia (arreglos de celdas, assets, jpg, png y avi (EVE2, 3 y 4) , se puede utilizar la librería SdFat en su versión mas reciente; accediendo al lector SDIO de cada una de las placas T3x o T4x. Salvo en el teensy 4, por lo que no es necesario instalar un lector microSD.

Sigue en proceso de revisión.

En los ratos libres he podido probar el funcionamiento de la librería en una pantalla NHD de 3.5" con chip FT813. Funciona según lo esperado, las primeras pruebas las hice sin el GPS instalado, ni el DS3231. En esta oportunidad, ambos dispositivos ya están conectados al teensy 4.1... y ¡voalá!, el arreglo funciona:

Se producen algunas observaciones de compilación, pero ninguna que impida la carga del sketch en el teensy 4.1

IDE arduino: 1.8.16
Teensyduino: 1.55
SdFat: 2.0.5-beta.1, 2.1.0

Sigo afinando detalles con la pantalla BT817, hay dos registros que me llaman la atención: cmd_testcard y cmd_logo, que no están presentes en los chips FT81x. Las habilitaré en la libreria para saber su función.

Pantalla NHD FT813 3.5" en STM32F411CE

Aunque esta placa lleva un tiempo en el mercado, recientemente la descubrí mirando en el portal de ventas del fabricante; y me quiero aventurar para explorar si es que es posible darla de alta como variante en el núcleo alternativo para el IDE de arduino creada por Danieleff ( danieleff/STM32GENERIC: Generic implementation of Arduino for STM32 boards (github.com)).

He utilizado las placas STM2F103C8, F429I-DISCO, Nucleo F767ZI, M4DEMO, M3DEMO, Core7XXI, entre otras, en este core alterno para STM32 y funcionan muy bien.

Uno de los atractivos de la F411CE es su tamaño, idéntico al de la F103C8, la frecuencia de operación y principalmente, que puede recibir algún overclock para llevarla de 100 MHz hasta 150 MHz, es probable que la funcionalidad en el bus USB se vea afectada, sin embargo creo que podría ser la base de un reproductor de video compacto, ya que la usaré en algún dispositivo portátil que no dependerá de la PC

Están por llegar algunas placas perforadas de 8x12 cm, mientras tanto encontré algunas tiras de pines de 2 cm de largo, para poder instalarlos en el PCB de la F411.

Intentaré crear la variante, siguiendo la siguiente estrategia:

  1. Copiar la carpeta de la variante con chip similar a la F411CE, y ubicarla en la ruta de variantes del Core alterno: C:\arduino-1.8.16\hardware\STM32GENERIC_danielefF\STM32\variants. La variante que mas se acerca a la 411CE, es la variante Nucleo_F411RE

  2. Cambiar el nombre de la carpeta, en este caso la designaré con el nombre BLACK_F411CE

  3. En la carpeta recién creada hay tres archivos, ajustaremos el archivo variant.h para que coincida con el pinout de la F411CE, ya que no todos los pines del chip están disponibles físicamente.

Con una inspección visual del PCB de la F411CE, podemos establecer cual es el pinout disponible y procedemos a reflejarlo en el archivo variant.h. Cabe señalar que el pin del led para esta placa es PC13.

También podemos ir a la ruta:
C:\arduino-1.8.16\hardware\STM32GENERIC_danielefF\STM32\system\STM32F4\stm32_chip

y localizar el archivo de definiciones que corresponde al chip de la placa, en este caso stm32_STM32F411CE.h y copiar la definición de pines, en variant.h:

#define VARIANT_PIN_LIST_DEFAULT \

Guardamos el archivo para conservar los cambios.

El contenido del archivo varian.h será entonces:

#ifndef VARIANT_H
#define VARIANT_H

#define LED_BUILTIN PC13

#define MOSI PA7
#define MISO PA6
#define SCK PA5
#define SS PA4

#define SDA PB9
#define SCL PB8

#define VARIANT_PIN_LIST \
   PIN(A,0), \
   PIN(A,1), \
   PIN(A,2), \
   PIN(A,3), \
   PIN(A,4), \
   PIN(A,5), \
   PIN(A,6), \
   PIN(A,7), \
   PIN(A,8), \
   PIN(A,9), \
   PIN(A,10), \
   PIN(A,11), \
   PIN(A,12), \
   PIN(A,15), \
   PIN(B,0), \
   PIN(B,1), \
   PIN(B,3), \
   PIN(B,4), \
   PIN(B,5), \
   PIN(B,6), \
   PIN(B,7), \
   PIN(B,8), \
   PIN(B,9), \
   PIN(B,10), \
   PIN(B,11), \
   PIN(B,12), \
   PIN(B,13), \
   PIN(B,14), \
   PIN(B,15), \
   PIN(C,13), \
   PIN(C,14), \
   PIN(C,15), 
#endif

Con ayuda del STM32CubeMX, he podido explorar algunos posibles números para obtener un overclock en el chip; mediante prueba y error se han verificado algunas opciones. El archivo variant.c: tiene lo necesario para conseguir este experimento. Ha quedado de esta forma:

#include "stm32_build_defines.h"
#include "stm32_def.h"

extern void SystemClock_Config(void) {
  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

  __HAL_RCC_PWR_CLK_ENABLE();

  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 16; //25-96MHz  20-120MHz  24-100MHz    16-150MHz  Menor a 16 no responde
  RCC_OscInitStruct.PLL.PLLN = 192;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  
  HAL_RCC_OscConfig(&RCC_OscInitStruct);


  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  
  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3);

   HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

Con PLLM en 16, es posible conseguir una frecuencia de 150 MHz.

Finalmente, debemos agregar algunas líneas al final del archivo boards.txt, ubicado en la ruta:
C:\arduino-1.8.16\hardware\STM32GENERIC_danielefF\STM32

Para poder dar de alta la nueva variante en el listado de placas del core alterno. Las líneas que he agregado son:

################################################################################
# BLACK_F411CE board

BLACK_F411CE.name=BLACK_F411CE

BLACK_F411CE.upload.maximum_size=524288
BLACK_F411CE.upload.maximum_data_size=131072

BLACK_F411CE.build.core=arduino
BLACK_F411CE.build.board=BLACK_F411CE

BLACK_F411CE.build.mcu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard
BLACK_F411CE.build.series=STM32F4
BLACK_F411CE.build.variant=BLACK_F411CE
BLACK_F411CE.build.extra_flags=-DSTM32F411CE
BLACK_F411CE.build.f_cpu=150000000L

BLACK_F411CE.upload.protocol=STLink
BLACK_F411CE.upload.tool=stlink_upload

BLACK_F411CE.menu.upload_method.STLinkMethod=STLink
BLACK_F411CE.menu.upload_method.STLinkMethod.upload.protocol=STLink
BLACK_F411CE.menu.upload_method.STLinkMethod.upload.tool=stlink_upload

BLACK_F411CE.menu.usb.SerialUSB=Serial [Virtual COM port]
BLACK_F411CE.menu.usb.SerialUSB.build.extra_flags_usb=-DMENU_USB_SERIAL

BLACK_F411CE.menu.serial.SerialUSB=SerialUSB
BLACK_F411CE.menu.serial.SerialUSB.build.extra_flags_serial=-DMENU_SERIAL=SerialUSB
BLACK_F411CE.menu.serial.SerialUART1=SerialUART1 [PA9/PA10]
BLACK_F411CE.menu.serial.SerialUART1.build.extra_flags_serial=-DMENU_SERIAL=SerialUART1

Al reiniciar el IDE de arduino, ya podemos localizar la variante que hemos creado

Probando el funcionamiento de la variante recién creada:

void setup()
{
  pinMode(PC0, OUTPUT);   //blue
}

void loop()
{
    digitalWrite(PC0, LOW); // led on
    delay(100);
    digitalWrite(PC0, HIGH);// led off
    delay(100);    
}

Ahora toca cablear la pantalla NHD-FT813 de 3.5"

Instalé el cableado en el PCB para que las uniones sean mas duraderas y no interfieran con las pruebas

VCC  (3.3V) y GND
SCK         PA5
MISO        PA6
MOSI        PA7
CS          PA4
Audio pin:  9 (TFT)
BL VCC      3.3V/5V
BL GND      GND

Ahora si la prueba de funcionamiento con el logo del chip FT813

Y nuevamente el test de saludo de toda la vida

Esta pantalla puede reproducir videos avi con audio por lo que de una vez instalé un jack de montaje superficial de 3.5.

Modifiqué la libreria GD23ZUTX para que pueda funcionar con la libreria SdFat más reciente, con la idea de que se puedan utilizar memorias SD de mas de 32 Gb.

El chip FT813 puede soportar imágenes jpg de 800x600 px; aunque la pantalla NHD de 3.5" tiene un tamaño nominal de 320x240 px, en teoría pueden subirse a la GRAM ese tipo de imágenes.

En el proyecto del GPS, los mapas que me gustaría subir son de por lo menos 800 px de largo por 400 pixeles de alto, ya que así los puedo convertir con el editor de imágenes, la idea es que cada mapa cargado en la GRAM pueda desplazarse, considerando el centro de la pantalla como el punto de referencia principal, al llegar al límite de coordenadas del mapa en pantalla, se cargará el siguiente mapa, permitiendo un mapeo de fondo continuo. Este es un ejemplo de los mapas que se podrán visualizar en el GPS:

La lectura del GPS puede realizarse en tiempo real, sin afectar la carga de imágenes en la pantalla.

He estado trabajando en el transcurso de la semana en el código que podrá permitir centrar el mapa, respecto al centro del TFT, considerando las coordenadas del GPS. Acá una muestra del resultado:

El GPS es un ublox 7, equipado con una antena externa, para mejorar la adquisición de las coordenadas. Está conectado en los pines PA2 (TX2, a RX-GPS), PA3 (RX2, a TX-GPS), del puerto USART2.

La libreria de comunicación entre la F411CE y el GPS, es una variante de la nmea (http://nmea.sourceforge.net, versión estable 0.5.3), corregida por el amigo RndMnkIII. Estoy preparando el repositorio github para compartir la libreria con los ajustes para STM32. En sus experimentos logró ajustar algunas funciones para poder estimar las coordenadas UTM y en grados decimales. Para que las conversiones funcionen correctamente es necesario utilizar la unidad de punto flotante de la placa STM32, definiendo las variables principales como double.

Adjunto el ejemplo que permite procesar las lecturas provenientes del GPS, también funciona en la placa Core7XXI (STM32F746IG)

CORE7XXI_nmealib_GPS_cadenas.zip (7.1 KB)

Pantalla ST7735 con panel táctil en F411CE

Es posible conectar otro tipo de pantallas con chips como el ST7735 en la variante F411CE, utilizando las librerías mas recientes de adafruit. Con lo aprendido en la librería GD23ZUTX, creo que es posible utilizar la librería SdFat V2 para el manejo de archivos de imagen.

Bueno lo primero, el TFT ST7735 que vamos a instalar es este:

El pinout del TFT lo vamos a conectar de esta forma:

ST7735_wiring

Para evitar algún fallo, sugiero conectar cada unión con hilos individuales soldados entre un cabezal hembra de 6 pines dobles y a cada pin del zócalo del MCU.

PCB1 PCB2

Estas son las líneas para el encabezado de configuración:

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <SPI.h>

#define TFT_CS        PA4//10
#define TFT_RST       PA0//8
#define TFT_DC        PA1//9

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

¡Funciona!

PCB3

La pantalla y el panel táctil están conectados al bus SPI 1. Podemos utilizar la librería XPT2046_Touchscreen, comentando las líneas que llaman a la función attachInterrupt, dentro del archivo ccp. La forma de usar esa función en STM32 es diferente a como se utiliza en ARM o AVR. No obstante, creo que aun podemos usar sin problemas esta librería sin recurrir al uso de interrupciones.

El lector externo está ya conectado en el bus SPI2, así que podemos aprovecharlo para ver si funciona para cargar imágenes bmp en la memoria de la F411CE. Podemos partir de las líneas que se utilizaron en GD23ZUTX, agregándolas en el encabezado

#include <SdFat.h>
#define SD_CS    PB12
#define SetSDSpeed  36
static SPIClass SPI_2(SPI2, PB15, PB14, PB13);
#define SD_CONFIG SdSpiConfig(SD_CS, DEDICATED_SPI, SD_SCK_MHZ(SetSDSpeed), &SPI_2)
SdFs SD;

En el setup, podemos iniciar el lector externo con esta línea:

SD.begin(SD_CONFIG);

En la red hay varias modificaciones de la función bmpDraw, que dependiendo de las modificaciones en la librería Adafruit_GFX utilizan ya sea writeRect o pushColor o alguna combinación entre ellas y alguna matriz para almacenar los patrones de colores RGB. La función pushColor se quedó solo como un comentario en la libreria GFX:

// displays supporting setAddrWindow() and pushColors()), but haven't
// implemented this yet.

En la versión mas reciente de la librería GFX, podemos usar writeRect, ya que es la que está definida, con ella podemos intentar leer las líneas del archivo de imagen para reconstruirla en la memoria de la pantalla, quizás no obtengamos una buena velocidad pero es posible que las optimizaciones de la librería SdFat V2 nos den un impulso extra.

Adjunto el ejemplo para poder verificar el funcionamiento del TFT-ST7735, el panel touch XPT2046 y el lector externo.

F411CE_ST7735_Test.zip (207.3 KB)

El panel táctil también funciona y la carga de imágenes, usando la writeRect dentro de bmpDraw, tal parece que si funciona!!!

Para poder inicializar el TFT, el panel táctil y el lector microSD el encabezado y el setup quedó así:

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <SPI.h>
#include <SdFat.h>
#include <XPT2046_Touchscreen.h>

#define CS_PIN  PA2  //touch

#define TFT_CS        PA4//10
#define TFT_RST       PA0//8
#define TFT_DC        PA1//9

XPT2046_Touchscreen ts(CS_PIN);
#define TIRQ_PIN  PA3//2

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

#define SD_CS    PB12

#define SetSDSpeed  36
static SPIClass SPI_2(SPI2, PB15, PB14, PB13);
#define SD_CONFIG SdSpiConfig(SD_CS, DEDICATED_SPI, SD_SCK_MHZ(SetSDSpeed), &SPI_2)
SdFs SD;

int x=0, y=0, Rotacion=3;
char PXY[40];
boolean wastouched = true;
boolean istouched = false;

void setup() {
 SD.begin(SD_CONFIG);
  
 tft.initR(INITR_BLACKTAB);
 tft.setRotation(Rotacion);
 tft.fillScreen(ST77XX_BLACK);

 bmpDraw("tiger.bmp", 0, 0);
  
 ts.begin();
 ts.setRotation(Rotacion);
}

La calibración táctil con esta librería depende de la rotación de la pantalla, debe ser igual a la rotación del panel táctil. Las coordenadas que se obtienen con la librería no pueden usarse directamente para calcular los pares (x,y), ya que son datos de resistencia eléctrica, que varia según el lugar que se presione en el panel táctil.

Los pares (p.x, p.y) deben ser convertidos a (x,y) mediante dos funciones de mapeo que vinculen la superficie de la pantalla con cada resistencia eléctrica.

Para obtener los valores máximo y mínimo en cada dirección, se debe obtener un promedio de los datos obtenidos en cada esquina del panel táctil, luego con ellos podemos usar la función map para poder relacionarla con los pixeles que tiene la pantalla. En este caso las dos funciones de mapeo que he podido conseguir son:

x = map (p.x, 201, 3950, 0, 160);     
y = map (p.y, 3850, 340, 0, 128);   //ST7735 1.8", rotación 1

Con lo aprendido hasta ahora, por fin es posible construir una interfaz para controlar un ventilador PWM, empleando una de las pantallas táctiles FT813, decidí utilizar una placa F411CE, por su tamaño compacto y porque sería mi primer placa STM32 usada en un proyecto para la PC. Usaré el dispositivo para controlar el ventilador lateral del gabinete. En algunas ocasiones ya sea por los días calurosos, el uso de algún juego demandante en la PC o bien alguna sesión de trabajo que implica el procesamiento de videos o una elevada carga de uso del GPU, resulta en que el chipset se calienta demasiado y me gustaría bajarle la temperatura.

El PCB del control lo instalaré en el lateral del gabinete, mas adelante me gustaría diseñar una ventana transparente en el lateral, donde habrá mejor forma de fijar tanto el ventilador como el TFT. La idea es mostrar como es que se puede usar uno de esos TFT en un proyecto.

Acá las piezas

Lo primero es construir un cabezal para sujetar la STM2F4111, permitiéndonos soldar todo el cableado para que luego no haya sorpresas. para ello usaré dos tiras de 40 pines hembra

Recortando los pines sobrantes y puliéndolos un poco con una lima. Así quedó luego de soldar en la cara posterior de la placa perforada

Para sujetar el TFT hay que armar un cabezal de 20 pines, retiramos los pines excedentes con unas pinzas de corte y luego pulimos el lateral del cabezal con una lima

Podemos aprovechar para instalar algunas tiras de pines macho en ángulo recto, que funcionarán como cabezales laterales para conectar los relevadores y algunos hilos de energía, hay que ubicar el cabezal del TFT de tal forma que sea posible instalar y retirar el TFT sin problemas

La pantalla tiene la capacidad de reproducir videos en formato avi con audio, así que podemos agregar un jack de 3.5 mm para poder usar esta característica y darle otro uso a la pantalla en cualquier momento.

Estos zócalos de superficie, viene con un par de centradores en la base, los podemos cortar para fijarlos de mejor forma en el PCB

El PCB del controlador ya va tomando forma

Primero toca conectar las uniones del MCU al TFT.

Aun estoy esperando algunas piezas para terminar de armar el controlador con el MCU F411CE, por eso he detenido un poco el avance del proyecto... cuando arribó ayer la placa STM32F407VG, aunque es un chip anterior, tiene una frecuencia base de 168 MHz, por las características que tiene el chip F407VG, cabe la posibilidad de experimentar un poco mas con el overclock, considerando todo el tiempo la generación de calor en el regulador 5V a 3v3.

Las placas F407 que tengo no pueden superar los 186 Mhz sin que aparezca algún fallo de lectura en el lector microSD externo o lo desconozca como dispositivo el sistema operativo. Parece que la versión VG tiene un poco menos restricciones con el manejo del reloj principal, ya que internamente el chip puede soportar cambios de frecuencia y cuenta con la electrónica para ello, vamos a poner a prueba esa característica midiéndola con algunos sketchs que con el tiempo se han ido afinando para saber si realmente tienen un efecto significativo los cambios de frecuencia en el reloj principal.

Para empezar conectaré el TFT en el bus SPI 1 y el lector externo en el bus SPI 2. No me fío del lector SDIO que viene con la placa, ya que este arreglo tiene algunos defectos en la librería SPI y muchos parámetros STM32-DMA y FIFO nativos por hardware de la plataforma STM32, aún no los he podido transferir al entorno de arduino, existen demasiadas capas HAL que van complicando las cosas al traducirlas a funciones dentro de la librería SPI.

La mejor aproximación que conozco la hizo Daniel en su núcleo alterno para STM32, simplificó muchas capas HAL en algunas funciones simples y lo mejor de todo, es que las agregó de tal forma a la librería SPI del núcleo, que puede aprovechar al máximo la librería SdFat que viene en el núcleo.

La limitante es que este arreglo SPI-SdFat solo puede reconocer memorias microSD de máximo 32 Gb. Es posible usar la librería SPI del núcleo para que funcione con la versión mas reciente de SdFat que está habilitada para reconocer memorias de mas de 64 Gb.

Esta es la flamante STM32F407VG, con 1 Mb de memoria y 168 Mhz de frecuencia base

Pienso colocarle pines largos en los dos cabezales, para facilitar pruebas futuras sin tener que desmontarlo todo de su PCB, además de que agruparé por colores las diferentes series de pines que tiene PAx, PBx, PCx, PDx y PEx. Agregué algo de soldadura extra en el cabezal microUSB ya que a mi modo de ver, viene muy frágil, no obstante es posible conectar un puerto miniUSB o un USB-C, en las líneas 5V, GND, D+ y D-. Utilizaré el datasheet de la placa para revisar este punto, ojalá y los pines D+ y D- estén disponibles en el pinout externo de la placa

Ojalá y lleguen pronto los elementos que faltan: resistencias SMD, capacitores SMD, los chips de conversión lógica y los sensores NTC-10K de película para construir las sondas de temperatura, me parece que aun están en la aduana.

Toca crear la variante BLACK_F407VG en el núcleo STM32 alterno, en tanto llegan las piezas restantes. Conectaré el TFT NHD-FT813 de 3.5" y el lector microSD, para hacer las pruebas con el cambio de frecuencias.

PD: la F411CE aun seguirá esperando...

Aún sigue en camino el pedido de piezas para construir los sensores de temperatura. La demora en estos tiempos que corren es normal, habrá que tener mas paciencia.

Finalmente tuve un tiempo libre para terminar de identificar por colores cada grupo de pines de la placa F407VG. Mediante prueba y error pude establecer la frecuencia máxima estable, quedó en 236 MHz, con apenas un incremento de 2-3 grados centígrados en la temperatura del encapsulado del microcontrolador. La frecuencia base es de 168 MHz

Los parámetros para establecer la frecuencia quedaron de esta forma:

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 236;  // 168   240
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 7;

Finalmente el pinout ha quedado así:

Voy a hacer las pruebas de funcionamiento con una pantalla de NHD 4.3" con chip FT813

Con las actualizaciones mas recientes en la librería GFX, creo que se podrían conectar pantallas como la ILI9341, ST7735, SD1306, SD1327 o la SD1331. En cuanto termine las pruebas con la FT813 voy a dedicarle un tiempo a revisar las librerías disponibles para ver como se pueden arreglar los constructores para cada pantalla. De la SD1327 sería teórico, ya que no cuento con una pantalla con ese chip

Afortunadamente he estado ocupado con el trabajo que recién va repuntando, esperemos que la situación actual en la que todos nos encontramos vaya reduciendo su fuerza y gradualmente retornemos a esto que se ha dado en llamar nueva normalidad.

Mis mejores deseos para todos, pronta resignación a todos quienes hemos perdido a compañeros de viaje y mucha fuerza para salir adelante.

En los pocos ratos libres he seguido experimentando con la F407VG, me topé con un fallo en el táctil, aprovecharé para dar una revisión a la librería, no sé si sea posible unificar las dos librerías en una sola (teensy 4.x y STM32), ya que ambas ya utilizan la ultima versión de la librería SdFat. Les tendré al tanto de los progresos.

Librería unificada para conectar pantallas FT81X/BT81X en STM32 o en Teensy 4x

Este fin de semana estuve trabajando en la librería para teensy 4.x, ajustándola para poder agregar placas STM32 del core alterno de danieleff. En ese core alterno para STM32, he podido agregar variantes como la F411CE, F407VG, F429i-DISCO y la Core7XXI. Sin embargo aun no he conseguido la meta: que funcione para ambos tipos de MCU.

Trabajé un tiempo modificando la librería para gameduino 2, para que funcione con la librería SdFat; pero en algún punto que no recuerdo a la fecha, terminé con una versión para STM32 y otra para teensy 4.x.

Ambas librerías funcionan correctamente teniendo como base la versión 2 oficial de SdFat, sin embargo, la modificación para STM32 por alguna razón me está dando fallas en el panel táctil de la pantalla NHD 4.3" con la placa F407VG. Al revisar las versiones de partida de ambas rutas, me he percatado que la versión para teensy está basada en la revisión mas reciente de la librería para gameduino 2, quizás allí podría radicar el fallo.

El vector de calibración del panel táctil de las pantallas FT81x/BT81x tiene 25 pares ordenados, en las placas teensy 4.x, se almacena usando la librería EEPROM default del IDE de arduino. Las placas STM32 no se llevan bien con esa librería, existen versiones que emulan en parte de la memoria flash una memoria de ese tipo, pero en las pruebas que he podido hacer saltan errores en la calibración del panel táctil.

La solución para STM32 fue utilizar la librería AT24Cxx para gestionar el vector en una memoria EEPROM externa. La librería unificada debe poder gestionar una u otra opción, con las definiciones correctas debe ser factible que convivan ambas librerías (EEPROM.h y AT24Cxx.h) sin que interfieran entre sí.

La clave debe ser el utilizar dentro de la librería unificada, estas líneas para placas STM32

#if defined(ARDUINO_TEENSY32)
 #endif

Para teensy 4x

#if defined(TEENSYDUINO)
 #endif

Pondré en práctica esto en la librería unificada, conforme vaya progresando les iré compartiendo.

Primer paso: configuración para la librería SdFat

Con estas líneas podré establecer los parámetros de configuración inicial en el archivo GDT4Xv134.h para teensy 4x y para STM32

#define CS 					10
#if defined(ARDUINO_ARCH_STM32)

 #define CS 			   PA4
 #define STM32_CPU        4073     //4073 F407VG-Danieleff y SdFat V2 oficial

 #define SetSDSpeed         36  
 
 #if(STM32_CPU == 4073) 
    #define SD_PIN        PB12  //PB12 SPI2-F407VG
  #endif  

#endif

Los constructores para SdFat deben definirse al principio del archivo GDT4Xv134.ccp. Para teensy 4x debe llamarse el constructor para SDIO, en el caso de las placas STM32, debe definirse claramente el puerto SPI en el que se colocará el lector microSD externo. Hay que recordar que la pantalla utiliza el bus SPI 1. Con SDIO no es necesario establecer otro bus SPI. Estas son las líneas con los constructores correctos para cada familia de MCU:

#ifdef TEENSYDUINO 
 SdFs SD;
#endif

#if defined(ARDUINO_ARCH_STM32)

 #if(STM32_CPU == 4073)
//                      SPI-bus,       MOSI,  MISO,  SCK
   extern SPIClass SPI_2(SPI2, PB15, PB14, PB10);   //M4DEMO, F407VG
   #define SD_CONFIG SdSpiConfig(SD_PIN, DEDICATED_SPI, SD_SCK_MHZ(SetSDSpeed), &SPI_2)
 #endif  

 SdFs SD;
#endif

Para activar el lector SDIO en teensy 4x o el lector externo en STM32, debe realizarse inmediatamente después de que se active el bus SPI-1 en el que está conectado el TFT. Este llamado se realiza dentro de la función

void GDClass::begin(int cs)

Que está ubicada en el archivoGDT4Xv134.ccp. Estas son las líneas que hay que adicionar:

  #ifdef TEENSYDUINO  	  
    SD.begin(SdioConfig(FIFO_SDIO));
  #endif

  #if defined(ARDUINO_ARCH_STM32)
	SD.begin(SD_CONFIG);
  #endif

Hasta aquí la librería unificada puede utilizar la librería SdFat V2 para gestionar imagenes, audio y video tanto en la teensy 4.1 como en la F407VG.

La placa F407VG viene con un lector SDIO integrado en el PCB, sin embargo la librería de gestión no está optimizada. Intenté realizar pruebas como si se tratar de la teensy 4.1, pero no hay respuesta en el lector. Anteriormente pude hacer funcionar el lector SDIO de una M4-DEMO, pero no reproduce audio correctamente y en el tema de velocidad, tiene la mitad de la que se puede conseguir con un lector externo.

Para el segundo paso, me falta afinar las líneas de configuración del vector táctil para STM32.

Partiendo de las líneas del archivo ccp, en las que se define la rutina de almacenamiento del vector de calibración del panel táctil, basado en la librería EEPROM para la placa teensy; podemos obtener su equivalente para las placas STM32 y la librería AT24Cxx.

Con los llamados correctos es posible que se pueda usar cualquiera de las dos librerías, dependiendo de la placa en la que se instale la pantalla.

Estas son las líneas que actualmente tiene la librería:

  if ((EEPROM.read(0) == 0)) 
   {
      self_calibrate();
      for (int i = 0; i < 24; i++)
        {
         EEPROM.write(1 + i, GDTR.rd(REG_TOUCH_TRANSFORM_A + i));
        }
      EEPROM.write(0, 0x1);
    } else {
      for (int i = 0; i < 24; i++)
        {
         GDTR.wr(REG_TOUCH_TRANSFORM_A + i, EEPROM.read(1 + i));
        }
    }

En el IDE de arduino, el llamado general placas teensy es este:
TEENSYDUINO

Para las placas STM32, es:
ARDUINO_ARCH_STM32

Una vez revisadas las instrucciones equivalentes, las líneas que voy a probar son:

#ifdef TEENSYDUINO  	  	
  if ((EEPROM.read(0) == 0)) 
   {
      self_calibrate();
      for (int i = 0; i < 24; i++)
        {
         EEPROM.write(1 + i, GDTR.rd(REG_TOUCH_TRANSFORM_A + i));
        }
      EEPROM.write(0, 0x1);
    } else {
      for (int i = 0; i < 24; i++)
        {
         GDTR.wr(REG_TOUCH_TRANSFORM_A + i, EEPROM.read(1 + i));
        }
    }
#endif

#if defined(ARDUINO_ARCH_STM32)
AT24Cxx eep(i2c_address, 32);
if (eep.read(0) != 0x1) {
self_calibrate();
      for (int i = 0; i < 24; i++) 
      {eep.write(1 + i, GDTR.rd(REG_TOUCH_TRANSFORM_A + i));
      }
      eep.write(0, 0x1);  
    } else {
           for (int i = 0; i < 24; i++)
           {
           GDTR.wr(REG_TOUCH_TRANSFORM_A + i, eep.read(1 + i));
           }
    }
#endif

Van ubicadas dentro de la función begin(), después de la asignación de los timmings del TFT.

Parece que la rutina para crear el vector táctil cuando hay que recalibrarlo o bien leerlo desde la EEPROM cuando ya lo tenemos, funciona mejor de lo que esperaba.

En el archivo .h solo hay que seleccionar el tamaño de pantalla correcto (3.5", 4.3", 5" y 7") y la placa en la que lo vamos a usar. Al momento se pueden usar estas placas: teensy 4.1, teensy 4, teensy 3.6, STM32F407VG, STM32F411CE. Este fin de semana tengo planeado actualizar el repositorio con los ajustes recientes.

Estoy explorando otras opciones como la nucleo F767ZI o la Core7XXI, pero presentan algún tipo de fallo en el lector microSD, creo que estoy pasando por alto alguna configuración del bus SPI o en la librería SdFat, mas adelante investigaré este detalle, ya que no es el objetivo de la librería usar este tipo de placas debido a sus dimensiones.

Subiré avances del proyecto con el reproductor de videos, ya he podido mejorar las ventanas que permiten seleccionar el video, reproducirlo y regresar al menú de selección, sin que salte algún error, también mejoré la rutina de asignación de tags, la que permite colocar el nombre del archivo y la que permite dibujar mas de 15 opciones por ventana, he podido conseguir que se puedan presentar menús de hasta 28 entradas por ventana. Al momento el reproductor cuenta con 336 archivos de video, es decir, 12 ventanas con 28 videos cada una.

La memoria microSD instalada es de 128 Gb.

Conectar fuentes de señales eléctricas a un MCU cualquiera, con la finalidad de medir una variable como presión, temperatura, peso, inclinación etc., siempre nos lleva a considerar si el valor que estamos leyendo del dispositivo es el correcto. Cuando contamos con una referencia y podemos comparar el resultado, podemos decidir si el dispositivo externo está funcionando dentro del comportamiento esperado. No obstante en ciertos momentos vemos valores que no son los esperados. Esto se debe a la presencia errores asociados con el cableado, también por la presencia de alguna fuente electromagnética en la red cercana, a saber: un refrigerador, un aire acondicionado, un taladro, etc.

Hace un tiempo traté de medir la temperatura de la PC, usando sensores NTC de película que recuperé de un panel frontal que ya no funciona. Con el tiempo caí en cuenta que las lecturas no eran las esperadas, ya que la variación que obtenía era de hasta 3 grados, mucho mas allá de los 0.3C reportados en el datasheet. Sin alternativas por explorar opté por retirar el sensor que había ensamblado de la PC.

Hace unos días estuve buscando librerías avanzadas que permitieran implementar alguna especie de filtro digital en las señales, encontré esta librería Arduino_filters y funciona muy bien en el teensy 4.1, pero es incompatible con el núcleo alterno STM32 de danieleff, por lo que no lo puedo usar en las placas F411CE o F407VG.

También encontré este tutorial para Smoothing en la biblioteca de tutoriales de arduino.

Me pareció que la aproximación que señalan es simple, pero muy poderosa. Con algunos ajustes al código para graficar señales en tiempo real que estoy trabajando para el controlador de la PC, por fin pude obtener un mejor comportamiento en las lecturas de los sensores NTC de película.

Este tipo de sensores tienen varias ventajas muy importantes:

  • Toleran distancias de cableado de mas de 40 cm
  • El circuito es muy simple, consiste en un divisor de voltaje resistivo. La lectura se obtiene en la unión entre las dos resistencias (la de referencia y el sensor NTC)
  • Alta velocidad de adquisición de datos
  • Calibración simple por aproximación lineal con solo dos puntos de referencia
  • Flexibilidad física
  • Espesor mínimo del sensor
  • La sensibilidad no es afectada por la manipulación del cableado

He conectado dos sensores, solo resta ajustar los dos puntos de calibración de cada sensor NTC, pero esta primer aproximación para "filtrar digitalmente" la señal me ha sorprendido.

Detalle del comportamiento de cada NTC. La gráfica muestra los datos directos del sensor y la señal filtrada de cada uno.

MCU: Black F407VG
TFT: Riverdi BT817 5"
librería: GDT4Xv134
Core STM32: alternativo de danieleff

Sketch
GDT4Xv134_Grafica_lineal_NTC0.zip (9.2 KB)

Excelente aporte @TFTLCDCyg.
Me pasó hace dias que trabaja con un sensor de Latidos de corazón y O2 y los resultados eran muy malos pero alguien se tomó el trabajo de usar unos filtros digitales que mejoraron notablemente los resultados. Quedé muy sorprendido, y ahora tambien siempre que puedo uso esos filtros.