Skip to content
Fromlu Editorial

How to connect a 1.54 inch 128x64 OLED display to Arduino?

To connect a 1.54 inch 128x64 OLED display to an Arduino, you need to use the SPI interface, which is the most common and fastest method for this display, requiring four wires besides power and ground. This specific OLED module, typically based on the SSD1309 or SH1106 driver, operates at 3.3V logic levels but can be powered by 5V from the Arduino if you include a level shifter or voltage divider for the data lines. The pinout standard for this display includes: GND (ground), VCC (3.3V or 5V depending on module), D0 (SCK/clock), D1 (MOSI/data), RES (reset), DC (data/command), and CS (chip select). On an Arduino Uno, you would connect these to the hardware SPI pins: D0 to pin 13 (SCK), D1 to pin 11 (MOSI), RES to any digital pin like pin 9, DC to pin 8, and CS to pin 10. Power the display with 3.3V from the Arduino’s 3.3V output, or use a 5V to 3.3V regulator if your module strictly requires 3.3V. The I2C variant exists but is slower and uses only two wires; however, for a 128x64 resolution with 1.54 inch diagonal, SPI is preferred for faster refresh rates, especially when rendering animations or sensor data. This display has a resolution of 128 pixels horizontally and 64 pixels vertically, with each pixel individually addressable, and the OLED technology means no backlight, high contrast (over 10000:1), and wide viewing angles up to 160 degrees. The typical power consumption is around 20mA at full brightness, but you can reduce it to below 1mA by turning off the display or using sleep mode.

Hardware Wiring and Pin Configuration

For a reliable connection, you must understand the exact pin functions. The 1.54 inch 128x64 oled display module from most manufacturers uses a 7-pin header (if SPI) or 4-pin (if I2C). The SPI version has these pins: GND, VCC, D0, D1, RES, DC, CS. Some modules label D0 as SCK and D1 as MOSI. On an Arduino Uno, the hardware SPI pins are fixed: SCK on pin 13, MOSI on pin 11, and MISO on pin 12 (not used for OLED). The CS pin is typically connected to pin 10, but you can use any digital pin as long as you set it low in software. The DC pin determines whether the data sent is a command or display data; connect it to pin 8 or any other digital pin. The RES pin is for resetting the display; connect it to pin 9. If you use a 5V Arduino, the OLED’s logic pins (D0, D1, RES, DC, CS) are 3.3V tolerant, but applying 5V directly can damage the driver IC. Therefore, you should use a voltage divider on each signal line: a 1k ohm resistor in series and a 2k ohm resistor to ground, giving a 3.3V output from a 5V source. Alternatively, use a 3.3V regulator like the AMS1117-3.3 to power the display and shift the data lines with a 74HCT125 buffer. The VCC pin can accept 3.3V to 5V on some modules, but check the datasheet; if it says 3.3V only, never exceed it. The GND pin must connect to the Arduino’s ground, and keep the wires as short as possible (under 20cm) to avoid signal noise, especially if you are running SPI at 8 MHz or higher. When using a breadboard, use a separate power rail for the OLED and add a 10uF capacitor between VCC and GND near the display to filter power spikes.

Software Libraries and Initialization

To drive the display, you need an appropriate library. The most common is the Adafruit SSD1306 library, which supports SSD1306 and SH1106 drivers. However, some 1.54 inch 128x64 OLEDs use the SSD1309 driver, which is compatible with the same library if you set the correct initialization sequence. Another option is the U8g2 library, which supports over 1000 displays and offers more flexibility with fonts and graphics. For the Adafruit library, install it via the Arduino Library Manager, then install the Adafruit GFX library for graphics primitives. The initialization code for SPI mode requires defining the pins: #define OLED_MOSI 11 #define OLED_CLK 13 #define OLED_DC 8 #define OLED_CS 10 #define OLED_RESET 9. Then create an object: Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);. In the setup() function, call display.begin(SSD1306_SWITCHCAPVCC) to initialize with internal charge pump. If the display does not respond, check the I2C address (for I2C versions) or try a different CS pin. The U8g2 library uses a different constructor: U8G2_SSD1306_128X64_NONAME_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 8, /* reset=*/ 9);. This library handles the hardware SPI automatically. After initialization, you can clear the display, set text size, and draw pixels. The OLED’s memory is organized as a 128x64 buffer, requiring 1024 bytes of RAM (128*64/8). The Adafruit library allocates this buffer in the Arduino’s RAM, which is fine for Uno (2KB RAM), but for smaller boards like ATtiny85, you might need to use the U8g2 library with reduced buffer or use a non-buffered mode.

Power Consumption and Brightness Control

The OLED display’s power consumption is a critical factor for battery-powered projects. At full brightness (contrast register set to 0xFF), the display draws about 20mA to 25mA from a 3.3V supply, which is 66mW to 82.5mW. However, the actual current depends on the number of pixels lit: if you display a white screen (all pixels on), it can draw up to 30mA, while a black screen (all pixels off) draws only 1mA to 2mA for the driver IC. The SSD1306 driver has a charge pump that generates the high voltage (around 7V to 15V) for the OLED panel, which is why the current is higher than a standard LCD. You can reduce power by setting the contrast register to a lower value, like 0x10, which reduces brightness but also cuts current to around 10mA. The library provides a function: display.ssd1306_command(SSD1306_SETCONTRAST); display.ssd1306_command(0x10); for Adafruit library, or u8g2.setContrast(10); for U8g2. Additionally, you can put the display into sleep mode by sending the command 0xAE, which turns off the display and reduces current to under 1µA. Wake it up with 0xAF. For a battery-operated project, use a MOSFET to cut power to the display completely when not in use, as the sleep mode still draws a tiny current from the charge pump. The display’s operating temperature range is typically -40°C to +85°C, making it suitable for outdoor use, but the OLED pixels degrade over time, with a typical lifetime of 20,000 to 50,000 hours at full brightness, depending on the color (blue pixels degrade faster than white). The 1.54 inch diagonal gives a pixel pitch of about 0.3mm, which is sharp for text at 12-point font size.

Display Performance and Refresh Rate

The SPI interface on the 1.54 inch 128x64 OLED can achieve a maximum clock speed of 10 MHz for the driver IC, but the Arduino Uno’s hardware SPI runs at 8 MHz by default (half of 16 MHz system clock). This gives a theoretical refresh rate of about 60 frames per second (fps) for a full screen update, but in practice, the library overhead and the buffer transfer time reduce it to around 30 fps. For a 128x64 monochrome display, each frame requires 1024 bytes of data. At 8 MHz SPI, transferring 1024 bytes takes about 1.024 milliseconds (1024 * 8 bits / 8 MHz), plus command overhead. The Adafruit library uses a double-buffered approach, so you can draw to the buffer and then call display.display() to update the screen. If you update partial areas, you can use the display.drawPixel() and display.fillRect() functions, but each call to display.display() sends the entire buffer. For faster updates, use the U8g2 library’s u8g2.sendBuffer() which also sends the whole buffer, but you can reduce the buffer size by using a smaller page mode. Another technique is to use the display’s hardware scrolling, which shifts the content without rewriting the buffer. The SSD1306 supports horizontal and vertical scrolling with commands like 0x26 and 0x27. For example, to scroll left continuously, send: display.ssd1306_command(0x2E); // stop scrolling display.ssd1306_command(0x26); // left scroll display.ssd1306_command(0x00); // dummy byte display.ssd1306_command(0x07); // start page display.ssd1306_command(0x07); // interval display.ssd1306_command(0x00); // end page display.ssd1306_command(0xFF); // dummy display.ssd1306_command(0x2F); // start scrolling. This is useful for text tickers without CPU overhead. The display’s response time is under 10 microseconds per pixel, so it is suitable for real-time data like oscilloscope traces, but the 128x64 resolution limits the detail.

Advanced Features: Graphics and Fonts

You can draw complex graphics using the Adafruit GFX library, which includes functions for lines, circles, rectangles, triangles, and bitmaps. The library supports monochrome bitmaps with a 1-bit per pixel format. For example, to display a 128x64 bitmap, you need an array of 1024 bytes, where each byte represents 8 vertical pixels. You can convert images using online tools or the convertImage script. The U8g2 library has built-in fonts, including proportional and fixed-width fonts, ranging from 5x7 to 24x32 pixels. You can also use custom fonts by generating them with the u8g2font tool. For text rendering, the U8g2 library is more efficient because it handles font kerning and supports Unicode characters. To display a string, use: u8g2.setFont(u8g2_font_ncenB08_tr); u8g2.drawStr(0, 20, "Hello");. The Adafruit library uses display.setTextSize(1); display.setCursor(0,20); display.println("Hello");. The difference is that U8g2 uses a coordinate system where the baseline is the y-coordinate, while Adafruit uses the top-left corner of the text. For Chinese characters, you need a font that supports UTF-8, like the u8g2_font_wqy12_t_chinese3 font, but this requires a large flash memory (over 100KB). The Arduino Uno has only 32KB flash, so you might need to store the font in an external SPI flash chip or use a smaller subset. Another advanced feature is the ability to use the OLED’s built-in charge pump to generate negative voltage for the OLED panel, which is automatically handled by the driver. You can also adjust the display’s frame frequency by changing the clock divider register, but this is rarely needed.

Troubleshooting Common Issues

If the display remains blank after wiring, first check the power: measure VCC with a multimeter to ensure it is 3.3V or 5V as required. If the display shows a faint glow or lines, the contrast might be too low; increase it with display.ssd1306_command(0x81); display.ssd1306_command(0xCF);. If the display shows random pixels or garbage, the initialization sequence might be wrong. For the SSD1306, the correct sequence is: reset the display (pull RES low for 10ms, then high), then send commands: 0xAE (display off), 0xD5 (set display clock), 0x80, 0xA8 (set multiplex), 0x3F, 0xD3 (set display offset), 0x00, 0x40 (set start line), 0x8D (charge pump), 0x14, 0x20 (memory mode), 0x00, 0xA1 (segment remap), 0xC8 (COM scan direction), 0xDA (COM pins), 0x12, 0x81 (contrast), 0xCF, 0xD9 (pre-charge), 0xF1, 0xDB (VCOM detect), 0x40, 0xA4 (display on resume), 0xA6 (normal display), 0x2E (deactivate scroll), 0xAF (display on). If you use the Adafruit library, this is done automatically, but if you use a custom library, you must include this sequence. Another common issue is using the wrong SPI pins: on the Arduino Uno, the hardware SPI is on pins 11 (MOSI), 12 (MISO), and 13 (SCK). If you use software SPI, you can use any pins, but the speed is slower and prone to timing errors. For the I2C version, the address is usually 0x3C or 0x3D, and you need to connect SDA to A4 and SCL to A5 on the Uno. If the display shows a mirror image, you need to reverse the segment mapping by sending command 0xA0 instead of 0xA1. The display’s viewing angle is excellent, but if you mount it behind a window, use a polarizer filter to reduce glare. The OLED panel is sensitive to moisture, so in humid environments, use a conformal coating or a sealed enclosure. The display’s lifespan can be extended by reducing the brightness and using a screensaver that turns off the display after a period of inactivity.

Performance Comparison: SPI vs I2C vs Parallel

For the 1.54 inch 128x64 OLED, the SPI interface is the fastest among the common options. The table below shows the typical data transfer rates and frame rates for a full screen update (1024 bytes) using an Arduino Uno at 16 MHz:

InterfaceMax Clock SpeedTransfer Time (1024 bytes)Max Frame Rate (theoretical)Pins Required
SPI (hardware)8 MHz1.024 ms~60 fps4 (D0, D1, DC, CS) + RES optional
SPI (software)~1 MHz~8 ms~10 fpsSame, but any pins
I2C400 kHz~20 ms (with overhead)~5 fps2 (SDA, SCL) + RES optional
Parallel 8-bit (6800/8080)10 MHz~0.1 ms~100 fps8 data + 3 control = 11 pins

As you can see, SPI is a good balance between speed and pin count. The parallel interface is faster but uses many pins, which is impractical for most Arduino projects. I2C is slower but uses only two pins, making it ideal for projects with limited I/O, like using an Arduino Nano with many sensors. However, the I2C version of this display often has a lower maximum clock due to the pull-up resistors and bus capacitance. For applications requiring smooth animation, like a video player or a game, use SPI at 8 MHz. If you need to update the display with sensor data every 100ms, I2C is sufficient. The display’s driver IC also supports a 4-wire SPI mode (without the DC pin, using a separate command byte), but that is less common. The hardware SPI pins on the Arduino Uno are shared with the ICSP header, so if you use an ISP programmer, you must disconnect the OLED. For the Arduino Mega, the hardware SPI pins are on 50 (MISO), 51 (MOSI), 52 (SCK), and 53 (SS). The display’s CS pin can be connected to any digital pin, but using pin 10 on the Uno is standard because it is the default SS pin for the SPI library. If you use a different pin, you must set it as an output and set it low before each transaction.

Run the operation in one place

Stop stitching five tools together. Start your free 14-day trial.

Fromlu replaces the patchwork of spreadsheets, sticky notes, and disconnected SaaS tools — one workspace for projects, invoices, and cash flow. No credit card required.

Start your free 14-day trial See the features