Cómo graficar datos en un display OLED SSD1306 I2C y Arduino muy fácil



Hola amigos hoy les traigo un ejemplo que les puede servir de inspiracion para sus proyectos con Arduino. Se trata de un sencillo código para desplegar una gráfica de un voltaje variable entre 0 y 5v muestreado por la entrada analógica A0 de la tarjeta Arduino UNO o NANO. 

Usamos un OLED SSD1306 I2C de 0.96" suficientes para desplegar información dinamica en una resolución de 128x64 pixeles. La comunicación I2C usa un puerto para reloj y uno para datos, lo cual hace mas fácil de implementar.


Para la demostración usaremos un potenciometro de 5K como divisor de tensión. La escala graduada en el display nos muestra como varia el voltaje en el tiempo y en la parte inferior se despliega el valor calculado del voltaje que ingresa al puerto A0 y el tiempo en milisegundos que tarda en procesar y mostrar el dato en la pantalla. 

Recuerden instalar estas librerías en su Arduino IDE:
https://github.com/adafruit/Adafruit-GFX-Library

Este gráfico al estilo del "serial plotter" se desplaza continuamente de derecha a izquierda, muy útil en todo tipo de aplicaciones relacionada con el seguimiento de sensores e instrumentación. Te dejo los comentarios en el código para que puedas adaptar a tus necesidades el programa.

Aquí puedes descargar el proyecto + el diagrama

Código .ino

/*
Ejemplo grafica xy en movimiento con escala en pantalla 
OLED 128x64 I2C con el driver SSD1306.

Este ejemplo es de dominio publico hagan lo que quieran con el :D
Autor: Sergio A. Yañez M.
Año: 2020
Tutorial para el canal AQUILES VAESA 
youtube.com/aqulesvaesa

***** CONEXIONES *****

DISPLAY - ARDUINO
    GND = GND
    VCC = 5V ó 3.3V
    SCL = A5
    SDA = A4

POT.  - ARDUINO 
    1 = GND
    2 = A0
    3 = 5V

Importante!!! necesitas instalar estas librerias:
https://github.com/adafruit/Adafruit-GFX-Library
https://github.com/adafruit/Adafruit_SSD1306

*/
#include "imagenes.h"
#include <Adafruit_SSD1306.h>  // incluye la libreria de adafruit para el driver del display OLED
#include <Adafruit_GFX.h>  // incluye la libreria de adafruit para gestionar los efectos graficos de manera facil
Adafruit_SSD1306 display(128, 64);  // declara la resolucion del display

int anteriorMillis = 0;
int tiempo = 0;
float valorAnalogico = 0;
float voltaje = 0;
float graficaVoltaje = 0;

int x[128]; //buffer de la grafica 
int y[128]; //buffer secundario de la grafica 


void setup(){                

  delay(100);  // se da una espera de 100ms para que el display inicie correctamente
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // inicia la comunicacion I2C con el display que tiene la direccion 0x3C
  display.setRotation(0);  // se escoje la orientacion del display puede ser 0 o 2
  display.dim(true); //dejamos el brillo en maximo
  display.setTextColor(WHITE);
  display.setTextSize(1);  // ajusta el tamaño de texto en el minimo valor

  //animacion inicial
  for(int i=0;i<1;i++){
    display.clearDisplay();  // limpia el buffer del display
    display.drawBitmap(0,0,imagen, 128, 64, 1); // despliega imagen
    display.display(); // muestra la informacion del buffer en la pantalla 
    delay(3000); //pausa 
    display.fillRect(0, 0, 128, 64, 1);
    display.drawBitmap(0,0,imagen, 128, 64, 0); // despliega imagen en negativo
    display.display(); // muestra la informacion del buffer en la pantalla 
    delay(1000); //pausa 
    display.clearDisplay(); //limpia buffer
    display.display(); //muestra el buffer limpio
  }

  //llenamos las matrices con un valor fuera del rango de medicion >1023
  for(int i=127;i>=0;i--){
    x[i]=9999;
  }
  for(int i=127;i>=0;i--){
    y[i]=9999;
  }
} 

void loop(){

  display.clearDisplay(); //limpia el buffer del display
  
  //dibuja escala
  display.setCursor(0, 0); 
  display.print(F("5V")); 
  display.setCursor(0, 11);   
  display.print(F("4V"));
  display.setCursor(0, 22); 
  display.print(F("3V"));
  display.setCursor(0, 32);  
  display.print(F("2V"));      
  display.setCursor(0, 43); 
  display.print(F("1V")); 

  display.drawLine(15, 0, 25, 0, WHITE);
  display.drawLine(15, 11, 25, 11, WHITE);
  display.drawLine(15, 22, 25, 22, WHITE);
  display.drawLine(15, 32, 25, 32, WHITE);
  display.drawLine(15, 43, 25, 43, WHITE);
  //dibuja eje X y Y 
  display.drawLine(0, 53, 127, 53, WHITE);
  display.drawLine(25, 53, 25, 0, WHITE);
 
  valorAnalogico = analogRead(A0); //lee el valor analogico del pin A0
  voltaje=(valorAnalogico*5)/1024; //calcula el valor en voltaje
  graficaVoltaje=map(valorAnalogico,0,1023,53,0); //escala el valor analogico a un pixel imprimible en pantalla

  x[127]=graficaVoltaje; //asigna el valor escalado a el ultimo dato de la matriz
  
  for(int i=127;i>=25;i--){ 
      display.drawPixel(i, x[i], WHITE); //dibuja punto a punto el contenido de x
      y[i-1]=x[i]; //guarda la informacion desplazada una posicion temporalmente en y
    }
  //imprime el voltaje en texto  
  display.setCursor(25, 57); 
  display.print(voltaje);
  display.print(F(" v    "));

  //imprime el tiempo que se tarda en tomar y mostrar cada dato
  tiempo = millis()-anteriorMillis;
  display.print(tiempo);
  anteriorMillis = millis();
  display.print(F(" ms"));
    
  display.display(); //despliega la informacion del buffer en la pantalla
  
  //delay(60); //pausa opcional

  for(int i=127;i>=0;i--){
    x[i]=y[i]; //envia los datos desplazados de vuelta a la variable x
  }
}

Código imagenes.h

// aqui ponemos las imagenes codificadas 
// asi es mas facil trabajar

static const unsigned char PROGMEM imagen[] ={
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00,
0x00, 0xC3, 0x0F, 0x0C, 0x33, 0xEC, 0x33, 0x70, 0x3C, 0x00, 0x78, 0x1E, 0x1B, 0x9C, 0x20, 0x00,
0x00, 0xC3, 0x1F, 0x8C, 0x33, 0xEC, 0x33, 0xF8, 0x7E, 0x00, 0xFC, 0x3F, 0x1F, 0xFE, 0x60, 0x00,
0x00, 0x66, 0x39, 0xCC, 0x31, 0x8C, 0x33, 0x9C, 0xC3, 0x01, 0xC6, 0x73, 0x98, 0xC6, 0x60, 0x00,
0x00, 0x66, 0x30, 0xCC, 0x31, 0x8C, 0x33, 0x0C, 0xFF, 0x01, 0x80, 0x61, 0x98, 0xC6, 0x60, 0x00,
0x00, 0x26, 0x30, 0xCC, 0x31, 0x8C, 0x33, 0x0C, 0xC0, 0x01, 0x80, 0x61, 0x98, 0xC6, 0x40, 0x00,
0x00, 0x3C, 0x39, 0xCC, 0x71, 0x8C, 0x73, 0x9C, 0xE3, 0x01, 0xC6, 0x73, 0x98, 0xC6, 0xC0, 0x00,
0x00, 0x3C, 0x1F, 0x8F, 0xF1, 0xEF, 0xF3, 0xF8, 0x7E, 0x18, 0xFC, 0x3F, 0x18, 0xC6, 0xC0, 0x00,
0x00, 0x18, 0x0F, 0x07, 0xB0, 0xE7, 0xB3, 0x70, 0x3C, 0x18, 0x78, 0x1E, 0x18, 0xC6, 0xC0, 0x00,
0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3E, 0x07, 0x66, 0x19, 0x98, 0x78, 0x3C, 0x61, 0x8F, 0x81, 0xE0, 0xF0, 0x7C, 0x00, 0x00,
0x00, 0x7F, 0x0F, 0xE6, 0x19, 0x98, 0xFC, 0x7E, 0x61, 0x9F, 0xC3, 0xF1, 0xF8, 0xFE, 0x00, 0x00,
0x00, 0x07, 0x1C, 0xE6, 0x19, 0x99, 0x86, 0x63, 0x33, 0x01, 0xC6, 0x19, 0x8C, 0x0E, 0x00, 0x00,
0x00, 0x3F, 0x18, 0x66, 0x19, 0x99, 0xFE, 0x3C, 0x33, 0x0F, 0xC7, 0xF8, 0xF0, 0x7E, 0x00, 0x00,
0x00, 0x73, 0x18, 0x66, 0x19, 0x99, 0x80, 0x0F, 0x12, 0x1C, 0xC6, 0x00, 0x3C, 0xE6, 0x00, 0x00,
0x00, 0x63, 0x1C, 0xE6, 0x39, 0x99, 0xC6, 0x63, 0x1E, 0x18, 0xC7, 0x19, 0x8C, 0xC6, 0x00, 0x00,
0x00, 0x7F, 0x0F, 0xE7, 0xF9, 0x98, 0xFC, 0x7F, 0x1E, 0x1F, 0xC3, 0xF1, 0xFC, 0xFE, 0x00, 0x00,
0x00, 0x39, 0x07, 0x63, 0xD9, 0x98, 0x78, 0x3E, 0x0C, 0x0E, 0x41, 0xE0, 0xF8, 0x72, 0x00, 0x00,
0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xE0, 0x00, 0x00, 0x07, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x40, 0x00, 0x00, 0x01, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x07, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xC0, 0x07, 0xC0, 0x01, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x07, 0xE0, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x40, 0x07, 0xF8, 0x01, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x07, 0xFC, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xC0, 0x07, 0xF8, 0x01, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x07, 0xE0, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x40, 0x07, 0xC0, 0x01, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x07, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xC0, 0x00, 0x00, 0x03, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x7F, 0xFF, 0xFF, 0xFD, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};

Un canal amigo llamado LarryBot hizo la prueba este proyecto y nos regaló un excelente video #short 


Puedes armar tu propia placa de circuito donde integres la Arduino el display, quizá una carcasa impresa en 3D, los limites están en tu imaginación, pues PCBWay es una empresa que nos ayudan a los aficionados y profesionales de la electrónica a  fabricar nuestros diseños.

Con un bajo costo podemos fabricar desde 1 prototipo hasta miles PCBWay cuenta con una planta de producción muy grande y automatizada que hace accesible a cualquier persona la fabricación de circuitos, esténciles para soldadura SMD y objetos impresos en 3D .


Publicar un comentario

12 Comentarios

  1. Aquiles , pues falto lo principal el código

    ResponderEliminar
    Respuestas
    1. Ahí esta disponible para copiar y pegar o lo puedes descargar.

      Eliminar
  2. Podrias proporcionar el código amigo para rodvel.97@gmail.com

    ResponderEliminar
  3. Buenas tardes, muy interesante su publicación, felicitaciones por ella y en general por su página, he intentado realizar esta en un arduino uno y en un arduino nano pero cuando termina de cargar el programa se queda pegado el arduino, dividiendo el programa en partes mediante comentarios he detectado que el inconveniente es este tramo del código
    //llenamos las matrices con un valor fuera del rango de medicion >1023
    for(int i=127;i>=0;i--){
    x[i]=3333;
    }
    for(int j=127;j>=0;j--){
    y[j]=9999;
    }

    especialmente la segunda parte con Y y[j]=9999;
    De pronto les ha ocurrido este inconveniente , muchas gracias por su atención

    ResponderEliminar
    Respuestas
    1. hola buenas dias pudistes solcuionar ese problema tengo el mismo problema

      Eliminar
  4. Hola Jamid es muy raro que suceda eso ya que el programa es muy sencillo y como 1/3de la memoria. Intenta quitarle el // a esta linea: //delay(60); debería quedar así: delay(60);
    prueba y me comentas.

    ResponderEliminar
    Respuestas
    1. hola buenas dias me sale el mismo problema comentado anteriormente fall al comunicacion cuando entra en el ciclo for

      Eliminar
  5. hola queria consultar sobre el "imagen.h" al principio del codigo. ¿es necesaria alguna libreria para eso? porque ejecuto el codigo y me salta error en esa linea. Desde ya muchas gracias por dar acceso a este codigo, ya que me sirve mucho para mi proyecto

    ResponderEliminar
    Respuestas
    1. Amigo si te das cuenta el video como se agrega el archivo de cabecera imagenes.h
      Yo te dejo ahí el código que debes poner en esa sección.

      Eliminar
  6. hola, tenes algun tutorial para mostrar imagenes con scroll o algun efecto? gracias

    ResponderEliminar
    Respuestas
    1. Muy interesante voy a hacer un tutorial sobre ese tema próximamente

      Eliminar