Thursday, 22 January 2015

Arduino - OLED Module with 3D demo sketch

Arduino Uno compatible OLED 128x64

Recently I bought a small OLED 128x64 screen module for use with my Arduino Uno. The module I chose was based upon a few key requirements. The module had to be cheap, under (£5 GPB), 128x64 screen resolution, work within 3-5volts , I2C compatible, minimum 4 wire setup and not require additional electrical components to get up and running. The module I eventually bought was a Chinese import from Amazon UK.

The module is manufactured by Heltec (
0.96 Inch I2C IIC SPI Serial 128 x 64 OLED LCD LED

Wiring the OLED module

The Arduino has two sets of pins allocated to I2C communication.Arduino boards with the R3 layout (1.0 pinout), the SDA (data line) and SCL (clock line) are on the pin headers close to the AREF pin. I used the alternative pins A4 (SDA), A5 (SCL) only to keep the wiring together.

OLED - Arduino Uno
VCC ---> 5V
GND ---> GND
SCL ---> Pin A5
SDA ---> Pin A4

U8G library for graphics

I chose to use the U8GLib library for all necessary graphics functions. The U8GLib examples have lists of Constructors (device drivers) embedded into the code, so matching the module to an appropriate driver was easy. (I initially tried using the Adafruit libraries but had problems getting images to show on the screen).

The library can be downloaded here:


1.  Copy the U8G files to an appropriate Arduino Library folder e.g. 
C:\Program Files\Arduino\libraries\U8glib\
2.  Launch the Arduino application
3.  Copy the 3d wireframe code below into a new sketch.
4.  Upload the sketch to the Arduino and enjoy the spinning 3D cube!

Compilation using the U8G library usually takes a while, so be patient!

Arduino sketch

//3D_Cube for Arduino OLED module by Colin Ord, 9/1/2015
//A port of my original JustBasic Cube_3D demo to the Arduino Uno using U8G library.

#include "U8glib.h"

//The following line will need changing depending on your board type!
U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_DEV_0 | U8G_I2C_OPT_FAST); // Dev 0, Fast I2C / TWI

float tx, nx, p;
float ty, ny, py;
float rot, rotx, roty, rotz, rotxx, rotyy, rotzz, rotxxx, rotyyy, rotzzz;
int i; //0 to 360
int fl, scale; //focal length
int wireframe[12][2];

int originx = 64;
int originy = 32; //32

int front_depth = 20;
int back_depth = -20;

//Store cube vertices
int cube_vertex[8][3] = {
{ -20, -20, front_depth},
{20, -20, front_depth},
{20, 20, front_depth},
{ -20, 20, front_depth},
{ -20, -20, back_depth},
{20, -20, back_depth},
{20, 20, back_depth},
{ -20, 20, back_depth}

int fd = 0; //0=orthographic

void setup(void)

//Clear Screen
do {
// empty screen
} while ( u8g.nextPage() );

void draw_vertices(void)
u8g.drawPixel (rotxxx, rotyyy);

void draw_wireframe(void)
u8g.drawLine(wireframe[0][0], wireframe[0][1], wireframe[1][0], wireframe[1][1]);
u8g.drawLine(wireframe[1][0], wireframe[1][1], wireframe[2][0], wireframe[2][1]);
u8g.drawLine(wireframe[2][0], wireframe[2][1], wireframe[3][0], wireframe[3][1]);
u8g.drawLine(wireframe[3][0], wireframe[3][1], wireframe[0][0], wireframe[0][1]);

//cross face above
u8g.drawLine(wireframe[1][0], wireframe[1][1], wireframe[3][0], wireframe[3][1]);
u8g.drawLine(wireframe[0][0], wireframe[0][1], wireframe[2][0], wireframe[2][1]);

u8g.drawLine(wireframe[4][0], wireframe[4][1], wireframe[5][0], wireframe[5][1]);
u8g.drawLine(wireframe[5][0], wireframe[5][1], wireframe[6][0], wireframe[6][1]);
u8g.drawLine(wireframe[6][0], wireframe[6][1], wireframe[7][0], wireframe[7][1]);
u8g.drawLine(wireframe[7][0], wireframe[7][1], wireframe[4][0], wireframe[4][1]);

u8g.drawLine(wireframe[0][0], wireframe[0][1], wireframe[4][0], wireframe[4][1]);
u8g.drawLine(wireframe[1][0], wireframe[1][1], wireframe[5][0], wireframe[5][1]);
u8g.drawLine(wireframe[2][0], wireframe[2][1], wireframe[6][0], wireframe[6][1]);
u8g.drawLine(wireframe[3][0], wireframe[3][1], wireframe[7][0], wireframe[7][1]);

void loop(void)
//picture loop
for (int angle = 0; angle <= 360; angle = angle + 3) {
do {
for (int i = 0; i < 8; i++) {

rot = angle * 0.0174532; //0.0174532 = one degree
rotz = cube_vertex[i][2] * cos(rot) - cube_vertex[i][0] * sin(rot);
rotx = cube_vertex[i][2] * sin(rot) + cube_vertex[i][0] * cos(rot);
roty = cube_vertex[i][1];
rotyy = roty * cos(rot) - rotz * sin(rot);
rotzz = roty * sin(rot) + rotz * cos(rot);
rotxx = rotx;
rotxxx = rotxx * cos(rot) - rotyy * sin(rot);
rotyyy = rotxx * sin(rot) + rotyy * cos(rot);
rotzzz = rotzz;

//orthographic projection
rotxxx = rotxxx + originx;
rotyyy = rotyyy + originy;

//store new vertices values for wireframe drawing
wireframe[i][0] = rotxxx;
wireframe[i][1] = rotyyy;
wireframe[i][2] = rotzzz;



} while (u8g.nextPage());