PLEASE NOTE: This site is no longer being actively maintained. For frequently updated BeagleBone resources please visit Beaglebone.org.

Wednesday, August 6, 2014

On 9:02 AM by Richard St-Pierre
BeagleBone OLED Logic SupplyBeagleBone OLED Beagle

Overview

The miniaturization and portability of electronics has increased the demand for tiny displays which are, in turn, creating new opportunities for the design community. Easy to interface via the I2C bus, and low power, these Organic Light Emitting Diode (OLED) displays are commonly used in telephones and other portable devices to display small graphical icons, and a wide variety of data.

The OLED display is small enough to fit in a BeagleBone Black case.

In this tutorial we will demonstrate how to interface an Organic LED (OLED) display using the I2C bus to the BeagleBone Black and display graphical images. We will use C/C++ and Debian in this tutorial. So let's take a look at these steps together.


What You Will Need

LGX BeagleBone Proto CapeJumper Wire Pack for BreadboardsMini Breadboard, White, 75-points

Introduction

In this project, we will interface an OLED display to the BeagleBone Black.
A C/C++ program will communicate over the digital I2C Bus and present display data to the small high contrast 128x64 pixel screen. (with built-in SSD1306 Controller).

Instructions

The OLED controller can operate in multiple interface modes. I2C (IIC) is the easiest.
There are three jumpers that must be set (BS0,BS1,BS2) for IIC mode as shown.
(A soldering iron and fine tweezers will be required if you need to change the jumper settings )


Connections to the OLED display can be made with a solderless breadboard and a jumper wire kit or a BeagleBone Proto Cape (recommended). A 2-by-8 2.54mm (0.1") female header socket is also suggested.

STEP 1 - Circuit Connections

Turn OFF the BeagleBone Black power and make the following connections.
Interfacing to the display is simple (many signals are unused and tied to ground).

I2C OLED Display BeagleBone - Logic Supply Tutorial
OLED
Pin
Signal
Name
Connection
BeagleBone
1+3.3VP9-3 3.3V
2GNDP9-1 Ground
3Data7P9-1 Ground
4Data6P9-1 Ground
5Data5P9-1 Ground
6Data4P9-1 Ground
7Data3P9-1 Ground
8Data2P9-20 I2C2-SDA
9Data1P9-20 I2C2-SDA
10Data0P9-19 I2C2-SCL
11RDP9-1 Ground
12RWP9-1 Ground
13DCP9-1 Ground
14RESP9-3 +3.3V
15CSP9-1 Ground
16NCNo connection

Only 4 connections are required from the BeagleBone.

Device PinBeagleBone Signal
GNDP9-1GND
VCCP9-3+3.3V
SDAP9-20I2C2-SDA
SCLP9-19I2C2-SCL


STEP 2 - I2C Bus Library and Utilities

Once the wire jumper connections are made to the BeagleBone, we should check that the OLED display is detected on the I2C BUS. Power ON the BeagleBone, and open a connection with ssh/putty.

Start the I2C detection utility on BUS 1 (/dev/i2c-1).

i2cdetect -y 1

root@beaglebone:~/i2c_oled# i2cdetect -r -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- 3c -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- UU UU UU UU -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

The OLED display is detected at address '3c' or '0x78'

STEP 3 - Program

Download bb_oled.c File (and save it without the txt extension)

Also a few graphics files:
Download box128x64.h File (and save it without the txt extension)
Download Q_NPN.h File (and save it without the txt extension)
Download Andoid.h File (and save it without the txt extension)
Download Inspire.h File (and save it without the txt extension)

Program Listing

//  BeagleBone Black {Debian}
//  Title   : I2C control of SSD1306 128x64 OLED display
//  Author  : Richard St-Pierre
//  Version : 1.0 Aug 5, 2014 Initial version 

#include <stdio .h>
#include <unistd .h>
#include <fcntl .h>
#include <linux i2c-dev.h>
#include <errno .h>
#include <sys ioctl.h>
#include <string .h>

// bitmapped image files for oled


#include "box128x64.h"                  // Outer perimeter box
#include "Q_NPN.h"                      // NPN Transistor
#include "Android.h"                    // Android
#include "Inspire.h"                    // Inspire


#define I2C_DEVID  (0x78 >>1);          // Translate Address
#define CMD_COMMAND     0x80            // Single command
#define CMD_CONT_CMD    0x00            // Continous command
#define CMD_DATA        0x40            // Single Data
#define CMD_CONT_DATAT  0xC0            // Continuous Data
#define CMD_DISP_ON     0xA4            //
#define CMD_DISP_OFF    0xAE            //
#define CMD_REVERSE     0xA1            //
#define CMD_NORMAL      0xA0            //
#define CMD_CONTRAST    0x81            //parameter 00-FF
#define CMD_SETPAGE     0x22            //

// Global variables
unsigned char   buffer[4];
int             i2c_oled_fd;
int             deviceI2CAddress = I2C_DEVID;

// Function protptyping
void send_command(unsigned char cmd);
void send_dat(unsigned  char dat);
 
// ============================================
//         M   A   I   N
// ============================================
int main (argc, argv)
        int argc;
        char *argv[];
         {
        int i;
        printf("\nBeagleBone I2C OLED DISPLAY - RSTP");

        i2c_oled_fd  = open("/dev/i2c-1", O_RDWR);

        if (i2c_oled_fd  < 0) {
                printf("\nError opening file: %s\n","/dev/i2c-1");
                return 1;
        }
        if (ioctl(i2c_oled_fd, I2C_SLAVE, deviceI2CAddress) < 0) {
                printf("\nError ioctl");
                return 1;
        }

        // Power up Display

        send_command(0x8D);
        send_command(0x14);

        send_command(0xAF);             // Display ON
        usleep(100000);
        sleep(1);

        printf("\nSending Display data\n");
        send_command(0x20);             // Memory addressing mode
        send_command(0x00);             // Horizontal mode
        sleep(1);

for (;;)
    {

        for ( i=0; i < 128*8; i++) {
        send_dat(box128x64[i]);
        }
        sleep(2);

        for ( i=0; i < 128*8; i++) {
        send_dat(Q_NPN[i]) ;
        }           
        sleep(2);

        for ( i=0; i < 128*8; i++) {
        send_dat(Android[i]) ;
        }
        sleep(2);
     
        for ( i=0; i < 128*8; i++) {
        send_dat(Inspire[i]) ;
        }
        sleep(2);
       
    }
 close(i2c_oled_fd);

        return 0;
}
//========================================
void send_command(unsigned char cmd)
{
unsigned char buf[3];

        buf[0]=0x80;
        buf[1]=cmd;
        write(i2c_oled_fd,buf,2);
        printf(" %02X%02X", buf[0],buf[1]);

}
void send_dat(unsigned char dat)
{
        buffer[0]=0x40;
        buffer[1]=dat;
        write(i2c_oled_fd,buffer,2);
}


Program Overview

In this -c- program, we first include a number of standard '*.h' files, and also the i2c-dev.h file required for the I2C bus. We then add a few sample graphics image files that have been converted into an array (see method below). You are encouraged to add or change the images as you wish. Next, we define commands that will be used to 'talk' to the the I2C OLED controller. We will need a buffer for the data, and integer for file descriptor and I2C device ID.

We create two functions: send_command() and send_dat(). "Send_command()" is used to give the display instructions, setting modes, while "send_dat()" is used to send the actual image data to the display.

In main(), we send a simple program identification message, before opening the "file" for I2C communication. In linux the I2C Bus (and almost all devices) are treated as files. Error checking is used to ensure that the bus is available and working properly.

With the I2C-Bus active, we can send initialization instructions to the display. Once the display is ready, we enter an endless loop, that simply loads each image in sequence, pausing two seconds between each graphic.

This is a simple demonstration program, which you are encouraged to play with. A filename could be passed as a command line argument to load images in a more dynamic mode. A dynamic image could also be created to display other data results, graphs and so much more.

STEP 4 - Compiling and Running the Program

To compile the program:
gcc bb_oled.c -o bb_oled

To run the program:
./bb_oled


STEP 5 - Creating Custom Graphics

The display has a resolution of 128x64 pixels. To create a custom graphic you can use a "Paint" program and save the output as monochrome (black & white). The white pixels on the graphics will light the OLED.  (Black text on white background would have most LEDs ON). An LCD Assistant program can be used to create an array for C/C++ that can be directly linked into your program. The following settings should be used for a full screen graphics.
  • Byte orientation (o) Vertical
  • Size Width [128] Height [64]
  • Size endianness (o) Little
  • Pixels/byte 8
  • Table name: __________ (choose a name, filename is default)
Once you have made the setting:
File->Load Image
and then
File->Save output.
This will create the file to include in your program.

Sample Outputs


Logic Supply BeagleBone Oled Logic Supply BeagleBone Oled Android BeagleBone Oled Vermont
Logic Supply BeagleBone Oled debian Logic Supply BeagleBone Oled Inspire Logic Supply BeagleBone Oled Penguin Linux
Logic Supply BeagleBone OLED  Coffee Java Logic Supply BeagleBone Oled Transistor NPN Logic Supply BeagleBone Oled Ski Vermont
Logic Supply BeagleBone OLED BarGraph Logic Supply BeagleBone Oled RF WiFi BLueTooth Logic Supply BeagleBone OLED Mouse
Logic Supply BeagleBone Oled Letters Logic Supply BeagleBone Oled Person Logic Supply BeagleBone Oled cellphone

Hope this inspired you to try a new project. If you enjoy these projects, leave us some feedback below.