128×64 OLED Display interfacing with a Raspberry Pi

This article describes how to connect up and write C code that enables 128x64 OLED display interfacing with a Raspberry Pi using I2C.

128×64 OLED Display interfacing with a Raspberry Pi

I had a little SSD1306 128 x 64 bit OLED display laying around from a previous Arduino project, so I thought it was time to do a bit of OLED display interfacing with a Raspberry Pi.


The device I had was an I2C version of the 0.96” 128x 64 bit SSD1306 OLED module. Monochrome only. These devices are available on Amazon for £3-£4 and make for a really interesting project.  It’s only 4 wires to connect; 2 for I2C communications, and 2 for power (it can be powered from the +3.3v line on the Pi GPIO).

oled display interfacing with a raspberry pi
So, little jumper wires between 3.3v, Gnd, SDA and SCL on the GPIO header, and the device (all clearly labelled) and we are ready to start.

There are some libraries and tools available for this device from Adafruit. It is sometimes useful to begin with those, if nothing else than to make sure the device works, and you have it wired up right. However, we want to do this ourselves, so the first thing we’ll need is a copy of the data sheet to understand how the device works. Googling it, I found copies for download here, and here.

The bits we are interested in are section 8.7 Graphic Display Data RAM, and sections 9 and 10 (Command Table and Command Descriptions). It’s tough reading, but you can get there eventually.
Essentially, we want to put it into Horizontal display mode so that we are writing one byte per column (128 columns per line), then moving down to the next line and writing the next set of bytes for this line of 128 columns. I’ve tried to explain this on a post-it…

oled display interfacing with a raspberry pi

OLED display interfacing with a Raspberry Pi – Software

Now that we have the device wired up and the datasheet downloaded it is time to write some code for OLED display interfacing with a Raspberry Pi.

I’ve tried to pull out all the ‘initialization’ commands and just lump them into an array – you can look them up in the data sheet if you want to understand this in a little more detail.
Here’s the sequence for init:

unsigned char initSequence[26] = {0x00,0xAE,0xA8,0x3F,0xD3,0x00,0x40,0xA1,0xC8,0xDA,0x12,0x81,0x7F,0xA4,0xA6,0xD5,0x80,0x8D,0x14,0xD9,0x22,0xD8,0x30,0x20,0x00,0xAF};

We also have to tell the display where we want to start the data being displayed from, in our case that is the top left. The command sequence for that is as follows:

unsigned char setFullRange[7] = {0x00,0x21,0x00,0x7F,0x22,0x00,0x07};

To get these commands sequences written to the device we need to send it over the I2C bus. Make sure your I2C is enabled (run sudo raspi-config). Here is the code we will use to send data over the I2C bus:

    void writeI2C(unsigned char* data, int bytes) {
char *deviceName = (char*)”/dev/i2c-1″;
if ((i2cHandle = open(deviceName, O_RDWR)) < 0)
printf(“error opening I2C\n”);
if (ioctl(i2cHandle, I2C_SLAVE, i2cAddress) < 0)
printf(“Error at ioctl\n”);
write(i2cHandle, data, bytes);

// Close the i2c device bus
char *deviceName = (char*)”dev/i2c-1″;


This simply opens the /dev/i2c-1 device, then gets a handle to our display device and writes data to it (and closes it afterwards).

When we have initialized the device we can then begin sending it data we want it to display. As you’ve seen above we just need to choose data bytes to send it that illuminate the pixels we want. For example sending 0xFF to every column (and page) will illuminate every pixel on the device. Sending 0x11 will produce 2 thin lines on each of the 8 pages (lines of characters).

That is great, but we want to send text characters to the device, how do we do that. Well the first thing we’ll need to do is to map out the characters and determine what bytes we will need to display them. Let’s start with ‘A’. You can see below that I have mapped this out over 4 bytes:

oled display interfacing with a raspberry pi

I’ve shaded in the pixels I want to illuminate to make the A character. The ‘Most Significant Bit’ (MSB) is on the bottom and the ‘Least Significant Bit’ (LSB) is at the top. You can see that I have also left the top line of pixels and the bottom line of pixels blank – this is to create a separation between each line of characters. The bytes we will need are 0x7E, 0x12, 0x12, 0x7E. We will also need to add a 0x40 byte before these to inform the display that we are sending some data to be displayed.

OLED display interfacing with a Raspberry Pi – Mini Sample App

So, if we initialize the display then send a sequence of these 5 bytes to it we’ll have the letter A displayed at the top left of the screen. Here’s the full code for an app that will display an A in the top left of the screen:

// Ken Hughes
// July 2016
#include <unistd.h>//Needed for I2C port
#include <fcntl.h>//Needed for I2C port
#include <sys/ioctl.h>//Needed for I2C port
#include <linux/i2c-dev.h>//Needed for I2C port
#include <stdio.h>
#include <string.h>


void writeI2C(unsigned char* data, int bytes) {
int i2cAddress = 0x3C;
int i2cHandle;

char *deviceName = (char*)”/dev/i2c-1″;
if ((i2cHandle = open(deviceName, O_RDWR)) < 0) {
printf(“error opening I2C\n”);
else {
if (ioctl(i2cHandle, I2C_SLAVE, i2cAddress) < 0) {
printf(“Error at ioctl\n”);
else {
write(i2cHandle, data, bytes);

// Close the i2c device bus
int main() {

// initialise the display
unsigned char initSequence[26] = {0x00,0xAE,0xA8,0x3F,0xD3,0x00,0x40,0xA1,0xC8,0xDA,0x12,0x81,0x7F,
writeI2C(initSequence, 26);

// set the range we want to use (whole display)
unsigned char setFullRange[7] = {0x00,0x21,0x00,0x7F,0x22,0x00,0x07};

// send the letter A to the display
unsigned char letterA[5] = {0x40,0x7E,0x12,0x12,0x7E};


You can compile this code with the following command

gcc –o display-a display-a.cpp

oled display interfacing with a raspberry pi

OLED display interfacing with a Raspberry Pi – Full Character Set

Instead of adding the bytes for each letter multiple times we are going to create ourselves a ‘look up table’ – we want a letter H?, the code looks up H in a table and there it finds the bytes we need. This is a bit of a labourious process of working out the byte sequence for every letter (and number and punctuation character) and putting all of them into an ‘array of arrays’. It is slightly complicated further because we might have a different number of bytes for different letters. For example the ‘@’ sign needs 5 bytes whereas the letter I only needs 3. Not a problem, for each letter the first byte of the sequence will tell us how many bytes for the letter. For the case of our letter, it would look like this:

    {4, 0x7E, 0x12, 0x12, 0x7e}, //A

The first byte is 4, telling us there are 4 bytes in the sequence to display the letter ‘A’. Here is the sequence for the ‘@’ sign, which requires 5 bytes.

    {5, 0x7E, 0x42, 0x5A, 0x52, 0x5E}, // @

Fast forward through the section where I work out all the byte sequences and populated our ‘array of arrays’.

oled display interfacing with a raspberry pi

Now, we make sure our ‘array of arrays’ is laid out in the same sequence as the standard ASCII table. This allows us to implement a neat trick where if we subtract the ASCII value for ‘<SPACE>’ we get the correct offset into our array of arrays. So if the start of our data looks like this…

int fontData[][6] = {
{2,0×00,0x00}, // SPACE
{1,0x5E}, // !
{3,0×02,0x00,0x02}, // ”
{5,0×24,0x7E,0x24,0x7E,0x24}, // #
{5,0×44,0x4A,0x7E,0x52,0x22}, // $
{5,0×22,0x10,0x08,0x04,0x42}, // %
{5,0×34,0x4A,0x54,0x20,0x40}, // &

… and we want to display a ‘#’ character (ASCII value 35) then we subtract the ASCII value of ‘<SPACE>’ (which is 32) and get 3. Allowing us to look up the byte array at fontData[3] – which is {5, 0x24,0x7E,0x24,0x7E,0x24}
The first number (5) is the number of bytes we need to display this character, and the following 5 bytes are the actual values we send to the device to display this pattern.

OLED display interfacing with a Raspberry Pi – Bringing it all together

Now that we know how to get the correct bytes sequences we just need to pull everything together. This is a case of combining the initialization, the interpreting the desired characters into bytes sequences and the writing of the bytes to the display.

I found the easiest way to do this was to create a 128 byte array for each line…

unsigned char displayLines[8][128];

… and to set all bytes to zero to begin with …

for(int i=0; i<8; i++) {
for(int j=0; j<128; j++) {
displayLines[i][j] = 0;

Now, whenever we get text to display we begin filling up the 128 bytes of the current line …

c = toupper(c); // we only support UPPERCASE letters
int letterIdx = (c – ‘ ‘);
if(letterIdx > 64)
letterIdx = 65;

int letterBytes = fontData[letterIdx][0];
for(int i=0; i<letterBytes; i++)
displayLines[currentLine][curr + i] = fontData[letterIdx][1 + i];

displayLines[currentLine][curr + letterBytes++] = 0x00;  // single byte space between letters

We also need to make sure that the remainder of the line is filled with zeros just in case we are overwriting a line that previously had text on it.

// now fill up any left over with 0x00s on the current line
while(currByteCount < 128)
displayLines[currentLine][currByteCount++] = 0x00;

Now that we have the displayLines arrays populated with the bytes we need it is a simple case of sending them to the device over I2C. We have to create a byte sequence that is a 0x40 (‘data stream coming’ command) followed by all the bytes for the line. We do this for each line…

unsigned char buffer[129] = {0};
buffer[0] = 0x40;
for(int i=0; i<128; i++) {
buffer[1 + i] = displayLines[line][i];
writeI2C(buffer, 129);

… and now we have working code that we can use to call a function with some text as the parameter and have that text displayed on the OLED screen.

oled display interfacing with a raspberry pioled display interfacing with a raspberry pi

Source Code

The full source for this OLED display interfacing with a Raspberry Pi project can be found on github at : https://github.com/kjhughes097/pi-ssd1306-oled
This separates out the functionality into a ‘SSD1306’ class that you can use in other apps. It also separates the character mapping header (charmap.h) out so that it is easy to add additional characters (you could try adding lowercase letters ?).
The ‘sample’ app, display-a.cpp is self contained and shows the basic use of I2C to send data to the display. The other ‘sample’ app, oled.cpp shows how to use the class. The makefile will compile the oled app – at the command line simply type


Hope this has been useful. Please leave a comment below if you thought so.

Another Raspberry Pi Zero Case

So, it was time to buy another Raspberry Pi Zero Case, as I’m now onto my third one of these amazing little devices. I had intended to buy another of the cases that I purchased for my first one. At the last minute I decide I should probably go for a bit of variety and choose a different one.

After a little searching around on Amazon and eBay, I settled on one of the modular laser cut acrylic style cases – £3.47 with free delivery. It arrived in a couple of days in a thin envelope.
There was a ~3mm thick piece of acrylic about 70mm wide by 200mm long, taped to a piece of card to hold it all together. From this the shape of each layer had been cut.


Snapping all the layers out and peeling the protective film off was a simple task. There are 4 layers plus an (optional) couple of super thin bits for some support.  You put the bottom 2 layers together then the Pi Zero, then (optionally the 2 super thin bit – I used the stand-offs instead) and then choose between the 2 top pieces. One designed for covering in the GPIO header (no pins soldered) and the other exposing the GPIO header. There are also 4 nuts/bolts provided to secure the whole thing together with the Pi Zero sandwiched in the middle.

The case looks good, is very functional and has easy access to all the ports, SD card and camera connector. There are a few little (tiny) blemishes on one of the parts, but they are hardly noticeable. The whole thing feels very secure and there is no movement, nor any undue pressure on the device.

All in all, a decent Raspberry Pi Zero Case. Here are some pics of the assembled unit.


Setup OTG Networking on a Pi Zero

It is possible to get the micro USB ‘OTG’ port on the Pi Zero configured for networking. After a couple of bits of configuration you can simply plug a cable between your PC / Laptop and the Pi Zero USB data port, it automatically creates a network between them and you can then SSH to your Pi Zero.

To enable this you’ll need the following line added to your /boot/config.txt file:


… and the following text added to your /boot/cmdline.txt (be sure to keep only space between each param and no newlines) after the  rootwait parameter:


That should be it complete. Reboot the Pi Zero and check it out.
NOTE: This will only work on a Pi Zero, none of the other versions support it.

Thanks to Andrew Mulholland for the pointers.

Raspberry Pi Zero Case

I thought it was about time I invested in a Raspberry Pi Zero Case. I had been using all my Pi Zeros ‘naked’ for several weeks with no problems, but you never know if they’ll touch a metal surface or object and short out.

Browsing around there are a lot of really nice looking wooden cases. I liked this one and this one with connector names etched into it. Maybe I’ll get one of those for use as my ‘clean’ Raspberry Pi Zero Case. In the meantime I opted for this clear plastic one. Functional and a touch less costly than the wooden ones. Only £3.99 with free delivery – bargain.


When it arrived it looked a bit bulky, but that was because it comes with 2 top sections. One top section is completely closed in on top with no access to the GPIO ports. The other top section has the GPIO ports open and accessible. The picture shows the one with the ports accessible.
This case also comes in White and Black, but I found both those colours to be a bit plain for my liking.

The Modification

There was also a very minor issue with the new v1.3 camera connector and this case. The cover for the camera connector sticks out a fraction of a millimetre over the side of the Pi Zero. This prevent the Pi Zero from fitting correctly into the bottom section of the case. A sharp knife and about 30 seconds work saw me cut a little section of the side lip. This allowed the Pi Zero to fit perfectly.
You can’t see from the pictures below but it only protrudes into the inside lip. When the top cover is on that still encases the camera connector, so it’s not sticking out the side in any way.


I’m now sporting a device housed safely in this really cool Raspberry Pi Zero Case. I’m also thinking of buying a couple more of these.

Raspberry Pi Zero USB Hub Hack

As much as we all love the Pi Zero, the connectivity options are very limited. With only one (micro) USB port (for peripherals) it means you need a micro <=> ‘normal’ USB adapter to get any of the usual accessories (keyboard, Wi-Fi dongle etc.) plugged in, and when you have that’s it – nothing else can be plugged in. Also, those little USB adapters just look a little bit to precarious for my liking. So, what I needed was a ‘Raspberry Pi Zero USB Hub Hack’.

I’d seen that the USB power and data lines are presented as pads on the board itself. I wasn’t alone in noticing this, and seemingly a bunch of people had success soldering on USB hubs directly. So I though I’d give it a go. I bought myself this little ‘no name’ 4 port USB2 hub from eBay for the princely sum of £2.09 (including delivery) – how they make any profit on these is beyond me.


As soon as it arrived, I pulled the case apart exposing the board itself and cut the USB cable off. (NOTE: I probably should have tested it on the laptop, or Pi first, but I was a bit too eager).


A simple soldering job had the 4 individual cables soldered to their respective pads on the Pi Zero. It wasn’t a great success to start with, as it was ‘hit and miss’ whether it showed up on the Pi after booting.


I guessed that it was likely that not enough power was being delivered, to the hub, by the super thin cables. I decided to remove those completely and replace themwith some thicker cable to make sure there was enough power to the hub. I also used some thicker signal wire for the Data + and –.


However, now it never showed up, not even for a short time.



It looked like it was recognising that a hub was plugged in, but it saw it as a ‘new low-speed USB device’. The seller on eBay had advertised this as a high-speed hub, so the ‘low-speed’ was odd. I would also get a lot of ‘device descriptor read/64, error -71’ errors in dmesg when the hub did not show up.

dmesg | grep usb


Googling around suggested trying out a bunch of dwc_otg settings in cmdline.txt, but none of those seemed to work. I also switched it to low speed (dwc_otg.speed=1) and that didn’t help. I knew all the connects were good and there were not shorts, so I began to think I had killed the IC on the hub somehow.
A last ditch attempt was to swap around the Data + – wires. I didn’t expect this to work as it was being ‘seen’ by the Pi, just not working. I figured, how could it ‘see’ the hub without being able to read ‘something’ from it). WRONG….

Swapping round the Data + – wires brought it to life, every time I powered on the Pi. Excellent. So now a little tidying things up, getting some anti-static foam between the boards and squishing them together with and elastic band (temporary) got me to the finish line.



dmesg | grep usb


Here are some pictures of the finished Raspberry Pi Zero USB Hack project (although it still needs tidying and a case etc.)…


Next up is to replace one of the hub ports with a directly soldered Wi-Fi dongle. Watch this space…

Raspberry Pi Music Player Project–Stage 1

I had a couple of hours free this evening, and so began to do work on the first stage of the Raspberry Pi Music Player project. This was mostly the modifications to the plastic power tool case which is going to serve as the ‘enclosure’ for the Music Player project.
Here’s a few pictures of the work…

First thing to do was to cut out a template for the speakers to make the marking easier.

raspberry pi music player - template drawing 1raspberry pi music player - template drawing 2

I then used that template to mark out where I needed to cut on the plastic box. I used the Dremel (fantastic piece of kit) to drill round the edge of the speaker hole.

raspberry pi music player - cutting 1raspberry pi music player - cutting 2

The speaker was a good snug fit, with none of the rough edges showing. This probably needs a little tidying up of that edge up before the final version.

raspberry pi music player - speaker fitting

Same again for the second speaker. Next, I started on a hole for the On/Off switch which I wanted on the side of the box. This is a green, 12v rocker switch that illuminates when on.

raspberry pi music player - switch 1raspberry pi music player - switch 2

With that done, I moved on to a few internal cuts to make sure there was room for the Pi (Model B+). The stereo amplifier board needed some holes drilled in the case to mount it in. That was pretty much the first stage complete. Looks quite neat so far.

raspberry pi music player - cutting complete

Next, will be the internal wiring and setting up the software for the Raspberry Pi Music Player. For this I’ll be using MPD. Watch this space for the next update…

Update (Sept 2016): The full project write up can be found here.

5 Essential Raspberry Pi Accessories To Buy Today

Got yourself a Raspberry Pi ? Here’s our list of the 5 essential Raspberry Pi Accessories you’ll need to make the most of your Pi. This list covers official, cheapest, most useful and some ‘advanced (DIY)’ accessories.


Raspberry Pi Accessories : Power To The Pi

The first thing you’ll need is some way of powering it, and the big decision is ‘fixed’ or ‘portable’. If you plan to leave your Pi in one location then you’ll want to go for a plug in charger style. If you think you’ll be moving it around, using it outside, using it for mobile projects then you’ll want some kind of portable supply.

  • The official Raspberry Pi power supply can be found on the element14 website here, and the RS Components website here.
  • Any cheap micro USB charger that supplies 1-2 amps should work fine. You might even get away with plugging it in to your laptop or desktop.
  • I recommend this version from Anker on Amazon – they also provide great customer service and really well made products.
  • For portable power, again any portable battery for charging phones will do (with ‘fast charge’)
  • I recommend, and use this 20000mAh pack, again from Anker. This gives me over 20 hours of continuous use, and I can charge my phone at the same time.
  • On the more costly side, if you want to work through power interruptions there is this add-on board. This acts as an Uninterruptable Power Supply (UPS).
  • For the more adventurous, there are opportunities to build your own UPS. Adafruit has many parts and batteries available that can be used to build your own.  Check out this video of someone that’s done just that.

Raspberry Pi Accessories : Project Wi-Fi

You might be lucky enough to have your workshop, or home fully wired with Cat5 network sockets in every room. Or plan to just have you Pi in a single location with cabled access, but if not then you’ll probably need Wi-Fi access. Of course, if you have a Pi 3 then you have Wi-Fi built in and your good to go. For those that do need Wi-Fi here’s some options:

Raspberry Pi Accessories : Keyboard (and Mouse) Bashing

If you’re using your Pi as a desktop machine, or you need some initial setup and configuration done manually then you’ll need a Keyboard and Mouse. I have moved completely to wireless keyboard and mouse combos for all my workstations. This has the benefit of only requiring a single USB port (for the dongle). I also find it generally helps not having cables getting tangled everywhere.

Raspberry Pi Accessories : Breadboard

If you’re into more than just software projects on your Pi, then you will want to connect to the ‘physical world’. For that you will likely need a breadboard. This is a board that you can use to prototype electronic circuits without having to solder. A breadboard makes it possible to interface devices and sensors, connect LEDs and the like. Breadboards come in various sizes but are all pretty similar in their function.

Raspberry Pi Accessories : Packing Your Case

Last but not least on our list is a case.  You will want to protect your Pi for short circuits, grubby fingers, and all manner of other dangers. So you will need a decent case. Cardboard, or 3D printing can be used to make cases. You can also cut the plastic box, the Pi is delivered in, into a case. There are lots of tutorials for all of these. Those are great, but I recommend getting a proper case. This is very much a thing of personal preference. Listed below are some cool cases that you might consider.


There you go, the 5 essential Raspberry Pi Accessories you need for your Raspberry Pi. Of course there are a lot of other neat add-on items that can improve your experience further, but those are for another post…


Did I miss anything ? let me know in the comments below, or feel free to include your favourite ‘must have’ items.

Raspberry Pi Versions

To date (July 2016), there have been 8 versions of the Raspberry Pi. Below is an outline of each.

Raspberry Pi Model A


The Model A sported the ARMv6 architecture (700MHz, single core ARM11) with a Broadcom BCM2835 SoC. It had 256MB of RAM and a 26 pin version of the header. Power was provided by the micro USB connector, video by the HDMI connector (supporting HDMI v1.3), a single USB port, composite video out RCA jack and a 3.5mm audio out connector. There is also a slot for a camera module and on board storage was via a slot for a full size SD Card. There was no Ethernet (RJ45) port on this model.




Raspberry Pi Model B


The Model B also used the same ARMv6 architecture (700MHz, single core ARM11) with a Broadcom BCM2835 SoC as the Model A. It had increased memory to 512MB of RAM. The header is the same 26 pins as the Model A, but it had an additional 4 GPIO pins available via the P5 header (if you user was willing to solder the pins). HDMI, composite video, audio and SD card slot all remain the same, but the USB ports are increased to 2 and there is now a Ethernet (RJ45) connector on-board also.




Raspberry Pi Compute Module


The Compute Module is a full system on a device with only a 200 pin DDR2 SO-DIMM. This uses the same ARMv6 architecture (700MHz, single core ARM11) with a Broadcom BCM2835 SoC as the Model A and B, has 512MB RAM on-board as well as an on-board 4GB eMMC flash chip for storage. There are no on-board ports, but all the usual inputs and outputs (and more) are exposed as pins on the 200 SO-DIMM connector.





The Model B+ sported the same ARMv6 architecture (700MHz, single core ARM11) with a Broadcom BCM2835 SoC as the Model A and B. It had the increased memory of 512MB of RAM same as the Model B. Now has a 40 pin version of the header which exposed 9 more GPIO pins and support for the HAT ID bus. It now has 4 on-board USB ports, and the composite video out (RCA) plug had been removed and the composite video combined with the audio out in the 3.5 jack . There is also a slot for a camera module and on board storage was via a smaller slot for a micro size SD Card. There was an on-board Ethernet (RJ45) port on this model. Power consumption has been improved as has audio quality.




Raspberry Pi Model A+


The Model A+ sported the same ARMv6 architecture (700MHz, single core ARM11) with a Broadcom BCM2835 SoC as the Model A and B. It had the increased memory of 512MB of RAM same as the Model B, the same 40 pin version of the header as the Model B (exposing 9 more GPIO pins and support for the HAT ID bus). It retains the single USB port of the Model A, and the composite video out (RCA) plug had been removed and the composite video combined with the audio out in the 3.5 jack . There is also a slot for a camera module and on board storage was via a smaller slot for a micro size SD Card. There was no still Ethernet (RJ45) port on this model. Power consumption has been improved as has audio quality.




Raspberry Pi 2 (Model B)


The second generation of the Model B moves to the ARMv7 architecture, using a quad core, 900MHz Cortex-A7 CPU and the Broadcom BCM2836 SoC. The memory is increased to 1GB, but all other hardware remains the same as the Model B+.




Raspberry Pi Zero


The Raspberry Pi Zero,  which has a smaller footprint and less connectivity, is based on ARMv6 architecture for the original Model A and Model B, using 1GHz single core ARM11 device and the original Broadcom 2835 SoC. It had only 1 micro USB port (OTG mode) and a mini HDMI connector for video and audio. Additional (composite) video and audio are available via GPIO pins. A micro SD card slot is available for storage and by default the GPIO 40 pin connector is unpopulated.




Raspberry Pi 3 (Model B)


The third generation of the Model B sees a move to the ARMv8 architecture, using a quad core, 1.2GHz 64 bit Cortex-A53 CPU and the Broadcom BCM2837 SoC. The memory stays at 1GB, and all other connectors and ports remains the same as the Pi 2 and Model B+. In addition, wireless networking (802.11n) and Bluetooth (4.1, BLE) are added.