|

Conecta un módulo de pantalla gráfica OLED con el ESP8266 NodeMCU

Tutorial para conectar una pantalla OLED con el ESP8266 NodeMCU

¿Quieres darle un toque gráfico a tus proyectos IoT con ESP8266? ¿O quizá quieres mostrar la dirección IP de tu ESP8266 sin recurrir a la salida serial? ¡Estas geniales pantallas OLED (diodo orgánico emisor de luz) pueden ser la opción perfecta! Son muy ligeras, casi tan delgadas como el papel, teóricamente flexibles y producen una imagen más brillante y nítida.

Descripción general del módulo de pantalla OLED

El módulo de pantalla OLED expone una pequeña pantalla OLED monocromática. Tiene 128 pixeles de ancho y 64 pixeles de alto, y mide 0.96″ en diagonal. Es diminuta, pero rinde bastante: la pantalla OLED es muy legible gracias a su alto contraste, y en ella cabe una cantidad de gráficos sorprendentemente grande.

Como la pantalla genera su propia luz, no requiere retroiluminación. Esto reduce significativamente la energía necesaria para operar la OLED y es la razón por la que la pantalla tiene un alto contraste, un ángulo de visión extremadamente amplio y puede mostrar niveles de negro profundos.

128x64 Blue I2C OLED Display

En el corazón del módulo hay un potente controlador de OLED CMOS de un solo chip: SSD1306, que se encarga de todo el almacenamiento en el búfer de RAM, de modo que tu ESP8266 tiene que hacer muy poco trabajo. Además, el voltaje de operación del controlador SSD1306 va de 1.65V a 3.3V, perfecto para conectarse con microcontroladores de 3.3V como el ESP8266.

Mapa de memoria de la OLED

Para tener control absoluto sobre tu módulo de pantalla OLED, es importante conocer su mapa de memoria.

Sin importar el tamaño del módulo OLED, el controlador SSD1306 tiene integrada 1KB de RAM de datos de pantalla gráfica (GDDRAM) para la pantalla, que contiene el patrón de bits que se mostrará. Esta área de memoria de 1K está organizada en 8 páginas (de la 0 a la 7). Cada página contiene 128 columnas/segmentos (bloque 0 al 127). Y cada columna puede almacenar 8 bits de datos (del 0 al 7). Eso claramente nos indica que tenemos

8 páginas x 128 segmentos x 8 bits de datos = 8192 bits = 1024 bytes = 1KB de memoria

Abajo se destaca toda la memoria de 1K con sus páginas, segmentos y datos.

1KB 128x64 OLED Display RAM Memory Map

Cada bit representa un pixel OLED específico de la pantalla que puede encenderse (ON) o apagarse (OFF) por programación.

NOTA

La pantalla OLED de 128×64 muestra todo el contenido de la RAM, mientras que la pantalla OLED de 128×32 muestra solo 4 páginas (la mitad del contenido) de la RAM.

Cableado del módulo de pantalla OLED al ESP8266 NodeMCU

¡Suficiente teoría, pasemos a la práctica! Vamos a conectar la pantalla al ESP8266 NodeMCU.

Las conexiones son bastante sencillas. Empieza conectando el pin VCC a la salida de 3.3V del NodeMCU y conecta GND a tierra.

Después, conecta el pin SCL al pin de reloj I2C D1 de tu NodeMCU y conecta el pin SDA al pin de datos I2C D2 de tu NodeMCU. Consulta el pinout del ESP8266 NodeMCU.

El siguiente diagrama te muestra cómo cablear todo.

Fritzing Wiring OLED Display with ESP8266 NodeMCU
Cableado de la pantalla OLED con el ESP8266 NodeMCU

Con eso, ya estás listo para subir algo de código y hacer que la pantalla imprima.

Instalando la librería para el módulo de pantalla OLED

El controlador SSD1306 de la pantalla OLED tiene drivers flexibles pero complejos. Se requiere un amplio conocimiento sobre direccionamiento de memoria para usar el controlador SSD1306. Por fortuna, la librería SSD1306 de Adafruit fue escrita para ocultar las complejidades del controlador SSD1306, de modo que podamos enviar comandos sencillos para controlar la pantalla.

Para instalar la librería, ve a Sketch > Include Library > Manage Libraries… Espera a que el Gestor de Librerías descargue el índice de librerías y actualice la lista de librerías instaladas.

Arduino Library Installation - Selecting Manage Libraries in Arduino IDE

Filtra tu búsqueda escribiendo ‘adafruit ssd1306’. Deberían aparecer un par de entradas. Busca Adafruit SSD1306 de Adafruit. Haz clic en esa entrada y luego selecciona Install.

Installing Adafruit SSD1306 Monochrome OLED Display Library

Esta librería Adafruit SSD1306 es una librería específica del hardware que maneja las funciones de más bajo nivel. Necesita combinarse con la librería Adafruit GFX para mostrar primitivas gráficas como puntos, líneas, círculos, rectángulos, etc. Instala también esta librería.

Installing Adafruit GFX Graphics Core Library

NOTA

La librería reserva 1KB (128×64)/8 bits) de memoria del ESP8266 como búfer. De esta forma, puede manipular el búfer de pantalla y luego realizar una transferencia masiva desde la memoria del ESP8266 a la memoria interna del controlador SSD1306.

Modificando la librería Adafruit SSD1306

La librería SSD1306 de Adafruit no viene configurada para las pantallas OLED de 128×64 (la que estamos usando ahora mismo). Hay que cambiar el tamaño de la pantalla en el archivo de cabecera Adafruit_SSD1306.h para que funcione en nuestro caso. Si no se cambia, puede aparecer un mensaje de error que dice #error (“Height incorrect, please fix Adafruit_SSD1306.h!”); al intentar verificar el sketch de ejemplo en el Arduino IDE:

Height incorrect, please fix Adafruit_SSD1306.h Error

Para cambiar el archivo de cabecera Adafruit_SSD1306.h, abre la ubicación de tu sketchbook. Por lo general es My Documents > Arduino. Ahora ve a libraries > Adafruit_SSD1306

Adafruit SSD1306 Library Location

Abre el archivo Adafruit_SSD1306.h en un editor de texto. Desplázate por el archivo hasta encontrar la sección con las SSD1306 Displays o ve directamente a la línea 73. Comenta #define SSD1306_128_32 y descomenta #define SSD1306_128_64 de modo que el código de esta sección quede así:

Remove Height Incorrect Error By Changing Adafruit_SSD1306.h File

Listo. Ahora guarda el archivo y reinicia tu Arduino IDE.

Código para ESP8266 – Mostrar texto

¡Ahora viene lo interesante!

El siguiente sketch de prueba imprimirá el mensaje ‘Hello World!’ en la pantalla. También incluye

  • Mostrar texto invertido
  • Mostrar números
  • Mostrar números con base (Hex, Dec)
  • Mostrar símbolos ASCII
  • Desplazar texto horizontal y verticalmente
  • Desplazar una parte de la pantalla

Esto te dará una comprensión completa de cómo usar la pantalla OLED y puede servir como base para experimentos y proyectos más prácticos.

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

Adafruit_SSD1306 display(-1);

void setup()   
{                
	// initialize with the I2C addr 0x3C
	display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  

	// Clear the buffer.
	display.clearDisplay();

	// Display Text
	display.setTextSize(1);
	display.setTextColor(WHITE);
	display.setCursor(0,28);
	display.println("Hello world!");
	display.display();
	delay(2000);
	display.clearDisplay();

	// Display Inverted Text
	display.setTextColor(BLACK, WHITE); // 'inverted' text
	display.setCursor(0,28);
	display.println("Hello world!");
	display.display();
	delay(2000);
	display.clearDisplay();

	// Changing Font Size
	display.setTextColor(WHITE);
	display.setCursor(0,24);
	display.setTextSize(2);
	display.println("Hello!");
	display.display();
	delay(2000);
	display.clearDisplay();

	// Display Numbers
	display.setTextSize(1);
	display.setCursor(0,28);
	display.println(123456789);
	display.display();
	delay(2000);
	display.clearDisplay();

	// Specifying Base For Numbers
	display.setCursor(0,28);
	display.print("0x"); display.print(0xFF, HEX); 
	display.print("(HEX) = ");
	display.print(0xFF, DEC);
	display.println("(DEC)"); 
	display.display();
	delay(2000);
	display.clearDisplay();

	// Display ASCII Characters
	display.setCursor(0,24);
	display.setTextSize(2);
	display.write(3);
	display.display();
	delay(2000);
	display.clearDisplay();

	// Scroll full screen
	display.setCursor(0,0);
	display.setTextSize(1);
	display.println("Full");
	display.println("screen");
	display.println("scrolling!");
	display.display();
	display.startscrollright(0x00, 0x07);
	delay(2000);
	display.stopscroll();
	delay(1000);
	display.startscrollleft(0x00, 0x07);
	delay(2000);
	display.stopscroll();
	delay(1000);    
	display.startscrolldiagright(0x00, 0x07);
	delay(2000);
	display.startscrolldiagleft(0x00, 0x07);
	delay(2000);
	display.stopscroll();
	display.clearDisplay();

	// Scroll part of the screen
	display.setCursor(0,0);
	display.setTextSize(1);
	display.println("Scroll");
	display.println("some part");
	display.println("of the screen.");
	display.display();
	display.startscrollright(0x00, 0x00);
}

void loop() {}

El sketch comienza incluyendo cuatro librerías, a saber: SPI.hWire.hAdafruit_GFX.h y Adafruit_SSD1306.h. Aunque la librería SPI.h no es necesaria para las pantallas OLED I2C, debemos agregarla para poder compilar nuestro programa.

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

Después, necesitamos crear un objeto de Adafruit_SSD1306.h. El constructor Adafruit_SSD1306 acepta el número de pin del ESP8266 al que se conecta el pin de reset de la pantalla. Como la pantalla OLED que estamos usando no tiene pin RESET, enviaremos 1 al constructor para que ninguno de los pines del ESP8266 se use como reset de la pantalla.

Adafruit_SSD1306 display(-1);

En la función setup: necesitamos inicializar el objeto OLED usando la función begin(). La función toma dos parámetros. El primer parámetro SSD1306_SWITCHCAPVCC enciende el circuito interno de bomba de carga, mientras que el segundo parámetro proporciona la dirección I2C de la pantalla OLED. La dirección I2C de este tipo de módulo de pantalla OLED es por lo general 0x3C. Es fija y no se puede cambiar.

Después, limpiamos el búfer antes de imprimir nuestro primer mensaje en la pantalla.

// initialize with the I2C addr 0x3C
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

// Clear the buffer.
display.clearDisplay();

Mostrar texto sencillo (Hello World)

Displaying Text On OLED Dsiplay Module
// Display Text
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,28);
display.println("Hello world!");
display.display();
delay(2000);

Para mostrar texto en la pantalla, necesitamos establecer el tamaño de fuente. Esto se hace llamando a setTextSize(font-size) y pasando el tamaño de fuente (empezando desde 1) como parámetro.

Después, necesitamos establecer el color de la fuente llamando a la función setTextColor(color) . Pasa el parámetro WHITE para fondo oscuro y pasa BLACK para fondo claro. Ahora, antes de imprimir el mensaje, necesitamos establecer la posición del cursor llamando a la función setCursor(X,Y). Los pixeles de la pantalla se direccionan mediante sus coordenadas horizontal (X) y vertical (Y). El sistema de coordenadas coloca el origen (0,0) en la esquina superior izquierda, con la X positiva aumentando hacia la derecha y la Y positiva aumentando hacia abajo.

Podemos usar la sencilla función print(“ ”) o  println(“ ”) para imprimir el mensaje en la pantalla, tal como imprimimos datos en el monitor serial. Recuerda que println() moverá el cursor a la siguiente línea.

Para que la librería pueda realizar operaciones matemáticas extremadamente rápidas sobre el búfer de pantalla (más de 100 cuadros por segundo), las llamadas a las funciones de impresión no transfieren de inmediato el contenido del búfer de pantalla al controlador SSD1306. Se requiere un comando display() para indicarle a la librería que realice la transferencia masiva desde el búfer de pantalla del ESP8266 a la memoria interna del controlador SSD1306. En cuanto la memoria se transfiere, los pixeles correspondientes al búfer de pantalla aparecerán en la pantalla OLED.

Mostrar texto invertido

Displaying Inverted Text On OLED Dsiplay Module
// Display Inverted Text
display.clearDisplay();
display.setTextColor(BLACK, WHITE); // 'inverted' text
display.setCursor(0,28);
display.println("Hello world!");
display.display();
delay(2000);

Para mostrar texto invertido, volveremos a llamar a la función setTextColor(FontColor,BackgroundColor). Si estás poniendo atención, sabrás que antes le pasamos solo un parámetro a esta función, pero ahora le pasamos dos parámetros. Esto es posible gracias a algo llamado sobrecarga de funciones. La sobrecarga de funciones es la capacidad de crear múltiples funciones con el mismo nombre pero con distintos conjuntos de parámetros. Las llamadas a una función sobrecargada ejecutarán una implementación específica de esa función según los parámetros que se le pasen.

En nuestro caso, pasar setTextColor(BLACK, WHITE) renderizará texto negro sobre un fondo relleno.

Escalando el tamaño de fuente

Changing Font Size On OLED Dsiplay Module
// Changing Font Size
display.clearDisplay();
display.setTextColor(WHITE);
display.setCursor(0,24);
display.setTextSize(2);
display.println("Hello!");
display.display();
delay(2000);

Antes en este tutorial, llamamos a la función setTextSize(font-size) para establecer el tamaño de fuente y le pasamos 1 como parámetro. Puedes usar esta función para escalar la fuente pasando cualquier entero no negativo.

Los caracteres se renderizan en una proporción de 7:10. Es decir, pasar tamaño de fuente 1 renderizará el texto a 7×10 pixeles por carácter, pasar 2 lo renderizará a 14×20 pixeles por carácter, y así sucesivamente.

La librería Adafruit_GFX es la responsable de renderizar la fuente. De manera predeterminada se selecciona la fuente monoespaciada. Sin embargo, las versiones más recientes de la librería Adafruit GFX ofrecen la posibilidad de usar fuentes alternativas. La librería incluye varias fuentes alternativas, además de la posibilidad de agregar nuevas.

Mostrar números

Displaying Numbers On OLED Dsiplay Module
// Display Numbers
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0,28);
display.println(123456789);
display.display();
delay(2000);

Los números pueden mostrarse en la pantalla OLED simplemente llamando a la función print() o println(). Una implementación sobrecargada de estas funciones acepta un unsigned int de 32 bits, por lo que solo puedes mostrar números del 0 al 4,294,967,295.

Especificar la base de los números

Displaying HEX, Decimal, OCT, Binary On OLED Dsiplay Module
// Specifying Base For Numbers
display.clearDisplay();
display.setCursor(0,28);
display.print("0x"); display.print(0xFF, HEX); 
display.print("(HEX) = ");
display.print(0xFF, DEC);
display.println("(DEC)"); 
display.display();
delay(2000);

Las funciones print() y println() tienen un segundo parámetro opcional que especifica la base (formato) a usar; los valores permitidos son BIN (binario, o base 2), OCT (octal, o base 8), DEC (decimal, o base 10), HEX (hexadecimal, o base 16). Para números de punto flotante, este parámetro especifica el número de decimales a usar. Por ejemplo:

  • print(78, BIN) da “1001110”
  • print(78, OCT) da “116”
  • print(78, DEC) da “78”
  • print(78, HEX) da “4E”
  • println(1.23456, 0) da “1”
  • println(1.23456, 2) da “1.23”
  • println(1.23456, 4) da “1.2346”

Mostrar símbolos ASCII

Displaying ASCII Symbols On OLED Dsiplay Module
// Display ASCII Characters
display.clearDisplay();
display.setCursor(0,24);
display.setTextSize(2);
display.write(3);
display.display();
delay(2000);

Las funciones print() y println() envían datos a la pantalla como texto ASCII legible para humanos, mientras que la función write() envía datos binarios a la pantalla. Así que puedes usar esta función para mostrar símbolos ASCII. En nuestro ejemplo, enviar el número 3 mostrará el símbolo de corazón.

Desplazamiento de pantalla completa

Full-Screen-Scrolling-On-OLED-Dsiplay-Module
// Scroll full screen
display.clearDisplay();
display.setCursor(0,0);
display.setTextSize(1);
display.println("Full");
display.println("screen");
display.println("scrolling!");
display.display();
display.startscrollright(0x00, 0x07);
delay(2000);
display.stopscroll();
delay(1000);
display.startscrollleft(0x00, 0x07);
delay(2000);
display.stopscroll();
delay(1000);    
display.startscrolldiagright(0x00, 0x07);
delay(2000);
display.startscrolldiagleft(0x00, 0x07);
delay(2000);
display.stopscroll();

Puedes desplazar la pantalla horizontalmente llamando a las funciones startscrollright(start page, stop page) y startscrollleft(start page, stop page) y en diagonal llamando a startscrolldiagright(start page, stop page) y startscrolldiagleft(start page, stop page). Todas estas funciones aceptan dos parámetros, a saber: la página de inicio y la página de fin. Consulta la sección Mapa de memoria de la OLED para la explicación de las páginas. Como hay ocho páginas en la pantalla, de la 0 a la 7, puedes desplazar toda la pantalla desplazando todas las páginas, es decir, pasando los parámetros 0x00 y 0x07.

Para detener el desplazamiento de la pantalla puedes usar la función stopscroll().

Desplazar una parte específica

Scrolling Part Of The Screen On OLED Dsiplay Module
// Scroll part of the screen
display.setCursor(0,0);
display.setTextSize(1);
display.println("Scroll");
display.println("some part");
display.println("of the screen.");
display.display();
display.startscrollright(0x00, 0x00);

A veces no queremos desplazar toda la pantalla. Puedes hacerlo pasando la información correcta de página de inicio y página de fin a las funciones de desplazamiento. Consulta la sección Mapa de memoria de la OLED para la explicación de las páginas. Como hay ocho páginas en la pantalla, de la 0 a la 7, puedes desplazar solo una parte de la pantalla pasando números de página específicos como parámetros.

En nuestro ejemplo, pasamos ambos parámetros como 0x00. Esto desplazará solo la primera página (las primeras 8 filas) de la pantalla.

Código para ESP8266 – Dibujos básicos

En este ejemplo vamos a probar algunos dibujos básicos. Este sketch demuestra muchas funciones de dibujo, incluyendo rectángulos, rectángulos redondeados, círculos y triángulos. Prueba el sketch y luego lo diseccionaremos con algo de detalle.

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

Adafruit_SSD1306 display(-1);

void setup()   
{                
	// initialize with the I2C addr 0x3C
	display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  

	// Clear the buffer.
	display.clearDisplay();

	display.setTextSize(1);
	display.setTextColor(WHITE);
	display.setCursor(0,0);
	display.println("Rectangle");
	display.drawRect(0, 15, 60, 40, WHITE);
	display.display();
	delay(2000);
	display.clearDisplay();

	display.setTextSize(1);
	display.setTextColor(WHITE);
	display.setCursor(0,0);
	display.println("Filled Rectangle");
	display.fillRect(0, 15, 60, 40, WHITE);
	display.display();
	delay(2000);
	display.clearDisplay();

	display.setTextSize(1);
	display.setTextColor(WHITE);
	display.setCursor(0,0);
	display.println("Round Rectangle");
	display.drawRoundRect(0, 15, 60, 40, 8, WHITE);
	display.display();
	delay(2000);
	display.clearDisplay();

	display.setTextSize(1);
	display.setTextColor(WHITE);
	display.setCursor(0,0);
	display.println("Filled Round Rectangl");
	display.fillRoundRect(0, 15, 60, 40, 8, WHITE);
	display.display();
	delay(2000);
	display.clearDisplay();

	display.setTextSize(1);
	display.setTextColor(WHITE);
	display.setCursor(0,0);
	display.println("Circle");
	display.drawCircle(20, 35, 20, WHITE);
	display.display();
	delay(2000);
	display.clearDisplay();

	display.setTextSize(1);
	display.setTextColor(WHITE);
	display.setCursor(0,0);
	display.println("Filled Circle");
	display.fillCircle(20, 35, 20, WHITE);
	display.display();
	delay(2000);
	display.clearDisplay();

	display.setTextSize(1);
	display.setTextColor(WHITE);
	display.setCursor(0,0);
	display.println("Triangle");
	display.drawTriangle(30, 15, 0, 60, 60, 60, WHITE);
	display.display();
	delay(2000);
	display.clearDisplay();

	display.setTextSize(1);
	display.setTextColor(WHITE);
	display.setCursor(0,0);
	display.println("Filled Triangle");
	display.fillTriangle(30, 15, 0, 60, 60, 60, WHITE);
	display.display();
	delay(2000);
	display.clearDisplay();
}

void loop() {}

La mayor parte del código (incluyendo las librerías y la inicialización de la pantalla) es igual que en el ejemplo de código anterior, salvo los siguientes fragmentos de código para hacer dibujos básicos.

Dibujar un rectángulo

Drawing Rectangle On OLED Dsiplay Module
Drawing Filled Rectangle On OLED Dsiplay Module
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Rectangle");
display.drawRect(0, 15, 60, 40, WHITE);
display.display();
delay(2000);

display.clearDisplay();  
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Filled Rectangle");
display.fillRect(0, 15, 60, 40, WHITE);
display.display();
delay(2000);

Puedes dibujar un rectángulo en la pantalla usando la función drawRect(X-coordinate, Y-coordinate, Width, Height, color). En realidad, esta función dibuja un rectángulo hueco con un borde de 1 pixel. Puedes dibujar un rectángulo relleno usando la función fillRect().

Dibujar un rectángulo redondeado

Drawing Round Rectangle On OLED Dsiplay Module
Drawing Filled Round Rectangle On OLED Dsiplay Module
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Round Rectangle");
display.drawRoundRect(0, 15, 60, 40, 8, WHITE);
display.display();
delay(2000);

display.clearDisplay();  
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Filled Round Rectangl");
display.fillRoundRect(0, 15, 60, 40, 8, WHITE);
display.display();
delay(2000);

Puedes dibujar un rectángulo redondeado en la pantalla usando la función drawRoundRect(X-coordinate, Y-coordinate, Width, Height, color). Esta función toma los mismos parámetros que la función drawRect() salvo un parámetro adicional: el radio del redondeo de las esquinas. En realidad, esta función dibuja un rectángulo redondeado hueco con un borde de 1 pixel. Puedes dibujar un rectángulo redondeado relleno usando la función fillRoundRect().

Dibujar un círculo

Drawing Circle On OLED Dsiplay Module
Drawing Filled Circle On OLED Dsiplay Module
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Circle");
display.drawCircle(20, 35, 20, WHITE);
display.display();
delay(2000);

display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Filled Circle");
display.fillCircle(20, 35, 20, WHITE);
display.display();
delay(2000);

Puedes dibujar un círculo en la pantalla usando la función drawCircle(X-coordinate of center, Y-coordinate of center, radius, color). Esta función dibuja un círculo hueco con un borde de 1 pixel. Puedes dibujar un círculo relleno usando la función fillCircle().

Dibujar un triángulo

Drawing Triangle On OLED Dsiplay Module
Drawing Filled Triangle On OLED Dsiplay Module
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Triangle");
display.drawTriangle(30, 15, 0, 60, 60, 60, WHITE);
display.display();
delay(2000);

display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Filled Triangle");
display.fillTriangle(30, 15, 0, 60, 60, 60, WHITE);
display.display();
delay(2000);

Puedes dibujar un triángulo en la pantalla usando la función drawTriangle(x0, y0, x1, y1, x2, y2, color). La función toma siete parámetros, a saber: las 3 coordenadas X e Y de los vértices del triángulo y el color. (X0,y0) representa el vértice superior,  (x1,y1) representa el vértice izquierdo y (x2,y2) representa el vértice derecho.

Esta función dibuja un triángulo hueco con un borde de 1 pixel. Puedes dibujar un triángulo relleno usando la función fillTriangle().

Código para ESP8266 NodeMCU – Mostrar un bitmap

Este último ejemplo muestra cómo dibujar imágenes bitmap en la pantalla OLED. Esto resulta útil para crear pantallas de bienvenida con logotipos de empresas, hacer sprites o simplemente crear gráficos divertidos para mostrar información. Copia el siguiente código, pégalo en el Arduino IDE y haz clic en subir.

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

Adafruit_SSD1306 display(-1);

// Bitmap of MarilynMonroe Image
const unsigned char MarilynMonroe [] PROGMEM = {
	0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x1f, 0xff, 0xff, 0xf0, 0x41, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xff, 0xf8, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0x87, 0xff, 0xff, 0xff, 0xf8, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0xf8, 0x01, 0xf1, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xf8, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xfc, 0x02, 0x78, 0x7f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xfe, 0x03, 0x7c, 0x1f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x07, 0xff, 0xff, 0xfe, 0x01, 0xfe, 0x1f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xfd, 0xe0, 0x03, 0xff, 0xff, 0xfc, 0x00, 0xfe, 0x0f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xfe, 0x87, 0xe0, 0xff, 0xff, 0xfc, 0x00, 0x06, 0x07, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xfc, 0x1f, 0xf9, 0xff, 0xff, 0xfc, 0x00, 0x02, 0x07, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xfc, 0x00, 0xc3, 0xc3, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xe0, 0x0c, 0x00, 0xe7, 0x81, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xe0, 0x02, 0x00, 0x02, 0x00, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x3f, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x1e, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x0f, 0xff, 0x3f, 0xf8, 0x00, 0x18, 0x7f, 0x1f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xf8, 0x01, 0x80, 0x03, 0xfc, 0x3f, 0xfc, 0x00, 0x70, 0xfe, 0x1f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xf0, 0x43, 0xff, 0xff, 0xf8, 0x7f, 0xf8, 0x00, 0x00, 0x7e, 0x1f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xf0, 0xff, 0xfc, 0x00, 0x00, 0x7c, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xe0, 0x0f, 0xff, 0xff, 0xf1, 0xef, 0xf8, 0x00, 0x01, 0xfc, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xe4, 0xff, 0xff, 0xff, 0xf3, 0x80, 0xa0, 0x00, 0x07, 0xfc, 0xaf, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xec, 0x5f, 0xff, 0xff, 0xe7, 0xf0, 0x00, 0x00, 0x03, 0xfe, 0xdf, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xee, 0x7f, 0xff, 0xff, 0xc7, 0xf8, 0x00, 0x00, 0x03, 0xff, 0xdf, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xf7, 0xc7, 0xff, 0x06, 0x00, 0x03, 0xff, 0xbf, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xfe, 0x5f, 0xff, 0xc7, 0x07, 0xff, 0x80, 0x00, 0x07, 0xdb, 0xbf, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xee, 0xff, 0xff, 0x80, 0x03, 0xff, 0xc0, 0x00, 0x03, 0xc3, 0x0f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0x98, 0x03, 0xff, 0xf8, 0x00, 0x07, 0xe0, 0x0f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xf8, 0x01, 0xff, 0xfc, 0x01, 0x07, 0xfc, 0x1f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xcf, 0xef, 0xff, 0xff, 0xe1, 0xff, 0xfc, 0x01, 0x07, 0xf8, 0x1f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0x7f, 0xf1, 0xff, 0xf8, 0x02, 0x07, 0x88, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xcf, 0xef, 0xf8, 0x0f, 0xff, 0xff, 0xe0, 0x00, 0x07, 0x84, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xe7, 0xef, 0xf0, 0x04, 0x7f, 0xff, 0xc0, 0x00, 0x07, 0x84, 0x7f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x3f, 0xff, 0xe0, 0x00, 0x1f, 0xff, 0x80, 0x00, 0x06, 0x04, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x3f, 0x7f, 0xe1, 0xf0, 0x07, 0xff, 0x80, 0x00, 0x07, 0x06, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xfe, 0x03, 0xff, 0x00, 0x00, 0x03, 0x80, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xf2, 0x3f, 0xc6, 0x7f, 0x81, 0xce, 0x00, 0x00, 0x01, 0xc1, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xe0, 0x3f, 0xc0, 0x07, 0xc1, 0xfe, 0x00, 0x00, 0x0d, 0xc0, 0x7f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xe0, 0x3f, 0xc0, 0x01, 0xe0, 0xfc, 0x00, 0x00, 0x0f, 0xc0, 0x7f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xc0, 0x3f, 0xc0, 0x00, 0x50, 0xfc, 0x00, 0x00, 0x0e, 0xc0, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xc0, 0x3f, 0xc0, 0x00, 0x18, 0xf8, 0x00, 0x00, 0x0e, 0xc1, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xc0, 0x3f, 0xc0, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x66, 0x81, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xc0, 0x1f, 0xc7, 0x80, 0x00, 0xf8, 0x00, 0x01, 0xe0, 0x00, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xc0, 0x1f, 0xc1, 0xe0, 0x01, 0xf8, 0x00, 0x03, 0xf0, 0x01, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x80, 0x1f, 0xc0, 0x3e, 0x03, 0xf0, 0x00, 0x00, 0xe0, 0x03, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x00, 0x1f, 0xe0, 0xe0, 0x03, 0xf2, 0x00, 0x00, 0xc0, 0x03, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x80, 0x1f, 0xf0, 0x00, 0x07, 0xe6, 0x00, 0x00, 0xc0, 0x03, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x80, 0x1f, 0xff, 0x00, 0x1f, 0xee, 0x00, 0x00, 0x80, 0x07, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xb8, 0x0f, 0xff, 0xf0, 0x3f, 0xdc, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xbc, 0x0f, 0xff, 0xff, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x9e, 0x0f, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x08, 0x0f, 0xff, 0xff, 0xff, 0x70, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x00, 0x0b, 0xff, 0xff, 0xfe, 0xe0, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x00, 0x0b, 0xff, 0xff, 0xf9, 0xc0, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x3c, 0x09, 0xff, 0xff, 0xf1, 0x80, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x1e, 0x08, 0x3f, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x1f, 0x08, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x80, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xce, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xfe, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff
};

void setup()   
{                
	// initialize with the I2C addr 0x3C
	display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  

	// Clear the buffer.
	display.clearDisplay();

	// Display bitmap
	display.drawBitmap(0, 0,  MarilynMonroe, 128, 64, WHITE);
	display.display();

	// Invert Display
	//display.invertDisplay(1);
}

void loop() {}

Así se ve el resultado.

Displaying Bitmap Image On OLED Dsiplay Module

Para mostrar una imagen bitmap en la pantalla OLED necesitamos llamar a la función drawBitmap(X-coordinate, Y-coordinate, bitmap array, width, height, color). Toma seis parámetros, a saber: la coordenada X de la esquina superior izquierda, la coordenada Y de la esquina superior izquierda, el arreglo de bytes del bitmap monocromático, el ancho del bitmap en pixeles, el alto del bitmap en pixeles y el color.

En nuestro ejemplo, la imagen bitmap tiene un tamaño de 128×64. Por eso, las coordenadas X e Y se establecen en 0, mientras que el ancho y el alto se establecen en 128 y 64.

// Display bitmap
display.drawBitmap(0, 0,  MarilynMonroe, 128, 64, WHITE);
display.display();

Pero, antes de poder llamar a la función drawBitmap(), primero necesitamos una imagen que dibujar. Recuerda que la resolución de pantalla de la OLED es de 128×64 pixeles, así que las imágenes más grandes que eso no se mostrarán correctamente. Para obtener una imagen del tamaño correcto, puedes usar tus programas de dibujo favoritos como Inkscape, Photoshop, Paint, etc., estableciendo el tamaño del lienzo en 128×64 pixeles.

Tomamos como ejemplo una imagen de Marilyn Monroe riendo, la convertimos a 128×64 pixeles usando Paint y la guardamos como .bmp.

Marilyn Monroe
Marilyn Monroe 128x64

Una vez que tengas un bitmap, es momento de convertirlo en un arreglo que el controlador OLED SSD1306 pueda entender. Esto se puede hacer de dos maneras: el método en línea usando image2cpp y el método sin conexión usando LCD Assistant.

Generador de arreglos de bitmap en línea – image2cpp

Existe una aplicación en línea llamada image2cpp – http://javl.github.io/image2cpp/ que puede convertir tu imagen en un arreglo. Image2cpp es más nueva y mucho más potente que LCD Assistant (la solución que veremos después). Te permitirá:

  • Convertir múltiples imágenes simultáneamente.
  • Escalar tu archivo de imagen – Estirar/Escalar para ajustar/Original
  • Ajustar el umbral de brillo entre blanco y negro.
  • Recentrar la imagen vertical u horizontalmente.
  • Invertir los colores de la imagen

Esta herramienta es tan potente que también puede funcionar sin conexión. Simplemente guarda la página en tu PC y ábrela en tu navegador. Gracias a Jasper van Loenen por su excelente contribución.

Para empezar, abre image2cpp en tu navegador y selecciona cualquier imagen que quieras mostrar en la pantalla OLED.

Select Image - image2cpp Bitmap to Data Array Online Conversion Tool

Las dimensiones de tu imagen se cargarán en la opción Canvas size dentro de la configuración de imagen (Image settings). Si seleccionaste una imagen más grande que 128×64, cámbiala a 128×64 y selecciona la opción de Scaling adecuada. Puedes ver el resultado en la sección de vista previa (Preview).

Puedes cambiar el Background color o invertir los colores de la imagen si es necesario.

Por último, cambia la opción más importante – Brightness threshold según lo que necesites. Ajustar el umbral hará que los pixeles por encima de ese nivel sean blancos y los que estén por debajo sean negros. En nuestro caso lo ajustamos a 171 para obtener buenos detalles de Marilyn Monroe.

Image Settings - image2cpp Bitmap to Data Array Online Conversion Tool

Esta pequeña vista previa refleja cualquier cambio que hagas en tu configuración. Puedes cambiar la configuración sin dejar de observarla.

Image Preview - image2cpp Bitmap to Data Array Online Conversion Tool

Una vez que estés satisfecho con el resultado, puedes proceder a generar el arreglo de datos. Simplemente selecciona Code output format como Arduino Code y haz clic en el botón Generate code.

Solo para tu información, hay una opción llamada Draw mode. En realidad crea la imagen según el patrón de barrido de la pantalla. Si tu imagen se ve toda distorsionada en la pantalla, prueba cambiando el modo.

Generating Output - image2cpp Bitmap to Data Array Online Conversion Tool

Listo. Se generará el arreglo de bytes de tu bitmap. Puedes usar el resultado directamente con nuestro código de ejemplo. Solo asegúrate de nombrarlo apropiadamente. Después, llama a tu arreglo dentro de la función drawBitmap().

Arduino Code Output - image2cpp Bitmap to Data Array Online Conversion Tool

Generador de arreglos de bitmap sin conexión – LCD Assistant

Existe otra aplicación llamada LCD assistant – http://en.radzio.dxp.pl/bitmap_converter/ que puede convertir tu imagen bitmap en un arreglo de datos. No es tan potente como image2cpp pero sigue siendo popular entre los aficionados.

Para empezar, necesitas convertir tu imagen en un bitmap monocromático de 1 bit de 128×64. Puedes usar tus programas de dibujo favoritos como Inkscape, Photoshop, Paint, etc. para hacerlo, tal como lo hicimos en MS Paint.

Abre tu archivo en MS Paint y cambia su tamaño a 128×64.

Opening Image in Paint

Ahora, guarda tu archivo como bitmap. Al guardar el archivo elige Save as type : Monochrome Bitmap(*.bmp;*.dib). Esto generará una imagen bitmap de 1 bit/binaria que tiene solo dos valores posibles para cada pixel, es decir, 0 (negro) o 1 (blanco).

Saving 1-bit Monochrome Bitmap Image in MS Paint

La única desventaja aquí es que no puedes ajustar el nivel del umbral de brillo. Está fijado en 50% de manera predeterminada y no se puede cambiar.

De cualquier forma, ahora descarga el programa LCD assistant. Abre el ejecutable y carga tu bitmap desde el menú File.

LCD Assistant Converts Bitmap Image to Data Array For LCD,OLED,Graphic Displays

No hay mucho que puedas hacer con esta herramienta. Así que, simplemente ve al menú File y haz clic en la opción Save output. Guarda el archivo como archivo de texto.

Solo para tu información, hay una opción llamada Byte Orientation. En realidad crea la imagen según el patrón de barrido de la pantalla. Si tu imagen se ve toda distorsionada en la pantalla, prueba cambiando el modo.

Save Output Of LCD Assistant

Listo. Con tu arreglo ya creado, pégalo en tu código.

Bitmap to Data Array Conversion Output - LCD Assistant Application

Solo asegúrate de nombrarlo apropiadamente. Después, llama a tu arreglo dentro de la función drawBitmap().

Artículo traducido al español. Fuente original: Last Minute Engineers.

Similar Posts

Deja un comentario