jueves, 8 de marzo de 2018

Termómetro OLED 128x64 con SSD1306Z y Arduino



Termómetro
OLED 128x64
SSD1306Z
GM009605
Arduino


Hace tiempo que me había llegado una pantalla del tipo OLED, con una resolución de 128x64, y aún no lo había empleado.
Nunca he trabajado con pantallas de tipo OLED, por lo que no sabía como trabajaba.
En primer lugar diremos que la pantalla viene para ser controlada mediante el bus I2C, por lo cual se necesitan pocos cables, alimentación y CLK , SDA.
Lo primero que suelo hacer es bajarme todos las manuales del fabricante que puedo.
Lo siguiente es intentar buscar alguna librería para arduino  que maneje la pantalla.
La librería mas famosa es la de Adafruit-GFX-Library , junto con Adafruit_SSD1306. Estas librerías funciona muy bien, tienen todo lo necesario para manejar gráficamente la pantalla.
Otra librería es  Universal 8bit Graphics Library, https://github.com/olikraus/u8glib/ ,  que puede manejar diferentes tipos de pantalla. Antes de utilizar esta librería de debe de descomentar la linea que corresponde a nuestra pantalla. En las pruebas que realicé para mi pantalla la línea era : U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);    // I2C / TWI
Estas librería están hechas para un montón de pantallas, por lo cual no están optimizadas para una en concreto. El resultado es que suelen ocupar bastante memoria de programa (10Kb), y la mitad de la memoria RAM 1024. En muchos casos no se puede añadir otra librería por falta de memoria.
Este aviso suele aparecer en la compilación:
Las variables Globales usan 1.956 bytes (95%) de la memoria dinámica, dejando 92 bytes para las variables locales. El máximo es 2.048 bytes.
Poca memoria disponible, se pueden producir problemas de estabilidad.

Como me gusta programar mis propias rutinas de manejo de pantalla, me puse manos a la obra.
Tomando como referencia la librería Adafruit , me puse crear mis rutinas sin utilizar librería alguna, todas las rutinas están en el propio programa.
Empecemos por conocer la estructura de pantalla del OLED.

La estructura es bastante común, líneas de 128 bytes, y el total de líneas es de 8, por lo cual el total de bytes es de 1024 bytes.
En anteriores montajes arnok.htmlmatrixd.html también había trabajado con esquemas de pantalla parecidos, por lo cual ya tengo alguna experiencia.
En líneas generales el funcionamiento es el siguiente:
  • -Se crea un buffer   (buffer[OLE_BUFFER];) de 1024 bytes donde se pintan todas las líneas o caracteres.
  • -Una vez pintado todo, se vuelca todo en la pantalla OLED mediante la orden display();
Esto es simple, y es el método que se utiliza en la mayoría de los programas de ordenador.
Pero mover 1024 bytes mediante en el Bus I2C no es lo rápido que debiera ser para no ser notado el repintado.
Para solucionar este problema, cree una rutina que solo repintaba 1 línea de la 8 que existen.
Mediante este método conseguía una velocidad 8 veces mayor en escritura de caracteres, no sirve para  puntos y líneas.
La activación de este método es mediante ModeDisplay=1; .

Otro problema que tuve fue lo pequeños que se ven los caracteres, diminutos, había que solucionarlo, crear diferentes tamaños de caracteres.

El resultado no fue del todo malo, por lo menos se veían los caracteres, que es lo que se pretendía.
En modo gráfico solo he implementado plot, line (en solo modo vertical y horizontal),y  drawBox.

Para probar todo he pensado un termómetro digital utilizando el 18B20, sencillo y rápido.

Esquema del circuito.


Circuito montado.

He realizado dos programas, uno inserta todas la rutinas en el propio programa y otro coloca un fichero de cabecera olex.h donde se colocan las rutinas. Los dos funcionan igual, pero en uno queda el programa mas sencillo de ver, solo queda el programa no las rutinas.
El tener que utilizar 1024 bytes a modo de buffer, implica usar la mitad de la memoria  impidiendo hacer programas más grandes.
En el próximo programa intentaré hacer rutinas para texto que solo utilicen 128 bytes.

En las mediciones de consumo se puede observar que varía bastante dependiendo los puntos que se encuentren encendidos, entre 3 mA y 17 mA, en modo normal. En las pruebas el circuito funcionaba perfectamente a 3.3V
PROGRAMA





Después de un par de días  pensando en la poca memoria RAM que dejaba al utilizar un buffer de 1024byes, decidí solucionar el problema.
La solución era reducir el buffer a 256bytes. Esto implica no poder utilizar gráficos (plot , líne). Además se imprime caracteres en líneas completas.
Para el caso que nos ocupa sirve de sobra, y la liberación de memoria es bastante 768 bytes.
La salida del compilador nos da lo siguiente:
El Sketch usa 7.320 bytes (22%) del espacio de almacenamiento de programa. El máximo es 32.256 bytes.
Las variables Globales usan 1.004 bytes (49%) de la memoria dinámica, dejando 1.044 bytes para las variables locales. El máximo es 2.048 bytes.

PROGRAMA2

Como seguía pensando en el montaje, y en la posibilidad de eliminar el buffer de la memoria RAM para representar caracteres, me puse manos a la obra. El resultado es la eliminación del buffer y la liberación de la memoria RAM, resultando 1300 bytes libres para ser utilizados por otras librerías.
También se corrigió el que salían los decimales negativos.
Salida del compilador nos da lo siguiente:
El Sketch usa 7.422 bytes (23%) del espacio de almacenamiento de programa. El máximo es 32.256 bytes.
Las variables Globales usan 748 bytes (36%) de la memoria dinámica, dejando 1.300 bytes para las variables locales. El máximo es 2.048 bytes.

PROGRAMA3



Hasta pronto.
Juan Galaz


Bibliografía:
https://github.com/adafruit/Adafruit_SSD1306
https://github.com/adafruit/Adafruit-GFX-Library
https://github.com/olikraus/u8glib/
arnok.html
matrixd.html
http://www.instructables.com/id/Monochrome-096-i2c-OLED-display-with-arduino-SSD13/

No hay comentarios:

Publicar un comentario