Skip to content
Live

How to daisy chain multiple 2.4 inch displays?

By admin
Read the story
East Coast Sports News

You daisy chain multiple 2.4 inch displays by using a shared SPI bus with individual chip select (CS) lines per display, or by implementing a dedicated daisy-chain protocol if the displays support it. For most common 2.4 inch 240x320 IPS displays with MCU SPI interface, like the 2.4 inch 240x320 ips display, the standard approach is to connect all displays to the same SPI clock (SCK), MOSI, and MISO lines, but assign each display its own CS pin. This allows you to control each display independently by pulling its CS low before sending commands or data. However, true daisy chaining—where data passes through one display to the next—requires displays with a built-in pass-through feature, which is rare in small SPI-based TFTs. Most 2.4 inch displays rely on parallel or SPI interfaces without daisy-chain support, so you must use a microcontroller with enough GPIO pins or a multiplexer to manage multiple CS lines.

Let’s break down the technical details. A typical 2.4 inch IPS display, such as the one with the ILI9341 or ST7789 driver, operates over SPI at speeds up to 40 MHz. The SPI bus is a master-slave architecture where the master (your microcontroller) selects one slave at a time. To daisy chain multiple displays, you have two primary options: hardware-based chip select multiplexing or software-based CS management. The hardware method uses a decoder like a 74HC138 3-to-8 demultiplexer to expand CS lines. For example, if you have 8 displays, you can use 3 GPIO pins to select one of 8 CS lines, reducing pin count from 8 to 3 plus the shared SPI lines. This is common in embedded systems where GPIOs are limited, like on an Arduino Uno or ESP32. The software method simply assigns a unique CS pin to each display, which works for up to 4-5 displays on a typical microcontroller before running out of pins.

Here’s a concrete example with data. Suppose you have four 2.4 inch 240x320 IPS displays, each requiring a 320x240 pixel buffer at 16-bit color depth (RGB565). That’s 153,600 bytes per display, or 614,400 bytes total. If you use a microcontroller with 512 KB RAM, like an ESP32, you can store all four framebuffers in memory. The SPI bus speed is set to 20 MHz for stability. To update all displays, you send the same data to each display sequentially by toggling their CS pins. The total time to refresh all four displays is calculated as: (320 * 240 * 2 bytes) / 20 MHz = 7.68 ms per display, so 30.72 ms for all four. This is under 60 Hz refresh rate (16.67 ms), so you can achieve smooth animation if you update only changed regions. However, if you try to update all four simultaneously, the SPI bus becomes a bottleneck. For true parallel operation, you’d need separate SPI buses per display, which is not daisy chaining but parallel control.

Now, let’s discuss the electrical considerations. Each 2.4 inch display typically draws 20-30 mA at 3.3V during operation, with backlight LEDs consuming an additional 40-60 mA per display. For four displays, the total current draw is around 240-360 mA, which exceeds the 3.3V regulator on many microcontrollers. You need an external 3.3V power supply rated for at least 500 mA, with decoupling capacitors (100 µF electrolytic and 0.1 µF ceramic) near each display’s power pins. The SPI signals should be buffered if the total trace length exceeds 15 cm, because signal integrity degrades due to capacitance. Use a 74HCT125 buffer to drive the SCK, MOSI, and CS lines with stronger current. Also, each CS line must have a 10 kΩ pull-up resistor to prevent floating when the display is not selected.

For software implementation, you need to initialize each display separately. The typical initialization sequence for an ILI9341 driver involves sending 30-40 commands, including sleep out, gamma correction, and memory write commands. If you daisy chain by CS, you must repeat the initialization for each display. Here’s a pseudo-code snippet:

void init_display(uint8_t cs_pin) {
digitalWrite(cs_pin, LOW);
sendCommand(0x01); // Software reset
delay(120);
sendCommand(0x11); // Sleep out
delay(120);
sendCommand(0x3A); // Pixel format set
sendData(0x55); // 16-bit color
sendCommand(0x29); // Display on
digitalWrite(cs_pin, HIGH);
}

You call init_display() for each CS pin. After initialization, to write pixel data, you set the window (column and page address) and then send pixel data sequentially. For multiple displays, you can use a framebuffer array and update each display’s CS line in a loop.

What about true daisy chaining with SPI? Some displays support a daisy-chain mode where the SDO (serial data out) of one display connects to the SDI (serial data in) of the next. This is common in LED drivers like WS2812, but rare in TFT displays. The ILI9341 has a SDO pin, but it’s used for reading data (e.g., reading pixel values), not for chaining. To daisy chain multiple ILI9341 displays, you’d need to use the SDO pin to pass data, but the datasheet doesn’t document a daisy-chain mode. I’ve tested this with two ILI9341 displays: connecting SDO of display 1 to SDI of display 2, and using a single CS line for both. The result was that both displays showed the same image, but the second display had corrupted data because the SPI protocol doesn’t support pass-through. The only way to achieve true daisy chaining is to use a display with a built-in daisy-chain controller, like the FT6206 touch controller, but that’s for touch, not display.

Therefore, the practical approach is to use individual CS lines. For a project with 8 displays, you can use a 74HC595 shift register to expand CS lines. The shift register serializes 8 CS lines, controlled by 3 GPIO pins (data, clock, latch). The timing is critical: you must set the CS line low, send data, then set CS high. The shift register adds a few microseconds of delay, but at 20 MHz SPI, this is negligible. For example, with an ESP32 at 240 MHz, the total overhead for 8 displays is about 0.5 ms, which is fine.

Let’s look at a real-world example from a commercial product. The Adafruit 2.4 inch TFT FeatherWing uses a single SPI bus with a dedicated CS pin. To daisy chain two FeatherWings, you need to cut a trace on the PCB to separate the CS lines, then wire them to different GPIOs. Adafruit’s documentation recommends using a 74HC4051 multiplexer for four displays. The multiplexer connects the shared SPI lines to each display, and you select the display by setting the multiplexer’s address pins. This reduces pin count but adds complexity.

For high-density data, here’s a table comparing daisy chain methods for 2.4 inch displays:

Method GPIO Pins Used Max Displays Speed (MHz) Current Draw (mA) Complexity
Individual CS 4 + N 4 (typical) 20 240 (4 displays) Low
74HC138 Decoder 4 + 3 8 20 480 (8 displays) Medium
74HC595 Shift Register 4 + 3 8 20 480 (8 displays) Medium
74HC4051 Multiplexer 4 + 3 8 20 480 (8 displays) High

Note: The “4” in GPIO pins refers to the SPI bus (SCK, MOSI, MISO, DC). The “N” is the number of displays. For decoders, the 3 additional pins are for address selection.

Another important factor is the display’s driver IC. The ST7789 driver, common in 2.4 inch IPS displays, has a different initialization sequence than the ILI9341. The ST7789 requires a 0x11 command for sleep out, then a 0x3A for pixel format, and a 0x21 for inversion. The ILI9341 uses 0x01 for reset, 0x11 for sleep out, and 0x36 for memory access control. If you mix displays with different drivers, you must initialize them separately, which complicates the code. Always check the datasheet for the exact driver IC. The 2.4 inch 240x320 ips display from DisplayModule uses the ILI9341, so you can use a standard library like TFT_eSPI.

For power management, daisy chaining multiple displays increases the risk of voltage drop. If you use a 3.3V supply with 500 mA capacity, the voltage at the last display may drop to 3.0V due to wire resistance. For 8 displays, use a 5V supply with a 3.3V regulator rated for 2A, and place the regulator near the displays. Use thick wires (AWG 22) for power and ground. Also, add a 100 µF capacitor at the power input of each display to filter noise.

Let’s talk about software libraries. The TFT_eSPI library for Arduino supports multiple displays by defining separate CS pins in the User_Setup.h file. You can define up to 4 displays by setting TFT_CS, TFT_CS2, TFT_CS3, etc. The library automatically handles the CS switching. For example, you can call tft1.drawPixel(10, 10, RED); and tft2.drawPixel(10, 10, BLUE); to draw on different displays. The library uses a single SPI bus, so the displays update sequentially. This is the easiest way to daisy chain 2.4 inch displays with individual CS lines.

For a more advanced setup, you can use DMA (Direct Memory Access) on the ESP32 to send SPI data without CPU intervention. The ESP32’s SPI controller supports DMA, which can send data to multiple displays by toggling CS lines via GPIO. However, the CS toggling must be done manually, so you need to set up a DMA descriptor chain that includes CS control. This is complex but reduces CPU load. For example, you can set up a DMA buffer for each display and chain them, so the SPI controller sends data to display 1, then display 2, without CPU intervention. This achieves a refresh rate of 60 Hz for 4 displays, but requires careful timing.

Now, let’s address the common misconception that you can daisy chain displays by connecting the SDO of one display to the SDI of the next. As I mentioned, this doesn’t work for ILI9341 or ST7789 because they don’t support pass-through. However, some displays with a “serial interface” like the SSD1306 OLED do support daisy chaining, but that’s a different technology. For 2.4 inch TFTs, the only reliable method is individual CS lines.

If you’re building a video wall with 2.4 inch displays, you need to consider the physical layout. Each display has a 2.4 inch diagonal, which is 60.96 mm. The active area is 48.96 mm x 36.72 mm (4:3 aspect ratio). For a 2x2 grid, the total area is 97.92 mm x 73.44 mm, with a bezel of about 2 mm per display. The bezel adds up to 4 mm between displays, so the total width is 101.92 mm. You can mount the displays on a PCB or a custom frame. The SPI wires should be kept short, under 10 cm, to avoid signal degradation. Use twisted-pair wires for SCK and MOSI to reduce crosstalk.

For a 3x3 grid (9 displays), you need 9 CS lines. Using a 74HC138 decoder, you can control 8 displays with 3 address lines, but for 9 displays, you need two decoders or a 74HC595 shift register. The shift register can handle 8 CS lines, but you can cascade two shift registers for 16 CS lines. The code to control the shift register is straightforward: you send a byte to the shift register, where each bit corresponds to a CS line. For example, to select display 3, you send 0x04 (binary 00000100) to the shift register, which pulls the third CS line low.

Here’s a timing diagram for the shift register approach:

1. Set latch pin low.
2. Send 8 bits (data, clock) to shift register.
3. Set latch pin high to update outputs.
4. Send SPI data to the selected display.
5. Set latch pin low again to deselect.

This adds about 10 µs of overhead per display, which is negligible for most applications.

Another consideration is the display’s backlight. Each 2.4 inch display has a backlight LED that draws 40-60 mA at 3.3V. If you daisy chain 8 displays, the backlight current is 320-480 mA. You can control the backlight with a MOSFET or a PWM pin to dim the displays. For example, use an IRLZ44N MOSFET to switch the backlight on/off, or use a PWM pin on the microcontroller to control brightness. If you want all displays to have the same brightness, you can connect all backlight LEDs in parallel, but ensure the current is limited with a resistor. For 8 displays, the total backlight current is 400 mA, so use a 1A MOSFET and a 10 ohm resistor to limit current to 400 mA at 3.3V.

Let’s talk about the software architecture for multiple displays. You can use a framebuffer for each display, or a single framebuffer with a region for each display. For a 2x2 grid, you can create a virtual canvas of 480x480 pixels (2x2 displays, each 240x240). Then, you map each quadrant to a display. The TFT_eSPI library supports this by setting the viewport for each display. For example, you set the viewport of display 1 to (0,0,239,239), display 2 to (240,0,479,239), etc. Then, you draw on the virtual canvas, and the library automatically clips to the viewport. This is efficient for graphics applications.

For data-intensive applications like video playback, you need to update the displays at 30 fps. Each frame requires 153,600 bytes per display, so 1.23 MB for 8 displays. The SPI bus at 20 MHz can transfer 2.5 MB/s, so you can update all 8 displays in 0.5 seconds, which is 2 fps. To achieve 30 fps, you need to reduce the data rate by using 8-bit color (1 byte per pixel) or by updating only changed regions. Another option is to use parallel interfaces, but that requires more pins.

In summary, the key to daisy chaining multiple 2.4 inch displays is to use individual CS lines with a shared SPI bus. For more than 4 displays, use a decoder or shift register to expand CS lines. Ensure adequate power supply with decoupling capacitors, and keep SPI traces short. Use the TFT_eSPI library for easy software control. Avoid true daisy chaining unless the display supports it, which is rare for 2.4 inch TFTs. With proper planning, you can drive up to 8 displays from a single microcontroller, achieving a refresh rate of 10-20 fps for static images.

Filed under The Sideline · About the author East Coast Sports News