Jul 21

OLED 128x64 on NodeMCU - ESP8266

Category: Design,electronics   — Published by goeszen on July 21, 2017 at 3:12 pm

Here's a little how-to and example script to demonstrate the connection of a cheap 0,96" 128x64 pixel OLED display (4-pin i2c bus, SDD1306 controller) to an NodeMCU ESP8266 development board.

Hardware layout:

We have pins D1 connected to the displays SDA connector, and NodeMCU's pin D2 to SCL, Ground to Ground and VCC to 3V3 - the normal i2c connection.


We're basically drawing a frame here, around the full size of the display, then, on each frame, we're shrinking the dimensions of this frame by a pixel - generation a little animation.

The OLED is controlled by an SSD1306 and we're using the u8glib library to drive it. In my older firmware I'm using here, it's already included.

-- OLED animated frame demo
-- a 4 pin I2C OLED 128x64 ssd1306 display module
-- connected to a NodeMCU ESP8266 dev board

-- declare vars
--   board's 3v3 connected to oled's VCC
--   boards' GND connected to oled's GND
sda = 1 -- oled's SDA pin connected to board Pin 1
scl = 2 -- olde's SCL Pin connected to board Pin 2

frame_x = 0
frame_y = 0

function init_OLED(sda,scl) --Set up the u8glib lib
     sla = 0x3C
     i2c.setup(0, sda, scl, i2c.SLOW)
     disp = u8g.ssd1306_128x64_i2c(sla)
     disp:setRot180()           -- Rotate Display if needed (we do)

function write_OLED() -- Write Display

     -- shrink the drawn frame on every iteration towards center
     disp:drawFrame(frame_x, frame_y, 128-(frame_x*2), 64-(frame_y*2))

     disp:drawStr(30, 27, "goeszen.com")	-- center text on screen, more or less
   until disp:nextPage() == false

-- Main Program

tmr.alarm(0, 300, 1, function() -- 700ms between frames
	-- NOTE: It is important to lower frame rates (ms between timer-triggered frame refreshes)
	-- not too far! If you go below the time it takes to push the data over i2c (NodeMCU only
	-- supports speed "SLOW"), you will trigger a crash!
	-- (the maximum is somewhere between 200 and 300ms, btw...)
   frame_x = frame_x + 1
   frame_y = frame_y + 1

   if frame_x > 23 then -- the 23 is an arbitrary number, it's where the frame is slightly larger than the text
	frame_x = 0
	frame_y = 0

An interesting detail is the maximum frame-rate achievable on this display via i2c. I've tracked the maximum down to be between 200 and 300 milliseconds in-between display refreshes. As I understand it, that's the time it takes to push the data over the i2c bus + some ms. If you go lovwer than that, with your timer triggering, you crash the board.

The i2c speed is a NodeMCU limitation. Compare the docs to find out that the only mode NodeMCU supports is "SLOW". Changing the CPU frequency to 160, via node.setcpufreq(node.CPU160MHZ), won't help. Markus has managed to get higher frame-rates, but only by hacking the underlying library and removing some hard-coded slow-downs.

I'm tinkering here with a NodeMCU ESP8266 board.
I'm using the ESP8266 Java IDE ESPlorer.
The firmware is version 0.9.6 build 20150704 powered by Lua 5.1.4

Leave a Reply