.96″ OLED display using Arduino UNO, I2C programming basics

This tutorial illustrates the basics of programming .96″ OLED display from Arduino by I2C interface. This program will give you an idea about the control and data bytes that should be sent to the OLED display.

#include <Wire.h>

#define SSD1306_DEACTIVATE_SCROLL   0x2E
#define SSD1306_MEMORYMODE          0x20 ///< See datasheet
#define SSD1306_COLUMNADDR          0x21 ///< See datasheet
#define SSD1306_PAGEADDR            0x22 ///< See datasheet
#define SSD1306_SETCONTRAST         0x81 ///< See datasheet
#define SSD1306_CHARGEPUMP          0x8D ///< See datasheet
#define SSD1306_SEGREMAP            0xA0 ///< See datasheet
#define SSD1306_SEGREMAP2           0xA1 ///< See datasheet
#define SSD1306_DISPLAYALLON_RESUME 0xA4 ///< See datasheet
#define SSD1306_DISPLAYALLON        0xA5 ///< Not currently used
#define SSD1306_NORMALDISPLAY       0xA6 ///< See datasheet
#define SSD1306_INVERTDISPLAY       0xA7 ///< See datasheet
#define SSD1306_SETMULTIPLEX        0xA8 ///< See datasheet
#define SSD1306_DISPLAYOFF          0xAE ///< See datasheet
#define SSD1306_DISPLAYON           0xAF ///< See datasheet
#define SSD1306_COMSCANINC          0xC0 ///< Not currently used
#define SSD1306_COMSCANDEC          0xC8 ///< See datasheet
#define SSD1306_SETDISPLAYOFFSET    0xD3 ///< See datasheet
#define SSD1306_SETDISPLAYCLOCKDIV  0xD5 ///< See datasheet
#define SSD1306_SETPRECHARGE        0xD9 ///< See datasheet
#define SSD1306_SETCOMPINS          0xDA ///< See datasheet
#define SSD1306_SETVCOMDETECT       0xDB ///< See datasheet

#define SSD1306_SETLOWCOLUMN        0x00 ///< Not currently used
#define SSD1306_SETHIGHCOLUMN       0x10 ///< Not currently used
#define SSD1306_SETSTARTLINE        0x40 ///< See datasheet

#define SSD1306_EXTERNALVCC         0x01 ///< External display voltage source
#define SSD1306_SWITCHCAPVCC        0x02 ///< Gen. display voltage from 3.3V

#define WIDTH     128
#define HEIGHT    64

  // put your setup code here, to run once:
const uint8_t vccstate = SSD1306_SWITCHCAPVCC;

const uint8_t i2caddr = 0x3C;
const uint8_t i2cAddress = 0x3C;
 
void wireWrite(const uint8_t* array, uint8_t arraySize)
{
  Wire.beginTransmission(0x3C);
  Wire.write((uint8_t)0x00);
  for(int i=0;i<arraySize;i++)
  {
    Wire.write(*array);
    array++;
  }
  Wire.endTransmission();
}

void clearDisplay(void)
{
  int count = 1024;
  uint8_t bytesOut = 0;

  Wire.beginTransmission(i2cAddress);
  Wire.write((uint8_t)0x40);
  while(count--)
  {
    if(bytesOut >= 31)
    { 
      Wire.endTransmission(); 
      Wire.beginTransmission(i2cAddress);
      Wire.write((uint8_t)0x40);
      bytesOut = 0;
    }
    Wire.write(0x00);
    bytesOut++;   
  } 
  Wire.endTransmission(); 
}

void allDisplayOn(void)
{
  const uint8_t array16[] = { SSD1306_DISPLAYALLON_RESUME  };
  wireWrite(array16, sizeof(array16));

  const uint8_t array17[] = { SSD1306_DISPLAYON  };
  wireWrite(array17, sizeof(array17));  
}

void allDisplayOff(void)
{
  const uint8_t array1[] = { SSD1306_DISPLAYOFF };
  wireWrite(array1, sizeof(array1));  
}

void displayLines(void)
{
  uint8_t *buffer; 

  int size = 1024;

  buffer = (uint8_t*)malloc(size);

  for(int i=0;i< size;i++)
  {
    buffer[i] = 0x01;
  }

  int count = WIDTH * HEIGHT;
  uint8_t bytesOut = 0;

  Wire.beginTransmission(i2cAddress);
  Wire.write((uint8_t)0x40);
  while(size--)
  {
    if(bytesOut >= 31)
    { 
      Wire.endTransmission(); 
      Wire.beginTransmission(i2cAddress);
      Wire.write((uint8_t)0x40);
      bytesOut = 0;
    }
    Wire.write(0x01);
    bytesOut++;   
  } 
  Wire.endTransmission(); 
}

void configureDisplay(void)
{
  const uint8_t array1[] = { SSD1306_DISPLAYOFF };
  wireWrite(array1, sizeof(array1));  

  const uint8_t array2[] = { SSD1306_DEACTIVATE_SCROLL };
  wireWrite(array2, sizeof(array2));  

  const uint8_t array3[] = { SSD1306_MEMORYMODE, 0x00 };
  wireWrite(array3, sizeof(array3));  

  const uint8_t array4[] = { SSD1306_SETSTARTLINE };
  wireWrite(array4, sizeof(array4));

  const uint8_t array5[] = { SSD1306_SEGREMAP2 };
  wireWrite(array5, sizeof(array5));  

  const uint8_t array6[] = { SSD1306_SETMULTIPLEX, HEIGHT - 1 };
  wireWrite(array6, sizeof(array6));

  const uint8_t array7[] = { SSD1306_COMSCANINC };
  wireWrite(array7, sizeof(array7));

  const uint8_t array8[] = { SSD1306_SETDISPLAYOFFSET, 0x0 };
  wireWrite(array8, sizeof(array8));

  const uint8_t array9[] = { SSD1306_SETCOMPINS, 0x12 };
  wireWrite(array9, sizeof(array9));

  const uint8_t array10[] = { SSD1306_SETDISPLAYCLOCKDIV, 0x80 };
  wireWrite(array10, sizeof(array10));

  const uint8_t array11[] = { SSD1306_SETPRECHARGE, (SSD1306_SWITCHCAPVCC == SSD1306_EXTERNALVCC) ? 0x22 : 0xF1 };
  wireWrite(array11, sizeof(array11));

  const uint8_t array12[] = { SSD1306_SETVCOMDETECT, 0x40 };
  wireWrite(array12, sizeof(array12));

  const uint8_t array13[] = { SSD1306_CHARGEPUMP, (SSD1306_SWITCHCAPVCC == SSD1306_EXTERNALVCC) ? 0x10 : 0x14 };
  wireWrite(array13, sizeof(array13));

  const uint8_t array14[] = { SSD1306_SETCONTRAST, (SSD1306_SWITCHCAPVCC == SSD1306_EXTERNALVCC) ? 0x9F : 0xCF  };
  wireWrite(array14, sizeof(array14));

  const uint8_t array15[] = { SSD1306_NORMALDISPLAY  };
  wireWrite(array15, sizeof(array15));

  const uint8_t array18[] = { SSD1306_COLUMNADDR, 0, 127  };
  wireWrite(array18, sizeof(array18));

  const uint8_t array19[] = { SSD1306_PAGEADDR, 0, 7  };
  wireWrite(array19, sizeof(array19));

  const uint8_t array16[] = { SSD1306_DISPLAYALLON_RESUME  };
  wireWrite(array16, sizeof(array16));

  const uint8_t array17[] = { SSD1306_DISPLAYON  };
  wireWrite(array17, sizeof(array17));
  
}

void setup() {

  Wire.begin();
  Serial.begin(9600);
  configureDisplay();
  allDisplayOff();
  clearDisplay();

  delay(1000);
  
  allDisplayOn();
  displayLines();
}

void loop() {
  // put your main code here, to run repeatedly:

}

Output of the above program will be as shown in the following image.

Published by

Leave a Reply

X