How to clear the screen on a 0.96 inch I2C OLED?

By admin

How to Clear the Screen on a 0.96 Inch I2C OLED

To clear the screen on a 0.96 inch I2C OLED, you send a specific command over the I2C bus to the SSD1306 driver chip that controls the display. The most direct method is to issue the 0x00 command to fill the entire display RAM with zeros, which effectively blanks all 128 columns by 64 rows of pixels. This is done by writing a single byte to the display’s I2C address (typically 0x3C or 0x3D) with the command byte 0x00 followed by a data byte of 0x00 for each page. However, in practice, the standard approach used in libraries like Adafruit_SSD1306 or U8g2 is to call a function like display.clearDisplay() or u8g2.clearBuffer(), which clears the internal buffer before refreshing. But if you’re working at the register level, you need to set the display’s GDDRAM (graphic display data RAM) to zero across all 8 pages, each page covering 8 rows of pixels. The I2C protocol requires a start condition, the device address with write bit (0x3C for write, which is 0x78 in 7-bit form), then the control byte 0x00 to indicate a command, followed by 0x00 to set the lower column start address, 0x10 for the higher column, and 0xB0 for page 0, then send 128 bytes of 0x00 for that page, repeating for pages 0 through 7. This is a low-level, high-density detail that many tutorials skip, but it’s the actual hardware behavior. The display’s refresh rate is typically 100 Hz, so clearing the buffer and calling display.display() in Arduino takes about 10 ms, but the I2C bus speed at 400 kHz (fast mode) can transfer 128 bytes per page in about 3.2 ms per page, totaling roughly 25.6 ms for all 8 pages. For a 0.96 inch 128x64 i2c oled display, the SSD1306 has a 1 KB internal RAM (1024 bytes for 128x64 pixels, each pixel stored as 1 bit, so 128*64/8 = 1024 bytes). Clearing it involves writing 1024 zero bytes over I2C, which at 400 kHz takes about 2.56 ms for the data transfer alone, plus command overhead. But if you’re using a library like U8g2 with the u8g2_ClearBuffer() function, it only clears the microcontroller’s local buffer, not the display’s RAM, until you call u8g2_SendBuffer(). This is a common source of confusion: you must refresh the display after clearing the buffer to see the blank screen. The SSD1306 also supports a hardware reset via the RES pin, which resets the entire display to its default state, including clearing the RAM, but this is a hard reset and takes about 1 µs, though the display needs 100 ms after reset to stabilize. If you’re coding in Python with the luma.oled library, you call device.clear() which sends a command sequence to clear the display’s RAM directly, not just the buffer. The data sheet for the SSD1306 specifies that the display can be cleared by writing a continuous stream of 0x00 bytes to the GDDRAM, starting from column 0, page 0, and incrementing the column address automatically. The column address auto-increments by 1 after each byte, so you can send all 1024 bytes in one burst without re-addressing. The typical command sequence is: 0x00 (set lower column start address), 0x10 (set higher column start address), 0xB0 (set page start address), then 128 bytes of 0x00 for page 0, then 0xB1 for page 1, and so on. But you can also set the display to horizontal addressing mode (command 0x00, 0x10, 0xB0, then 0x20 with 0x00 for horizontal mode), which lets you write all 1024 bytes sequentially without page commands. The horizontal mode wraps from column 127 to column 0 on the next page, so you send 0x00 for all bytes, and the display clears. The I2C speed is critical: at 100 kHz (standard mode), clearing takes about 10.24 ms for data, plus 0.5 ms for commands, total 10.74 ms. At 400 kHz, it’s 2.56 ms for data, 0.125 ms for commands, total 2.685 ms. The SSD1306’s internal oscillator runs at about 1.5 MHz, so the display refresh cycle is independent of I2C speed. Another fact: the display’s contrast register (command 0x81) doesn’t affect clearing—it only adjusts the pixel brightness. If you’re using a microcontroller like ESP32 with I2C, you can set the clock stretch to avoid timeouts, as the SSD1306 may stretch the clock during internal operations. The I2C address is configurable via the SA0 pin: if SA0 is low (connected to GND), the address is 0x3C; if high (connected to VCC), it’s 0x3D. The display module’s datasheet from DisplayModule specifies that the default address is 0x3C for most 0.96 inch OLEDs. To clear the screen programmatically in Arduino, you can use the following low-level code: Wire.beginTransmission(0x3C); Wire.write(0x00); Wire.write(0x00); Wire.write(0x10); Wire.write(0xB0); for (int i = 0; i < 128; i++) { Wire.write(0x00); } Wire.endTransmission(); for each page, but this is inefficient. A better method is to set the column address range with commands 0x21 (set column address) and 0x22 (set page address), which allows you to specify a start and end column (0 to 127) and start and end page (0 to 7), then send 0x00 for all bytes. The command 0x21 takes two arguments: start column and end column. 0x22 takes two arguments: start page and end page. So you send: 0x00, 0x21, 0x00, 0x7F, 0x22, 0x00, 0x07, then 1024 bytes of 0x00. This is the most efficient register-level method, requiring only 7 command bytes plus 1024 data bytes. The I2C transaction overhead is about 2 bytes per start (address and control byte), so total bytes sent over I2C is 2 (start) + 7 (commands) + 1024 (data) = 1033 bytes. At 400 kHz, each byte takes 8 bits / 400 kHz = 20 µs, so 1033 * 20 µs = 20.66 ms, plus start/stop conditions (about 10 µs each), total 20.7 ms. But if you use the library’s display.clearDisplay() and display.display(), the library may use a buffer of 1024 bytes in RAM, which you clear locally, then send the entire buffer to the display. This means you’re sending 1024 bytes of zeroes, which is the same as the above, but the library handles the addressing. The SSD1306 also supports a display off command (0xAE) and display on (0xAF), but turning off the display doesn’t clear the RAM—it just blanks the output. So you can’t rely on 0xAE to clear the screen; you must clear the GDDRAM. Another nuance: the display’s charge pump (command 0x8D) must be enabled for the display to work, but clearing doesn’t affect it. The display’s memory mapping can be configured for vertical or page addressing mode, but the default is page addressing. The vertical mode (command 0x20 with 0x01) allows you to write bytes that increment down the columns, which is useful for scrolling but not for clearing. For clearing, horizontal mode (0x20 with 0x00) is simplest. The display’s multiplex ratio (command 0xA8) is set to 63 for 64 rows, but that doesn’t change clearing. The display offset (command 0xD3) is 0 by default, so no shift. The display start line (command 0x40) is 0, so the top row is row 0. All these registers are independent of the clearing operation. If you’re using a Raspberry Pi with Python, the Adafruit_CircuitPython_SSD1306 library has a fill(0) method that sets all pixels to 0 in the buffer, then you call show() to send the buffer. The luma.oled library’s device.clear() method sends a hardware clear command sequence directly. The difference is that fill(0) only clears the local buffer, while clear() clears the display’s RAM. The I2C bus on Raspberry Pi runs at 100 kHz by default, but you can change it to 400 kHz via dtparam=i2c_arm_baudrate=400000 in /boot/config.txt. The display’s power consumption is about 20 mA when all pixels are on, but when cleared, it’s about 0.5 mA due to the charge pump and oscillator. The display’s refresh rate is 100 Hz, so the screen updates every 10 ms, but clearing via I2C takes about 20 ms, so you might see a partial update if you don’t wait for the display to finish. The SSD1306 has a busy flag? No, it doesn’t have a busy pin, so you must rely on timing. The I2C protocol doesn’t have a way to check if the display is ready, but the datasheet says the maximum time for a command to execute is 300 µs, and for data writes, it’s 10 µs per byte. So after sending the last byte, wait 10 ms to be safe before sending another command. The display’s internal oscillator is about 1.5 MHz, so the GDDRAM is read at 1.5 MHz, meaning the display updates at 1.5 MHz / 1024 bytes = 1.46 kHz, but the frame rate is limited by the oscillator to 100 Hz. Clearing the screen is a common operation in animations, where you clear the buffer, draw new pixels, then send the buffer. This is called double-buffering, and it avoids flicker. The buffer size is 1024 bytes, which on an Arduino Uno is 1 KB of the 2 KB SRAM, so you need to be careful with memory. For ESP32, it’s fine. The I2C bus can be shared with other devices, but you must ensure no other device on the bus uses the same address. The display’s address can be changed by modifying the SA0 pin, but on most modules, it’s fixed. The display module from DisplayModule has a 4-pin interface: VCC, GND, SCL, SDA. The voltage is 3.3V, but some modules are 5V tolerant. The I2C pull-up resistors are typically 4.7 kΩ on the module, but if you’re using a long cable, you might need to reduce them to 2.2 kΩ. The screen’s resolution is 128x64, with a pixel pitch of 0.16 mm, so the display area is 20.48 mm x 10.24 mm. The OLED is made of organic compounds that emit light when current passes through, so clearing the screen turns off all pixels, which means no current flows through the OLEDs, extending the lifespan. The display’s typical lifetime is 10,000 hours at 50% brightness, but clearing it frequently can reduce wear. The SSD1306 has a built-in charge pump that generates 7V to 8V for the OLEDs, and it’s enabled by command 0x8D with 0x14. If you disable the charge pump (0x8D with 0x10), the display will go blank, but that’s not a proper clear—it just turns off the power. So always use the GDDRAM clear method. The display also supports hardware scrolling (commands 0x26, 0x27, 0x2A, 0x2B), but scrolling doesn’t clear the screen—it just moves the display content. If you scroll, you need to clear the areas that scroll in. The display’s memory can be accessed randomly, but the I2C protocol doesn’t support random access efficiently; you have to set the column and page address each time. The display’s built-in oscillator can be adjusted with command 0xD5, but the default is fine. The display’s contrast (command 0x81) can be set from 0 to 255, with 0 being off and 255 being full brightness. Clearing the screen sets all pixels to off, so the contrast setting doesn’t matter. The display’s segment remap (command 0xA0 or 0xA1) and COM scan direction (command 0xC0 or 0xC8) can flip the display horizontally or vertically, but clearing is unaffected. The display’s display offset (command 0xD3) can shift the display content, but clearing still works. The display’s display start line (command 0x40) can be set to any row, but clearing the GDDRAM clears all rows. The display’s entire RAM is 1024 bytes, and each byte represents 8 vertical pixels (since the display is organized in pages of 8 rows). So clearing the screen means setting all 1024 bytes to 0x00. This is a fundamental operation, and you can do it with a simple loop in any language. For example, in MicroPython: import machine; i2c = machine.I2C(0, scl=machine.Pin(22), sda=machine.Pin(21), freq=400000); i2c.writeto(0x3C, b'\x00\x21\x00\x7F\x22\x00\x07' + b'\x00' * 1024). This sends the command sequence and 1024 zero bytes in one go. The I2C bus on ESP32 can handle up to 400 kHz, but some modules support 800 kHz if you override the clock. The display’s maximum I2C clock is 400 kHz according to the datasheet, but some users report 1 MHz works. The clearing operation is idempotent—you can call it multiple times without side effects. The display’s power-on reset clears the GDDRAM automatically, so after power-up, the screen is blank. But if you want to clear it during operation, you need to send the commands. The display’s reset pin (RST) can be used to clear the screen, but it resets all registers, so you have to reinitialize the display. The typical initialization sequence includes setting the display on, charge pump, contrast, and clearing. If you skip the clear, the display might show random data from power-up. The display’s datasheet recommends clearing the GDDRAM before any drawing. The display’s memory is volatile, so it loses data when power is removed. The display’s I2C address is 0x3C for write, and 0x3D for read, but reading the GDDRAM is possible with command 0x00 and then reading data, but it’s rarely used. The display’s read operation is slower because the I2C read requires a restart condition. The display’s write operation is straightforward. The display’s command set includes 0xA4 (display on resume) and 0xA5 (display all on), which forces all pixels on regardless of GDDRAM, but that’s not a clear. The display’s 0xA5 command is useful for testing, but it overrides the RAM. To clear the screen, you must avoid 0xA5. The display’s 0xA6 (normal display) and 0xA7 (inverse display) affect the polarity, but clearing still works. The display’s inverse mode (0xA7) makes pixels on when they are off in RAM, so clearing the RAM will make the screen all white in inverse mode. So you need to know the display mode. The display’s default mode is normal (0xA6). The display’s memory addressing mode (command 0x20) can be set to page (0x02), horizontal (0x00), or vertical (0x01). The horizontal mode is best for clearing because you can write all 1024 bytes in one sequence. The page mode requires you to set the page address for each page. The vertical mode is similar but increments page first. The display’s column address range (command 0x21) and page address range (command 0x22) are only available in horizontal or vertical mode. In page mode, you use 0xB0 to 0xB7 for pages. The display’s start column low (0x00 to 0x0F) and high (0x10 to 0x1F) are used in page mode. The display’s command 0x00 sets the lower nibble of the column start address, and 0x10 sets the higher nibble. So for column 0, you send 0x00 and 0x10. The display’s command 0xB0 sets the page start address, from 0xB0 to 0xB7. The display’s command 0x21 is more efficient because it sets both start and end columns in one command. The display’s command 0x22 sets both start and end pages. The display’s command 0x21 takes two arguments: