Display ILI9341 - pensactius/Tutoriales GitHub Wiki

Introducción

En este tutorial veremos como usar pantallas basadas en el chipset ILI9341 usando placas Arduino UNO (y similares) y placas ESP8266/ESP32. Los módulos TFT ILI9341 contienen un controlador de pantalla con el mismo nombre: ILI9341. Es un controlador de pantalla a color que usa protocolo de interfaz SPI y requiere 4 o 5 pines de control, son baratas y fáciles de usar. La resolución de estas pantallas es de 240 x 320 (76800 pixels en total). El controlador ILI9341 trabaja a 3.3V y no soportan 5V (no son tolerantes a 5V).

Nunca conectes estas pantallas directamente a los pines de Arduino UNO ya que puedes dañar el controlador de pantalla ILI9341.

Pinout

En la siguiente figura puede verse un resumen de los diferentes usos de los pines de conexión: ILI9341 pinout

Estas pantallas tienen 14 pines, de los cuales 9 pines se usan para la pantalla y 5 son para la interfaz táctil. En la parte de la pantalla los 9 pines son:

  • VCC (5V)
  • GND (Ground)
  • CS (Chip Select)
  • RST (Reset)
  • DC (o D/C: data/command)
  • MOSI (o SDI: Master-Out Slave-In, o Serial Data In)
  • SCK (Clock)
  • LED (o BL: Back light LED)
  • MISO (o SDO: Master-In Slave-Out, o Serial Data Out)

Conexión

Como hemos explicado anteriormente, el controlador de pantalla ILI9341 funciona a 3.3V. El módulo de pantalla se alimenta con 5V (VCC) que podemos alimentar desde los 5V de nuestra placa. El módulo tiene un regulador de tensión de 3.3V para alimentar el controlador de pantalla con 3.3V a partir de estos 5V.

Pero para el resto de pines deberemos "poner algo" entre medio que reduzca el voltaje de salida de los pines de 5V a 3.3V.

Si trabajas con una placa ESP8266, ESP32 o cualquier placa que funcione a 3.3V puedes saltarte esta parte y pasar directamente a Conexión con otras placas

Conexión a placas con lógica de 5V (Arduino UNO y similares)

En general, para reducir el voltaje de 5V que dan los pines de salida de una placa como Arduino UNO hasta los 3.3V que requiere el módulo ILI9341, disponemos de varias alternativas:

  • Usar resistencias a modo de divisor de tensión
  • Utilizar un módulo de conversión de lógica (en inglés Level Shifter o Logic Level Converter)

En este tutorial veremos los dos métodos.

Divisor de tensión

Como se puede observar los pines del módulo TFT se conectan a la placa Arduino UNO (o cualquier otra con logica de 5V) usando resistencias a modo de divisores de tensión. Cada divisor de tensión consta de un par de resistencias de 2.2K y 3.3K, lo que reduce el voltaje de 5V a 3V que ya es suficiente.

Fíjate que la alimentación de la pantalla (VCC) se alimenta directamente a 5V.

Por tanto, el TFT ILI9341 está conectado a la placa Arduino como sigue (cada uno usando su divisor de tensión):

  • CS pin 8
  • RST pin 9
  • D/C pin 10
  • MOSI pin 11
  • SCK pin 13

El resto de pines se conectan como sigue:

  • VCC pin 5V
  • GND cualquier pin GND
  • LED (BL) pin 5V (recomendable una resistencia de 220ohm)
  • MISO no conectado

Puedes ahorrarte un pin conectando RST al pin de RESET de Arduino UNO -RST en Arduino Pro/Mini- con su correspondiente divisor de tensión.

Conversión de nivel de lógica - Level Shifters

El método utilizado anteriormente funciona pero no es el más óptimo, a parte de usar una gran cantidad de resistencias extras. Otra alternativa es usar conversores de lógica como este módulo que puedes adquirir en Aliexpress.

Necesitarás usar dos conversores de lógica si vas a usar todas las funcionalidades de la pantalla (táctil y/o SD). Pero si sólo vas a usar la pantalla sin las funciones táctil con un único módulo ya tienes suficiente.

En el siguiente diagrama puedes ver un ejemplo de como se podría conectar.

Puede parecer algo complejo al principio, pero es mas simple de lo que parece. Estos módulos están divididos en dos áreas:

  • nivel alto: Conectaremos la alimentación y lógica de 5V
  • nivel bajo: Conectaremos la alimentación y lógica de 3.3V

Fíjate que cada área tiene su alimentación de 5V y 3.3V. Aquí puedes conectar directamente los 5V y 3.3V desde la placa Arduino. A priori puede parecer extraño que necesitemos alimentar también a 3.3V, pero piénsalo bien, sino ¿de dónde salen los 3.3V de los pines de la lógica baja?

Destacar que estos módulos se pueden usar tanto para convertir de 5V a 3.3V como a la inversa, es decir, de 3.3V a 5V. Esto puede ser útil si tenemos placas de 3.3V como ESP8266/ESP32 o Raspberry Pi que han de interactuar con dispositivos que funcionan a 5V (como las pantallas de 16x2 caracteres).

Conexión con otras placas

ESP8266

Conectaremos la pantalla ILI9341 a la placa ESP8266 de la siguiente forma:

ILI9341 SPI TFT ESP8266
VCC 3.3V
GND GND
CS D2 (GPIO4)
RESET RST
DC D4 (GPIO2)
SDI/MOSI D7 (GPIO13)
SCK D5 (GPIO14)
LED 3.3V
SDO/MISO NO CONECTADO

Obsérvese que estamos usando SPI por hardware (que es más rápido) para controlar la pantalla. La comunicación SPI hardware en el ESP8266 se realiza mediante los pines E/S D5 (SCK), D6 (MISO) y D7 (MOSI). Los pines de chip select (CS) y Data/Command (DC) son configurables por software y no es determinante qué pines se usan.

Programación con Arduino

A la hora de programar las pantallas ILI9341 hay varias librerías a escoger. La más utilizada suele ser la librería Adafruit ILI9341. Ésta a su vez requiere la librería Adafruit GFX Library por tanto habría que instala también. Para placas de 32 bits como las ESP8266 y ESP32 hay otra librería más versátil llamada TFT_eSPI. Por ahora utilizaremos las librerías de Adafruit que, aunque menos optimizadas, son más sencillas de utilizar.

Instalación de Adafruit GFX Library

Tanto la librería Adafruit ILI9341 como la Adafruit GFX Library pueden instalarse directamente desde el Gestor de Librerías del editor de Arduino.

Ejemplo Básico

El siguiente ejemplo para placa Arduino UNO y similares muestra el típico mensaje Hola Mundo por pantalla. Puedes encontrar la versión para ESP8266 más abajo

Ejemplo Básico - Arduino UNO

#include "SPI.h"
#include <Adafruit_GFX.h>       // include Adafruit graphics library
#include <Adafruit_ILI9341.h>   // include Adafruit ILI9341 TFT library
constexpr int TFT_CS = 8;
constexpr int TFT_RST = 9;
constexpr int TFT_DC = 10;
// initialize ILI9341 TFT library with hardware SPI module
// SCK (CLK) ---> Arduino 13
// MOSI(DIN) ---> Arduino 11
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
void setup() {
  // Inicializa el dispositivo ILI9341
  tft.begin();  
  // Llena toda la pantalla de color negro (borra pantalla)
  tft.fillScreen(ILI9341_BLACK);
}

void loop() {
  // Coordenadas en pixels dónde aparecerá el siguiente texto
  tft.setCursor(24, 50);

  // Establece el color del texto
  tft.setTextColor(ILI9341_YELLOW);

  // Muestra el mensaje
  tft.println("Hola Mundo!");
}  

En el caso de conectar el pin RST de la pantalla al pin RST de la placa sustituye esta línea:

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

por

Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);

Ejemplo Básico - ESP8266

#include "SPI.h"
#include <Adafruit_GFX.h>       // include Adafruit graphics library
#include <Adafruit_ILI9341.h>   // include Adafruit ILI9341 TFT library
constexpr int TFT_CS = D2;
constexpr int TFT_DC = D4;
// initialize ILI9341 TFT library with hardware SPI module
// SCK (CLK) ---> NodeMCU pin D5 (GPIO14)
// MOSI(DIN) ---> NodeMCU pin D7 (GPIO13)
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);

void setup() {
  // Inicializa el dispositivo ILI9341
  tft.begin();  
  // Llena toda la pantalla de color negro (borra pantalla)
  tft.fillScreen(ILI9341_BLACK);
}

void loop() {
  // Coordenadas en pixels dónde aparecerá el siguiente texto
  tft.setCursor(24, 50);

  // Establece el color del texto
  tft.setTextColor(ILI9341_YELLOW);

  // Muestra el mensaje
  tft.println("Hola Mundo!");
}  

Resumen de la API Adafruit GFX

El ejemplo anterior es muy básico pero la librería Adafruit GFX permite muchas opciones como dibujar figuras geométricas, imágenes etc. Los ejemplos incorporados en la librería son una buena forma de aprender a usarla. El ejemplo graphicstest hace uso extensivo de los comandos más usados.

A continuación se muestra un pequeño resumen de los comandos de la API que más se suelen usar:

/**
 * Dibuja píxel individual
 */
void drawPixel(int16_t x, int16_t y, uint16_t color);

/**
 * Borra pantalla
 */
void fillScreen(uint16_t color);

/**
 * Líneas
 */
void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color)
void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);

/**
 * Rectángulos
 */
void drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
void fillRect(int16_t x0, int16_t y0, int16_t w, int16_t h, uint16_t color);

/**
 * Círculos
 */
void drawCircle(int16_t x, int16_t y, int16_t r, uint16_t color);
void fillCircle(int16_t x, int16_t y, int16_t r, uint16_t color);

/**
 * Rectángulos Redondeados
 */
void drawRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t radius, uint16_t color);
void fillRoundRect(uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, uint16_t radius, uint16_t color);

/**
 * Triángulos
 */
void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color);
void fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color);

/**
 * Textos y caracteres
 *
 * Para escrbir un único caracter se puede usar drawChar
 *
 * Para escribir textos más amplios se usa la función de Arduino
 * print/println, precedida de la variable objeto que controla
 * la pantalla. El tamaño, color y posición se pueden configurar
 * previamente usando las funciones mostradas.
 */
void drawChar(uint16_t x, uint16_t y, char c, uint16_t color, uint16_t bg, uint8_t size);
void setCursor(int16_t x0, int16_t y0);
void setTextColor(uint16_t color);
void setTextColor(uint16_t color, uint16_t backgroundcolor);
void setTextSize(uint8_t size);
void setTextWrap(boolean w);

/**
 * Rotar pantalla
 *    rotation: 0, 1, 2, 3
 */
void setRotation(uint8_t rotation);

// Color definitions
#define ILI9341_BLACK 			0x0000      ///<   0,   0,   0
#define ILI9341_NAVY 			0x000F      ///<   0,   0, 123
#define ILI9341_DARKGREEN 		0x03E0   	///<   0, 125,   0
#define ILI9341_DARKCYAN 		0x03EF    	///<   0, 125, 123
#define ILI9341_MAROON 			0x7800      ///< 123,   0,   0
#define ILI9341_PURPLE 			0x780F      ///< 123,   0, 123
#define ILI9341_OLIVE 			0x7BE0      ///< 123, 125,   0
#define ILI9341_LIGHTGREY 		0xC618   	///< 198, 195, 198
#define ILI9341_DARKGREY 		0x7BEF    	///< 123, 125, 123
#define ILI9341_BLUE 			0x001F      ///<   0,   0, 255
#define ILI9341_GREEN 			0x07E0      ///<   0, 255,   0
#define ILI9341_CYAN 			0x07FF      ///<   0, 255, 255
#define ILI9341_RED 			0xF800      ///< 255,   0,   0
#define ILI9341_MAGENTA 		0xF81F     	///< 255,   0, 255
#define ILI9341_YELLOW 			0xFFE0      ///< 255, 255,   0
#define ILI9341_WHITE 			0xFFFF      ///< 255, 255, 255
#define ILI9341_ORANGE 			0xFD20      ///< 255, 165,   0
#define ILI9341_GREENYELLOW 	0xAFE5 		///< 173, 255,  41
#define ILI9341_PINK 			0xFC18 

Conversor RGB a 565

Fuentes Personalizadas

Bibliografía

⚠️ **GitHub.com Fallback** ⚠️