bclose

Display OLED 0.96”

Otro tipo de displays

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.
ProtoboardUna Protoboard .
conexionesAlgunos 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.

OLEDARDUINO
GNDGND
Vcc5V
SCLD12
SDAD11
RSTD10
DCD9

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 habitua, 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ágenen 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 LCDAssistant, 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 trabajártelo.

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);

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

 
 

 

 

 

(15) Comments

    • Jesus

    Si quisiera conectar un sensor de pulso cardíaco, ¿se pude? ¿me podrías enseñar?

    • Me temo Jesus que aunque existen no dispongo de ninguno para jugar con el

  • Ya he buscado y no he encontrado nada que valga,lo dejare por aqui otra vez,ya que ocupa poco. Gracias por la ayuda. 😉

  • Hola buenas!! me a encantado este articulo,y ademas buscando en el cajon de los recuerdos tengo un apantalla oled de 96×16 tiene 30 pines y he busaco su ficha tecnica,que es esta ” https://www.google.es/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0ahUKEwiK6tGypqHOAhUEfxoKHWFeDhQQFggcMAA&url=https%3A%2F%2Fmedia.digikey.com%2Fpdf%2FData%2520Sheets%2FOsram%2520PDFs%2FPictiva_0.8in_96x16.pdf&usg=AFQjCNFHC9GqPSPMwFuttoNA0mXckXyrPA&sig2=GZGJcHJZRW4JrPyGRpFREg
    y me ha sorprendido ver que no encuentro los pines de “scl,sca,etc..” asi que no se como conectarla. Me echais una mano?

    • Hola david, el display que me enseñas tiene 30 pines y aunque el hardware sea aprecido el interface de tu display tien 30 pines y habria que buscar la docuemtacion y hoja tecnica para saber como s emaneja porque es diferente del display i2c que yo uso y por eso no encuentras los pines que me mencionas.

      Hay que buscae la hoja tecnica y trabajarse el tema y por eso yo siempre trato de usar un bus tipo el i2c o el spi que al final te quuitan doleres de cabeza

    • Chocarrat

    Buenas noches Admin.
    Al final me ha llegado la pantalla Oled de .96″
    En principio todo Ok, aunque como es una I2C con 4 pines, tiene algunas diferencias con respecto a la del tutorial.
    Esta se conecta al A4 y A5 y hay que hacer un Scan por el puerto serie para sacar un parámetro (no lo tengo delante ahora y hablo un poco de memoria)
    La cosa es que habiendo conseguido cargar el ejemplo de Adafruit quería dar un paso más y probarla.
    He conseguido poner algún bitmap, y alguna cadena de texto usando una librería de un tal Oscar bastante apañada.
    Mi problema viene al querer sacar a la pantalla valores de variables (quería poner los valores del termómetro).
    Resulta que no lo consigo, y a lo más que llego es usando un printChart, es que me saque simbolos (creo que son los ASCII que se corresponden con el valor de la variable, pero no estoy seguro.
    He probado a pasar a string el valor de la variable y luego poner printString, pero no me deja.
    Hay alguna forma sencilla de sacar a pantalla el valor de una variable?
    A lo mejor no está esto muy bien preguntado. Mañana intentó localizar la librería en cuestión y te la pongo.
    Un saludo!

    • Hola Chocarrat hay mil cosas que pueden cambiar en cada pantalla y adema esta el tema de que depende de que libreria uses. En principio deberia etar bien documentado como imprimir una ariable con la libreria que uses

        • Chocarrat

        Gracias! efectivamente era cuestión de documentarse. Al final usando una libreria llamada U8glib lo he conseguido! No encuentro información fácil y accesible de la de Adafruit (que tiene mucha mejor pinta). Pero con esta lo he conseguido de forma sencilla. Que pena no poder poner foto aqui!!
        Un saludo.

  • Buenas tardes/noches. Creo que me he equivocado, y he pedido una oled, pero es I2C… Imagino que esa no la puedo pinchar directamente a la UNO verdad? Tiene 4 patillas y dos de ellas van a los analógicos 4 y 5 creo.
    Supongo que no es tan grave, pero tenía la idea de acoplarla tal cual para compactar bien el robot (es para un proyecto de robot).
    En cuanto a su uso, es válido el tutorial para las I2C?
    Gracias y un saludo!

    • claro que la puedes pinchas chocarrat y en la sesion tienes un ejemplo de ello

      • Ahhh! Perfecto pues. Pensaba que eso sólo lo podía hacer con las SPI.
        A ver si llega, que tengo ganas de meterme a trastear.

    • TonyG

    Gracias por el aporte así como el resto del curso (me lo he leído casi entero)
    Estoy pensando en hacer (¡tantas cosas! 😉 un pequeño invento pero necesitaría usar dos, o tal vez tres pantallas de estas.
    ¿Sería posible controlarlas?
    Si los pines de control se pueden escoger ¿podríamos hacer algo así?
    int SCL_PIN1=12;//D0
    int SDA_PIN1=11; //D1
    int RST_PIN1=10;//RST
    int DC_PIN1 =9; //DC

    int SCL_PIN2=8;//D0
    int SDA_PIN2=7; //D1
    int RST_PIN2=6;//RST
    int DC_PIN2 =5; //DC

    Y luego en LED_WrDat y LED_WrCmd que son las que “hacen el trabajo” hacer un pequeño cambio para que usen SCL_PIN1 o SCL_PIN2, SDA_PIN1 o SDA_PIN2, etc. con una variable global (por no andar pasando parámetros entre tantas funciones) según en la pantalla que queramos escribir.

    Tan sólo una duda de “estilo”
    ¿int SCL_PIN=12;?
    ¿byte SCL_PIN=12;?
    ¿const byte SCL_PIN=12;?
    ¿#define SCL_PIN 12?

    Un saludo

    • Hola Tony,
      EL modelo de display que hablamos es SPI. Eso significa que puedes conectar varios en paralelo directamente, usando los mismos pines excepto el de seleccion SS o RSt que en el ARduino UNO es el D10, si no recuerdo mal.

      Todos los displays que conectes en paralelo reciben la misma informacion pero solo el que actives poniendo bajo (Ojo que vuelvo a hablar de memoria) con un pin digital mostrara el contenido que pones en el bus comun

      En cuanto a la cuestion de estilo por lo que se refiere a la definicion de las variables, nuestros arduinos van cortos de memoria por lo que siempre es mejor deescartarel definir una variable si no es necesaria, por lo que pueds usar el modo de C a secas como #define, o el mas elegante para mi gusto const de C++
      Un saludo

    • Cesar

    Enhorabuena por la página .

    • Tony

    Una guía muy interesante y funcional que no descarto usar para mis proyectos. Gracias y enhorabuena por la página

Give a Reply

WordPress Anti-Spam by WP-SpamShield