Usando Um Arduino® Para Controlar Ecrãs OLED Por I2C

08-07-2022

Um pequeno projecto de 10 minutos para poder controlar um ecrã OLED por I2C com o Arduino.

Material Necessário:

Software:
  • Software Arduino IDE (https://www.arduino.cc/en/software).

Hardware + Componentes Electrónicos:

  • 1x Um Arduino UNO;
  • 1x Ecrã OLED SD1306, I2C, 3,3V ou 5V, (de 0.96 polegadas, 128x64 pixels ou de 0.91 polegadas, 128x32 pixels);
  • 1x breadboard;
  • Vários fios eléctricos para ligar os componentes.

Esquema/Diagrama de Ligação:

Código/Sketch:

----------------------- OLED-I2C.ino -----------------------

///////////////////////////////////////////////////////////////////////////////
// Project: OLED Display Test
// URL:     
// File:    OLED-I2C.ino
//
// Description:
//          This Sketch controls a small OLED display (0.91" or 0.96") via I2C of the Arduino.
//
// Copyright (C) 2019-2022:
//          José Caetano Silva / CaetanoSoft
//
// License:
//          This file is part of OLED Display Test.
//
//          OLED Display Test is free software: you can redistribute it and/or modify
//          it under the terms of the GNU General Public License as published by
//          the Free Software Foundation, either version 3 of the License, or
//          (at your option) any later version.
//
//          OLED Display Test is distributed in the hope that it will be useful,
//          but WITHOUT ANY WARRANTY; without even the implied warranty of
//          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//          GNU General Public License for more details.
//
//          You should have received a copy of the GNU General Public License
//          along with OLED Display Test.  If not, see <https://www.gnu.org/licenses/>.
///////////////////////////////////////////////////////////////////////////////

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

// Add comment to the next line to use an OLED Display
// of 0.91" 128x32 pixels, insted of a 0.96" 128x64 pixels
#define OLED_128x64

#ifdef OLED_128x64
// # OLED 0.96" #
// OLED display width, in pixels
#define SCREEN_WIDTH 128
// OLED display height, in pixels
#define SCREEN_HEIGHT 64
#else
// # OLED 0.91" #
// OLED display width, in pixels
#define SCREEN_WIDTH 128
// OLED display height, in pixels
#define SCREEN_HEIGHT 32
#endif

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
// Reset pin # (or -1 if sharing Arduino reset pin)
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, & Wire, OLED_RESET);

// Number of snowflakes in the animation example
#define NUMFLAKES 10

// Snowflake sprite height
#define SPRITE_HEIGHT 16
// Snowflake  widthsprite
#define SPRITE_WIDTH 16
// Sprite pixels data
static
const unsigned char PROGMEM spriteBitmap[] = {
                                B00000000,
                                B11000000,
                                B00000001,
                                B11000000,
                                B00000001,
                                B11000000,
                                B00000011,
                                B11100000,
                                B11110011,
                                B11100000,
                                B11111110,
                                B11111000,
                                B01111110,
                                B11111111,
                                B00110011,
                                B10011111,
                                B00011111,
                                B11111100,
                                B00001101,
                                B01110000,
                                B00011011,
                                B10100000,
                                B00111111,
                                B11100000,
                                B00111111,
                                B11110000,
                                B01111100,
                                B11110000,
                                B01110000,
                                B01110000,
                                B00000000,
                                B00110000
                              };

/** 
 *  The setup function runs once when you press reset or power the board.
 */
void setup()
{
  // Initialization of the console's communication baud rate
  Serial.begin(115200);

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C))
  {
    // Error
    Serial.println(F("SSD1306 allocation failed"));
    // Don't proceed, loop forever
    for (;;);
  }

  // Show initial display buffer contents on the screen --
  // the library initializes this with an Adafruit splash screen.
  display.display();
  // Pause for 2 seconds
  delay(2000);

  // Clear the buffer
  display.clearDisplay();

  // Draw a single pixel in white
  display.drawPixel(10, 10, WHITE);

  // Show the display buffer on the screen. You MUST call display() after
  // drawing commands to make them visible on screen!
  display.display();
  delay(2000);

  // display.display() is NOT necessary after every single drawing command,
  // unless that's what you want...rather, you can batch up a bunch of
  // drawing operations and then update the screen all at once by calling
  // display.display(). These examples demonstrate both approaches...

  // # Draw many lines
  TestDrawLine();

  // # Draw rectangles (outlines)
  TestDrawRect();

  // # Draw rectangles (filled)
  TestDrawFillRect();

  // # Draw circles (outlines)
  TestDrawCircle();

  // # Draw circles (filled)
  TestDrawFillCircle();

  // # Draw rounded rectangles (outlines)
  TestDrawRoundRect();

  // # Draw rounded rectangles (filled)
  TestDrawFillRoundRect();

  // # Draw triangles (outlines)
  TestDrawTriangle();

  // # Draw triangles (filled)
  TestDrawFillTriangle();

  // # Draw characters of the default font
  TestDrawChar();

  // # Draw 'stylized' characters
  TestDrawStylesChar();

  // # Draw scrolling text
  TestScrollText();

  // # Draw a small bitmap image
  TestDrawBitmap();

  // Invert and restore display, pausing in-between
  display.invertDisplay(true);
  delay(1000);
  display.invertDisplay(false);
  delay(1000);

  // Animate bitmaps
  TestAnimate(spriteBitmap, SPRITE_WIDTH, SPRITE_HEIGHT);
}

/**
 *  The loop function runs over and over again forever.
 */
void loop()
{
  // Do nothing
}

/**
 *  Draw many lines.
 */
void TestDrawLine()
{
  int16_t i;

  // Clear the display buffer
  display.clearDisplay();
  for (i = 0; i < display.width(); i += 4)
  {
    display.drawLine(0, 0, i, display.height() - 1, WHITE);
    // Update screen with each newly-drawn line
    display.display();
    delay(1);
  }

  for (i = 0; i < display.height(); i += 4)
  {
    display.drawLine(0, 0, display.width() - 1, i, WHITE);
    display.display();
    delay(1);
  }

  delay(250);
  
  display.clearDisplay();
  for (i = 0; i < display.width(); i += 4)
  {
    display.drawLine(0, display.height() - 1, i, 0, WHITE);
    display.display();
    delay(1);
  }

  for (i = display.height() - 1; i >= 0; i -= 4)
  {
    display.drawLine(0, display.height() - 1, display.width() - 1, i, WHITE);
    display.display();
    delay(1);
  }

  delay(250);
  
  display.clearDisplay();
  for (i = display.width() - 1; i >= 0; i -= 4)
  {
    display.drawLine(display.width() - 1, display.height() - 1, i, 0, WHITE);
    display.display();
    delay(1);
  }

  for (i = display.height() - 1; i >= 0; i -= 4)
  {
    display.drawLine(display.width() - 1, display.height() - 1, 0, i, WHITE);
    display.display();
    delay(1);
  }

  delay(250);
  
  display.clearDisplay();
  for (i = 0; i < display.height(); i += 4)
  {
    display.drawLine(display.width() - 1, 0, 0, i, WHITE);
    display.display();
    delay(1);
  }

  for (i = 0; i < display.width(); i += 4)
  {
    display.drawLine(display.width() - 1, 0, i, display.height() - 1, WHITE);
    display.display();
    delay(1);
  }

  // Pause for 2 seconds
  delay(2000);
}

/**
 *  Draw rectangles (outlines)
 */
void TestDrawRect(void)
{
  display.clearDisplay();

  for (int16_t i = 0; i < display.height() / 2; i += 2)
  {
    display.drawRect(i, i, display.width() - 2 * i, display.height() - 2 * i, WHITE);
    display.display();
    delay(1);
  }

  delay(2000);
}

/**
 *  Draw rectangles (filled)
 */
void TestDrawFillRect(void)
{
  display.clearDisplay();

  for (int16_t i = 0; i < display.height() / 2; i += 3)
  {
    // The INVERSE color is used so rectangles alternate white/black
    display.fillRect(i, i, display.width() - i * 2, display.height() - i * 2, INVERSE);
    display.display();
    delay(1);
  }

  delay(2000);
}

/**
 *  Draw circles (outlines)
 */
void TestDrawCircle(void)
{
  display.clearDisplay();

  for (int16_t i = 0; i < max(display.width(), display.height()) / 2; i += 2)
  {
    display.drawCircle(display.width() / 2, display.height() / 2, i, WHITE);
    display.display();
    delay(1);
  }

  delay(2000);
}

/**
 *  Draw circles (filled)
 */
void TestDrawFillCircle(void)
{
  display.clearDisplay();

  for (int16_t i = max(display.width(), display.height()) / 2; i > 0; i -= 3)
  {
    // The INVERSE color is used so circles alternate white/black
    display.fillCircle(display.width() / 2, display.height() / 2, i, INVERSE);
    display.display();
    delay(1);
  }

  delay(2000);
}


/**
 *  Draw rounded rectangles (outlines)
 */
void TestDrawRoundRect(void)
{
  display.clearDisplay();

  for (int16_t i = 0; i < display.height() / 2 - 2; i += 2)
  {
    display.drawRoundRect(i, i, display.width() - 2 * i, display.height() - 2 * i,
                          display.height() / 4, WHITE);
    display.display();

    delay(1);
  }

  delay(2000);
}

/**
 *  Draw rounded rectangles (filled)
 */
void TestDrawFillRoundRect(void)
{
  display.clearDisplay();

  for (int16_t i = 0; i < display.height() / 2 - 2; i += 2)
  {
    // The INVERSE color is used so round-rects alternate white/black
    display.fillRoundRect(i, i, display.width() - 2 * i, display.height() - 2 * i,
                          display.height() / 4, INVERSE);
    display.display();

    delay(1);
  }

  delay(2000);
}

/**
 *  Draw triangles (outlines)
 */
void TestDrawTriangle(void)
{
  display.clearDisplay();

  for (int16_t i = 0; i < max(display.width(), display.height()) / 2; i += 5)
  {
    display.drawTriangle(
              display.width() / 2, display.height() / 2 - i,
              display.width() / 2 - i, display.height() / 2 + i,
              display.width() / 2 + i, display.height() / 2 + i, WHITE);
    display.display();

    delay(1);
  }

  delay(2000);
}

/**
 *  Draw triangles (filled)
 */
void TestDrawFillTriangle(void)
{
  display.clearDisplay();

  for (int16_t i = max(display.width(), display.height()) / 2; i > 0; i -= 5)
  {
    // The INVERSE color is used so triangles alternate white/black
    display.fillTriangle(
              display.width() / 2, display.height() / 2 - i,
              display.width() / 2 - i, display.height() / 2 + i,
              display.width() / 2 + i, display.height() / 2 + i, INVERSE);
    display.display();
  
    delay(1);

  }
  delay(2000);
}

/**
 *  Draw characters of the default font
 */
void TestDrawChar(void)
{
  display.clearDisplay();

  // Normal 1:1 pixel scale
  display.setTextSize(1);
  // Draw white text
  display.setTextColor(WHITE);
  // Start at top-left corner
  display.setCursor(0, 0); 
  // Use full 256 char 'Code Page 437' font
  display.cp437(true);
  // Not all the characters will fit on the display. This is normal.
  // Library will draw what it can and the rest will be clipped.
  for (int16_t i = 0; i < 256; i++)
  {
    if (i == '\n')
  {
    display.write(' ');
  }
    else
  {
    display.write(i);
  }
  }

  display.display();

  delay(2000);
}

/**
 *  Draw 'stylized' characters
 */
void TestDrawStylesChar(void)
{
  display.clearDisplay();

  // Normal 1:1 pixel scale
  display.setTextSize(1); 
  // Draw white text
  display.setTextColor(WHITE);
  // Start at top-left corner
  display.setCursor(0, 0);
  display.println(F("Hello, world!"));
  // Draw 'inverse' text
  display.setTextColor(BLACK, WHITE);
  display.println(3.141592);
  // Draw 2X-scale text
  display.setTextSize(2); 
  display.setTextColor(WHITE);
  display.print(F("0x"));
  display.println(0xDEADBEEF, HEX);

  display.display();

  delay(2000);
}

/**
 *  Draw scrolling text
 */
void TestScrollText(void)
{
  display.clearDisplay();

  // Draw 2X-scale text
  display.setTextSize(2); 
  display.setTextColor(WHITE);
  display.setCursor(10, 0);
  display.println(F("scroll"));
  // Show initial text
  display.display();

  delay(100);

  // Scroll in various directions, pausing in-between:
  display.startscrollright(0x00, 0x0F);

  delay(2000);

  display.stopscroll();

  delay(1000);

  display.startscrollleft(0x00, 0x0F);

  delay(2000);

  display.stopscroll();

  delay(1000);

  display.startscrolldiagright(0x00, 0x07);

  delay(2000);

  display.startscrolldiagleft(0x00, 0x07);

  delay(2000);

  display.stopscroll();

  delay(1000);
}

/**
 *  Draw a small bitmap image
 */
void TestDrawBitmap(void)
{
  display.clearDisplay();

  display.drawBitmap(
    (display.width() - SPRITE_WIDTH) / 2,
    (display.height() - SPRITE_HEIGHT) / 2,
    spriteBitmap, SPRITE_WIDTH, SPRITE_HEIGHT, 1);
  display.display();

  delay(1000);
}

/**
 *  Draw a small bitmap image
 */
void TestAnimate(const uint8_t * bitmap, uint8_t w, uint8_t h)
{
  // Indexes into the 'icons' array in function below
  static const int XPOS = 0;
  static const int YPOS = 1;
  static const int DELTAY = 2;
  
  int8_t f, icons[NUMFLAKES][3];

  // Initialize 'snowflake' positions
  for (f = 0; f < NUMFLAKES; f++)
  {
    icons[f][XPOS] = random(1 - SPRITE_WIDTH, display.width());
    icons[f][YPOS] = -SPRITE_HEIGHT;
    icons[f][DELTAY] = random(1, 6);
  
    Serial.print(F("x: "));
    Serial.print(icons[f][XPOS], DEC);
    Serial.print(F(" y: "));
    Serial.print(icons[f][YPOS], DEC);
    Serial.print(F(" dy: "));
    Serial.println(icons[f][DELTAY], DEC);
  }

  // Loop forever...
  for (;;)
  {
    // Clear the display buffer
    display.clearDisplay();

    // Draw each snowflake:
    for (f = 0; f < NUMFLAKES; f++)
    {
      display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, WHITE);
    }
  
    // Show the display buffer on the screen
    display.display();

    // Pause for 1/10 second
    delay(200);

    // Then update coordinates of each flake...
    for (f = 0; f < NUMFLAKES; f++)
    {
      icons[f][YPOS] += icons[f][DELTAY];

      // If snowflake is off the bottom of the screen...
      if (icons[f][YPOS] >= display.height())
      {
        // Reinitialize to a random position, just off the top
        icons[f][XPOS] = random(1 - SPRITE_WIDTH, display.width());
        icons[f][YPOS] = -SPRITE_HEIGHT;
        icons[f][DELTAY] = random(1, 6);
      }
    }
  }
}

----------------------- OLED-I2C.ino -----------------------

Instruções de Montagem:

Tabela 1: Ligações Arduino <--> OLED SD1306
Arduino Uno OLED SD1306
SDA (Pin A4) SDA
SCL (Pin A5) SCL
GND GND
5V VCC

Faça as conexões entre os componentes como é mostrado na tabela 1 acima e no diagrama de ligação.

Caso ainda não tenha instalado, instale no Arduino IDE, as seguintes bibliotecas, instalando todas as dependências:

    * SPI ;

    * Wire;

    * Adafruit GFX;

    * Adafruit SSD1306.

Use o Arduino IDE para colar o sketch "OLED-I2C.ino" e gravar-lo, depois compile-o e envie-o para o dispositivo Arduino Uno.

Funcionamento:

Ao alimentar o seu Arduino com tensão, o ecrã OLED vai demonstrar as capacidades gráficas e de texto. 

© 2022 José Caetano Silva. Todos os direitos reservados.
Desenvolvido por Webnode Cookies
Crie o seu site grátis! Este site foi criado com a Webnode. Crie o seu gratuitamente agora! Comece agora