ESP8266 Built-in OLED – Heltec WiFi Kit 8


A  set-up guide for the Heltec WiFi Kit 8 development board (an ESP8266 with built-in OLED display).

Follow the easy steps below to get up and running with this board using standard Arduino libraries.

This board is based on the ESP8266 chip and has onboard WiFi,  a 0.96inch 128*32 OLED display, lithium battery connector charging and a CP2014 USB to serial interface. It also works with the Arduino IDE! I bought mine from here: but it’s also available on eBay and Amazon.

Setting Up the Arduino IDE for the ESP8266 Range

The ESP8266 boards are much easier to set up in the Arduino IDE than the ESP32 range. If you don’t already have it installed, download and install the IDE from here: (don’t use the Web version).

In the IDE, open the File Menu and choose Preferences and enter into the Additional Board Manager URLs field.

Add ESP 8266 Library

Open the Boards Manager from Tools > Board:xxxxx menu

Board Manager

Find esp8266 by ESP8266 Community in the list and click Install

Hardware Library

The ESP8266 Hardware Libraries are now installed and you can test your new board with a simple Sketch.

Testing the WiFi is Functioning

In the Arduino IDE, in the Tools > Board menu choose NodeMCU 1.0 (ESP-12E Module)

Select Nodemcu

Select the port (It might not be COM4)

Select Port

You can now upload Sketches to the board. A good test is use the example WiFiScan sketch.

Open File> Examples > ESP8266WiFi > WifiScan and upload the sketch.

If you open the Serial Monitor (Tools > Serial Monitor) you will be able to see any WiFi access points in range. Check the baud rate is the same as in the sketch – probably 115200.

WiFi Scan Example


Displaying data on the WiFi Kit 8 OLED

You should be able to use any SSD1306 library for the OLED. I prefer the U8g2 ( library. It can be installed using the Arduino IDE library manager. Open Sketch > Include Library > Manage Libraries and search for and then install U8g2.

U8g2 has three different display methods. To test the board we are using the Full Buffer method. Open the example Sketch:  File> Examples > U8g2 > full_buffer > GraphicsTest

In the code for this Sketch, paste:
U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ 16, /* clock=*/ 5, /* data=*/ 4);
or the slower software driver version: U8G2_SSD1306_128X32_UNIVISION_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ 5, /* data=*/ 4, /* reset=*/ 16);
Above this line: // Please UNCOMMENT one of the contructor lines below
Upload the sketch. You should see some different graphics appearing on the screen. Don’t worry that they are cut off, this example sketch is designed for different size screens.

If this doesn’t work you might have a different version of the board. Try pasting the following:
U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ 4, /* clock=*/ 14, /* data=*/ 2);
or the slower software driver version: U8G2_SSD1306_128X32_UNIVISION_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ 14, /* data=*/ 2, /* reset=*/ 4);

Displaying a Scrolling Message on the OLED

Displaying a scrolling message can be a little tricky due to hardware and font limitations. The following sketch (based on the U8g2 ScrollingText example) will horizontally scroll a short piece of text.

#include <U8g2lib.h>

//U8g2 Contructor
U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ 16, /* clock=*/ 5, /* data=*/ 4);
// Alternative board version. Uncomment if above doesn't work.
// U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ 4, /* clock=*/ 14, /* data=*/ 2);

u8g2_uint_t offset;     // current offset for the scrolling text
u8g2_uint_t width;      // pixel width of the scrolling text (must be lesser than 128 unless U8G2_16BIT is defined
const char *text = "ROB01 "; // scroll this text from right to left

void setup(void) {

  u8g2.setFont(u8g2_font_logisoso32_tf); // set the target font to calculate the pixel width
  width = u8g2.getUTF8Width(text);    // calculate the pixel width of the text

  u8g2.setFontMode(0);    // enable transparent mode, which is faster

void loop(void) {
  u8g2_uint_t x;

  do {

    // draw the scrolling text at current offset
    x = offset;
    u8g2.setFont(u8g2_font_logisoso32_tf);   // set the target font
    do {                // repeated drawing of the scrolling text...
      u8g2.drawUTF8(x, 32, text);     // draw the scolling text
      x += width;           // add the pixel width of the scrolling text
    } while ( x < u8g2.getDisplayWidth() );   // draw again until the complete display is filled

    u8g2.setFont(u8g2_font_logisoso32_tf);   // draw the current pixel width
    u8g2.setCursor(0, 64);
    u8g2.print(width);          // this value must be lesser than 128 unless U8G2_16BIT is set

  } while ( u8g2.nextPage() );

  offset -= 1;            // scroll by one pixel
  if ( (u8g2_uint_t)offset < (u8g2_uint_t) - width )
    offset = 0;             // start over again

If you want to scroll a longer piece of text you have to edit one of the display library files to allow 16bit mode.

Open the file /libraries/U8g2_Arduino/src/clib/u8g2.h and uncomment this line:
// #define U8G2_16BIT

Save the file and you can now use longer text by replacing this line:
const char *text = “ROB01 “; // scroll this text from right to left
with (for example):
const char *text = “ROBOTZERO.ONE “; // scroll this text from right to left

You’ll then see something like the animation below:

Bonus tip! You can make the animation smoother by boosting the CPU speed to 160Mhz for the uploaded Sketch:

CPU Frequency

Further Information

More detailed information about pins and the two board versions:
Reference for the display library, including custom fonts etc:
ESP32 version setup:
Heltec on Github:


22 Replies to “ESP8266 Built-in OLED – Heltec WiFi Kit 8”

  1. William MOORE says:

    Love this guide thanks! but I’m stuck at no port selectable. I’ve picked out the exact board stated, and port remains dimmed sadly! No reaction from windows 10 when plugged in yet the board happily displays a hello world sketch from factory.. I notice in the manual for this which is in Chinese lol.. the board is selected as wifi_kit_32 ?? With a dead link to I presume a zip file of drivers :/ (installed cp210 and rebooted before all this btw – doesn’t show in DM at all)

    1. WordBot says:

      Is it the Kit 8 or the 32 you have?

      Kit 8 looks like this in my Device Manager…

      Can you see anything with question marks in Device Manager?

      1. William MOORE says:

        Kit 8 printed on board.
        Problem was my side. I got so fed up I backed all my stuff up to the NAS and reset the entire PC! lol
        -Installed the CP210 drivers again from another page – that I didn’t know I needed in win10 reading this guide,
        and hey presto. Though I might add I get a menu of examples just for this Node. (you suggest using examples/wifi/wifi scan -not there for me.)

        Got it going through the examples/examples for nodeMCU 1 etc/esp8266wifi/wifiscan
        and your graphics example. This was no plain sail but thanks for some pointers.
        The simplest of sketches takes up to 2-3 mins to compile and upload, that surprised me I thought it would be quicker.

        1. WordBot says:

          Where did you get the CP210 drivers? I had to install this for the ESP32 version of this board to work. I might need to add that to the instructions. I thought I’d created this on a fresh Win10 install but maybe not.

          I’ve corrected the WiFi Scan menu path in the article to the correct path as you’ve written.

          I think they take a long time as the ESP8266 is much more complicated that the original Arduino boards so the libraries etc are much larger so take a while to compile and upload.

          1. krishnan says:

            For a Macbook I had to install the vintage VCP driver to get the board recognised and the serial to show up.
            When you double click the dmg, one also sees a “Vintage” folder. Inside there is another dmg. I installed that dmg that to get my serial port recognised on the Macbook . This works for the heltec and also for the AMICA NodeMCU (12E ), since both have the CP210x UART. Hope this helps

          2. WordBot says:

            Cool. Thanks for the tip.

  2. Redbeard says:

    Hi, Thanks for the write up. Do you know what kind of JST cable fits this particular unit? I’m looking to get a Lithium battery for it, but I don’t know what kind to get.

    1. WordBot says:

      Maybe JST 1.25 mm 2 pin? The LiPo connector I have doesn’t fit. Make sure you use batteries with the built in protection circuit as I don’t know how well the charging circuit on this device manages over charging or discharging. Something I need to investigate.

  3. Pavel says:

    I believe, the right mating connector is Hirose DF13-2S-1.25C. yes, it is 1.25mm. Didn’t find them available wired. Molex Micro JST 1.25 mm picoblade also fits in, although the fit is a bit loose.

  4. J3QQ4 says:

    What pins should i connect MAX6675 to work simultaneously with the screen? I’ve tried smth like this with a huge number of variants on delays, pins order, connecting to the D1-D8-D6 or D5 (14) – D8-D6 or even D1 – D7-D6, lots of libraries, but nothing worked correct.

    #ifdef U8X8_HAVE_HW_SPI
    #ifdef U8X8_HAVE_HW_I2C

    MAX6675_Thermocouple thermocouple(D1, D8, D6);
    U8G2_SSD1306_128X32_UNIVISION_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ 5, /* data=*/ 4, /* reset=*/ 16);

    void u8g2_prepare(void) {

    void setup(void) {

    void loop(void) {
    u8g2.drawStr( 0, 0, “TEST PE4”);

    String stringVar = String(thermocouple.readCelsius());
    char temp[20];
    stringVar.toCharArray(temp, 20);
    u8g2.drawStr( 0, 10, temp);

    I have either random values or just zero 🙁 Maybe the problem is about SPI , but i don’t have much experience to solve this . Can someone help?

    1. WordBot says:

      If your device is plugged into D0 to D7 then this script should find it. Run it first with nothing plugged into the 8266..

      EDIT: Sorry – you have an SPI based device so I’m not sure how to test it.

  5. Miguel Salinas says:

    Great tutorial, you have I’m trying to use the SSD1306 from Do you ghow to use it?, because the demo examples and they not show anything.

    1. WordBot says:

      Hi. That library is for the 128×64 version so it might not work with this display as it’s 128×32, Looking briefly at the instructions one of the following might work…
      SSD1306Wire display(0x3c, 4, 5);
      SSD1306Wire display(0x3c, 2, 14);

  6. AllTheKingsMen says:

    Does anyone know if the battery LED can be disabled? With no battery connected it just keeps blinking and driving me insane.

  7. Bill Knight says:

    As an FYI, if you have version A of the board (SDA on 4 & SCL 0n 5) the following HW driver will update the display faster that the SW driver.

    U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C display(U8G2_R0, DSP_RST, DSP_SCL, DSP_SDA);

    Note: The order of the pins is different from the SW driver.

    1. WordBot says:

      Ah, thanks for the information…

      U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ 16, /* clock=*/ 5, /* data=*/ 4);

      is much faster. I’ve updated the tutorial.

  8. zack says:

    I’m a noob to esp8266. Can anyone tell me how I could get a message to appear on the OLED when the wifi has connected?

  9. Pasi says:

    If reset is in pin16, does this mean that you can not use I2C, because I2C SDA is in pin16 ?

    1. WordBot says:

      I have version 1 of the board with SDA on GPIO4 and SCL on GPIO5. I tested it with a Si7021 using the sketch below and it works fine.

      #include <Adafruit_Si7021.h>
      #include <U8g2lib.h>
      U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ 16, /* clock=*/ 5, /* data=*/ 4);

      Adafruit_Si7021 sensor = Adafruit_Si7021();

      void setup(void) {

      void loop(void) {

      float temp = sensor.readTemperature();
      float humid = sensor.readHumidity();

      do {

      u8g2.drawStr(0, 32, “T: “);

      u8g2.setCursor(18, 32);
      u8g2.print(temp, 0);

      u8g2.drawStr(64, 32, “H: “);

      u8g2.setCursor(84, 32);
      u8g2.print(humid, 0);

      } while ( u8g2.nextPage() );

      Pin info:

      The screen uses the same i2c connections so you might see a conflict depending on the device you use.

      Si7021 library info:

  10. Jeff says:

    I have the TTGO (version A) board that I got on AliExpress. Works great except for one thing: If I upload from my laptop, it works. If I unplug & replug the USB, it does not run until I hit the reset button. While not running, the serial monitor shows an endless stream of
    Fatal exception (0):
    epc1=0x40100000, epc2=0x00000000, epc3=0x00000000, excvaddr=0x00000000, depc=0x00000000
    at the bootloader speed of 74880bd.
    Very strange. Works after reset but not without a reset.
    Anyone ever seen this?

    1. Jason Lewis says:

      Hi Jeff,
      Yes! I had exactly the same issue with that board from AliExpress. Fix was found here:

      Basically you have to remove the resister above the 2 caps above d6 when looking at the underside of the board, and then bridge the pads where the resistor was with solder.

  11. Jason says:

    Thanks for this tutorial. I tried lots of other libraries with the Heltec NodeMCU with OLED built in. None worked and I was ready to give up – your guide and the U8g2 library worked perfectly for me. Great work!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

scroll to top