Using an OLED Display and I2C

0.96" OLED displays are cheaply available, some come in size 1.3" but have the same processor as the smaller ones.


These OLEDs have 128x64 pixels. Some of the cheap OLED have a part of the screen in one color and a header-like 64 segment of a second color. These colors are fixed and may be used in your application.


The OLED comes with a fixed I2C address of 0x3c, some OLED have the address 0x3d. Use the i2cScanner if in doubt.


You need the Adafruit libraries

  • Adafruit_SSD1306
  • Adafruit_GFX

(There are other libraries for the SSD1306, e.g. u8glib - feel free to play)


Connect the OLED display to the I2C port pins on the bottom of the HelvePic32:

Demo Code from Adafruit:

/*********************************************************************
 * This is an example for our Monochrome OLEDs based on SSD1306 drivers
 * 
 * Pick one up today in the adafruit shop!
 * ------> http://www.adafruit.com/category/63_98
 * 
 * This example is for a 128x64 size display using I2C to communicate
 * 3 pins are required to interface (2 I2C and one reset)
 * 
 * Adafruit invests time and resources providing this open source code, 
 * please support Adafruit and open-source hardware by purchasing 
 * products from Adafruit!
 * 
 * Written by Limor Fried/Ladyada  for Adafruit Industries.  
 * BSD license, check license.txt for more information
 * All text above, and the splash screen must be included in any redistribution
 *********************************************************************/

#include 
#include 
#include 
#include 

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

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


#define LOGO16_GLCD_HEIGHT 16 
#define LOGO16_GLCD_WIDTH  16 
static const unsigned char PROGMEM logo16_glcd_bmp[] =
{ 
        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 };

#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

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

        // by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
        display.begin(SSD1306_SWITCHCAPVCC, 0x3c);  // initialize with the I2C addr 0x3D (for the 128x64)
        // init done

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

        // draw a single pixel
        display.drawPixel(10, 10, WHITE);
        display.display();
        delay(2000);
        display.clearDisplay();

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

        // draw rectangles
        testdrawrect();
        display.display();
        delay(2000);
        display.clearDisplay();

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

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

        // draw a white circle, 10 pixel radius
        display.fillCircle(display.width()/2, display.height()/2, 10, WHITE);
        display.display();
        delay(2000);
        display.clearDisplay();

        testdrawroundrect();
        delay(2000);
        display.clearDisplay();

        testfillroundrect();
        delay(2000);
        display.clearDisplay();

        testdrawtriangle();
        delay(2000);
        display.clearDisplay();

        testfilltriangle();
        delay(2000);
        display.clearDisplay();

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

        // draw scrolling text
        testscrolltext();
        delay(2000);
        display.clearDisplay();

        // text display tests
        display.setTextSize(1);
        display.setTextColor(WHITE);
        display.setCursor(0,0);
        display.println("Hello, world!");
        display.setTextColor(BLACK, WHITE); // 'inverted' text
        display.println(3.141592);
        display.setTextSize(2);
        display.setTextColor(WHITE);
        display.print("0x"); 
        display.println(0xDEADBEEF, HEX);
        display.display();
        delay(2000);

        // miniature bitmap display
        display.clearDisplay();
        display.drawBitmap(30, 16,  logo16_glcd_bmp, 16, 16, 1);
        display.display();

        // invert the display
        display.invertDisplay(true);
        delay(1000); 
        display.invertDisplay(false);
        delay(1000); 

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


void loop() {

}


void testdrawbitmap(const uint8_t *bitmap, uint8_t w, uint8_t h) {
        uint8_t icons[NUMFLAKES][3];

        // initialize
        for (uint8_t f=0; f< NUMFLAKES; f++) {
                icons[f][XPOS] = random(display.width());
                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< NUMFLAKES; f++) {
                        display.drawBitmap(icons[f][XPOS], icons[f][YPOS], logo16_glcd_bmp, w, h, WHITE);
                }
                display.display();
                delay(200);

                // then erase it + move it
                for (uint8_t f=0; f< NUMFLAKES; f++) {
                        display.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] > display.height()) {
                                icons[f][XPOS] = random(display.width());
                                icons[f][YPOS] = 0;
                                icons[f][DELTAY] = random(5) + 1;
                        }
                }
        }
}


void testdrawchar(void) {
        display.setTextSize(1);
        display.setTextColor(WHITE);
        display.setCursor(0,0);

        for (uint8_t i=0; i < 168; i++) {
                if (i == '\n') continue;
                display.write(i);
                if ((i > 0) && (i % 21 == 0))
                        display.println();
        }    
        display.display();
}

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

void testfillrect(void) {
        uint8_t color = 1;
        for (int16_t i=0; i<display.height()/2; i+=3) {
                // alternate colors
                display.fillRect(i, i, display.width()-i*2, display.height()-i*2, color%2);
                color++;
        }
        display.display();
}

void testdrawtriangle(void) {
        for (int16_t i=0; i<min(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();
}

void testfilltriangle(void) {
        uint8_t color = WHITE;
        for (int16_t i=min(display.width(),display.height())/2; i>0; i-=5) {
                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, WHITE);
                if (color == WHITE) color = BLACK;
                else color = WHITE;
        }
        display.display();
}

void testdrawroundrect(void) {
        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();
}

void testfillroundrect(void) {
        uint8_t color = WHITE;
        for (int16_t i=0; i<display.height()/2-2; i+=2) {
                display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i, display.height()/4, color);
                if (color == WHITE) color = BLACK;
                else color = WHITE;
        }
        display.display();
}

void testdrawrect(void) {
        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();
}

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

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

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

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

void testscrolltext(void) {
        display.setTextSize(2);
        display.setTextColor(WHITE);
        display.setCursor(10,0);
        display.clearDisplay();
        display.println("scroll");
        display.display();

        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();
}