How to print a bitmap on a 0.66 inch 64x64 OLED?

By admin

How to print a bitmap on a 0.66 inch 64x64 OLED

To print a bitmap on a 0.66 inch 64x64 OLED, you need to convert the image into a byte array format that the display controller can interpret, typically using a monochrome bitmap-to-hex converter, then send that data via SPI or I2C to the OLED driver (like SSD1306 or SH1107). The 0.66 inch 64x64 oled display uses a 64x64 pixel matrix, meaning the bitmap must be resized to exactly 64x64 pixels, with each pixel represented as 1 bit (0 for off, 1 for on) in a monochrome format. The total memory required is 64x64/8 = 512 bytes, which is stored in the microcontroller’s flash or RAM. You’ll need a microcontroller like Arduino, ESP32, or STM32 to drive the OLED via SPI, sending commands to initialize the display, set the memory addressing mode, and then transfer the bitmap data page by page (each page is 8 rows tall).

Hardware setup and pin connections

Start by connecting the OLED to your microcontroller. The 0.66 inch 64x64 OLED with SPI interface uses 7 pins: VCC (3.3V or 5V), GND, SCK (clock), MOSI (data), CS (chip select), DC (data/command), and RST (reset). For an Arduino Uno, typical wiring: VCC to 3.3V, GND to GND, SCK to pin 13, MOSI to pin 11, CS to pin 10, DC to pin 9, and RST to pin 8. The display operates at 3.3V logic, but many modules include a voltage regulator for 5V compatibility. The SPI clock speed should be set to 4-8 MHz for reliable communication; higher speeds may cause data corruption due to signal reflections on breadboard wires. Always use short wires (under 10 cm) to minimize noise. The OLED driver IC (e.g., SSD1306) has a maximum SPI clock of 10 MHz, but 4 MHz is a safe starting point.

Bitmap conversion process

You cannot send a raw JPEG or PNG file to the OLED. Convert the image to a 64x64 monochrome bitmap using tools like Image2LCD (Windows), LCD Assistant, or online converters (e.g., 0.66 inch 64x64 oled display converter tools). Set the parameters: image width = 64, height = 64, color mode = monochrome (1 bit per pixel), byte order = row-major, and pixel order = column-major (most OLEDs use vertical addressing). The output is a C array like: const unsigned char bitmap[] = {0xFF, 0x81, 0x81, ...}; with 512 bytes. For best results, use high-contrast black-and-white images (no grayscale) because the OLED has only 1-bit per pixel. Dithering algorithms (like Floyd-Steinberg) can simulate grayscale, but they reduce sharpness on a 64x64 resolution. Test the bitmap with a simple pattern: a checkerboard of 8x8 pixel squares (alternating 0x00 and 0xFF bytes) to verify pixel mapping.

Initializing the OLED driver

Before sending bitmap data, initialize the OLED with a sequence of commands. For the SSD1306 driver (common in 64x64 OLEDs), the init sequence includes: power on (0xAF), set display clock divide (0xD5, 0x80), set multiplex ratio (0xA8, 0x3F for 64 rows), set display offset (0xD3, 0x00), set start line (0x40), charge pump enable (0x8D, 0x14), set memory addressing mode (0x20, 0x00 for horizontal mode), set segment re-map (0xA1 for column 127 mapped to SEG0), set COM scan direction (0xC8 for bottom-up), set COM pins hardware config (0xDA, 0x12), set contrast (0x81, 0x7F), set pre-charge period (0xD9, 0xF1), set VCOMH deselect level (0xDB, 0x40), set display all on resume (0xA4), set normal display (0xA6), and deactivate scroll (0x2E). The total initialization takes about 20-30 milliseconds. If you use the SH1107 driver (some 64x64 OLEDs), the commands differ slightly: set display start line (0xDC, 0x00), set segment re-map (0xA0), and set COM scan direction (0xC0). Check the datasheet of your specific module.

Sending bitmap data via SPI

After initialization, set the column and page address range. For SSD1306 in horizontal addressing mode, send command 0x21 (set column address) followed by 0x00 (start column) and 0x3F (end column, since 64 columns = 0 to 63). Then command 0x22 (set page address) followed by 0x00 (start page) and 0x07 (end page, since 64 rows / 8 pages = 8 pages). Now send the 512-byte bitmap array as data (DC pin high). Each byte represents 8 vertical pixels in a column, with the least significant bit (LSB) corresponding to the top pixel of the page. For example, byte 0x81 means the top and bottom pixels of that column are on, while the middle six are off. The SPI transfer is done via SPI.transfer() in Arduino, or using DMA on ESP32 for faster updates. A full screen refresh takes about 512 bytes * 8 microseconds per byte (at 1 MHz SPI) = 4.1 ms, but at 4 MHz it’s ~1 ms. Avoid sending the bitmap repeatedly in the loop unless the image changes; instead, store it in flash memory using PROGMEM on AVR microcontrollers to save RAM.

Optimizing bitmap display for 64x64 resolution

Because the 0.66 inch 64x64 OLED has a small physical size (about 16.8 mm x 16.8 mm), each pixel is roughly 0.26 mm wide. Fine details like text below 5 pixels tall become unreadable. For bitmaps, use simple icons or logos with thick lines (at least 2 pixels wide). If you need to display text, use a 5x7 font (5 pixels wide, 7 pixels tall) which fits 9 characters per row and 9 rows (since 64/7 ≈ 9.1). Pre-render the text into a bitmap using a font generator tool like 0.66 inch 64x64 oled display font libraries. For animations, pre-compute multiple bitmaps and store them in flash; a 10-frame animation at 10 fps requires 5120 bytes of flash, which is feasible on ESP32 (4 MB flash) but tight on Arduino Uno (32 KB flash). Use the Adafruit_SSD1306 library or U8g2 library for higher-level functions, but note that these libraries add overhead (e.g., U8g2 uses ~2 KB of RAM for buffer). For direct bitmap control, write your own SPI functions to minimize latency.

Common pitfalls and debugging

If the bitmap appears inverted, swap the color mode in the converter (e.g., from 0=black to 0=white). If the image is shifted or duplicated, check the column and page address commands. For example, some 64x64 OLEDs with SH1107 require column start at 2 (0x02) instead of 0, because the driver has 128 columns but only 64 are used. If the display shows random pixels, verify the SPI polarity and phase: SSD1306 uses SPI mode 0 (CPOL=0, CPHA=0). If the display remains blank, check the reset sequence: hold RST low for 10 ms, then high, then wait 100 ms before sending commands. Use a logic analyzer to capture SPI transactions; the data should show 512 bytes after the address commands. Measure the power supply: the OLED draws about 20 mA typical, but peaks at 40 mA when all pixels are on. A 3.3V regulator with 100 mA capacity is sufficient. If using a breadboard, add a 10 µF capacitor between VCC and GND near the OLED to filter noise.

Performance benchmarks

Here are typical frame rates for different microcontrollers when updating the full 64x64 bitmap via SPI at 4 MHz:

MicrocontrollerSPI SpeedFrame Rate (fps)RAM Usage
Arduino Uno (16 MHz)4 MHz~60 fps512 bytes + 2 KB buffer
ESP32 (240 MHz)8 MHz~120 fps512 bytes + 4 KB buffer
STM32F103 (72 MHz)9 MHz~150 fps512 bytes + 1 KB buffer

These values assume the bitmap is stored in flash and only the SPI transfer time is measured. Including image processing (e.g., scaling) drops the frame rate to 10-20 fps on Arduino Uno. For smooth animations, use double buffering: render the next frame in a RAM buffer while the current frame is displayed, then swap buffers. On ESP32, use DMA to transfer data without CPU intervention, achieving 200+ fps.

Advanced techniques for bitmap printing

For partial updates, only send the changed bytes. For example, if you update a 16x16 pixel icon, send only 32 bytes (16 columns * 16 rows / 8). Use the SSD1306’s page addressing mode to set the column and page range for the update region. This reduces SPI traffic and power consumption. For scrolling bitmaps, use the hardware scroll command (0x26 or 0x27) with a frame rate set by 0x2E. The scroll speed depends on the divide ratio; a value of 0x00 scrolls one pixel every 2 frames, while 0x07 scrolls one pixel every 6 frames. You can also implement vertical scrolling by shifting the display start line (0x40 to 0x7F). For bitmaps with transparency (e.g., overlaying an icon on a background), perform a bitwise AND/OR operation in the microcontroller: read the background byte, mask the icon area, and combine. This requires a RAM buffer of 512 bytes, which is feasible on ESP32 but not on Arduino Uno (only 2 KB SRAM). In that case, use a smaller buffer for partial updates.

Power consumption considerations

The 0.66 inch 64x64 OLED consumes 15-25 mA at 3.3V when displaying a full white bitmap, and 10-15 mA when displaying a black bitmap (since OLED pixels are emissive, black pixels are off). In battery-powered projects, use the display sleep mode (command 0xAE) to drop consumption to 1-5 µA. When printing a bitmap, minimize the number of white pixels to save power. For example, a clock display with white numbers on a black background uses 12 mA, while a full white screen uses 22 mA. The charge pump (enabled via 0x8D, 0x14) adds 5-10 mA; disable it if you supply an external 3.3V to the OLED VCC pin. The SPI bus itself draws negligible current (under 1 mA). For long battery life, update the bitmap only when the content changes, and use a low-power microcontroller like the ESP32-S3 with deep sleep mode.

Testing with a sample bitmap

Create a simple test bitmap: a 64x64 image with a centered 32x32 white square. The byte array for the first 8 rows (page 0) would be: 0x00 for columns 0-15, then 0xFF for columns 16-47 (the square), then 0x00 for columns 48-63. Repeat for pages 0-3 (rows 0-31), then all zeros for pages 4-7 (rows 32-63). The total size is 512 bytes. Upload this to the OLED using the init sequence above. If the square appears correctly, you can proceed to more complex images. For debugging, send a ramp pattern: each byte increments by 1 from 0x00 to 0xFF, which produces vertical stripes. This helps identify column mapping issues. If the stripes are not evenly spaced, the segment re-map command (0xA1 vs 0xA0) is wrong.

Using libraries vs raw SPI

Popular libraries like Adafruit_SSD1306 and U8g2 simplify bitmap printing with functions like display.drawBitmap() or u8g2.drawXBM(). However, they add overhead: Adafruit’s library uses a 512-byte RAM buffer (on top of the display’s internal RAM), which doubles memory usage. U8g2 can work in buffered or unbuffered mode; unbuffered mode saves RAM but requires calling the draw function for each pixel, which is slow (0.5 fps for full screen). For high-speed bitmap printing, raw SPI is 10-100x faster. For example, raw SPI takes 1 ms to send 512 bytes, while Adafruit’s library takes 3 ms due to buffer management. On ESP32, raw SPI with DMA achieves 0.5 ms. If you need to render text or shapes, use a library for development, then switch to raw SPI for production. The 0.66 inch 64x64 oled display module’s datasheet includes example code for raw SPI in C, which you can adapt for any microcontroller.