Qwiic Micro OLED Hookup Guide
Introduction
The Qwiic Micro OLED is a Qwiic enabled version of our micro OLED display! This small monochrome, blue-on-black OLED display displays incredibly clear images
This hookup guide will show you how to get started drawing objects and characters on your OLED.
Required Materials
To get started, you'll need a microcontroller to, well, control everything.
Now to get into the Qwiic ecosystem, the key will be one of the following Qwiic shields to match your preference of microcontroller:
You will also need a Qwiic cable to connect the shield to your OLED, choose a length that suits your needs.
Suggested Reading
If you aren't familiar with the Qwiic system, we recommend reading here for an overview.
![]() |
Qwiic Connect System |
We would also recommend taking a look at the following tutorials if you aren't familiar with them.
Qwiic Shield for Arduino & Photon Hookup Guide
Hardware Overview
Listed below are some of the operating ranges and characteristics of the Qwiic Micro OLED.
Characteristic | Range |
---|---|
Voltage | 3.3V |
Temperature | -40°C to 85°C |
I2C Address | 0X3D (Default) or 0X3C (Closed Jumper) |
Pins
Pin | Description | Direction |
---|---|---|
GND | Ground | In |
3.3V | Power | In |
SDA | Data | In |
SCL | Clock | In |
Optional Features
There are several jumpers on board that can be changed to facilitate several different functions. The first of which is the I2C pull-up jumper, highlighted below. If multiple boards are connected to the I2C bus, the equivalent resistance goes down, increasing your pull up strength. If multiple boards are connected on the same bus, make sure only one board has the pull-up resistors connected.
The ADDR jumper (highlighted below) can be used to change the I2C address of the board. The default jumper is open by default, pulling the address pin high and giving us an I2C address of 0X3D. Closing this jumper will ground the address pin, giving us an I2C address of 0X3C.
Hardware Assembly
If you haven't yet assembled your Qwiic Shield, now would be the time to head on over to that tutorial. With the shield assembled, Sparkfun's new Qwiic environment means that connecting the screen could not be easier. Just plug one end of the Qwiic cable into the OLED display, the other into the Qwiic Shield and you'll be ready to start displaying images on your little display.
The OLED screen itself is loosely attached to the breakout board initially, so be careful handling it! You can either use your own enclosure for the OLED display, or you can use some double sided foam tape for a less permanent solution.
Library Overview
Note: This example assumes you are using the latest version of the Arduino IDE on your desktop. If this is your first time using Arduino, please review our tutorial on installing the Arduino IDE. If you have not previously installed an Arduino library, please check out our installation guide.
First, you'll need to download and install the SparkFun Micro OLED library. You can install this library automatically in the Arduino IDE's Library Manager by searching for "Micro OLED Breakout". Or you can manually download it from the GitHub repository. Also, make sure to download the Qwiic example sketches, which we will be reviewing in this tutorial.
Before we get started developing a sketch, let's look at the available functions of the library.
void command(uint8_t c);
--- Sends the display a command byte.void data(uint8_t c);
--- Sends the display a data byte.void setColumnAddress(uint8_t add);
--- Sets the column address.void setPageAddress(uint8_t add);
--- Sets the page address.
LCD Drawing Functions
void clear(uint8_t mode):
--- Clears the screen buffer in the OLED's memory, pass in mode = ALL to clear GDRAM in the OLED controller. Pass in mode = PAGE to clear the screen page buffer.void clear(uint8_t mode, uint8_t c);
--- clears the screen buffer in the OLED's memory, replaces it with a character 'c'.void invert(boolean inv);
--- Turns every black pixel white, turns all white pixels black.void contrast(uint8_t contrast);
--- Changes the contrast value anywhere between 0 and 255.void display(void);
--- Moves display memory to the screen to draw the image in memory.void setCursor(uint8_t x, uint8_t y);
--- Set cursor position to (x, y).void pixel(uint8_t x, uint8_t y);
--- Draw a pixel using the current fore color and current draw mode in the screen buffer's x,y position.void pixel(uint8_t x, uint8_t y, uint8_t color, uint8_t mode);
--- Draw a pixel with NORM or XOR draw mode in the screen buffer's x,y position.void line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1);
--- Draw line using current fore color and current draw mode from x0,y0 to x1,y1 of the screen buffer.void line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t color, uint8_t mode);
--- Draw line using color and mode from x0,y0 to x1,y1 of the screen buffer.void lineH(uint8_t x, uint8_t y, uint8_t width);
--- Draw horizontal line using current fore color and current draw mode from x,y to x+width,y of the screen buffer.void lineH(uint8_t x, uint8_t y, uint8_t width, uint8_t color, uint8_t mode);
--- Draw horizontal line using color and mode from x,y to x+width,y of the screen buffer.void lineV(uint8_t x, uint8_t y, uint8_t height);
--- Draw vertical line using current fore color and current draw mode from x,y to x,y+height of the screen buffer.void lineV(uint8_t x, uint8_t y, uint8_t height, uint8_t color, uint8_t mode);
--- Draw vertical line using color and mode from x,y to x,y+height of the screen buffer.void rect(uint8_t x, uint8_t y, uint8_t width, uint8_t height);
--- Draw rectangle using current fore color and current draw mode from x,y to x+width,y+height of the screen buffer.void rect(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color , uint8_t mode);
---Draw rectangle using color and mode from x,y to x+width,y+height of the screen buffer.void rectFill(uint8_t x, uint8_t y, uint8_t width, uint8_t height);
--- Draw filled rectangle using current fore color and current draw mode from x,y to x+width,y+height of the screen buffer.void rectFill(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color , uint8_t mode);
--- Draw filled rectangle using color and mode from x,y to x+width,y+height of the screen buffer.void circle(uint8_t x, uint8_t y, uint8_t radius);
--- Draw circle with radius using current fore color and current draw mode with center at x,y of the screen buffer.void circle(uint8_t x, uint8_t y, uint8_t radius, uint8_t color, uint8_t mode);
--- Draw circle with radius using color and mode with center at x,y of the screen buffer.void circleFill(uint8_t x0, uint8_t y0, uint8_t radius);
--- Draw filled circle with radius using current fore color and current draw mode with center at x,y of the screen buffer.void circleFill(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t color, uint8_t mode);
--- Draw filled circle with radius using color and mode with center at x,y of the screen buffer.void drawChar(uint8_t x, uint8_t y, uint8_t c);
--- Draws a character at position (x, y).void drawChar(uint8_t x, uint8_t y, uint8_t c, uint8_t color, uint8_t mode);
--- Draws a character using a color and mode at position (x, y)void drawBitmap(uint8_t * bitArray);
--- Draws a preloaded bitmap.uint8_t getLCDWidth(void);
--- Gets the width of the LCD as a byte.uint8_t getLCDHeight(void);
--- Gets the height of the LCD as a byte.
Font Settings
uint8_t getFontWidth(void);
--- Gets the current font width as a byte.uint8_t getFontHeight(void);
--- Gets the current font height as a byte.uint8_t getTotalFonts(void);
--- Return the total number of fonts loaded into the MicroOLED's flash memory.uint8_t getFontType(void);
--- Returns the font type number of the current font (Font types shown below).uint8_t setFontType(uint8_t type);
--- Sets the font type (Font types shown below).
Font Type | Maximum Columns | Maximum Rows | Description |
---|---|---|---|
0 | 10 | 6 | Smallest, 5x7-pixel characters. |
1 | 6 | 3 | Medium, 8x16-pixel characters. |
2 | 5 | 3 | 7-segment display style characters, 10x16-pixels each. |
3 | 5 | 1 | Large, 12x48 (the entire screen height) characters. |
uint8_t getFontStartChar(void);
--- Returns the starting ASCII character of the current font.uint8_t getFontTotalChar(void);
--- Return the total characters of the current font.
Rotation and Scrolling
The following functions will scroll the screen in the various specified directions of each function. Start and Stop indicate the range of rows/columns that will be scrolling.
void scrollRight(uint8_t start, uint8_t stop);
--- Scrolls rightvoid scrollLeft(uint8_t start, uint8_t stop);
void scrollVertRight(uint8_t start, uint8_t stop);
void scrollVertLeft(uint8_t start, uint8_t stop);
void scrollStop(void);
The following two functions are pretty self explanatory, they will flip the graphics ifflip
is true.void flipVertical(boolean flip);
void flipHorizontal(boolean flip);
Examples
Example: Feature Demo
This first example demonstrates many of the available features of the screen through several applications. Keep in mind when looking at this example that drawing anything takes two steps. You must first write what you want the screen to display into the screens memory, then you must tell the screen to display what is in its memory. To begin, we must include our Wire
library to use I2C, and the SFE_MicroOLED
library to control the screen. Then the code initializes the OLED using DC_JUMPER = 1
. If you have closed the jumper on the breakout board, use DC_JUMPER = 0
.
language:c
#include <Wire.h> // Include Wire if you're using I2C
#include <SFE_MicroOLED.h> // Include the SFE_MicroOLED library
#define PIN_RESET 9
#define DC_JUMPER 1
MicroOLED oled(PIN_RESET, DC_JUMPER); // I2C declaration
void setup()
{
delay(100);
Wire.begin();
oled.begin(); // Initialize the OLED
oled.clear(ALL); // Clear the display's internal memory
oled.display(); // Display what's in the buffer (splashscreen)
delay(1000); // Delay 1000 ms
oled.clear(PAGE); // Clear the buffer.
randomSeed(analogRead(A0) + analogRead(A1));
}
The code below tells the microcontroller how to print each example. This is a good place to look to see examples of how the functions discussed earlier are implemented.
language:c
void lineExample()
{
int middleX = oled.getLCDWidth() / 2;
int middleY = oled.getLCDHeight() / 2;
int xEnd, yEnd;
int lineWidth = min(middleX, middleY);
printTitle("Lines!", 1);
for (int i=0; i<3; i++)
{
for (int deg=0; deg<360; deg+=15)
{
xEnd = lineWidth * cos(deg * PI / 180.0);
yEnd = lineWidth * sin(deg * PI / 180.0);
oled.line(middleX, middleY, middleX + xEnd, middleY + yEnd);
oled.display();
delay(10);
}
for (int deg=0; deg<360; deg+=15)
{
xEnd = lineWidth * cos(deg * PI / 180.0);
yEnd = lineWidth * sin(deg * PI / 180.0);
oled.line(middleX, middleY, middleX + xEnd, middleY + yEnd, BLACK, NORM);
oled.display();
delay(10);
}
}
}
void shapeExample()
{
printTitle("Shapes!", 0);
// Silly pong demo. It takes a lot of work to fake pong...
int paddleW = 3; // Paddle width
int paddleH = 15; // Paddle height
// Paddle 0 (left) position coordinates
int paddle0_Y = (oled.getLCDHeight() / 2) - (paddleH / 2);
int paddle0_X = 2;
// Paddle 1 (right) position coordinates
int paddle1_Y = (oled.getLCDHeight() / 2) - (paddleH / 2);
int paddle1_X = oled.getLCDWidth() - 3 - paddleW;
int ball_rad = 2; // Ball radius
// Ball position coordinates
int ball_X = paddle0_X + paddleW + ball_rad;
int ball_Y = random(1 + ball_rad, oled.getLCDHeight() - ball_rad);//paddle0_Y + ball_rad;
int ballVelocityX = 1; // Ball left/right velocity
int ballVelocityY = 1; // Ball up/down velocity
int paddle0Velocity = -1; // Paddle 0 velocity
int paddle1Velocity = 1; // Paddle 1 velocity
//while(ball_X >= paddle0_X + paddleW - 1)
while ((ball_X - ball_rad > 1) &&
(ball_X + ball_rad < oled.getLCDWidth() - 2))
{
// Increment ball's position
ball_X+=ballVelocityX;
ball_Y+=ballVelocityY;
// Check if the ball is colliding with the left paddle
if (ball_X - ball_rad < paddle0_X + paddleW)
{
// Check if ball is within paddle's height
if ((ball_Y > paddle0_Y) && (ball_Y < paddle0_Y + paddleH))
{
ball_X++; // Move ball over one to the right
ballVelocityX = -ballVelocityX; // Change velocity
}
}
// Check if the ball hit the right paddle
if (ball_X + ball_rad > paddle1_X)
{
// Check if ball is within paddle's height
if ((ball_Y > paddle1_Y) && (ball_Y < paddle1_Y + paddleH))
{
ball_X--; // Move ball over one to the left
ballVelocityX = -ballVelocityX; // change velocity
}
}
// Check if the ball hit the top or bottom
if ((ball_Y <= ball_rad) || (ball_Y >= (oled.getLCDHeight() - ball_rad - 1)))
{
// Change up/down velocity direction
ballVelocityY = -ballVelocityY;
}
// Move the paddles up and down
paddle0_Y += paddle0Velocity;
paddle1_Y += paddle1Velocity;
// Change paddle 0's direction if it hit top/bottom
if ((paddle0_Y <= 1) || (paddle0_Y > oled.getLCDHeight() - 2 - paddleH))
{
paddle0Velocity = -paddle0Velocity;
}
// Change paddle 1's direction if it hit top/bottom
if ((paddle1_Y <= 1) || (paddle1_Y > oled.getLCDHeight() - 2 - paddleH))
{
paddle1Velocity = -paddle1Velocity;
}
// Draw the Pong Field
oled.clear(PAGE); // Clear the page
// Draw an outline of the screen:
oled.rect(0, 0, oled.getLCDWidth() - 1, oled.getLCDHeight());
// Draw the center line
oled.rectFill(oled.getLCDWidth()/2 - 1, 0, 2, oled.getLCDHeight());
// Draw the Paddles:
oled.rectFill(paddle0_X, paddle0_Y, paddleW, paddleH);
oled.rectFill(paddle1_X, paddle1_Y, paddleW, paddleH);
// Draw the ball:
oled.circle(ball_X, ball_Y, ball_rad);
// Actually draw everything on the screen:
oled.display();
delay(25); // Delay for visibility
}
delay(1000);
}
void textExamples()
{
printTitle("Text!", 1);
// Demonstrate font 0. 5x8 font
oled.clear(PAGE); // Clear the screen
oled.setFontType(0); // Set font to type 0
oled.setCursor(0, 0); // Set cursor to top-left
// There are 255 possible characters in the font 0 type.
// Lets run through all of them and print them out!
for (int i=0; i<=255; i++)
{
// You can write byte values and they'll be mapped to
// their ASCII equivalent character.
oled.write(i); // Write a byte out as a character
oled.display(); // Draw on the screen
delay(10); // Wait 10ms
// We can only display 60 font 0 characters at a time.
// Every 60 characters, pause for a moment. Then clear
// the page and start over.
if ((i%60 == 0) && (i != 0))
{
delay(500); // Delay 500 ms
oled.clear(PAGE); // Clear the page
oled.setCursor(0, 0); // Set cursor to top-left
}
}
delay(500); // Wait 500ms before next example
// Demonstrate font 1. 8x16. Let's use the print function
// to display every character defined in this font.
oled.setFontType(1); // Set font to type 1
oled.clear(PAGE); // Clear the page
oled.setCursor(0, 0); // Set cursor to top-left
// Print can be used to print a string to the screen:
oled.print(" !\"#$%&'()*+,-./01234");
oled.display(); // Refresh the display
delay(1000); // Delay a second and repeat
oled.clear(PAGE);
oled.setCursor(0, 0);
oled.print("56789:;<=>?@ABCDEFGHI");
oled.display();
delay(1000);
oled.clear(PAGE);
oled.setCursor(0, 0);
oled.print("JKLMNOPQRSTUVWXYZ[\\]^");
oled.display();
delay(1000);
oled.clear(PAGE);
oled.setCursor(0, 0);
oled.print("_`abcdefghijklmnopqrs");
oled.display();
delay(1000);
oled.clear(PAGE);
oled.setCursor(0, 0);
oled.print("tuvwxyz{|}~");
oled.display();
delay(1000);
// Demonstrate font 2. 10x16. Only numbers and '.' are defined.
// This font looks like 7-segment displays.
// Lets use this big-ish font to display readings from the
// analog pins.
for (int i=0; i<25; i++)
{
oled.clear(PAGE); // Clear the display
oled.setCursor(0, 0); // Set cursor to top-left
oled.setFontType(0); // Smallest font
oled.print("A0: "); // Print "A0"
oled.setFontType(2); // 7-segment font
oled.print(analogRead(A0)); // Print a0 reading
oled.setCursor(0, 16); // Set cursor to top-middle-left
oled.setFontType(0); // Repeat
oled.print("A1: ");
oled.setFontType(2);
oled.print(analogRead(A1));
oled.setCursor(0, 32);
oled.setFontType(0);
oled.print("A2: ");
oled.setFontType(2);
oled.print(analogRead(A2));
oled.display();
delay(100);
}
// Demonstrate font 3. 12x48. Stopwatch demo.
oled.setFontType(3); // Use the biggest font
int ms = 0;
int s = 0;
while (s <= 5)
{
oled.clear(PAGE); // Clear the display
oled.setCursor(0, 0); // Set cursor to top-left
if (s < 10)
oled.print("00"); // Print "00" if s is 1 digit
else if (s < 100)
oled.print("0"); // Print "0" if s is 2 digits
oled.print(s); // Print s's value
oled.print(":"); // Print ":"
oled.print(ms); // Print ms value
oled.display(); // Draw on the screen
ms++; // Increment ms
if (ms >= 10) // If ms is >= 10
{
ms = 0; // Set ms back to 0
s++; // and increment s
}
}
}
// Center and print a small title
// This function is quick and dirty. Only works for titles one
// line long.
void printTitle(String title, int font)
{
int middleX = oled.getLCDWidth() / 2;
int middleY = oled.getLCDHeight() / 2;
oled.clear(PAGE);
oled.setFontType(font);
// Try to set the cursor in the middle of the screen
oled.setCursor(middleX - (oled.getFontWidth() * (title.length()/2)),
middleY - (oled.getFontWidth() / 2));
// Print the title:
oled.print(title);
oled.display();
delay(1500);
oled.clear(PAGE);
}
The example code will then loop between all of the examples. This is a good way to see exactly what your code looks like on the screen.
void loop()
{
lineExample(); // Then the line example function
shapeExample(); // Then the shape example
textExamples(); // Finally the text example
}
The example code will look something like the GIF below.
Example: Drawing Bitmaps
It is also possible to load bitmaps of your own custom images into the screen. This can be done using this Bitmap generator. The tool is pretty self explanatory, just load in an image, tell the tool that your screen is 64x48, go to File, and Save the output.
Open the file generated as a text file, it should look something like the below image.
This array is the image that will be displayed by the screen, so now we just have to paste it into the bitmaps.h
header file as the correct data type so our compiler is able to find the image. Make sure you change the array to a uint8_t
. The pasted bitmap should looke something like the below image, with the variable type changed to uint8_t
.
Now we will be able to call drawBitmap(Untitled)
to draw our image. Some example code showing how to display some Rick and Morty bitmaps is shown below.
language:c
#include <Wire.h> // Include Wire if you're using I2C
#include <SFE_MicroOLED.h> // Include the SFE_MicroOLED library
#include "bitmaps.h"
//The library assumes a reset pin is necessary. The Qwiic OLED has RST hard-wired, so pick an arbitrarty IO pin that is not being used
#define PIN_RESET 9
//The DC_JUMPER is the I2C Address Select jumper. Set to 1 if the jumper is open (Default), or set to 0 if it's closed.
#define DC_JUMPER 0
MicroOLED oled(PIN_RESET, DC_JUMPER); // I2C declaration
void setup()
{
delay(100);
oled.begin(); // Initialize the OLED
oled.clear(ALL); // Clear the display's internal memory
oled.display(); // Display what's in the buffer (splashscreen)
delay(1000); // Delay 1000 ms
oled.clear(PAGE); // Clear the buffer.
}
void loop()
{
drawRick();
delay(5000);
drawMorty();
delay(5000);
}
void drawRick()
{
oled.clear(ALL);
oled.clear(PAGE);
oled.drawBitmap(rick);//Display Logo
oled.display();
}
void drawMorty()
{
oled.clear(ALL);
oled.clear(PAGE);
oled.drawBitmap(morty);//Display Logo
oled.display();
}
The output of this code will look something like the GIF below.
Resources and Going Further
Now that you've successfully got your OLED displaying things, it's time to incorporate it into your own project!
For more on the Qwiic Micro OLED, check out the links below:
- Schematic (PDF)
- Eagle Files (ZIP)
- Datasheet (PDF)
- Bitmap Generator
- Qwiic System Landing Page
- SparkFun Micro OLED Arduino Library
- Qwiic Micro OLED Python Package
- SparkFun Qwiic Micro OLED GitHub Repository -- Board design files for the Qwiic Micro OLED.
- Product Showcase: Qwiic Presence Sensor & OLED
Need some inspiration for your next project? Check out some of these related tutorials:
Micro OLED Breakout Hookup Guide
Photon OLED Shield Hookup Guide
MicroView Hookup Guide
Or check out the following blogs for ideas.