Skip to content
Issue 1,847 · Est. 2017
Daily Drop · Software Intelligence

How to display a QR code on a 2.08 inch 256x64 OLED display?

aBy admin·Filed under software intelligence

How to Display a QR Code on a 2.08 inch 256x64 OLED Display

To display a QR code on a 2.08 inch 256x64 OLED display, you need to generate the QR code matrix data, format it for a monochrome screen, and then send it via SPI to the display controller, typically an SSD1306 or SH1106. This process involves several key steps, from understanding the display's resolution and addressing scheme to selecting the appropriate library and configuring the hardware interface. The following detailed guide will walk you through each stage, ensuring you can successfully render a scannable QR code on this specific OLED module.

Understanding the Display Resolution and QR Code Scaling

The 2.08 inch 256x64 OLED display has a total of 16,384 pixels arranged in a horizontal resolution of 256 columns and a vertical resolution of 64 rows. A standard QR code, such as version 4, consists of 33x33 modules (the smallest square elements that make up the QR pattern). This means each module can be represented by a block of pixels on the display. To make the QR code easily scannable, you should scale each module to a size of at least 4x4 pixels, which results in a QR code area of 132x132 pixels (since 33 modules x 4 pixels per module = 132 pixels). However, this leaves ample room for borders, labels, or other graphics on the 256x64 screen. For example, you could set each QR module to a 4x4 pixel block, giving a 132x132 pixel area, but note that the vertical resolution is only 64 pixels, so you must fit the QR code within the 64-pixel height. A more practical approach is to use a 2x2 pixel block size, resulting in a 66x66 pixel QR code, which fits comfortably within the 64-pixel height if you orient the QR code vertically or use a smaller version. Alternatively, you can use a version 2 QR code (25x25 modules) with a 2x2 pixel block size, yielding a 50x50 pixel area, which leaves 14 pixels of vertical margin and ample horizontal space. The key is to balance readability with available screen real estate, ensuring the QR code is large enough to be scanned from a typical distance of 10-15 cm.

Internal Display Architecture and Addressing

The display uses a 128x64 page layout internally, but the 256x64 model doubles the horizontal resolution by using two 128x64 segments. This means the display controller treats the screen as two separate halves, each 128 pixels wide. To address the full 256-pixel width, you must configure the SPI commands to write to both segments sequentially. The SH1106 controller, commonly used in these displays, has an internal RAM of 132x64 pixels, but only 256x64 is visible. You need to set the column start address to 0x00 and the column end address to 0x7F for each half, and then send data for the left half first, followed by the right half. The SSD1306 controller, on the other hand, has a native 128x64 resolution, but some 256x64 displays use two SSD1306 chips in parallel, requiring careful initialization to synchronize them. In either case, the SPI transaction must send 8-bit command bytes followed by 8-bit data bytes, with the DC pin low for commands and high for data. The display's contrast register (0x81) can be set to 0x7F for optimal brightness in indoor lighting, and you may need to adjust the charge pump settings for stable operation.

Selecting the Right Library and Initialization Sequence

A typical approach is to use a library like Adafruit_SSD1306 or U8g2, which support 256x64 with proper initialization sequences. However, these libraries are primarily designed for SSD1306 controllers, so you may need to modify the initialization commands for SH1106-based displays. For example, the SH1106 requires a segment remap command (0xA0 or 0xA1) to reverse the column order, and a COM scan direction command (0xC0 or 0xC8) to reverse the row order. The initialization sequence for SH1106 typically includes commands like 0xAE (display off), 0xD5 (display clock divide ratio/oscillator frequency), 0x80 (reset value), 0xA8 (multiplex ratio), 0x3F (64 rows), 0xD3 (display offset), 0x00 (no offset), 0x40 (start line), 0x8D (charge pump), 0x14 (enable), 0x20 (memory addressing mode), 0x00 (horizontal mode), 0xA1 (segment remap), 0xC8 (COM scan direction), 0xDA (COM pins hardware configuration), 0x12 (alternative configuration), 0x81 (contrast), 0x7F (value), 0xD9 (pre-charge period), 0xF1 (value), 0xDB (VCOMH deselect level), 0x40 (value), 0xA4 (display on resume), 0xA6 (normal display), 0xAF (display on). For the SSD1306, the sequence is similar but with different values for some commands, such as 0xDA (COM pins) set to 0x02, and 0xD9 (pre-charge) set to 0x22. The U8g2 library provides a more flexible framework that supports both controllers with pre-defined initialization sequences, but you must select the correct constructor for your display, such as U8G2_SH1106_256X64_1_4W_HW_SPI or U8G2_SSD1306_256X64_1_4W_HW_SPI.

Generating the QR Code Matrix Data

The QR code bitmap can be generated using a Python script with the qrcode library, then converted to a byte array for C code. First, install the library with pip install qrcode[pil]. Then, write a script that generates a QR code with error correction level M (15%) to ensure readability even if the display has minor contrast issues. The script should output the QR code as a monochrome image, then extract the pixel data and convert it to a byte array suitable for the display's framebuffer. For example, you can use the following Python code:

import qrcode
from PIL import Image

qr = qrcode.QRCode(version=4, error_correction=qrcode.constants.ERROR_CORRECT_M, box_size=2, border=1)
qr.add_data('https://example.com')
qr.make(fit=True)
img = qr.make_image(fill_color='black', back_color='white').convert('1')
pixels = list

Stop triaging 14,000 changelogs by hand.

BestUpdate surfaces the 4% of releases that actually move your category — every weekday at 7am PT.

Get the Daily Drop →