Display TFT SPI 1.8″

Objetivos

 

  • Presentar el display OLED 128×64.
  • Describir sus características.
  • Montar un circuito de ejemplo y un programa sencillo que lo use sacando texto.
  •  

    Material requerido.

     

    Imagen de Arduino UNO   Arduino UNO.
    Protoboard Una Protoboard .
    conexiones Algunos cables de protoboard.
    Display de 128x64 pixels  Un display OLED de 0.98” SPI.

     

    Los displays OLED de 128×64

     

    Lo primero que te sorprende cuando recibes una de estos displays OLED de casi una pulgada, es su tamaño. Son pequeños. Casi diría que son ridículamente minúsculos y desde luego, acostumbrados como estamos a ver displays del tipo del Nokia de la sesión anterior uno parece esperar una pantalla similar, pero en su lugar esta pantalla parece un sello de correos, no un display como es debido.

    Bueno, no prejuzguemos nada, vamos a montarla y luego opinamos. Y aquí comienza un peregrinaje por Internet, buscando como se conecta y configura la pantalla que acaba resultando bastante frustrante, porque como casi todos los modelos nuevos de fabricantes chinos, andan muy escasos de documentación con un mínimo de calidad, y ni siquiera en inglés parece haber demasiado.

    Así que vamos a ver si podemos aportar algo de luz en tema que merece la pena. Pero antes de nada…

    ¿Para qué queremos otro display pequeñajo y de tecnología OLED?

    Pues en principio, porque nos gusta jugar (que le vamos a hacer) y después porque el consumo que presenta este display es increíblemente  ridículo: unos 16 mA, aún menos que un LED y eso con una resolución de 128×64 pixels.

    Y lo sorprendente es que en cuanto lo pones en marcha te olvidas de lo enano que es y empiezan las buenas noticias. Tiene un contraste magnifico y no necesita  backlit para poder ver el display, ya que la tecnología OLED genera la luz de por sí.

  • Lo de OLED viene de Organic Leight Emitting Diode, o sea que son diodos LED con otra tecnología.
  •  

    El mío es de un precioso azul clarito y resulta muy agradable de leer, tanto a plena luz, como en la oscuridad completa.

    Además permite la representación tanto de caracteres como de matrices graficas e imágenes en una cierta resolución claro, 128×64 pixels, pero me ha encantado porque este display tiene muchas ventajas, entre ellas que supuestamente funciona igual a 5V que a 3.3V, tanto para la alimentación como para las señales de datos.

    Así que sin más preámbulos vamos a ver cómo utilizar este precioso display.

     

    Conexión de un displays OLED de 128×64

     

    Hay variantes de estos displays en I2C y en versión SPI. Yo he elegido de este último tipo porque en principio es más rápido y da menos guerra de configurar. La conexión resulta trivial.

    OLED ARDUINO
    GND GND
    Vcc 5V
    SCL D12
    SDA D11
    RST D10
    DC D9

    Como es habitual, podemos aprovecharnos de la facilidad de usar una protoboard para conectar los pines del display OLED directamente a los pines digitales de Arduino, para programarlos directamente.

    Esquema de protoboard

    Y el asunto no da para más, ya veis.

     

    El programa de control

     

    Hay varias librerías disponibles para manejar estos OLED, pero en general no me han convencido mucho. Podemos usar una librería de Adafruit para manejar los displays basados en el controlador  SSD1306 que es el chip que usa nuestro display.

    La podéis descargar de Github como Adafruit_SSD1306, y luego podemos usar varias de las librerías habituales de Adafruit como la GFX para dibujar gráficos en este display, pero me dió problemas.

    Así que al final encontré un programa en Instructables que manejaba directamente el display por programa y que aunque parece un poco más complicada, tiene dos grandes ventajas.

  • Una que funciona a la primera sin configurar nada más que los mensajes de texto que queremos sacar.
  • Otra que disponemos de todo el código a mano para modificar lo que queramos, lo que no está mal porque podríamos hacernos las librerías graficas o funciones de dibujo, si las necesitamos.
  •  

    El programa es este que tenéis aquí: Prog_42_2

    No os asustéis cuando veáis que contiene un montón de funciones definidas. Simplemente están a la vista en lugar de estar escondidas en la librería, pero podemos usar el display sin más que manejar una única función con los textos que nos interesen.

    Vamos con algunas definiciones:

    const int SCL_PIN=12;
    const int SDA_PIN=11;
    const int RST_PIN=10;
    const int DC_PIN =9;
    
    #include "stdio.h"
    char buffer[10];

    Las constantes son para definir los pines que usamos de control del display. Pero el include del stdio.h es una novedad y merece una explicación, que vamos a retrasar un poco hasta que surja el motivo de su uso. También definimos un buffer de caracteres para usar luego.

    En  el setup, inicializamos de todo como es habitual, mediante un par de funciones que podeis consultar sin problemas mas adelante:

    void setup()
       {   LEDPIN_Init();
           LED_Init();
       }

    La primera instrucción define los pines como entrada y salida, y la segunda se encarga de inicializar el display dejándolo listo para su uso. Ambas funciones están un poco más abajo.

    Podemos ignorar tranquilamente el resto, con excepción del loop, ya que no es necesario para manejar el display.

    void loop()
       {  long t= millis()/1000 ;
          int horas = t/3600 ;
          int minutos = (t % 3600) / 60;
          int segs = (t - horas*3600 - minutos * 60) % 60 ;
    
          int n = sprintf(buffer, "%02d:%02d:%02d", horas, minutos, segs);
          //char *S = "hola" ;
    
          LED_P8x16Str(20,0,  "    ...." );
          LED_P8x16Str(22,2,"Prometec.net");
          LED_P8x16Str(20,4,  buffer );
          LED_P8x16Str(20,6,  "    ...." );
       }

    Para imprimir un texto, usamos una función de nombre extravagante: P8x16Str. A la que le pasamos por valor un array de char o String.

  • Al ser un display de 64 pixels de alto las líneas las numeramos como 0, 2, 4,6; Porque antes había displays de estos de 32 pixels de alto y este es de altura doble (No te líes, las líneas se numeran de forma par).
  • Si tu display es de los modelos antiguos de 128×32, consulta la pagina de instructables que mencionamos mas arriba, porque he elimado el array y las funciones correspondientes para no cargar el ejmplo y la memoria.
  • El primer parámetro indica la distancia en pixels del margen izquierdo, el segundo parámetro el número de línea, y el tercero el texto a imprimir.
  •  

    Podemos pasarle textos directamente por valor, pero para poder imprimir un numero formateado, necesitaba la función sprintf(), que no viene incluida en Arduino por defecto y por eso usamos al principio las líneas:

    #include "stdio.h"
    char buffer[10];

    Para poder disponer de esa función sin complicarme la vida formateando el número. Quería mostrar un reloj  a partir de los millis (), y por eso calculamos horas minutos y segundos a partir del tiempo que lleva Arduino iniciado.

    Por lo demás, para quienes no estéis acostumbrados a C++ y a sprintf, sirva decir que esta función formatea un texto de acuerdo a las reglas que le marcamos en la cadena de control entre comillas y lo deposita en buffer, a la vez que devuelve la longitud de la cadena formateada.

    En «%02d:%02d:%02d» cada ‘d’ significa un numero decimal, el 2 que queremos que tenga 2 dígitos, y el 02d, significa un decimal con dos dígitos y con un cero de relleno si el número es de un solo digito.

    Fijaros además que al poner un ‘:’ entre las máscaras, el resultado final son números de dos dígitos rellenos de 0 cuando se necesita, separados por ‘:’, o sea como un reloj.

    El sprintf (buffer, «%02d:%02d:%02d», horas, minutos, segs) indica que queremos mostrar las variables  horas, minutos y segs, con la máscara indicada entre comillas y guardar el resultado en buffer. Al final, la función nos devuelve la longitud del texto generado aunque aquí no lo usamos para nada útil.

    Aquí os pongo un mini video con el resultado.

    Pero otra virtud de este pequeño display, es que al tener en fila los pines y consumir muy poco, podemos alimentarlo directamente desde un pin de Arduino UNO y usar el resto para controlar el display.

    Los que aspiran a nota, se habrán dado cuenta de que hemos elegido astutamente, los pines seguidos con toda la intención de pinchar el display directamente a Arduino,

    En la función de inicio LEDPIN_Init (), incluimos deliberadamente una llamada a pinMode para usarlo como OUTPUT y luego pusimos un HIGH para alimentar el display,

    void LEDPIN_Init(void)
       {   pinMode(SCL_PIN,OUTPUT);
           pinMode(SDA_PIN,OUTPUT);
           pinMode(RST_PIN,OUTPUT);
           pinMode(DC_PIN,OUTPUT);
    
           pinMode(13, OUTPUT);
           digitalWrite(13,HIGH);
       }

    Y el resultado es este

     

    Mostrando imágenes

     

    Este pequeño display es capaz de mostrar imágen en bitmaps en monocromo, si se las pasamos en el tamaño adecuado de 128×64 pixels.

    Hay varios programas que sirven para montar un array de char  a partir de una imagen en jpg o similar. El más sencillo que he visto es LCDA ssistant, y podéis descargarlo fácilmente con una búsqueda en Google.

    A partir de la imagen, te genera un fichero de texto con la fuente de un array de char para C, con el equivalente monocromo de la imagen. Lo que quiere decir que se pierden colores y grises y los resultados no son siempre lo esperas, pero es cuestión de trabajarlo.

    Como yo soy un poco inútil trabajando las imágenes, usaré una con el logo de Bently que nos proporcionaba Alex Chu en Instructables como ejemplos:

    Prog_42_3.

    EL programa es el mismo que el anterior, pero ahora tenemos un array logo:

    const unsigned char logo[]=
      { 0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
        0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x80,0x80,
        0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
        0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
        0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
        …………………..
       };

    Que incluye el array de 168×64 a mostrar en pantalla. Y en el loop, usamos una llamada a :

    LED_PrintBMP(0,0,128,7,(unsigned char *)logo);

    ¡Accede al contenido!

    Para mostrar la imagen logo en pantalla. Aquí os dejo una imagen del display:

    logo_1

     

    Por aun tenía una duda pendiente. Según la documentación, esta pequeña joyita puede funcionar tanto a 5V como hemos hecho hasta ahora con el UNO, como a 3.3V, tanto en alimentación como en señales.

    Además, otro problema es que no tengo claro  hasta que corriente puede suministrar el DUE en uno de sus pines, pues lo que he podido encontrar en la página de Arduino DUE es que hay un límite entre 3mA y 15mA dependiendo del pin, pero no específica cual es cual.

    Como el display OLED que nos ocupa, da un consumo máximo de 15 mA (Supongo que cuando todos los pixels esta encendidos) nos queda una cierta incertidumbre de si el DUE puede manejarlo o no.

    Y como no lo veía nada claro probé a conectarlo directamente a mi Arduino DUE (Si, me encanta el DUE, que queréis que os diga), y para mi satisfacción funcionó a la primera exactamente igual que con el Arduino UNO. Impresionante.

    Aquí os dejo una imagen del DUE corriendo este mismo programa del reloj, como prueba:

    Display OLED 128x64

     

    Resumen de la sesión

     

  • Hemos presentado los displays OLED con este pequeño primer modelo.
  • Vimos que la conexión es trivial y que podemos montarlo directamente en los conectores de nuestros Arduino, lo que supone un plus muy interesante.
  • Es bastante fácil de manejar, tanto para textos como para pequeños bitmaps y disponemos de los ejemplos necesarios para usarlo.
  • Un display que me ha gustado por su nitidez, porque emite luz propia con un consumo ridículo y un precio menor que el de una entrada de cine
  •  

  • Presentar los primeros displays TFT de 1,8”.
  • Mostrar la forma de conectarlo correctamente.
  • Mostrar algunos programas para sacarle partido imprimiendo texto de diferentes colores y tamaños de letra.
  • Presentar las primitivas graficas disponibles.
  • Material requerido.

    Imagen de Arduino UNO

    Arduino Uno o similar. Esta sesión acepta cualquier otro modelo de Arduino.

    Protoboard

    Una Protoboard.

    conexiones

    Cables  de protoboard

    Resitor resistencias de 1kΩ

    resistencias de 1kΩ

    Pantalla TFT

     Un display TFT de 1.8″ con SPI

     

    Los displays SPI

     

    Casi cualquier proyecto que planteemos tendrá, invariablemente, una parte en la que necesitaremos mostrar información al usuario exterior, y para ello necesitaremos alguna forma de display.

    En el curso de introducción fuimos viendo algunas de las opciones disponibles en el mercado, especialmente las más accesibles para alguien que quiere introducirse en el mundo de Arduino y la electrónica.

    Per naturalmente, el mercado nos ofrece un sinfín de posibilidades de displays cuya capacidades y grados de sofisticación son crecientes y que suelen conllevar un cierto grado también de complejidad.

    En los últimos años han ido apareciendo un creciente número de displays de buenas prestaciones con precios inimaginables (Por lo bajos, gracias a Dios) hasta hace muy poco y muchos de ellos incorporan algún tipo de bus de control para simplificar su acceso.

    Es el caso de los displays TFT que empezaron a venderse, en distintos tamaños, para los teléfonos móviles y que han acabado popularizándose como displays en color y  de pequeño tamaño.

    Pantalla TFT

    Pantalla TFT con SPI vista posterior

    En esta sesión vamos a ver como conectar a nuestros Arduinos un modelo de 1,8” en color con interface SPI, que son relativamente sencillos de encontrar muy baratos y que, por lo que he visto, están bastante mal documentados.

    Y es una pena porque son unos displays magníficos que por muy poco dinero nos permite manejar texto y gráficos a color con muy poco esfuerzo, aunque naturalmente la resolución no es gran cosa, es baja 128 x 160 puntos en pantalla.

    Vamos a ver como conectarlos

     

    Esquema de conexiones

     

    La conexión es muy sencilla y os incluye el ejemplo de conexión a la protoboard de la forma natural, es decir con el display hacia arriba y los pines de conexión hacia abajo, de manera que encajen en la protoboard.

    He estado bastante tiempo volviéndome loco tratando de conectar este display, sin conseguirlo, porque la documentación que hay en internet es muy pobre y se olvidan de darte una clave fundamental para que la cosa funcione.

    Hay que poner resistencias de 1KΩ en los pines de datos para el SPI y el único que parece haberse dado cuenta son los chicos de domipheus.

    Una vez que lo tienes claro, la conexión es trivial. Así pues, montar esas resistencias y veréis como enseguida vuestro display estará haciendo cositas a colorines.

    Esquema protoboard

    Por cierto el pin al lado del GND del display, está rotulado como BL o Back Light, y se usa para encender la luz de fondo del display y que pueda verse lo que hay en pantalla. Yo lo he conectado a 5V directamente, pero puedes usar un pin de tu Duino para encenderla y apagarla a voluntad.

     

    El Programa de control

     

    Como no podía ser de otra manera, vamos a utilizar las librerías de Adfruit para TFTs, modificadas para el control vía SPI. Tenemos que cargar dos librerías Libreria Adafruit GFX.zip y Libreria Adafruit_QDTech.zip.

    Seguid el procedimiento habitual para instalar librerías y veréis que también os instalarán una serie de ejemplos. Cargad el ejemplo:

    Archivo\ejemplos\Adafruit_QDTech\graphicsTest_QDTech

    Aquí tenéis el resultado del ejemplo:

    Vamos ahora con el detalle de cómo se maneja. Empecemos con las definiciones:

    define sclk 13           // No cambiar
    #define mosi 11          // No cambiar
    #define cs   9
    #define dc   8
    #define rst  7              //Es el reset del display
    #include <Adafruit_GFX.h>    // Core graphics library
    #include <Adafruit_QDTech.h> // Hardware-specific library
    #include <SPI.h>

    Son las definiciones de pines de conexión que corresponden con la imagen de la protoboard arriba. Mas las librerías necesarias incluyendo la SPI, que es el interface del display actual.

    Adafruit_QDTech tft = Adafruit_QDTech(cs, dc, rst);

    Creamos una instancia del objeto Adafruit_QDTech que llamamos tft. Lo siguiente es inicializar el objeto, Seleccionar la orientación vertical y borrar la pantalla:

    tft.init();                 // Inicializamos tft
    tft.setRotation(0);         // 0 - Portrait, 1 - Lanscape
    tft.fillScreen(QDTech_BLACK);   // Rellenar de negro, o sea, borrar

    Y aquí es donde le vamos a mandar escribir y dibujar:

    tft.fillRect (0, 16, 128, 18 ,QDTech_BLUE);
    testdrawtext ("   Curso Arduino\n    Prometec.net   \nPantalla de 21 x 20\n    caracteres.\n", QDTech_WHITE);
    
    tft.fillRect (0, 100, 128, 160 ,QDTech_RED);

    Le pedimos que rellene  un recuadro con fillRect(), del punto x=0, y=16 hasta el punto 128,18 de color azul.

     

  • La pantalla va del punto (0,0) en la esquina superior izquierda hasta el punto (128,160) en la esquina inferior derecha.
  •  

    Para escribir usamos la función testdrawtext(“xxxxxxxx”), o bien posicionamos el cursor en un punto y usamos tft.print(“Text”)

     Prog_40_1 

    #define sclk 13  // No cambiar
    #define mosi 11  // No cambiar
    #define cs   9
    #define dc   8
    #define rst  7  // Podemos conectarlo al  Arduino reset
    #include <Adafruit_GFX.h>    // Core graphics library
    #include <Adafruit_QDTech.h> // Hardware-specific library
    #include <SPI.h>
    
    Adafruit_QDTech tft = Adafruit_QDTech(cs, dc, rst);  // Invoke custom library
    
    void setup()
       {
            tft.init();             // Inicializa la pantalla
            tft.setRotation(0);     // 0 - Portrait, 1 - Lanscape
            tft.fillScreen(QDTech_BLACK);
    
            tft.fillRect (0, 16, 128, 18 ,QDTech_BLUE);
            testdrawtext ("   Curso Arduino\n    Prometec.net   \nPantalla de 21 x 20\n            caracteres.\n", QDTech_WHITE);
    
            tft.fillRect (0, 100, 128, 160 ,QDTech_RED);  // Rellena de rojo
            tft.setCursor(10, 50);                          // Cursor a 10,50
            tft.setTextColor(QDTech_BLUE); // Color del texto azul
            tft.print("Display SPI de 1.8\"");    // Escribe en la posicion del cursor
       }
    void loop() {}
    
    void testdrawtext(char *text, uint16_t color)
       {     tft.setCursor(0, 0);
             tft.setTextColor(color);
             tft.setTextWrap(true);      // Si el texto no cabe pasalo a la siguiente linea
             tft.print(text);
       }

    Objetivos

     

  • Presentar el display OLED 128×64.
  • Describir sus características.
  • Montar un circuito de ejemplo y un programa sencillo que lo use sacando texto.
  •  

    Material requerido.

     

    Imagen de Arduino UNO   Arduino UNO.
    Protoboard Una Protoboard .
    conexiones Algunos cables de protoboard.
    Display de 128x64 pixels  Un display OLED de 0.98” SPI.

     

    Los displays OLED de 128×64

     

    Lo primero que te sorprende cuando recibes una de estos displays OLED de casi una pulgada, es su tamaño. Son pequeños. Casi diría que son ridículamente minúsculos y desde luego, acostumbrados como estamos a ver displays del tipo del Nokia de la sesión anterior uno parece esperar una pantalla similar, pero en su lugar esta pantalla parece un sello de correos, no un display como es debido.

    Bueno, no prejuzguemos nada, vamos a montarla y luego opinamos. Y aquí comienza un peregrinaje por Internet, buscando como se conecta y configura la pantalla que acaba resultando bastante frustrante, porque como casi todos los modelos nuevos de fabricantes chinos, andan muy escasos de documentación con un mínimo de calidad, y ni siquiera en inglés parece haber demasiado.

    Así que vamos a ver si podemos aportar algo de luz en tema que merece la pena. Pero antes de nada…

    ¿Para qué queremos otro display pequeñajo y de tecnología OLED?

    Pues en principio, porque nos gusta jugar (que le vamos a hacer) y después porque el consumo que presenta este display es increíblemente  ridículo: unos 16 mA, aún menos que un LED y eso con una resolución de 128×64 pixels.

    Y lo sorprendente es que en cuanto lo pones en marcha te olvidas de lo enano que es y empiezan las buenas noticias. Tiene un contraste magnifico y no necesita  backlit para poder ver el display, ya que la tecnología OLED genera la luz de por sí.

  • Lo de OLED viene de Organic Leight Emitting Diode, o sea que son diodos LED con otra tecnología.
  •  

    El mío es de un precioso azul clarito y resulta muy agradable de leer, tanto a plena luz, como en la oscuridad completa.

    Además permite la representación tanto de caracteres como de matrices graficas e imágenes en una cierta resolución claro, 128×64 pixels, pero me ha encantado porque este display tiene muchas ventajas, entre ellas que supuestamente funciona igual a 5V que a 3.3V, tanto para la alimentación como para las señales de datos.

    Así que sin más preámbulos vamos a ver cómo utilizar este precioso display.

     

    Conexión de un displays OLED de 128×64

     

    Hay variantes de estos displays en I2C y en versión SPI. Yo he elegido de este último tipo porque en principio es más rápido y da menos guerra de configurar. La conexión resulta trivial.

    OLED ARDUINO
    GND GND
    Vcc 5V
    SCL D12
    SDA D11
    RST D10
    DC D9

    Como es habitual, podemos aprovecharnos de la facilidad de usar una protoboard para conectar los pines del display OLED directamente a los pines digitales de Arduino, para programarlos directamente.

    Esquema de protoboard

    Y el asunto no da para más, ya veis.

     

    El programa de control

     

    Hay varias librerías disponibles para manejar estos OLED, pero en general no me han convencido mucho. Podemos usar una librería de Adafruit para manejar los displays basados en el controlador  SSD1306 que es el chip que usa nuestro display.

    La podéis descargar de Github como Adafruit_SSD1306, y luego podemos usar varias de las librerías habituales de Adafruit como la GFX para dibujar gráficos en este display, pero me dió problemas.

    Así que al final encontré un programa en Instructables que manejaba directamente el display por programa y que aunque parece un poco más complicada, tiene dos grandes ventajas.

  • Una que funciona a la primera sin configurar nada más que los mensajes de texto que queremos sacar.
  • Otra que disponemos de todo el código a mano para modificar lo que queramos, lo que no está mal porque podríamos hacernos las librerías graficas o funciones de dibujo, si las necesitamos.
  •  

    El programa es este que tenéis aquí: Prog_42_2

    No os asustéis cuando veáis que contiene un montón de funciones definidas. Simplemente están a la vista en lugar de estar escondidas en la librería, pero podemos usar el display sin más que manejar una única función con los textos que nos interesen.

    Vamos con algunas definiciones:

    const int SCL_PIN=12;
    const int SDA_PIN=11;
    const int RST_PIN=10;
    const int DC_PIN =9;
    
    #include "stdio.h"
    char buffer[10];

    Las constantes son para definir los pines que usamos de control del display. Pero el include del stdio.h es una novedad y merece una explicación, que vamos a retrasar un poco hasta que surja el motivo de su uso. También definimos un buffer de caracteres para usar luego.

    En  el setup, inicializamos de todo como es habitual, mediante un par de funciones que podeis consultar sin problemas mas adelante:

    void setup()
       {   LEDPIN_Init();
           LED_Init();
       }

    La primera instrucción define los pines como entrada y salida, y la segunda se encarga de inicializar el display dejándolo listo para su uso. Ambas funciones están un poco más abajo.

    Podemos ignorar tranquilamente el resto, con excepción del loop, ya que no es necesario para manejar el display.

    void loop()
       {  long t= millis()/1000 ;
          int horas = t/3600 ;
          int minutos = (t % 3600) / 60;
          int segs = (t - horas*3600 - minutos * 60) % 60 ;
    
          int n = sprintf(buffer, "%02d:%02d:%02d", horas, minutos, segs);
          //char *S = "hola" ;
    
          LED_P8x16Str(20,0,  "    ...." );
          LED_P8x16Str(22,2,"Prometec.net");
          LED_P8x16Str(20,4,  buffer );
          LED_P8x16Str(20,6,  "    ...." );
       }

    Para imprimir un texto, usamos una función de nombre extravagante: P8x16Str. A la que le pasamos por valor un array de char o String.

  • Al ser un display de 64 pixels de alto las líneas las numeramos como 0, 2, 4,6; Porque antes había displays de estos de 32 pixels de alto y este es de altura doble (No te líes, las líneas se numeran de forma par).
  • Si tu display es de los modelos antiguos de 128×32, consulta la pagina de instructables que mencionamos mas arriba, porque he elimado el array y las funciones correspondientes para no cargar el ejmplo y la memoria.
  • El primer parámetro indica la distancia en pixels del margen izquierdo, el segundo parámetro el número de línea, y el tercero el texto a imprimir.
  •  

    Podemos pasarle textos directamente por valor, pero para poder imprimir un numero formateado, necesitaba la función sprintf(), que no viene incluida en Arduino por defecto y por eso usamos al principio las líneas:

    #include "stdio.h"
    char buffer[10];

    Para poder disponer de esa función sin complicarme la vida formateando el número. Quería mostrar un reloj  a partir de los millis (), y por eso calculamos horas minutos y segundos a partir del tiempo que lleva Arduino iniciado.

    Por lo demás, para quienes no estéis acostumbrados a C++ y a sprintf, sirva decir que esta función formatea un texto de acuerdo a las reglas que le marcamos en la cadena de control entre comillas y lo deposita en buffer, a la vez que devuelve la longitud de la cadena formateada.

    En «%02d:%02d:%02d» cada ‘d’ significa un numero decimal, el 2 que queremos que tenga 2 dígitos, y el 02d, significa un decimal con dos dígitos y con un cero de relleno si el número es de un solo digito.

    Fijaros además que al poner un ‘:’ entre las máscaras, el resultado final son números de dos dígitos rellenos de 0 cuando se necesita, separados por ‘:’, o sea como un reloj.

    El sprintf (buffer, «%02d:%02d:%02d», horas, minutos, segs) indica que queremos mostrar las variables  horas, minutos y segs, con la máscara indicada entre comillas y guardar el resultado en buffer. Al final, la función nos devuelve la longitud del texto generado aunque aquí no lo usamos para nada útil.

    Aquí os pongo un mini video con el resultado.

    Pero otra virtud de este pequeño display, es que al tener en fila los pines y consumir muy poco, podemos alimentarlo directamente desde un pin de Arduino UNO y usar el resto para controlar el display.

    Los que aspiran a nota, se habrán dado cuenta de que hemos elegido astutamente, los pines seguidos con toda la intención de pinchar el display directamente a Arduino,

    En la función de inicio LEDPIN_Init (), incluimos deliberadamente una llamada a pinMode para usarlo como OUTPUT y luego pusimos un HIGH para alimentar el display,

    void LEDPIN_Init(void)
       {   pinMode(SCL_PIN,OUTPUT);
           pinMode(SDA_PIN,OUTPUT);
           pinMode(RST_PIN,OUTPUT);
           pinMode(DC_PIN,OUTPUT);
    
           pinMode(13, OUTPUT);
           digitalWrite(13,HIGH);
       }

    ¡Accede al contenido!

    Y el resultado es este

     

    Mostrando imágenes

     

    Este pequeño display es capaz de mostrar imágen en bitmaps en monocromo, si se las pasamos en el tamaño adecuado de 128×64 pixels.

    Hay varios programas que sirven para montar un array de char  a partir de una imagen en jpg o similar. El más sencillo que he visto es LCDA ssistant, y podéis descargarlo fácilmente con una búsqueda en Google.

    A partir de la imagen, te genera un fichero de texto con la fuente de un array de char para C, con el equivalente monocromo de la imagen. Lo que quiere decir que se pierden colores y grises y los resultados no son siempre lo esperas, pero es cuestión de trabajarlo.

    Como yo soy un poco inútil trabajando las imágenes, usaré una con el logo de Bently que nos proporcionaba Alex Chu en Instructables como ejemplos:

    Prog_42_3.

    EL programa es el mismo que el anterior, pero ahora tenemos un array logo:

    const unsigned char logo[]=
      { 0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
        0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x80,0x80,
        0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
        0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
        0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
        …………………..
       };

    Que incluye el array de 168×64 a mostrar en pantalla. Y en el loop, usamos una llamada a :

    LED_PrintBMP(0,0,128,7,(unsigned char *)logo);

    ¡Accede al contenido!

    Para mostrar la imagen logo en pantalla. Aquí os dejo una imagen del display:

    logo_1

     

    Por aun tenía una duda pendiente. Según la documentación, esta pequeña joyita puede funcionar tanto a 5V como hemos hecho hasta ahora con el UNO, como a 3.3V, tanto en alimentación como en señales.

    Además, otro problema es que no tengo claro  hasta que corriente puede suministrar el DUE en uno de sus pines, pues lo que he podido encontrar en la página de Arduino DUE es que hay un límite entre 3mA y 15mA dependiendo del pin, pero no específica cual es cual.

    Como el display OLED que nos ocupa, da un consumo máximo de 15 mA (Supongo que cuando todos los pixels esta encendidos) nos queda una cierta incertidumbre de si el DUE puede manejarlo o no.

    Y como no lo veía nada claro probé a conectarlo directamente a mi Arduino DUE (Si, me encanta el DUE, que queréis que os diga), y para mi satisfacción funcionó a la primera exactamente igual que con el Arduino UNO. Impresionante.

    Aquí os dejo una imagen del DUE corriendo este mismo programa del reloj, como prueba:

    Display OLED 128x64

     

    Resumen de la sesión

     

  • Hemos presentado los displays OLED con este pequeño primer modelo.
  • Vimos que la conexión es trivial y que podemos montarlo directamente en los conectores de nuestros Arduino, lo que supone un plus muy interesante.
  • Es bastante fácil de manejar, tanto para textos como para pequeños bitmaps y disponemos de los ejemplos necesarios para usarlo.
  • Un display que me ha gustado por su nitidez, porque emite luz propia con un consumo ridículo y un precio menor que el de una entrada de cine
  •  

  • Fíjate en que para poder poner 1.8” en la última línea de texto hemos escrito «Display SPI de 1.8\»» esto no es un error. Para poder escribir las comillas y que C++ no lo confunda con el cierre del string literal he usado \” para indicarle que quiero usar las comillas dentro del literal.
  • Texto de prueba

     

    A la izquierda teneís el resultado del programa, y por cierto los colores disponibles de serie son:

    QDTech_BLACK 
    QDTech_RED
    QDTech_GREEN
    QDTech_BLUE 
    QDTech_YELLOW
    QDTech_MAGENTA
    QDTech_CYAN
    QDTech_WHITE
    QDTech_GREY

    Pero no debería ser demasiado difícil definir nuevos colores.

     Prog_40_2

    #define sclk 13  // No cambiar
    #define mosi 11  // No cambiar
    #define cs   9
    #define dc   8
    #define rst  7  
    #include <Adafruit_GFX.h>    
    #include <Adafruit_QDTech.h> 
    #include <SPI.h>
    
    Adafruit_QDTech tft = Adafruit_QDTech(cs, dc, rst);  // Invoke custom library
    
    void setup()
       {   tft.init();
           tft.setRotation(0);      // 0 - Portrait, 1 - Lanscape
           tft.fillScreen(QDTech_BLACK);
           tft.setTextWrap(true);
           delay(500);
    
           tft.setTextSize(1);
           tft.setCursor(0, 10);           // Cursor a 10,50
           tft.setTextColor(QDTech_BLUE);  // Color del texto azul
           tft.print("Display");           // Escribe en la posicion del cursor
          
          tft.setTextSize(2);
          tft.setCursor(0, 25);            // Cursor a 10,50
          tft.setTextColor(QDTech_RED);    // Color del texto rojo
          tft.print("Display");            // Escribe en la posicion del cursor
    
          tft.setTextSize(3);
          tft.setCursor(0, 50);            // Cursor a 10,50
          tft.setTextColor(QDTech_GREEN);  // Color del texto azul
          tft.print("Display");            // Escribe en la posicion del cursor
    
          tft.setTextSize(4);
          tft.setTextWrap(false);      // Si cambias esto lo que no quepa sigue en la siguiente linea
          tft.setCursor(0, 80);        // Cursor a 10,50
          tft.setTextColor(QDTech_CYAN);      // Color del texto cian
          tft.print("Display"); 
    
          tft.setRotation(1); // 0 - Portrait, 1 – Lanscape, Cambiamos orientacion
          tft.setTextSize(2);
          tft.setCursor(0, 10);             // Al cambiar la orientación cambia el punto 0,0
          tft.setTextColor(QDTech_YELLOW);          // Color del texto amarillo
          tft.print("Display");             // Escribe en la posicion del cursor
       }
    void loop() {}

    El resultado es como este:

    Muestras de posibilidades

    La instancia de tft tiene varios métodos gráficos interesantes:

    Método Descripción
    tft.fillScreen( Color ) Borra la pantalla con el color indicado
    tft.fillRect (x0,y 0,x1, y1, Color); Rellena un recuadro de color entre x0,y0 a x1,y1
    tft.drawPixel(x0,y0, Color); Pinta el pixel y ya está ( A mí no me miréis)
    tft.drawLine(x0,y 0, x1, y1,Color) Dibuja una línea
    tft.drawFastHLine(x0,y0, L, Color) Dibuja una línea horizontal de la longitud L
    tft.drawFastHLine(x0,y0, H, Color) Dibuja una línea vertical de la longitud L
    tft.fillCircle(x, y, radius, color); Dibuja un circulo relleno
    tft.drawCircle(x, y, radius, color); Dibuja el contorno de un circulo
    tft.drawTriangle(x0, y0, x1, y1,x2, y2, color); Dibuja un triángulo entre los 2 puntos indicaos
    tft.drawRoundRect(x0, y0, x1,y1h, R, color) Rectángulo redondeado entre P0 y P1 con redondeo de radio R

    Y alguna propiedades que merecen destacar como tft.width(), que nos devuelve la anchura de la pantalla y tft.height(), que nos devuelve la altura.

     

    Resumen de la sesión

    Objetivos

     

  • Presentar el display OLED 128×64.
  • Describir sus características.
  • Montar un circuito de ejemplo y un programa sencillo que lo use sacando texto.
  •  

    Material requerido.

     

    Imagen de Arduino UNO   Arduino UNO.
    Protoboard Una Protoboard .
    conexiones Algunos cables de protoboard.
    Display de 128x64 pixels  Un display OLED de 0.98” SPI.

     

    Los displays OLED de 128×64

     

    Lo primero que te sorprende cuando recibes una de estos displays OLED de casi una pulgada, es su tamaño. Son pequeños. Casi diría que son ridículamente minúsculos y desde luego, acostumbrados como estamos a ver displays del tipo del Nokia de la sesión anterior uno parece esperar una pantalla similar, pero en su lugar esta pantalla parece un sello de correos, no un display como es debido.

    Bueno, no prejuzguemos nada, vamos a montarla y luego opinamos. Y aquí comienza un peregrinaje por Internet, buscando como se conecta y configura la pantalla que acaba resultando bastante frustrante, porque como casi todos los modelos nuevos de fabricantes chinos, andan muy escasos de documentación con un mínimo de calidad, y ni siquiera en inglés parece haber demasiado.

    Así que vamos a ver si podemos aportar algo de luz en tema que merece la pena. Pero antes de nada…

    ¿Para qué queremos otro display pequeñajo y de tecnología OLED?

    Pues en principio, porque nos gusta jugar (que le vamos a hacer) y después porque el consumo que presenta este display es increíblemente  ridículo: unos 16 mA, aún menos que un LED y eso con una resolución de 128×64 pixels.

    Y lo sorprendente es que en cuanto lo pones en marcha te olvidas de lo enano que es y empiezan las buenas noticias. Tiene un contraste magnifico y no necesita  backlit para poder ver el display, ya que la tecnología OLED genera la luz de por sí.

  • Lo de OLED viene de Organic Leight Emitting Diode, o sea que son diodos LED con otra tecnología.
  •  

    El mío es de un precioso azul clarito y resulta muy agradable de leer, tanto a plena luz, como en la oscuridad completa.

    Además permite la representación tanto de caracteres como de matrices graficas e imágenes en una cierta resolución claro, 128×64 pixels, pero me ha encantado porque este display tiene muchas ventajas, entre ellas que supuestamente funciona igual a 5V que a 3.3V, tanto para la alimentación como para las señales de datos.

    Así que sin más preámbulos vamos a ver cómo utilizar este precioso display.

     

    Conexión de un displays OLED de 128×64

     

    Hay variantes de estos displays en I2C y en versión SPI. Yo he elegido de este último tipo porque en principio es más rápido y da menos guerra de configurar. La conexión resulta trivial.

    OLED ARDUINO
    GND GND
    Vcc 5V
    SCL D12
    SDA D11
    RST D10
    DC D9

    Como es habitual, podemos aprovecharnos de la facilidad de usar una protoboard para conectar los pines del display OLED directamente a los pines digitales de Arduino, para programarlos directamente.

    Esquema de protoboard

    Y el asunto no da para más, ya veis.

     

    El programa de control

     

    Hay varias librerías disponibles para manejar estos OLED, pero en general no me han convencido mucho. Podemos usar una librería de Adafruit para manejar los displays basados en el controlador  SSD1306 que es el chip que usa nuestro display.

    La podéis descargar de Github como Adafruit_SSD1306, y luego podemos usar varias de las librerías habituales de Adafruit como la GFX para dibujar gráficos en este display, pero me dió problemas.

    Así que al final encontré un programa en Instructables que manejaba directamente el display por programa y que aunque parece un poco más complicada, tiene dos grandes ventajas.

  • Una que funciona a la primera sin configurar nada más que los mensajes de texto que queremos sacar.
  • Otra que disponemos de todo el código a mano para modificar lo que queramos, lo que no está mal porque podríamos hacernos las librerías graficas o funciones de dibujo, si las necesitamos.
  •  

    El programa es este que tenéis aquí: Prog_42_2

    No os asustéis cuando veáis que contiene un montón de funciones definidas. Simplemente están a la vista en lugar de estar escondidas en la librería, pero podemos usar el display sin más que manejar una única función con los textos que nos interesen.

    Vamos con algunas definiciones:

    const int SCL_PIN=12;
    const int SDA_PIN=11;
    const int RST_PIN=10;
    const int DC_PIN =9;
    
    #include "stdio.h"
    char buffer[10];

    Las constantes son para definir los pines que usamos de control del display. Pero el include del stdio.h es una novedad y merece una explicación, que vamos a retrasar un poco hasta que surja el motivo de su uso. También definimos un buffer de caracteres para usar luego.

    En  el setup, inicializamos de todo como es habitual, mediante un par de funciones que podeis consultar sin problemas mas adelante:

    void setup()
       {   LEDPIN_Init();
           LED_Init();
       }

    La primera instrucción define los pines como entrada y salida, y la segunda se encarga de inicializar el display dejándolo listo para su uso. Ambas funciones están un poco más abajo.

    Podemos ignorar tranquilamente el resto, con excepción del loop, ya que no es necesario para manejar el display.

    void loop()
       {  long t= millis()/1000 ;
          int horas = t/3600 ;
          int minutos = (t % 3600) / 60;
          int segs = (t - horas*3600 - minutos * 60) % 60 ;
    
          int n = sprintf(buffer, "%02d:%02d:%02d", horas, minutos, segs);
          //char *S = "hola" ;
    
          LED_P8x16Str(20,0,  "    ...." );
          LED_P8x16Str(22,2,"Prometec.net");
          LED_P8x16Str(20,4,  buffer );
          LED_P8x16Str(20,6,  "    ...." );
       }

    Para imprimir un texto, usamos una función de nombre extravagante: P8x16Str. A la que le pasamos por valor un array de char o String.

  • Al ser un display de 64 pixels de alto las líneas las numeramos como 0, 2, 4,6; Porque antes había displays de estos de 32 pixels de alto y este es de altura doble (No te líes, las líneas se numeran de forma par).
  • Si tu display es de los modelos antiguos de 128×32, consulta la pagina de instructables que mencionamos mas arriba, porque he elimado el array y las funciones correspondientes para no cargar el ejmplo y la memoria.
  • El primer parámetro indica la distancia en pixels del margen izquierdo, el segundo parámetro el número de línea, y el tercero el texto a imprimir.
  •  

    Podemos pasarle textos directamente por valor, pero para poder imprimir un numero formateado, necesitaba la función sprintf(), que no viene incluida en Arduino por defecto y por eso usamos al principio las líneas:

    #include "stdio.h"
    char buffer[10];

    Para poder disponer de esa función sin complicarme la vida formateando el número. Quería mostrar un reloj  a partir de los millis (), y por eso calculamos horas minutos y segundos a partir del tiempo que lleva Arduino iniciado.

    Por lo demás, para quienes no estéis acostumbrados a C++ y a sprintf, sirva decir que esta función formatea un texto de acuerdo a las reglas que le marcamos en la cadena de control entre comillas y lo deposita en buffer, a la vez que devuelve la longitud de la cadena formateada.

    En «%02d:%02d:%02d» cada ‘d’ significa un numero decimal, el 2 que queremos que tenga 2 dígitos, y el 02d, significa un decimal con dos dígitos y con un cero de relleno si el número es de un solo digito.

    Fijaros además que al poner un ‘:’ entre las máscaras, el resultado final son números de dos dígitos rellenos de 0 cuando se necesita, separados por ‘:’, o sea como un reloj.

    El sprintf (buffer, «%02d:%02d:%02d», horas, minutos, segs) indica que queremos mostrar las variables  horas, minutos y segs, con la máscara indicada entre comillas y guardar el resultado en buffer. Al final, la función nos devuelve la longitud del texto generado aunque aquí no lo usamos para nada útil.

    Aquí os pongo un mini video con el resultado.

    Pero otra virtud de este pequeño display, es que al tener en fila los pines y consumir muy poco, podemos alimentarlo directamente desde un pin de Arduino UNO y usar el resto para controlar el display.

    Los que aspiran a nota, se habrán dado cuenta de que hemos elegido astutamente, los pines seguidos con toda la intención de pinchar el display directamente a Arduino,

    En la función de inicio LEDPIN_Init (), incluimos deliberadamente una llamada a pinMode para usarlo como OUTPUT y luego pusimos un HIGH para alimentar el display,

    void LEDPIN_Init(void)
       {   pinMode(SCL_PIN,OUTPUT);
           pinMode(SDA_PIN,OUTPUT);
           pinMode(RST_PIN,OUTPUT);
           pinMode(DC_PIN,OUTPUT);
    
           pinMode(13, OUTPUT);
           digitalWrite(13,HIGH);
       }

    ¡Accede al contenido!

    Y el resultado es este

     

    Mostrando imágenes

     

    Este pequeño display es capaz de mostrar imágen en bitmaps en monocromo, si se las pasamos en el tamaño adecuado de 128×64 pixels.

    Hay varios programas que sirven para montar un array de char  a partir de una imagen en jpg o similar. El más sencillo que he visto es LCDA ssistant, y podéis descargarlo fácilmente con una búsqueda en Google.

    A partir de la imagen, te genera un fichero de texto con la fuente de un array de char para C, con el equivalente monocromo de la imagen. Lo que quiere decir que se pierden colores y grises y los resultados no son siempre lo esperas, pero es cuestión de trabajarlo.

    Como yo soy un poco inútil trabajando las imágenes, usaré una con el logo de Bently que nos proporcionaba Alex Chu en Instructables como ejemplos:

    Prog_42_3.

    EL programa es el mismo que el anterior, pero ahora tenemos un array logo:

    const unsigned char logo[]=
      { 0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
        0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x80,0x80,
        0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
        0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
        0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
        …………………..
       };

    Que incluye el array de 168×64 a mostrar en pantalla. Y en el loop, usamos una llamada a :

    LED_PrintBMP(0,0,128,7,(unsigned char *)logo);

    ¡Accede al contenido!

    Para mostrar la imagen logo en pantalla. Aquí os dejo una imagen del display:

    logo_1

     

    Por aun tenía una duda pendiente. Según la documentación, esta pequeña joyita puede funcionar tanto a 5V como hemos hecho hasta ahora con el UNO, como a 3.3V, tanto en alimentación como en señales.

    Además, otro problema es que no tengo claro  hasta que corriente puede suministrar el DUE en uno de sus pines, pues lo que he podido encontrar en la página de Arduino DUE es que hay un límite entre 3mA y 15mA dependiendo del pin, pero no específica cual es cual.

    Como el display OLED que nos ocupa, da un consumo máximo de 15 mA (Supongo que cuando todos los pixels esta encendidos) nos queda una cierta incertidumbre de si el DUE puede manejarlo o no.

    Y como no lo veía nada claro probé a conectarlo directamente a mi Arduino DUE (Si, me encanta el DUE, que queréis que os diga), y para mi satisfacción funcionó a la primera exactamente igual que con el Arduino UNO. Impresionante.

    Aquí os dejo una imagen del DUE corriendo este mismo programa del reloj, como prueba:

    Display OLED 128x64

     

    Resumen de la sesión

     

  • Hemos presentado los displays OLED con este pequeño primer modelo.
  • Vimos que la conexión es trivial y que podemos montarlo directamente en los conectores de nuestros Arduino, lo que supone un plus muy interesante.
  • Es bastante fácil de manejar, tanto para textos como para pequeños bitmaps y disponemos de los ejemplos necesarios para usarlo.
  • Un display que me ha gustado por su nitidez, porque emite luz propia con un consumo ridículo y un precio menor que el de una entrada de cine
  •  

  • Hemos presentado los displays TFT de 1,8”.
  • Hemos visto que el único truco que tienen para conectarlos es usar unas resistencias de 1kΩ en los pines de datos, algo que está muy mal documentado y que ha generado mucha confusión en internet.
  • Hemos visto los principios básicos para mostrar textos en varios colores y tamaños, así como la forma de posicionarlos en pantalla.
  • Presentar sin entrar mucho en ello las primitivas graficas que nos permiten dibujar líneas, círculo y rectángulos.
  •  

     

    Deja una respuesta