# 4.1 IIC - OLED

The ESP32 chips have a GPIO matrix that allows you to route most peripherals (like I2C) to any available GPIO pin. In other words: pick two convenient GPIO pins, make sure they're not otherwise occupied (flash connected to them, bootstrap pins etc), and you can use them as your I2C pins.

In this tutorial we’ll take a look at the I2C communication protocol with OLED Display.

{% embed url="<https://youtu.be/9--A4w01hjs>" %}

## Introduction

### 1. IIC or I2C Protocol

IIC or I2C means **I**nter **I**ntegrated **C**ircuit (it’s pronounced I-squared-C), and it is a synchronous, multi-master, multi-slave communication protocol. You can connect **multiple slaves to one master** or **multiple masters controlling the same slave. I2C** stands out for its simplicity and it is an ideal choice for short distance communications.

The ESP32 supports I2C communication that can serve as I2C master or slave. We use this protocol with the ESP32 to communicate with external devices like sensors and displays. In these cases, the ESP32 is the master chip and the OLED display is the slave.

<figure><img src="https://2579747216-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkSq9ZTh3ba8gAVAntL52%2Fuploads%2FJKw5XyfrVtrzLkS9oVhO%2Fimage.png?alt=media&#x26;token=9c9d73cb-3f57-4419-980d-5c63812a365d" alt="" width="375"><figcaption></figcaption></figure>

### 2. IIC Wiring

I2C communication protocol uses two wires to share information: the **Serial Clock Line** (**SCL**) and the **Serial Data Line** (**SDA**). Note that in many boards, the SDA line may also be labeled as SDI and the SCL line as SCK.

The SDA and SCL lines are active low, so they should be <mark style="color:red;">pulled up with resistors</mark>. Typical values are 4.7k Ohm for 5V devices and 2.4k Ohm for 3.3V devices. Most sensors and displays are already have the resistors built-in. If not, you need to connect pull-up resistors by yourself.

Connecting an I2C device to an ESP32 is normally as simple as follows.

| I2C Device     | ESP32                                    |
| -------------- | ---------------------------------------- |
| **SDA or SDI** | SDA (can use any GPIO pins not occupied) |
| **SCL or SCK** | SCL (can use any GPIO pins not occupied) |
| **GND**        | GND                                      |
| **VCC**        | usually 3.3V or 5V                       |

### 3. IIC Device Address

With I2C communication, each slave on the bus has its own address, a hexadecimal number that allows the ESP32 to communicate with each device.

The I2C address can be usually found on the component or its datasheet. However, if it is difficult to find out, you may need to run an I2C scanner sketch to find out the I2C address.

<details>

<summary>Code for finding your devices’ I2C address</summary>

```cpp
#include <Wire.h>
 
void setup() {
  Wire.begin();
  Serial.begin(115200);
  Serial.println("\nI2C Scanner");
}
 
void loop() {
  byte error, address;
  int nDevices;
  Serial.println("Scanning...");
  nDevices = 0;
  for(address = 1; address < 127; address++ ) {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
    if (error == 0) {
      Serial.print("I2C device found at address 0x");
      if (address<16) {
        Serial.print("0");
      }
      Serial.println(address,HEX);
      nDevices++;
    }
    else if (error==4) {
      Serial.print("Unknow error at address 0x");
      if (address<16) {
        Serial.print("0");
      }
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0) {
    Serial.println("No I2C devices found\n");
  }
  else {
    Serial.println("done\n");
  }
  delay(5000);          
}
```

You’ll get something similar as follows in your Serial Monitor.&#x20;

<img src="https://i0.wp.com/randomnerdtutorials.com/wp-content/uploads/2018/07/scan_i2c.png?resize=624%2C248&#x26;quality=100&#x26;strip=all&#x26;ssl=1" alt="" data-size="original">

</details>

### 4. OLED Display

OLED means Organic Light-Emitting Diode, and OLED display doesn’t require backlight, which results in a very nice contrast in dark environments. Additionally, its pixels consume energy only when they are on, so the OLED display consumes less power when compared to other displays.

The OLED display that we’ll use in this tutorial is the 0.96 inch 128x64 Pixel OLED Display with SSD1306 Driver and I2C protocol.

* The model we’re using has four pins and communicates with any microcontroller using I2C communication protocol.&#x20;
  * **VCC:** This is the power supply pin for 3.3V or 5V power to the display.
  * **GND:** This is the ground pin for the module.
  * **SCL and SDA:** These are the serial clock and serial data pins for I2C communication.
* The SSD1306 controller supports both SPI and I2C communication protocols.There are models that come with an extra RESET pin or using SPI communication protocol.

<figure><img src="https://2579747216-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkSq9ZTh3ba8gAVAntL52%2Fuploads%2FfdEA7NJUcGht0F6c9kpR%2Fimage.png?alt=media&#x26;token=3a7f030b-9e41-429b-9551-db91ff686799" alt="" width="273"><figcaption></figcaption></figure>

## Hardware Circuit

### 1. Parts Required

Here’s a list of the parts to you need to build the circuit:

* ESP32-S3-N16R8
* OLED Display with SSD1306 Driver and I2C protocol
* Pull-up resistors
* Breadboard
* Jumper wires

### 2. Wiring

As the OLED display uses I2C communication protocol, wiring is very simple. Here we use GPIO 6 as SDA and GPIO 5 as SCL as shown below:

<figure><img src="https://2579747216-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkSq9ZTh3ba8gAVAntL52%2Fuploads%2F1Dmthxfulnjlb5JLSNdG%2Fimage.png?alt=media&#x26;token=a803c9ec-3a7f-4d6b-96ff-0e18b2b27f95" alt="" width="375"><figcaption></figcaption></figure>

{% hint style="info" %}
You can use any other GPIO pins that are not occupied as SDA and SCL .
{% endhint %}

## Coding and Testing

### 1. Available Libraries

For Arduino IDE, use the `Wire.h` library to communicate with devices using I2C protocol. However, you can use third-party libraries. There are several libraries available for ESP32 to control the OLED display driven by SSD1306:

* [Adafruit\_SSD1306 library](https://github.com/adafruit/Adafruit_SSD1306) and [Adafruit\_GFX library](https://github.com/adafruit/Adafruit-GFX-Library)
* [U8G2](https://github.com/olikraus/u8g2)
* [ThingPulse/esp8266-oled-ssd1306](https://github.com/ThingPulse/esp8266-oled-ssd1306?tab=readme-ov-file)

No matter what OLED screen and library, it can be abstracted into a pixel matrix. If you want to display something, just light up the pixels at a specific location. For example, SSD1306 is a 128X64 pixel matrix. This matrix has its own set of coordinate systems. In the coordinate system, the upper left corner is the origin, the right is the X axis, and the bottom is the Y axis.

<figure><img src="https://2579747216-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkSq9ZTh3ba8gAVAntL52%2Fuploads%2F97oF7dknCGAn8CFN8z9f%2Fimage.png?alt=media&#x26;token=5bc5136e-4a7f-4c0e-af38-7e839225c0ab" alt="" width="173"><figcaption></figcaption></figure>

### 2. Use Adafruit libraries

Firstly, Install the two libraries in the PlatformIO IDE: Go to Libraries, search for `Adafruit GFX` and `Adafruit_SSD1306` and add them to your project.

<figure><img src="https://2579747216-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkSq9ZTh3ba8gAVAntL52%2Fuploads%2FOknx5MjSAg6gE3K7NM4Q%2Fimage.png?alt=media&#x26;token=eca43614-7e53-4fc2-ba52-4c4f2be42f8d" alt="" width="443"><figcaption></figcaption></figure>

Then, you can check the example code:&#x20;

* In your PlatformIO IDE, go to **.pio > libdeps > Adafruit SSD1306 > Examples** and select the example `ssd1306_128x64_i2c.ino`&#x20;
* If your OLED doesn’t have a RESET pin, you should set the OLED\_RESET variable to -1 as shown below:

  ```
  #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
  ```
* Using the Adafruit\_SSD1306 library is divided into three steps:&#x20;
  * Initialize OLED, call the constructor, and call the begin method;&#x20;
  * After initialization, call the drawing class function, and you can set the color, font, etc.&#x20;
  * After drawing, call the display class function.

Finally, upload the code to your ESP32 board.&#x20;

* Don’t forget to select the right board and COM port.

If your OLED display is not showing anything:

* Check that the OLED display is properly wired to the ESP32
* Double-check the OLED display I2C address
* Double check if your display has built-in pull-up resistor

<details>

<summary>Use Different I2C Pins with ESP32 (change default I2C pins)</summary>

With the ESP32 you can set almost any pin to have I2C capabilities, you just need to set that in your code. When using the ESP32 with the Arduino IDE, use the `Wire` library to communicate with devices using I2C.

1. Check wire definition, which is defined in Wire.cpp\
   ![](https://2579747216-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkSq9ZTh3ba8gAVAntL52%2Fuploads%2FnVzZgVyYls1A83bFkvU5%2Fimage.png?alt=media\&token=ea58ceb9-95b9-468d-bdd9-9a896af2307a)
2. In Wire.cpp, go to SDA definition\
   ![](https://2579747216-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkSq9ZTh3ba8gAVAntL52%2Fuploads%2FwmGpF6Un5eG3MG0q9ex5%2Fimage.png?alt=media\&token=4e98eb8d-708c-44f2-83dc-e5aca158878b)
3. Change the default SDA Pin and SCL Pin as your wiring\
   ![](https://2579747216-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkSq9ZTh3ba8gAVAntL52%2Fuploads%2F98wGYxGzL5AENsUO7exf%2Fimage.png?alt=media\&token=22c2c673-e472-4af9-81c2-eb6718c741c3)<br>

</details>

### 3. OLED Display Text

The Adafruit library for the OLED display comes with several functions to write text. In this section, you’ll learn how to write and scroll text using the library functions.

1. Static text display\
   The following code displays *Hello, world!* message in the OLED display. (If you use different Pins with ESP32, change it first.)

```cpp
#include <Arduino.h>

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

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

void setup() {
  Serial.begin(115200);

  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
  delay(2000);
  display.clearDisplay();

  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  // Display static text
  display.println("Hello, world!");
  display.display(); 
}

void loop() {
  
}
```

<details>

<summary>How the code works</summary>

**Importing libraries**

First, you need to import the necessary libraries. The Wire library to use I2C and the Adafruit libraries to write to the display: Adafruit\_GFX and Adafruit\_SSD1306.

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

**Initialize the OLED display**

Then, you define your OLED width and height. In this example, we’re using a 128×64 OLED display. If you’re using other sizes, you can change that in the SCREEN\_WIDTH, and SCREEN\_HEIGHT variables.

```
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
```

Then, initialize a display object with the width and height defined earlier with I2C communication protocol (\&Wire).

```
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
```

The (-1) parameter means that your OLED display doesn’t have a RESET pin. If your OLED display does have a RESET pin, it should be connected to a GPIO. In that case, you should pass the GPIO number as a parameter.

In the setup(), initialize the Serial Monitor at a baud raute of 115200 for debugging purposes.

```
Serial.begin(115200);
```

Initialize the OLED display with the begin() method as follows:

```
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { 
  Serial.println("SSD1306 allocation failed");
  for(;;); // Don't proceed, loop forever
}
```

This snippet also prints a message on the Serial Monitor, in case we’re not able to connect to the display.

```
Serial.println("SSD1306 allocation failed");
```

In case you’re using a different OLED display, you may need to change the OLED address. In our case, the address is 0x3C.

```
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { 
```

If this address doesn’t work, you can run an I2C scanner sketch to find your OLED address.&#x20;

After initializing the display, add a two second delay, so that the OLED has enough time to initialize before writing text:

```
delay(2000);
```

**Clear display, set font size, color and write text**

After initializing the display, clear the display buffer with the clearDisplay() method:

```
display.clearDisplay();
```

Before writing text, you need to set the text size, color and where the text will be displayed in the OLED.

Set the font size using the setTextSize() method:

```
display.setTextSize(1);             
```

Set the font color with the setTextColor() method:

```
display.setTextColor(WHITE);        
```

WHITE sets white font and black background.

Define the position where the text starts using the setCursor(x,y) method. In this case, we’re setting the text to start at the (0,0) coordinates – at the top left corner.

```
display.setCursor(0,0);             
```

Finally, you can send the text to the display using the println() method, as follows:

```
display.println("Hello, world!");
```

Then, you need to call the display() method to actually display the text on the screen.

```
display.display();
```

</details>

2. #### Scrolling Text

   The Adafruit OLED library provides useful methods to easily scroll text.

   * `startscrollright(0x00, 0x0F)`: scroll text from left to right
   * `startscrollleft(0x00, 0x0F)`: scroll text from right to left
   * `startscrolldiagright(0x00, 0x07)`: scroll text from left bottom to right upper&#x20;
   * `startscrolldiagleft(0x00, 0x07)`: scroll text from right bottom to left upper&#x20;

   The following code implements those methods.

```c
#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

void setup() {
  Serial.begin(115200);

  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
  delay(2000);
  display.clearDisplay();

  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  // Display static text
  display.println("Scrolling Hello");
  display.display(); 
  delay(100);
 
}

void loop() {
  // 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);
}
```

The Adafruit GFX library allows us to use some other fonts besides the built-in fonts.&#x20;

To use one of those fonts, first you need to include it in your sketch, for example:

```
#include <Fonts/FreeSerif12pt7b.h>
```

Next, you just need to use the setFont() method and pass as argument, the specified font:

```
display.setFont(&FreeSerif12pt7b);
```

After specifying the font, all methods to write text will use that font.&#x20;

To get back to use the original font, you just need to call the setFont() method with no arguments:

```
display.setFont();
```

### 4. OLED Display Shapes

The Adafruit OLED library provides useful methods to draw pixels, lines and shapes.&#x20;

* **Draw a pixel**

  To draw a pixel in the OLED display, you can use the drawPixel(x, y, color) method that accepts as arguments the x and y coordinates where the pixel appears, and color. For example:

  ```
  display.drawPixel(64, 32, WHITE);
  ```
* #### Draw a line

  Use the drawLine(x1, y1, x2, y2, color) method to create a line. The (x1, y1) coordinates indicate the start of the line, and the (x2, y2) coordinates indicates where the line ends. For example:

  ```
  display.drawLine(0, 0, 127, 20, WHITE);
  ```
* #### Draw a rectangle

  The drawRect(x, y, width, height, color) provides an easy way to draw a rectangle. The (x, y) coordinates indicate the top left corner of the rectangle. Then, you need to specify the width, height and color:

  ```
  display.drawRect(10, 10, 50, 30, WHITE);
  ```

  You can use the fillRect(x, y, width, height, color) to draw a filled rectangle. This method accepts the same arguments as drawRect().

  ```
  display.fillRect(10, 10, 50, 30, WHITE);
  ```
* #### Draw a circle

  To draw a circle use the drawCircle(x, y, radius, color) method. The (x,y) coordinates indicate the center of the circle. You should also pass the radius as an argument. For example:

  ```
  display.drawCircle(64, 32, 10, WHITE);
  ```

  In the same way, to build a filled circle, use the fillCircle() method with the same arguments:

  ```
  display.fillCircle(64, 32, 10, WHITE);
  ```
* #### Draw a triangle

  Use the the drawTriangle(x1, y1, x2, y2, x3, y3, color) method to build a triangle. This method accepts as arguments the coordinates of each corner and the color.

  ```
  display.drawTriangle(10, 10, 55, 20, 5, 40, WHITE);
  ```

  Use the fillTriangle() method to draw a filled triangle.

  ```
  display.fillTriangle(10, 10, 55, 20, 5, 40, WHITE);
  ```
* #### Invert

  The library provides an additional method that you can use with shapes or text: the invertDisplay() method. Pass true as argument to invert the colors of the screen or false to get back to the original colors.

  ```
  display.invertDisplay(true);
  ```

#### Code for Draw Shapes: Upload the following code that implements each snippet of code we’ve covered previously and goes through all the shapes.

```cpp
#include <Arduino.h> // Some code
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

void setup() {
  Serial.begin(115200);

  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
  delay(2000); // Pause for 2 seconds

  // Clear the buffer
  display.clearDisplay();

  // Draw a single pixel in white
  display.drawPixel(64, 32, WHITE);
  display.display();
  delay(3000);

  // Draw line
  display.clearDisplay();
  display.drawLine(0, 0, 127, 20, WHITE);
  display.display();
  delay(3000);
  
  // Draw rectangle
  display.clearDisplay();
  display.drawRect(30, 10, 50, 30, WHITE);
  display.display();
  delay(3000);
  // Fill rectangle
  display.fillRect(30, 10, 50, 30, WHITE);
  display.display();
  delay(3000);

  // Draw round rectangle
  display.clearDisplay();
  display.drawRoundRect(10, 10, 30, 50, 2, WHITE);
  display.display();
  delay(3000);
  // Fill round rectangle
  display.clearDisplay();
  display.fillRoundRect(10, 10, 30, 50, 2, WHITE);
  display.display();
  delay(3000);
  
  // Draw circle
  display.clearDisplay();
  display.drawCircle(64, 32, 10, WHITE);
  display.display();
  delay(3000);
  // Fill circle
  display.fillCircle(64, 32, 10, WHITE);
  display.display();
  delay(3000);
  
  // Draw triangle
  display.clearDisplay();
  display.drawTriangle(10, 10, 55, 20, 5, 40, WHITE);
  display.display();
  delay(3000);
  // Fill triangle
  display.fillTriangle(10, 10, 55, 20, 5, 40, WHITE);
  display.display();
  delay(3000);

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

void loop() {
  
}
```

### 5. Display Bitmap Images

You can display 128×64 bitmap monocolor images on the OLED display.

First, use an imaging program to resize a photo or picture and **save it as monochrome bitmap**. If you’re on a Windows PC, you can use Paint.

Then, use a Image to C Array converter to convert the image into an array. I’ve used [LCD Image Converter](https://sourceforge.net/projects/lcd-image-converter/files/). Run the program and start with a new image. Go to **Image** > **Import** and select the bitmap image you’ve created earlier.

<figure><img src="https://2579747216-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkSq9ZTh3ba8gAVAntL52%2Fuploads%2FHQezh5HijJ9EmelS2tDt%2Fimage.png?alt=media&#x26;token=e4365f38-b3d5-45ea-9c60-62bac0b1ee6d" alt=""><figcaption></figcaption></figure>

Go to **Options** > **Conversion** and in the **Prepare** tab, select the following options:

* **Type:** Monochrome, Threshold Dither
* **Main Scan Direction:** Top to Bottom
* **Line Scan Direction:** Forward

<figure><img src="https://i0.wp.com/randomnerdtutorials.com/wp-content/uploads/2019/05/image-converter-monochrome.png?resize=662%2C439&#x26;quality=100&#x26;strip=all&#x26;ssl=1" alt="" height="439" width="662"><figcaption></figcaption></figure>

Go to the Image tab and select the following options:

* Split to rows
* **Block size:** 8 bit
* **Byte order:** Little-Endian

<figure><img src="https://i0.wp.com/randomnerdtutorials.com/wp-content/uploads/2019/05/options-image-lcd-converter.png?resize=567%2C430&#x26;quality=100&#x26;strip=all&#x26;ssl=1" alt="Display Bitmap Images OLED convert image export" height="430" width="567"><figcaption></figcaption></figure>

Then, click **OK**. Finally, in the main menu, go to **File** > **Convert**. A new file with *.c* extension should be saved. That file contains the C array for the image.&#x20;

Open that file with a text editor, and copy your array to the code. Then, to display the array, use the drawBitmap() method that accepts the following arguments (x, y, image array, image width, image height, rotation). The (x, y) coordinates define where the image starts to be displayed.

Copy the code below to display your bitmap image in the OLED.

```cpp
#include <Arduino.h>

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

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

static const uint8_t image_data_Saraarray[480] = {  
  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, 0x83, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0x39, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xfe, 0xed, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xfc, 0xc4, 0x7f, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xfb, 0xc5, 0x3f, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xf3, 0xcd, 0x9f, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xef, 0xf9, 0xdf, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xcf, 0xf3, 0xe7, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xbf, 0xe7, 0xf3, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0x3f, 0xd9, 0xfb, 0xff, 0xff, 0xff, 
    0xff, 0xfe, 0xff, 0x9c, 0xfb, 0xff, 0xff, 0xff, 
    0xff, 0xfc, 0x3f, 0x7e, 0xfb, 0xff, 0xff, 0xff, 
    0xff, 0xf9, 0x5e, 0x7f, 0x23, 0xff, 0xff, 0xff, 
    0xff, 0xf3, 0xcd, 0xff, 0x99, 0xff, 0xff, 0xff, 
    0xff, 0xe6, 0x61, 0xff, 0xfc, 0xff, 0xff, 0xff, 
    0xff, 0xec, 0x37, 0xff, 0xfe, 0xff, 0xff, 0xff, 
    0xff, 0xec, 0x37, 0xff, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xec, 0x67, 0xff, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xef, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xe7, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xe0, 0x37, 0xff, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xe0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xe0, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xe0, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xe0, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xe0, 0x00, 0x3f, 0xff, 0x00, 0xe1, 0xff, 
    0xff, 0xe0, 0x00, 0x1f, 0xff, 0x00, 0x43, 0xff, 
    0xff, 0xe0, 0x00, 0x0f, 0xff, 0x00, 0xc3, 0xff, 
    0xff, 0xe0, 0x00, 0x07, 0xfe, 0x18, 0xc3, 0xff, 
    0xff, 0xe0, 0x00, 0x07, 0xfe, 0x10, 0x87, 0xff, 
    0xff, 0xe0, 0x00, 0x03, 0xfe, 0x01, 0x87, 0xff, 
    0xff, 0xe0, 0x00, 0x01, 0xfc, 0x03, 0x87, 0xff, 
    0xff, 0xe0, 0x00, 0x01, 0xfc, 0x03, 0x0f, 0xff, 
    0xff, 0xe0, 0x00, 0x01, 0xfc, 0x63, 0x0f, 0xff, 
    0xff, 0xe0, 0x00, 0x00, 0xf8, 0x43, 0x0f, 0xff, 
    0xff, 0xe0, 0x00, 0x00, 0xf8, 0x42, 0x1f, 0xff, 
    0xff, 0xe0, 0x00, 0x00, 0xf8, 0x46, 0x1f, 0xff, 
    0xff, 0xe0, 0x00, 0x00, 0xf0, 0x86, 0x07, 0xff, 
    0xff, 0xe0, 0x00, 0x00, 0x70, 0x84, 0x07, 0xff, 
    0xff, 0xe0, 0x00, 0x00, 0xf5, 0xdd, 0x1f, 0xff, 
    0xff, 0xf5, 0x55, 0x55, 0x7f, 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
};
 
void setup() {
  Serial.begin(115200);
 
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
  delay(2000); // Pause for 2 seconds
 
  // Clear the buffer.
  display.clearDisplay();
  //display.setCursor(20,20); 
  // Draw bitmap on the screen
  display.drawBitmap(20, 0, image_data_Saraarray, 64, 64, 1);
  display.display();
}
 
void loop() {
  
}
```

### 6. Other Libraries

For other libraries, the application is similar. For example, we can install and have a quick test the [ThingPulse/esp8266-oled-ssd1306](https://github.com/ThingPulse/esp8266-oled-ssd1306?tab=readme-ov-file) library as follows:

```cpp
#include <Arduino.h>

#include <Wire.h>
#include "SSD1306.h"

SSD1306 display(0x3c, 6, 5);

void setup() {
  display.init();

  display.setFont(ArialMT_Plain_24);
  display.drawString(0, 0, "Hello World");
  display.display();
}

void loop() {
  Serial.println("Hello Robotlabs");
}
```

## Summary

In this tutorial you learned about I2C communication protocol with the ESP32. Also, we talk about how to develop the OLED display with SSD1306 Driver and I2C protocol. Now, you can go further and integrate the OLED display in your own projects.

Finally, if you want to learn more about other controllers, take a look at our Youtube channel:

{% embed url="<https://www.youtube.com/@RobotLabs>" %}
