OLED SPI Interface with Arduino Tutorial

Posted by: Chao Category: Interface Tags: , , Comments: 15

OLED SPI Interface with Arduino Tutorial

When you get our OLED, they are followings so may have to do before you start to use it.

It’s a quite cheap and easy to use OLED, offering a few communication protocol 68XX, 8080, 4 wires, 3 wires and I2C, we are now going to try the 4 wires. It’s also fast and good at animation, looks cool. You can find the product here.

See the demo video at break.

Soldering

Soldering so break way headers

The resistor on the back (BS0, BS1, BS2) are the configuration of different interface. See the page 9 and sub-title ‘MCU Bus Interface Pin Selection ‘, since we are going to use 4-wires configuration, so you need to move the BS1 resistor from “1” to “0” posistion, just heat it up a little bit with iron tip, and then grab and move with tweeter, it’s easy.

Library

Install the <SSD1306> library, get it from the product page, upload the following codes into your arduino, and then you can see how it works.

Demo Codes

Now you can start using the following demo codes, see the wiring of the first couple of lines.
[c]
#define OLED_DC 11
#define OLED_CS 12
#define OLED_CLK 10
#define OLED_MOSI 9
#define OLED_RESET 13

#include <SSD1306.h>

SSD1306 oled(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2

#define LOGO16_GLCD_HEIGHT 16
#define LOGO16_GLCD_WIDTH 16
static unsigned char __attribute__ ((progmem)) logo16_glcd_bmp[]={
0x30, 0xf0, 0xf0, 0xf0, 0xf0, 0x30, 0xf8, 0xbe, 0x9f, 0xff, 0xf8, 0xc0, 0xc0, 0xc0, 0x80, 0x00,
0x20, 0x3c, 0x3f, 0x3f, 0x1f, 0x19, 0x1f, 0x7b, 0xfb, 0xfe, 0xfe, 0x07, 0x07, 0x07, 0x03, 0x00, };

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

// If you want to provide external 7-9V VCC, uncomment next line and comment the one after
//oled.ssd1306_init(SSD1306_EXTERNALVCC);

// by default, we’ll generate the high voltage from the 3.3v line internally! (neat!)
oled.ssd1306_init(SSD1306_SWITCHCAPVCC);

// init done

oled.display(); // show splashscreen
delay(2000);
oled.clear(); // clears the screen and buffer

// Fill screen
oled.fillrect(0, 0, SSD1306_LCDWIDTH-1, SSD1306_LCDHEIGHT-1, WHITE);
oled.display();
delay(2000);

// draw a single pixel
oled.setpixel(10, 10, WHITE);
oled.display();
delay(2000);
oled.clear();

// draw many lines
testdrawline();
oled.display();
delay(2000);
oled.clear();

// draw rectangles
testdrawrect();
oled.display();
delay(2000);
oled.clear();

// draw multiple rectangles
testfillrect();
oled.display();
delay(2000);
oled.clear();

// draw mulitple circles
testdrawcircle();
oled.display();
delay(2000);
oled.clear();

// draw a white circle, 10 pixel radius, at location (32,32)
oled.fillcircle(32, 32, 10, WHITE);
oled.display();
delay(2000);
oled.clear();

// draw the first ~12 characters in the font
testdrawchar();
oled.display();
delay(2000);
oled.clear();

// draw a string at location (0,0)
oled.drawstring(0, 0, "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation");
oled.display();
delay(2000);
oled.clear();

// miniature bitmap display
oled.drawbitmap(30, 16, logo16_glcd_bmp, 16, 16, 1);
oled.display();

// invert the display
oled.ssd1306_command(SSD1306_INVERTDISPLAY);
delay(1000);
oled.ssd1306_command(SSD1306_NORMALDISPLAY);
delay(1000);

// draw a bitmap icon and ‘animate’ movement
testdrawbitmap(logo16_glcd_bmp, LOGO16_GLCD_HEIGHT, LOGO16_GLCD_WIDTH);
}

void loop()
{
for (uint8_t i=0; i&lt;SSD1306_LCDWIDTH; i++) {
for (uint8_t j=0; j&lt;SSD1306_LCDHEIGHT; j++) {
oled.setpixel(i, j, WHITE);
oled.display();
}
}

}

void testdrawbitmap(const uint8_t *bitmap, uint8_t w, uint8_t h) {
uint8_t icons[NUMFLAKES][3];
srandom(666); // whatever seed

// initialize
for (uint8_t f=0; f&lt; NUMFLAKES; f++) {
icons[f][XPOS] = random() % SSD1306_LCDWIDTH;
icons[f][YPOS] = 0;
icons[f][DELTAY] = random() % 5 + 1;

Serial.print("x: ");
Serial.print(icons[f][XPOS], DEC);
Serial.print(" y: ");
Serial.print(icons[f][YPOS], DEC);
Serial.print(" dy: ");
Serial.println(icons[f][DELTAY], DEC);
}

while (1) {
// draw each icon
for (uint8_t f=0; f&lt; NUMFLAKES; f++) {
oled.drawbitmap(icons[f][XPOS], icons[f][YPOS], logo16_glcd_bmp, w, h, WHITE);
}
oled.display();
delay(200);

// then erase it + move it
for (uint8_t f=0; f&lt; NUMFLAKES; f++) { oled.drawbitmap(icons[f][XPOS], icons[f][YPOS], logo16_glcd_bmp, w, h, BLACK); // move it icons[f][YPOS] += icons[f][DELTAY]; // if its gone, reinit if (icons[f][YPOS] &gt; SSD1306_LCDHEIGHT) {
icons[f][XPOS] = random() % SSD1306_LCDWIDTH;
icons[f][YPOS] = 0;
icons[f][DELTAY] = random() % 5 + 1;
}
}
}
}

void testdrawchar(void) {
for (uint8_t i=0; i &lt; 168; i++) {
oled.drawchar((i % 21) * 6, i/21, i);
}
}

void testdrawcircle(void) {
for (uint8_t i=0; i&lt;SSD1306_LCDHEIGHT; i+=2) {
oled.drawcircle(63, 31, i, WHITE);
}
}

void testdrawrect(void) {
for (uint8_t i=0; i&lt;SSD1306_LCDHEIGHT; i+=2) {
oled.drawrect(i, i, SSD1306_LCDWIDTH-i, SSD1306_LCDHEIGHT-i, WHITE);
}
}

void testfillrect(void) {
for (uint8_t i=0; i&lt;SSD1306_LCDHEIGHT; i++) {
// alternate colors for moire effect
oled.fillrect(i, i, SSD1306_LCDWIDTH-i, SSD1306_LCDHEIGHT-i, i%2);
}
}

void testdrawline() {
for (uint8_t i=0; i&lt;SSD1306_LCDWIDTH; i+=4) {
oled.drawline(0, 0, i, SSD1306_LCDHEIGHT-1, WHITE);
oled.display();
}
for (uint8_t i=0; i&lt;SSD1306_LCDHEIGHT; i+=4) {
oled.drawline(0, 0, SSD1306_LCDWIDTH-1, i, WHITE);
oled.display();
}

delay(1000);

for (uint8_t i=0; i&lt;SSD1306_LCDWIDTH; i+=4) {
oled.drawline(i, SSD1306_LCDHEIGHT-1, 0, 0, BLACK);
oled.display();
}
for (uint8_t i=0; i&lt;SSD1306_LCDHEIGHT; i+=4) {
oled.drawline(SSD1306_LCDWIDTH – 1, i, 0, 0, BLACK);
oled.display();
}
}
[/c]

Share this post

Comments (15)

  • Charly86 Reply

    Hello,

    This tutorial bring me some questions :
    – According to the documentation, default mode for LCD interface is 8080 parallel mode. So to switch to 4 wires SPI mode we need to change BS1 and BS2 ?
    – The tutorial do not mention level shifter, does this mean we can drive the LCD with the +5V of the arduino board and apply high level 5V to the inputs ?

    Thank you for your help

    September 11, 2012 at 5:54 pm
  • Chao Reply

    Hi charly,

    yes you need to switch BS1 and BS2 to 1 position.
    and this module does work with 5V voltage, it’s no problem, just connect it directly with arduino.

    September 12, 2012 at 1:33 pm
  • Tim Reply

    Hi,

    The documentation says
    “When I2C
    mode is selected, D2 & D1 should be tired together an
    serve as SDAout & SDAin in application and D0 is the
    serial clock input SCL.”

    By “tired” does it mean D2 and D1 should be joined together?

    October 2, 2012 at 8:57 am
  • Chao Reply

    Hello Tim,

    I guess it’s a typing mistake, it’s simply just “wired” not “tired”, sorry for the confusing! And it should means not wired together, but connect respectively for it’s function.

    October 2, 2012 at 10:38 am
    • Tim Reply

      Also the test code from above is incomplete, the void loop is missing code.

      I tried 4 wires as used in the tutorial,
      OLED pin 1 – Vcc > Arduino +5v
      OLED pin 2 – Ground > Arduino GRND
      OLED pin 3 – CS > Arduino Digital Pin 12
      OLED pin 4 – RES > Arduino Digital Pin 13
      OLED pin 5 – D/C > Arduino Digital Pin 11
      OLED pin 8 – CLK > Arduino Digital Pin 10
      OLED pin 9 – MOSI > Arduino Digital Pin 9

      Resoldered BS1 from factory stock 1 to 0 so BS0,1,2 all have resistors on 0.

      Any idea what I’m doing wrong? OLED dosent power up or disply anything at all.

      October 2, 2012 at 1:08 pm
      • Tim Reply

        Actually got the OLED working now on 4 wires serial, although a i2c tutorial would be awesome if you guys ever get time!

        October 2, 2012 at 1:23 pm
        • berlin Reply

          Hi, I’m totally new to this and would also ask if anybody has a i2c solution (code) for this display. explaining the wiring would also be very helpful (oled –> arduino).

          Thank you very much!!

          October 12, 2012 at 7:06 pm
  • Chao Reply

    Hello Tim,
    I just updated the code, it’s complied successfully, some errors we made during editing this post. if you have any further questions with it please let me know.

    October 2, 2012 at 1:29 pm
  • Manuel Reply

    Hi,

    I don’t seem to be able to find the I2C library for this OLED display. Even the Demo Code uses SPI not I2C. Can you kindly point me to the right library?

    Thanks!

    February 9, 2014 at 9:58 pm
  • Chao Reply

    Hello Manuel,

    I think there is only SPI demo code available, IIC is not yet available, thanks.

    February 9, 2014 at 11:16 pm
  • andy Reply

    Is it possible to buy these already set up properly for SPI, to match the demo code?

    Moving surface mount resistors around might be easy if you’re young and have good eyesight and steady hands. None of those things apply to me any more, unfortunately.

    February 16, 2014 at 10:40 am
  • Pete Reply

    Any way to make this work on a Chipkit Uno 32 without drastic library rewritting? I’m not that versed to rewrite libraries.

    December 19, 2014 at 1:23 am
  • David Reply

    I downloaded the library from the product page and attempted to compile the code provided using the arduino IDE and this code is not compiling.

    “lt was not declared in this scope”

    December 27, 2014 at 12:26 pm
  • poulbran Reply

    This is awesome pushing the limits of arduino!

    September 12, 2016 at 8:22 am
  • Sebastian Scholle Reply

    What are the pins for n Arduino Mega? the ones above only work for the Uno

    October 25, 2020 at 4:05 am

Leave a Reply

Your email address will not be published. Required fields are marked *