Componentes · 17 min de lectura

ILI9341 Arduino: conectar la pantalla TFT, táctil e imágenes SD

Cómo conectar una pantalla TFT ILI9341 a Arduino: nivel de 3,3 V en el Uno, Adafruit GFX, táctil XPT2046, BMP desde SD, ESP32 con TFT_eSPI y la pantalla blanca.

Conectar una ILI9341 a Arduino es la forma más barata y extendida de añadir a tu proyecto una pantalla de 240×320 píxeles con 65 mil colores. Estos módulos TFT de 2,4 y 2,8 pulgadas sobre placa roja se conectan por SPI con solo unos pocos cables, y las versiones táctiles llevan además un controlador táctil XPT2046 y una ranura para tarjeta microSD. Con un solo módulo puedes mostrar gráficos en color, botones táctiles e imágenes leídas de la tarjeta. Es ideal para menús, paneles de control, juegos y marcos de fotos donde una OLED o una LCD de caracteres ya no basta.

En esta guía aprenderás paso a paso cómo funciona el módulo, cómo conectar con seguridad las salidas de 5 V del Arduino Uno a las entradas de 3,3 V de la pantalla, cómo dibujar textos, formas y colores con las librerías Adafruit_ILI9341 y Adafruit GFX, cómo leer el táctil y cómo mostrar imágenes BMP desde una tarjeta SD. Después veremos el dibujo mucho más rápido en el ESP32 con TFT_eSPI, el uso de MicroPython en la Raspberry Pi Pico y todas las causas del problema de la "pantalla blanca", con el que casi todo el mundo se encuentra alguna vez.

Módulo de pantalla TFT a color ILI9341
Módulo de pantalla TFT a color ILI9341: 240×320 píxeles, conexión SPI y 65 mil colores. Las versiones táctiles también llevan en la placa un chip XPT2046 y una ranura microSD.

¿Qué es la pantalla TFT ILI9341 y cómo funciona?

El ILI9341 es el chip controlador que hay detrás del cristal. Contiene unos 172 KB de memoria de imagen (GRAM) donde caben los 240×320 píxeles. El Arduino envía comandos y datos de color a esa memoria por SPI, y el chip refresca la imagen por sí solo decenas de veces por segundo. Por eso la imagen no tiene que guardarse en la RAM del Arduino: incluso un Uno con 2 KB de RAM puede manejar una pantalla grande a color. Para dibujar algo, primero se elige una ventana (x, y, ancho, alto) y luego se envían los píxeles de esa ventana uno tras otro. El pin DC indica si el byte enviado es un comando (LOW) o un dato (HIGH). Los colores suelen enviarse en formato RGB565, es decir, 16 bits por píxel: 5 bits de rojo, 6 de verde y 5 de azul. Cómo funciona el bus SPI lo tienes explicado en detalle en Qué es SPI.

CaracterísticaValor
Chip controladorILI9341
Resolución240×320 píxeles (320×240 en horizontal)
Color65.536 colores con RGB565 (el chip admite 262 mil)
Tamaños2,2", 2,4", 2,8" y 3,2" (todos 240×320)
InterfazSPI de 4 hilos: CS, DC, SCK, MOSI (MISO para leer)
Alimentación (VCC)3,3–5 V (la placa lleva un regulador de 3,3 V)
Nivel lógico3,3 V (no tolera 5 V)
ConsumoUnos 0,3–0,6 W, casi todo de la retroiluminación
TáctilResistivo, controlador XPT2046 (en los modelos táctiles)
Hardware extraRanura para tarjeta microSD (pines SPI propios)

¿2,4 o 2,8 pulgadas? Módulo SPI frente a shield para Uno

CaracterísticaMódulo SPI 2,4"Módulo SPI 2,8"Shield 2,4" para Uno
Resolución240×320240×320240×320
ConexiónSPI, con cablesSPI, con cablesParalelo de 8 bits, se pincha encima del Uno
Pines usados5 para la pantalla, 8–9 con táctil y SD5 para la pantalla, 8–9 con táctil y SDCasi todos (D2–D9, A0–A4, D10–D13 para la SD)
ControladorILI9341ILI9341Variable: ILI9341, ILI9325, ST7789 y otros
LibreríaAdafruit_ILI9341, TFT_eSPIAdafruit_ILI9341, TFT_eSPIMCUFRIEND_kbv
TáctilXPT2046 (SPI)XPT2046 (SPI)Analógico de 4 hilos (librería TouchScreen)
ESP32 y PicoCompatibleCompatiblePensado para Uno y Mega

Este artículo trata del módulo SPI, porque también funciona con el ESP32 y la Pico y deja libres la mayoría de los pines del Uno. Los dos módulos SPI tienen exactamente los mismos pines y el mismo código; la pantalla de 2,8 pulgadas tiene píxeles algo más grandes, así que es más fácil acertar en los botones táctiles. Si tu pantalla es un shield que se pincha directamente sobre el Uno, las librerías SPI no pueden manejarla y el resultado suele ser una pantalla blanca. Para ese tipo de shield instala la librería MCUFRIEND_kbv, lee el identificador del controlador con tft.readID() (0x9341 en el ILI9341) e inicialízala con tft.begin(ID). Si buscas una alternativa más pequeña pero más nítida, mira Pantalla TFT ST7789, y para comparar todas las opciones, Tipos de pantallas para Arduino.

Pines del ILI9341 y tabla de conexiones

En un borde del módulo está el conector principal de 14 pines: los 9 primeros son para la pantalla y los 5 últimos, que empiezan por T_, para el táctil. Los 4 pines del borde opuesto (SD_CS, SD_MOSI, SD_MISO, SD_SCK) van a la ranura de la tarjeta. Los tres dispositivos pueden compartir el mismo bus SPI (SCK, MOSI, MISO); solo sus pines CS tienen que ser distintos. La tabla coincide con todos los códigos de este artículo; en la Pico, el táctil va a un bus SPI aparte por la diferencia de velocidad.

Pin del móduloArduino Uno (con conversor de nivel)ESP32Raspberry Pi Pico
VCC5V3V33V3(OUT)
GNDGNDGNDGND
CSD10GPIO 15GP17
RESETD8GPIO 4GP21
DCD9GPIO 2GP20
SDI (MOSI)D11GPIO 23GP19
SCKD13GPIO 18GP18
LED3.3V3V33V3(OUT)
SDO (MISO)D12 (directo)GPIO 19GP16
T_CLKD13GPIO 18GP10
T_CSD7GPIO 21GP13
T_DIND11GPIO 23GP11
T_DOD12 (directo)GPIO 19GP12
T_IRQD2 (directo)LibreLibre
SD_CSD4GPIO 5Libre
SD_MOSI / SD_MISO / SD_SCKD11 / D12 / D13GPIO 23 / 19 / 18Libre
El pin VCC de los módulos ILI9341 admite 5 V, pero los pines de señal son solo de 3,3 V. El regulador de la placa únicamente baja la alimentación; en las líneas CS, DC, RESET, SCK y MOSI no hay conversión de nivel. Conectar directamente las salidas de 5 V del Uno suele acabar en una pantalla blanca y a veces daña el chip para siempre. El puente J1 de la parte trasera sirve para saltarse el regulador: ciérralo con estaño solo si alimentas VCC con 3,3 V. Con J1 cerrado, meter 5 V en VCC quema la pantalla.

Conversión de nivel a 3,3 V en el Arduino Uno

El ESP32 y la Raspberry Pi Pico ya trabajan a 3,3 V, así que puedes conectar la pantalla directamente. En placas de 5 V como el Uno, el Nano y el Mega, en cambio, cada línea que va del Arduino a la pantalla debe bajarse a 3,3 V: CS, DC, RESET, SCK, MOSI y, si usas el táctil y la SD, T_CLK, T_DIN, T_CS, SD_CS, SD_MOSI y SD_SCK. Las líneas SDO, T_DO, SD_MISO y T_IRQ, que van de la pantalla al Arduino, no necesitan conversor: el Uno lee como HIGH cualquier tensión por encima de 3 V, y una salida de 3,3 V lo cumple. En la práctica hay cuatro opciones:

  • Buffer 74HC4050 (la solución más limpia): se alimenta a 3,3 V, admite 5 V en sus entradas y convierte 6 líneas en un solo chip. Es rápido y funciona sin problemas con SPI a 8 MHz. El antiguo CD4050 también sirve, pero es lento; si la imagen sale corrupta tendrás que bajar la velocidad del SPI. Para la pantalla sola bastan 5 líneas; con táctil y SD se suman T_CS y SD_CS, en total 7, así que usa un segundo chip o un divisor de tensión para la séptima.
  • Divisores de tensión con resistencias: en cada línea pon 1 kΩ entre el pin del Arduino y el de la pantalla, y 2 kΩ entre el pin de la pantalla y GND; obtienes 5 V × 2 / 3 ≈ 3,3 V. Puedes calcular otras parejas de resistencias con la calculadora de divisor de tensión. Es barato, pero 10 resistencias para 5 líneas llenan la protoboard.
  • Módulo conversor de nivel ya hecho: los módulos de 4 u 8 canales con MOSFET BSS138 se cablean fácilmente, pero sus resistencias pull-up suavizan los flancos de la señal a altas velocidades. Si la imagen sale corrupta, baja el SPI a 4 MHz con tft.begin(4000000). Tienes los métodos comparados en Conversor de nivel lógico.
  • El método que debes evitar: el popular truco de "una resistencia de 10 kΩ en serie en cada línea" descarga el exceso de tensión en los diodos de protección internos del chip. Puede funcionar un tiempo, pero es inestable y a la larga puede dañar la pantalla.

Paso a paso: primera prueba con Adafruit_ILI9341

  1. Abre el Gestor de librerías del Arduino IDE, busca Adafruit ILI9341 e instálala. Cuando pregunte por las dependencias, elige Install all para que se instalen también Adafruit GFX y Adafruit BusIO. Si es tu primera librería, te ayudará Cómo añadir una librería en Arduino.
  2. Para el táctil, instala además la librería XPT2046_Touchscreen de Paul Stoffregen. La librería SD ya viene con el Arduino IDE.
  3. Conecta la pantalla según la tabla de arriba, a través de un conversor de nivel en el Uno. En la primera prueba puedes dejar libres los pines del táctil y de la SD.
  4. Carga el siguiente código y abre el Monitor Serie a 9600 baudios. En la pantalla deberían aparecer textos y formas, y en el Monitor Serie los códigos de diagnóstico de la pantalla.
  5. Prueba también los ejemplos incluidos: Archivo > Ejemplos > Adafruit ILI9341 > graphicstest mide cuántos microsegundos tarda cada operación de dibujo.
C++ (Arduino IDE)
1#include <SPI.h>
2#include <Adafruit_GFX.h>
3#include <Adafruit_ILI9341.h>
4
5#define TFT_CS  10   // ekran seçme / chip select
6#define TFT_DC  9    // komut/veri seçimi / command/data select
7#define TFT_RST 8    // donanım reset / hardware reset
8
9Adafruit_ILI9341 tft(TFT_CS, TFT_DC, TFT_RST);   // donanım SPI: D11 MOSI, D13 SCK / hardware SPI
10uint16_t orange;                                  // kendi rengimiz / our own colour
11
12void setup() {
13  Serial.begin(9600);
14  tft.begin();                                    // Uno'da 8 MHz SPI / 8 MHz SPI on Uno
15
16  // Teşhis: çalışan ekranda 0x94 ve 0xC0 beklenir / Diagnostics: a working display reports 0x94 and 0xC0
17  Serial.print(F("Power Mode: 0x"));
18  Serial.println(tft.readcommand8(ILI9341_RDMODE), HEX);
19  Serial.print(F("Self Diagnostic: 0x"));
20  Serial.println(tft.readcommand8(ILI9341_RDSELFDIAG), HEX);
21
22  tft.setRotation(1);                             // yatay, 320x240 / landscape, 320x240
23  tft.fillScreen(ILI9341_BLACK);
24  orange = tft.color565(255, 128, 0);             // RGB'den RGB565'e / RGB to RGB565
25
26  tft.setTextColor(ILI9341_WHITE);
27  tft.setTextSize(3);                             // 18x24 piksel karakter / 18x24 px characters
28  tft.setCursor(10, 10);
29  tft.print(F("BlueGrays"));
30  tft.setTextColor(ILI9341_CYAN);
31  tft.setTextSize(2);
32  tft.setCursor(10, 45);
33  tft.print(F("ILI9341 320x240"));
34
35  tft.fillRect(10, 75, 90, 60, ILI9341_RED);                  // dolu dikdörtgen / filled rectangle
36  tft.drawRect(115, 75, 90, 60, ILI9341_GREEN);               // çerçeve / outline
37  tft.fillCircle(265, 105, 30, ILI9341_BLUE);                 // dolu daire / filled circle
38  tft.fillRoundRect(10, 150, 140, 50, 10, orange);            // yuvarlak köşeli düğme / rounded button
39  tft.drawTriangle(180, 200, 240, 150, 300, 200, ILI9341_YELLOW);
40  tft.drawFastHLine(0, 220, 320, ILI9341_MAGENTA);            // yatay çizgi / horizontal line
41}
42
43void loop() {
44  // Arka plan rengiyle yazınca eski rakam silinir, ekran titremez / writing with a background colour erases the old digits, no flicker
45  tft.setTextColor(ILI9341_WHITE, orange);
46  tft.setTextSize(2);
47  tft.setCursor(22, 167);
48  tft.print(millis() / 1000);
49  tft.print(F(" s"));
50  delay(200);
51}
FunciónQué hace
tft.begin(frecuencia)Inicia la pantalla; sin frecuencia usa SPI a 8 MHz en el Uno y a 40 MHz en el ESP32
tft.setRotation(0–3)Elige la orientación: 0 y 2 vertical (240×320), 1 y 3 horizontal (320×240)
tft.fillScreen(color)Pinta toda la pantalla de un color
tft.setTextColor(texto, fondo)Fija el color del texto; con color de fondo sobrescribe limpiamente el texto anterior
tft.setTextSize(n)Amplía el texto n veces; tamaño 1 = caracteres de 6×8 píxeles
tft.drawRect / fillRect(x, y, ancho, alto, color)Rectángulo con borde o relleno
tft.fillRoundRect(x, y, ancho, alto, r, color)Rectángulo relleno con esquinas redondeadas; ideal para botones
tft.drawCircle / fillCircle(x, y, r, color)Círculo o círculo relleno
tft.color565(r, g, b)Convierte valores RGB de 0–255 en un color de 16 bits
tft.readcommand8(comando)Lee un registro de la pantalla (MISO debe estar conectado); para diagnosticar fallos

La librería trae constantes de color listas para usar (19, como ILI9341_RED, ILI9341_NAVY e ILI9341_ORANGE); para un color propio usa color565(). Esta función coloca uno junto a otro los 5 bits altos del rojo, los 6 bits altos del verde y los 5 bits altos del azul: color = (R >> 3) << 11 | (G >> 2) << 5 | (B >> 3). Para el naranja (255, 165, 0), por ejemplo, 31 << 11 = 0xF800 y 41 << 5 = 0x0520 se combinan en 0xFD20, que es justo el valor de ILI9341_ORANGE en la librería. El verde recibe un bit más porque el ojo humano es más sensible al verde.

Borrar con fillScreen() y volver a escribir cada vez los números que cambian hace que la pantalla parpadee; en el Uno, pintar toda la pantalla tarda al menos 0,15 segundos con SPI a 8 MHz. En su lugar, usa setTextColor(texto, fondo) como en el código o borra con fillRect() solo la pequeña zona que cambia. Escribir los textos fijos dentro de F("...") también ahorra los 2 KB de RAM del Uno; si tienes problemas de memoria, consulta Memoria insuficiente en Arduino.

Leer la pantalla táctil XPT2046

En los módulos táctiles hay una fina capa resistiva sobre el cristal. Donde presiona tu dedo o un lápiz, dos capas conductoras se tocan; el chip XPT2046 mide la posición X e Y de ese punto con un ADC de 12 bits como valores brutos de 0 a 4095 y además da un valor de presión (Z). La librería considera que no hay toque si Z está por debajo de 400. El chip comparte el bus SPI con la pantalla, pero se comunica más despacio, a unos 2 MHz; la librería ajusta la velocidad por sí sola en cada lectura. El pin T_IRQ pasa a LOW al tocar y evita que el procesador haga lecturas inútiles. El siguiente código convierte la pantalla en una pequeña pizarra: eliges un color en las casillas de arriba y borras la pantalla con el botón "SIL" (borrar).

C++ (Arduino IDE)
1#include <SPI.h>
2#include <Adafruit_GFX.h>
3#include <Adafruit_ILI9341.h>
4#include <XPT2046_Touchscreen.h>
5
6#define TFT_CS  10
7#define TFT_DC  9
8#define TFT_RST 8
9#define T_CS    7    // dokunmatik seçme / touch chip select
10#define T_IRQ   2    // dokununca LOW olur / goes LOW on touch
11#define SD_CS   4    // SD kullanılmıyor, HIGH tutulur / SD unused, kept HIGH
12
13// Kalibrasyon: Seri Monitör'deki ham değerlerle değiştir / Calibration: replace with the raw values from Serial Monitor
14#define TS_MINX 300
15#define TS_MAXX 3800
16#define TS_MINY 300
17#define TS_MAXY 3800
18
19Adafruit_ILI9341 tft(TFT_CS, TFT_DC, TFT_RST);
20XPT2046_Touchscreen ts(T_CS, T_IRQ);
21
22uint16_t brush = ILI9341_YELLOW;                  // fırça rengi / brush colour
23
24void drawPalette() {
25  tft.fillRect(0, 0, 40, 40, ILI9341_RED);
26  tft.fillRect(40, 0, 40, 40, ILI9341_GREEN);
27  tft.fillRect(80, 0, 40, 40, ILI9341_BLUE);
28  tft.fillRect(120, 0, 40, 40, ILI9341_YELLOW);
29  tft.drawRect(260, 0, 60, 40, ILI9341_WHITE);    // silme düğmesi / clear button
30  tft.setTextColor(ILI9341_WHITE);
31  tft.setTextSize(2);
32  tft.setCursor(273, 13);
33  tft.print(F("SIL"));
34}
35
36void setup() {
37  Serial.begin(9600);
38  pinMode(SD_CS, OUTPUT);
39  digitalWrite(SD_CS, HIGH);                      // SD kart hattı meşgul etmesin / keep the SD card off the bus
40  tft.begin();
41  tft.setRotation(1);                             // ekran yatay / display landscape
42  ts.begin();
43  ts.setRotation(1);                              // dokunmatik de aynı yönde / touch in the same orientation
44  tft.fillScreen(ILI9341_BLACK);
45  drawPalette();
46}
47
48void loop() {
49  if (!ts.touched()) return;                      // dokunma yok / no touch
50  TS_Point p = ts.getPoint();                     // ham x, y (0-4095) ve basınç z / raw x, y and pressure z
51  Serial.print(p.x); Serial.print(',');
52  Serial.print(p.y); Serial.print(',');
53  Serial.println(p.z);
54
55  int16_t x = constrain(map(p.x, TS_MINX, TS_MAXX, 0, 319), 0, 319);   // ekran koordinatı / screen coordinate
56  int16_t y = constrain(map(p.y, TS_MINY, TS_MAXY, 0, 239), 0, 239);
57
58  if (y < 40) {                                   // üst şerit: palet ve düğme / top strip: palette and button
59    if (x < 40)        brush = ILI9341_RED;
60    else if (x < 80)   brush = ILI9341_GREEN;
61    else if (x < 120)  brush = ILI9341_BLUE;
62    else if (x < 160)  brush = ILI9341_YELLOW;
63    else if (x >= 260) { tft.fillScreen(ILI9341_BLACK); drawPalette(); }
64  } else {
65    tft.fillCircle(x, y, 3, brush);               // parmağın altına nokta / dot under the finger
66  }
67}

Los valores brutos no son 0 y 4095 justo en las esquinas; en la mayoría de los módulos los bordes quedan aproximadamente entre 200–400 y 3700–3900. Para calibrar, abre el Monitor Serie, toca con un lápiz la esquina superior izquierda y la inferior derecha, y escribe los valores x e y que veas en las constantes TS_MINX, TS_MAXX, TS_MINY y TS_MAXY. Si el punto aparece reflejado respecto a tu dedo, intercambia el mínimo y el máximo de ese eje en map(); si X e Y están totalmente cambiados, prueba valores de 0 a 3 en ts.setRotation(). Un menú real funciona igual: dibujas botones y compruebas dentro de qué rectángulo cae el punto tocado. La capa resistiva responde también al dedo, pero para botones pequeños es más precisa una punta tipo lápiz.

Mostrar imágenes BMP desde la tarjeta SD

La ranura microSD de la parte trasera del módulo te permite guardar logotipos, fondos y fotos en una tarjeta y mostrarlos en la pantalla. Para preparar una imagen, reduce una foto a 320×240 píxeles y guárdala en Paint como Mapa de bits de 24 bits (.bmp). Como la librería SD de Arduino trabaja con nombres de archivo cortos, usa un nombre de 8 caracteres como máximo, por ejemplo RESIM.BMP, y formatea la tarjeta en FAT32. Los detalles de la tarjeta y la solución al error initialization failed están en Módulo de tarjeta SD para Arduino. Recuerda que esta ranura también es de 3,3 V: en el Uno, las líneas SD_CS, SD_MOSI y SD_SCK también deben pasar por el conversor de nivel.

C++ (Arduino IDE)
1#include <SPI.h>
2#include <SD.h>
3#include <Adafruit_GFX.h>
4#include <Adafruit_ILI9341.h>
5
6#define TFT_CS  10
7#define TFT_DC  9
8#define TFT_RST 8
9#define SD_CS   4
10#define T_CS    7
11#define CHUNK   20   // tek okumada 20 piksel (60 bayt) / 20 pixels (60 bytes) per read
12
13Adafruit_ILI9341 tft(TFT_CS, TFT_DC, TFT_RST);
14
15uint16_t read16(File &f) {                        // BMP sayıları küçük uçlu / BMP numbers are little-endian
16  uint16_t lo = f.read();
17  uint16_t hi = f.read();
18  return lo | (hi << 8);
19}
20
21uint32_t read32(File &f) {
22  uint32_t lo = read16(f);
23  uint32_t hi = read16(f);
24  return lo | (hi << 16);
25}
26
27bool drawBmp(const char *name, int16_t x, int16_t y) {
28  File f = SD.open(name);
29  if (!f) return false;                                   // dosya yok / file not found
30  if (read16(f) != 0x4D42) { f.close(); return false; }  // "BM" imzası / "BM" signature
31  read32(f);                                              // dosya boyutu / file size
32  read32(f);                                              // ayrılmış alan / reserved
33  uint32_t offset = read32(f);                            // piksel verisinin başı / start of pixel data
34  read32(f);                                              // başlık boyutu / header size
35  int32_t w = (int32_t)read32(f);
36  int32_t h = (int32_t)read32(f);
37  read16(f);                                              // düzlem sayısı / colour planes
38  uint16_t depth = read16(f);
39  uint32_t comp = read32(f);
40  if (depth != 24 || comp != 0) { f.close(); return false; }   // yalnız 24 bit, sıkıştırmasız / 24-bit uncompressed only
41
42  bool bottomUp = true;                                   // BMP satırları alttan üste / rows are stored bottom-up
43  if (h < 0) { h = -h; bottomUp = false; }
44  uint32_t rowSize = (w * 3 + 3) & ~3UL;                  // satırlar 4 baytın katı / rows padded to 4 bytes
45  int32_t drawW = w, drawH = h;
46  if (x + drawW > tft.width())  drawW = tft.width() - x;   // ekrana sığmayanı kırp / clip to the screen
47  if (y + drawH > tft.height()) drawH = tft.height() - y;
48
49  uint8_t sdBuf[CHUNK * 3];
50  uint16_t line[CHUNK];
51  for (int32_t row = 0; row < drawH; row++) {
52    uint32_t pos = offset + (bottomUp ? (h - 1 - row) : row) * rowSize;
53    f.seek(pos);                                          // satırın başına git / jump to the start of the row
54    for (int32_t col = 0; col < drawW; col += CHUNK) {
55      int16_t n = drawW - col;
56      if (n > CHUNK) n = CHUNK;
57      f.read(sdBuf, n * 3);
58      for (int16_t i = 0; i < n; i++) {                   // BGR'den RGB565'e / BGR to RGB565
59        line[i] = tft.color565(sdBuf[i * 3 + 2], sdBuf[i * 3 + 1], sdBuf[i * 3]);
60      }
61      tft.drawRGBBitmap(x + col, y + row, line, n, 1);    // parçayı ekrana bas / push the chunk to the screen
62    }
63  }
64  f.close();
65  return true;
66}
67
68void setup() {
69  Serial.begin(9600);
70  pinMode(T_CS, OUTPUT);
71  digitalWrite(T_CS, HIGH);                       // dokunmatik hattı meşgul etmesin / keep touch off the bus
72  tft.begin();
73  tft.setRotation(1);                             // 320x240 yatay / landscape
74  tft.fillScreen(ILI9341_BLACK);
75  tft.setTextSize(2);
76
77  if (!SD.begin(SD_CS)) {                         // kart başlatılamadı / card init failed
78    tft.setTextColor(ILI9341_RED);
79    tft.setCursor(10, 10);
80    tft.print(F("SD kart bulunamadi"));
81    return;
82  }
83  uint32_t t = millis();
84  if (!drawBmp("RESIM.BMP", 0, 0)) {
85    tft.setTextColor(ILI9341_YELLOW);
86    tft.setCursor(10, 10);
87    tft.print(F("RESIM.BMP okunamadi"));
88  }
89  Serial.print(F("Cizim suresi / Draw time (ms): "));
90  Serial.println(millis() - t);
91}
92
93void loop() {
94}

Los primeros 54 bytes de un archivo BMP son la cabecera: ahí están la firma "BM", dónde empiezan los datos de píxeles, el ancho, el alto y la profundidad de color. Los píxeles se guardan en orden azul, verde, rojo (BGR) y normalmente de abajo arriba, y cada fila se rellena hasta un múltiplo de 4 bytes. Por eso el código salta a la posición correcta del archivo para cada fila de la pantalla, lee 20 píxeles (60 bytes) de una vez, los convierte a RGB565 y los dibuja con drawRGBBitmap(). Trabajar en trozos pequeños mantiene todo dentro de la RAM del Uno y permite que la tarjeta SD y la pantalla se turnen en el mismo bus SPI. El tiempo de dibujo se muestra en el Monitor Serie; en el Uno, una imagen a pantalla completa aparece fila a fila en unos pocos segundos. Si quieres mostrar PNG o JPEG y dibujar mucho más rápido, pasa a un ESP32 con las librerías TFT_eSPI y TJpg_Decoder.

Dibujo rápido en el ESP32 con TFT_eSPI

Placa de desarrollo ESP32
Gracias a su lógica de 3,3 V, el ESP32 se conecta directamente al ILI9341 y maneja el SPI a 40 MHz, dibujando muchas veces más rápido que el Uno.

El ESP32 funciona a 3,3 V y puede llevar el SPI hasta 40 MHz, así que no necesitas conversor de nivel y rellenar toda la pantalla baja en teoría a unos 31 milisegundos. Para aprovechar de verdad esa velocidad se suele usar la librería TFT_eSPI de Bodmer. Accede directamente al hardware SPI del ESP32, admite fuentes suavizadas y, sobre todo, búferes fuera de pantalla llamados sprites. Dibujas todo lo que quieras en un sprite en la RAM y envías el resultado a la pantalla de una vez, así que incluso los gráficos que cambian rápido no parpadean. Lo que distingue a TFT_eSPI es que los pines no se configuran en el código, sino en el archivo User_Setup.h de la carpeta de la librería. Ábrelo, comenta las líneas de pines del ESP8266 (NodeMCU) que vienen activas por defecto y activa estas:

C++ (Arduino IDE)
1// TFT_eSPI/User_Setup.h içinde yalnız bu satırlar açık kalsın / keep only these lines active in TFT_eSPI/User_Setup.h
2#define ILI9341_DRIVER
3
4#define TFT_MISO 19
5#define TFT_MOSI 23
6#define TFT_SCLK 18
7#define TFT_CS   15   // ekran seçme / chip select
8#define TFT_DC    2   // komut/veri / data/command
9#define TFT_RST   4   // sıfırlama / reset
10#define TOUCH_CS 21   // dokunmatik seçme (T_CS) / touch chip select (T_CS)
11
12#define LOAD_GLCD     // 1: 8 piksel yazı tipi / 8 px font
13#define LOAD_FONT2    // 2: 16 piksel / 16 px
14#define LOAD_FONT4    // 4: 26 piksel / 26 px
15#define LOAD_FONT7    // 7: 7 segment rakamlar / 7-segment digits
16#define LOAD_GFXFF    // Adafruit FreeFont'lar / Adafruit FreeFonts
17#define SMOOTH_FONT
18
19#define SPI_FREQUENCY       40000000   // kablolar uzunsa 27000000 / 27 MHz with long wires
20#define SPI_READ_FREQUENCY  20000000
21#define SPI_TOUCH_FREQUENCY  2500000
C++ (Arduino IDE)
1#include <SPI.h>
2#include <TFT_eSPI.h>                     // pinler User_Setup.h içinde / pins are set in User_Setup.h
3
4TFT_eSPI tft = TFT_eSPI();
5TFT_eSprite graph = TFT_eSprite(&tft);    // ekran dışı çizim alanı / off-screen canvas
6
7// Touch_calibrate örneğinin verdiği 5 sayıyla değiştir / replace with the 5 numbers from the Touch_calibrate example
8uint16_t calData[5] = {286, 3534, 283, 3600, 6};
9
10const int GW = 300, GH = 100;             // grafik boyutu / graph size
11uint8_t samples[GW];                      // son 300 ölçüm / last 300 readings
12uint32_t frames = 0, fps = 0, lastFps = 0;
13
14void setup() {
15  tft.init();
16  tft.setRotation(1);                     // yatay, 320x240 / landscape, 320x240
17  tft.setTouch(calData);
18  tft.fillScreen(TFT_BLACK);
19  tft.setTextColor(TFT_WHITE, TFT_BLACK);
20  tft.drawString("ESP32 + TFT_eSPI", 10, 8, 4);   // 4 numaralı yazı tipi, 26 px / font 4, 26 px
21  graph.createSprite(GW, GH);             // 300x100x2 bayt = 60 KB RAM / 60 KB of RAM
22}
23
24void loop() {
25  memmove(samples, samples + 1, GW - 1);                          // grafiği sola kaydır / scroll the graph left
26  samples[GW - 1] = map(analogRead(34), 0, 4095, 0, GH - 1);       // GPIO 34'teki potansiyometre / pot on GPIO 34
27
28  graph.fillSprite(TFT_BLACK);
29  for (int y = 0; y < GH; y += 25) graph.drawFastHLine(0, y, GW, TFT_DARKGREY);   // ızgara / grid
30  for (int x = 1; x < GW; x++) {
31    graph.drawLine(x - 1, GH - 1 - samples[x - 1], x, GH - 1 - samples[x], TFT_GREEN);
32  }
33  graph.setTextColor(TFT_YELLOW);
34  graph.drawString(String(fps) + " FPS", 4, 4, 2);
35  graph.pushSprite(10, 50);               // tek seferde ekrana gönder, titreme yok / push in one go, no flicker
36
37  uint16_t tx, ty;
38  if (tft.getTouch(&tx, &ty)) {           // dokunulduysa / if touched
39    tft.fillRect(10, 170, 300, 30, TFT_BLACK);
40    tft.setTextColor(TFT_CYAN, TFT_BLACK);
41    tft.drawString("Dokunma / Touch: " + String(tx) + ", " + String(ty), 10, 175, 2);
42  }
43
44  frames++;
45  if (millis() - lastFps >= 1000) {       // saniyede bir FPS hesapla / compute FPS once per second
46    fps = frames;
47    frames = 0;
48    lastFps = millis();
49  }
50}

El código dibuja el valor de un potenciómetro conectado al GPIO 34 como una gráfica que se desplaza y muestra los fotogramas por segundo (FPS) en la esquina del sprite. Un sprite de 300×100 píxeles con color de 16 bits ocupa 60 KB de RAM; es unas 30 veces toda la memoria del Uno, pero no supone ningún problema para el ESP32. En el táctil, los pines T_CLK, T_DIN y T_DO se unen a las líneas SCK, MOSI y MISO de la pantalla, y solo T_CS (GPIO 21) va aparte. Para obtener tus propios valores de calibración, ejecuta una vez el ejemplo Generic > Touch_calibrate de TFT_eSPI, toca las flechas de las esquinas y copia en el array calData los 5 números que aparecen en el Monitor Serie. La línea ya preparada Setup42_ILI9341_ESP32.h de User_Setup_Select.h elige los mismos pines de pantalla, pero tendrás que añadirle tú la línea TOUCH_CS. Si empiezas con el ESP32, lee antes Qué es el ESP32.

Cuando actualizas TFT_eSPI desde el Arduino IDE, la carpeta de la librería se reescribe y se pierden tus ajustes de User_Setup.h; si una pantalla que ayer funcionaba hoy se queda blanca, es lo primero que debes revisar, así que guarda una copia de tu archivo de configuración. Si el rojo y el azul están intercambiados, activa TFT_RGB_ORDER TFT_BGR; si los colores parecen un negativo, activa TFT_INVERSION_ON; algunos paneles funcionan mejor con ILI9341_2_DRIVER. TFT_eSPI 2.5.43 puede bloquearse y reiniciarse al arrancar en algunas placas con las versiones 3.x del paquete esp32; si te pasa, vuelve a una versión 2.0.x del paquete esp32 desde el Gestor de placas.

ILI9341 con la Raspberry Pi Pico y MicroPython

La Pico también es una placa de 3,3 V, así que la pantalla se conecta directamente. El controlador de MicroPython más usado son los archivos ili9341.py y xpt2046.py del repositorio micropython-ili9341 de rdagger; basta con copiar ambos a la Pico con Thonny. En el siguiente código, la pantalla está en el SPI0 a 40 MHz y el táctil en un bus SPI1 aparte a 1 MHz, así que la diferencia de velocidad entre los dos chips no da problemas. El código dibuja textos y formas y luego pone puntos amarillos donde toques, creando una pizarra sencilla. Si usas la Pico y Thonny por primera vez, empieza por Qué es la Raspberry Pi Pico.

MicroPython
1from machine import Pin, SPI
2from time import sleep_ms
3from ili9341 import Display, color565      # ili9341.py Pico'da olmalı / must be on the Pico
4from xpt2046 import Touch                  # xpt2046.py Pico'da olmalı / must be on the Pico
5
6# Ekran: SPI0, 40 MHz / Display: SPI0, 40 MHz
7spi_tft = SPI(0, baudrate=40000000, sck=Pin(18), mosi=Pin(19), miso=Pin(16))
8tft = Display(spi_tft, cs=Pin(17), dc=Pin(20), rst=Pin(21), width=240, height=320, rotation=0)
9
10# Dokunmatik: ayrı SPI1, 1 MHz / Touch: separate SPI1, 1 MHz
11spi_touch = SPI(1, baudrate=1000000, sck=Pin(10), mosi=Pin(11), miso=Pin(12))
12touch = Touch(spi_touch, cs=Pin(13), width=240, height=320)
13
14WHITE = color565(255, 255, 255)
15YELLOW = color565(255, 255, 0)
16
17tft.clear(color565(0, 0, 0))                                   # ekranı temizle / clear the screen
18tft.draw_text8x8(10, 10, "BlueGrays + Pico", WHITE)
19tft.fill_rectangle(10, 30, 100, 50, color565(255, 0, 0))       # dolu dikdörtgen / filled rectangle
20tft.draw_rectangle(130, 30, 100, 50, color565(0, 255, 0))      # çerçeve / outline
21tft.fill_circle(60, 130, 30, color565(0, 128, 255))            # dolu daire / filled circle
22tft.draw_line(0, 175, 239, 175, color565(255, 0, 255))         # çizgi / line
23tft.draw_text8x8(10, 185, "Ekrana dokun / Touch me", YELLOW)
24
25while True:
26    raw = touch.raw_touch()                # dokunma yoksa None / None when not touched
27    if raw is not None:
28        x, y = touch.normalize(*raw)       # ham değeri piksele çevir / raw value to pixels
29        y = 319 - y                        # eksen ters ise / if the axis is inverted
30        x = min(max(x, 3), 236)            # ekran dışına taşma / keep inside the screen
31        y = min(max(y, 3), 316)
32        tft.fill_circle(x, y, 3, YELLOW)
33    sleep_ms(20)

En vertical (rotation=0) el ancho es 240 y el alto 320; para usar la pantalla en horizontal, pasa width=320 y height=240 junto con rotation=90. La calibración por defecto del táctil (x_min=100, x_max=1962) puede no encajar con todos los módulos; si el punto se desvía, imprime los valores de raw_touch() y pasa a Touch() tus propios x_min, x_max, y_min e y_max. Para mostrar imágenes, la función draw_image() del controlador lee archivos .raw convertidos a RGB565; el script utils/img2rgb565.py del repositorio hace esa conversión en tu ordenador.

Pantalla blanca: causas y solución

El problema más famoso del ILI9341 es una pantalla completamente blanca con la retroiluminación encendida. En realidad, la pantalla blanca es una pista: la alimentación y la retroiluminación funcionan, pero el chip controlador nunca llegó a inicializarse. Cuando el panel no recibe comandos, los píxeles dejan pasar la luz y la pantalla se ve blanca. Así que el problema casi siempre está en la comunicación. Revisa la tabla de arriba abajo:

SíntomaCausa probableSolución
Pantalla blanca, conectada directamente al UnoSeñales de 5 V sin conversor de nivelUsa un 74HC4050 o divisores de tensión; si el chip se dañó, cambia el módulo
Pantalla blanca con los cables conectadosCS y DC intercambiados, o los pines del código no coinciden con el cableadoCompara una a una las definiciones TFT_CS, TFT_DC y TFT_RST con la tabla
Pantalla blanca, RESET al aireRESET sin conectar o en el pin equivocadoConecta RESET al pin del código o a 3,3 V; nunca lo dejes al aire
Pantalla blanca en el ESP32 (TFT_eSPI)User_Setup.h sin editar o borrado por una actualizaciónDesactiva las líneas del ESP8266 y vuelve a escribir los pines del ESP32 y ILI9341_DRIVER
Blanca a ratos, imagen desplazada o corruptaCables jumper largos, SPI demasiado rápido, contactos flojos en la protoboardUsa cables de menos de 10–15 cm; baja el SPI a 20–27 MHz, o a 4 MHz en el Uno
Blanca solo con el táctil o la SD conectadosEl CS del otro dispositivo está al aire y bloquea el busPon en el código cada CS sin usar como OUTPUT y en HIGH
No funciona con ningún códigoLa pantalla no es ILI9341 (ST7789, ILI9488) o es un shield paraleloLee la serigrafía trasera; una de 3,5 pulgadas y 320×480 es ILI9488, un shield necesita MCUFRIEND_kbv
Pantalla blanca y retroiluminación que parpadeaAlimentación insuficienteAlimenta VCC desde 5 V y prueba otro cable USB y otra fuente
Para acotar el fallo, usa las líneas de diagnóstico del primer código. Si el Monitor Serie muestra Power Mode: 0x94 y Self Diagnostic: 0xC0, la pantalla recibe los comandos y el problema está en el software (orientación, colores o código de dibujo). Si los valores son 0x0 o 0xFF, el Arduino no consigue hablar con la pantalla: revisa los cables, el conversor de nivel y los pines CS y DC. Esta lectura solo funciona con la línea SDO (MISO) conectada.

Otros errores frecuentes

  • Colores incorrectos: si el rojo sale azul, el panel usa orden BGR; cambia el ajuste TFT_RGB_ORDER en TFT_eSPI. Si los colores parecen un negativo, prueba tft.invertDisplay(true).
  • Imagen al revés o reflejada: cambia el valor de setRotation() entre 0 y 3 y ajusta los ejes del táctil en consecuencia.
  • La pantalla funciona, pero el táctil o la SD no: comprueba que T_CS y SD_CS coinciden con los pines del código. En algunos módulos, la salida SDO de la pantalla no libera el bus; en ese caso prueba a desconectar el pin SDO de la pantalla, y solo dejará de funcionar la lectura de diagnóstico.
  • El BMP no aparece: la tarjeta no está en FAT32, el nombre del archivo tiene más de 8 caracteres o la imagen no es de 24 bits. No olvides elegir 24 bits en Paint; este código no dibuja BMP de 16 ni de 32 bits.
  • No salen las tildes ni la ñ: la fuente por defecto de GFX no incluye caracteres como á, é o ñ. En TFT_eSPI puedes crear tu propia fuente suavizada o usar una fuente GFX que incluya esos caracteres.
  • La pantalla va lenta: en el Uno, refrescar la pantalla completa tarda al menos 0,15 segundos. Para animaciones y juegos pasa a un ESP32 o una Pico y redibuja solo la zona que cambia.
  • El módulo se calienta: puede que haya 5 V en VCC con el puente J1 cerrado o que VCC y GND estén invertidos; desconecta la alimentación de inmediato.

Ideas de proyectos con el ILI9341

  • Panel táctil de casa inteligente: controla luces y relés con botones grandes en la pantalla; tienes ideas en Proyecto de casa inteligente con Arduino.
  • Pantalla del tiempo a color: muestra el tiempo que el ESP32 obtiene de internet con iconos y números grandes (Estación meteorológica con ESP32).
  • Panel de sensores: dibuja la temperatura, la humedad y la presión de un BME280 como indicadores de aguja con una gráfica de las últimas 24 horas.
  • Consola de juegos retro: juega a la serpiente, al Pong o al Tetris en color; añade un módulo joystick para controlarlos y busca ideas en Proyectos de juegos con Arduino.
  • Marco de fotos digital: cambia cada pocos segundos las imágenes BMP de la tarjeta SD.
  • Mini osciloscopio: dibuja los valores de analogRead como una onda fluida con un sprite en el ESP32.
  • Cerradura táctil con clave: dibuja un teclado numérico en la pantalla y abre un relé o un servo cuando se introduzca el código correcto.

El ILI9341 es la forma más económica de dar a tus proyectos una interfaz táctil a color: empieza con el Uno para aprender las funciones básicas de dibujo y pasa al ESP32 con TFT_eSPI cuando necesites velocidad y animaciones fluidas. Si prefieres empezar con una pantalla más pequeña, Pantalla OLED (SSD1306) es un buen punto de partida. En la app BlueGrays encontrarás la pantalla del tiempo con ESP32, el registrador de temperatura, el sensor de aparcamiento y proyectos de juegos con pantalla, con esquemas de circuito y código paso a paso.

Preguntas frecuentes

¿La pantalla ILI9341 funciona con 5 V?

El pin VCC del módulo admite 3,3–5 V porque la placa lleva un regulador de 3,3 V. Sin embargo, los pines de señal como CS, DC, SCK y MOSI son solo de 3,3 V. Con un Arduino Uno debes poner en esas líneas un conversor de nivel, como un 74HC4050 o divisores de tensión.

¿Por qué mi ILI9341 se queda en blanco?

La pantalla blanca indica que la retroiluminación está encendida pero el chip controlador no se ha inicializado. Las causas más frecuentes son un cableado incorrecto de CS, DC o RESET, no usar conversor de nivel en el Uno, no editar User_Setup.h en TFT_eSPI y usar una pantalla que en realidad no es ILI9341.

¿Qué librería se usa para el ILI9341?

Para Arduino Uno, Nano y Mega, lo más sencillo es Adafruit_ILI9341 con Adafruit GFX. En placas ESP32, ESP8266 y RP2040 se prefiere TFT_eSPI, que es mucho más rápida. Los shields paralelos de 2,4 pulgadas que se pinchan sobre el Uno necesitan MCUFRIEND_kbv.

¿Cómo se calibra el táctil del ILI9341?

El controlador táctil XPT2046 devuelve valores brutos de 0 a 4095. Anota los valores mínimo y máximo que ves en el Monitor Serie al tocar las esquinas y conviértelos a coordenadas de pantalla con map(). Si usas TFT_eSPI, el ejemplo Touch_calibrate lo hace por ti y te da un array de calibración listo.

¿Qué diferencia hay entre el ILI9341 de 2,4 y el de 2,8 pulgadas?

Los dos tienen una resolución de 240×320 píxeles y usan los mismos pines y el mismo código. La de 2,8 pulgadas tiene píxeles algo más grandes, así que el texto se lee mejor y es más fácil pulsar los botones táctiles. El módulo de 2,4 pulgadas cabe en cajas más pequeñas.

¿Se puede usar el ILI9341 con un Arduino Nano?

Sí. Los pines SPI del Nano son los mismos que los del Uno: D13 SCK, D11 MOSI y D12 MISO. El Nano también trabaja con lógica de 5 V, así que necesitas un conversor de nivel. Sus 2 KB de RAM bastan para manejar la pantalla, pero no para guardar imágenes grandes, que tendrás que leer de la tarjeta SD por partes.

Ver todos los proyectos
ESP32 HTTPClient + API del tiempo (con pantalla OLED SSD1306)
#134Avanzado
Premium

ESP32 HTTPClient + API del tiempo (con pantalla OLED SSD1306)

En este proyecto, utilizamos el ESP32 para realizar una llamada a la API REST de la información meteorológica (wttr.in) a través de Internet, utilizando HTTPClient.h. A diferencia de la versión anterior con pantalla LCD I2C, aquí utilizamos una pantalla OLED SSD1306 (128×64), lo que permite utilizar fuentes grandes, iconos vectoriales y una presentación visual muy rica en una sola pantalla. Para indicar el tiempo, se dibujan en tiempo de ejecución 7 iconos vectoriales diferentes (soleado, parc

4.3(10)
19
Registrador de Temperatura ESP32 (DHT22 + DS1307 RTC + microSD + OLED)
#144Avanzado
Premium

Registrador de Temperatura ESP32 (DHT22 + DS1307 RTC + microSD + OLED)

¡Construye un registrador de temperatura con marca de tiempo con ESP32! Lee temperatura/humedad del DHT22 cada minuto, obtén la hora real del DS1307 RTC y registra en tarjeta microSD como CSV. El OLED muestra en vivo la temperatura (fuente grande), porcentaje de humedad, marca de tiempo y contador de registros. El archivo /temp_log.csv en la tarjeta SD se abre en Excel, Google Sheets o Python pandas para análisis — perfecto para monitoreo de invernadero, seguimiento de temperatura del hog

4.7(7)
12
Lámpara con mezclador de colores ESP32 (3 potenciómetros + LED RGB + OLED)
#138Avanzado
Premium

Lámpara con mezclador de colores ESP32 (3 potenciómetros + LED RGB + OLED)

¡Una lámpara mezcladora de colores inteligente que combina el color que quieras girando tres potenciómetros con el ESP32! A medida que giras los potenciómetros de rojo, verde y azul, el LED RGB de cátodo común cambia de color al instante. En la pantalla OLED SSD1306 se muestran en tiempo real los valores de cada color en un rango de 0 a 255, barras de relleno visuales y el código de color HEX para la web (como #FF8040). Un miniestudio de color profesional: enseña la teoría del color RGB, la lect

4.7(6)
10
Sensor de aparcamiento ESP32 (HC-SR04 + barra de 5 LED + zumbador + OLED)
#142Avanzado
Premium

Sensor de aparcamiento ESP32 (HC-SR04 + barra de 5 LED + zumbador + OLED)

¡La versión ESP32 del sensor de aparcamiento para coches! Medimos la distancia al objeto que hay delante mediante el sensor ultrasónico HC-SR04. A medida que la distancia disminuye, la barra de 5 LED se va llenando (verde → amarillo → rojo) y la frecuencia de los pitidos del zumbador se acorta. Cuando se acerca demasiado (menos de 10 cm), suena una alarma continua y se encienden todos los LED. En la pantalla OLED SSD1306 se muestra, en letra grande, el valor actual en centímetros, un mensaje de

0.0(0)
14
Juego de Raquetas - SSD1306
#86Intermedio
Premium

Juego de Raquetas - SSD1306

Una pelota, dos palas y tú: juegas al tenis de mesa, uno de los primeros videojuegos de la historia, en una pequeña pantalla OLED. Con dos botones mueves tu pala de la derecha arriba y abajo, mientras

4.5(47)
65
OLED T-Rex Run: Juego del dinosaurio con Arduino
#87Avanzado
Premium

OLED T-Rex Run: Juego del dinosaurio con Arduino

El juego del dinosaurio que aparece cuando se va internet, ahora en tu mesa: el dinosaurio corre por la pequeña pantalla OLED, los cactus se le echan encima y tú saltas con un solo botón. Tu puntuació

4.7(33)
53
Pantalla LCD I2C para ESP32 (16x2)
#119Intermedio
Premium

Pantalla LCD I2C para ESP32 (16x2)

En este proyecto, mostramos texto conectando una pantalla LCD de 16x2 caracteres al ESP32 a través del protocolo I2C. Gracias al I2C, podemos controlar la pantalla con solo 2 pines de datos (SDA y SCL); así se elimina el desperdicio de pines que supone la conexión paralela clásica, que requiere más de 6 pines. El código imprime un mensaje fijo en la primera línea y un contador que aumenta cada segundo en la segunda línea. Además, al inicio ejecutamos el escáner I2C para mostrar la dirección de l

4.9(23)
40
Juego Arduino LCD Runner
#98Intermedio
Premium

Juego Arduino LCD Runner

Juego endless runner de desplazamiento lateral que se ejecuta en una pantalla LCD de 16x2 caracteres. El héroe corre automáticamente, el jugador salta los obstáculos pulsando el botón. Aparecen obstáculos aleatorios en las filas superior e inferior. El zumbador pasivo reproduce la melodía de apertura, el sonido de salto, el sonido de celebración de 50 puntos y la melodía de fin de partida. La pantalla de inicio "BlueGrays - Arduino Projects" se muestra al arrancar.

4.6(32)
55