The features on this page require CircuitPython 6.2 or later (including 6.2.0-alpha.1)

If you have multiple identical panels, you can extend a single display across them, vertically, horizontally, or both.

led_matrices_matrices-tiled-from-back.jpg
Back view of four 64x32 panels in a 2x2 arrangement. The MatrixPortal controller is at top left.

Inspect the rear of your panel. There are two 10-pin connectors. You can "chain" multiple displays by using a ribbon cable to hook the "OUT" of one panel to the "IN" of the next panel.

Many of Adafruit's panels include a ribbon cable; check the description.

Next, you'll need to power all your panels. Each panel has a 4-pin power connector, and most of Adafruit's panels include a Y-splitter power cable which can be connected to 2 panels. The power supply current requirement increases according to the number of panels, but the voltage requirement is always 5V. Remember that we recommend a 5V 4A supply for a single 64x32 pixel panel, so our recommendation becomes 4×2=8A for 2 panels and 4×4=16A for 4 panels.  By using dimmer colors and avoiding big solid areas on the display, you may be able to get by with a smaller power supply.

An insufficient power supply is frequent problem and can lead to flickering and jumbled displays.

More displays also means more memory (RAM) usage. Using bit_depth=6, approximate RAM usage is as follows:

  • one 64×32 panel uses 17kB
  • two 64×32 panels use 33kB
  • four 64×32 panels use 65kB

Using bit_depth=3, approximate RAM usage is as follows:

  • one 64×32 panel uses 11kB
  • two 64×32 panels use 21kB
  • four 64×32 panels use 42kB

Using bit_depth=1, approximate RAM usage is as follows:

  • one 64×32 panel uses 7kB
  • two 64×32 panels use 13kB
  • four 64×32 panels use 25kB

The total number of panels is limited by RAM usage, CPU usage and refresh rate. Other arrangements than those shown, such as 1×3, 3×1, 2x3, 3x2, etc., are possible.

Chaining and Tiling

This script for MatrixPortal will be used to demonstrate the different chaining and tiling options:

import displayio
import board
import rgbmatrix
import framebufferio

bit_depth = 1
base_width = 64
base_height = 32
chain_across = 1
tile_down = 1
serpentine = True

width = base_width * chain_across
height = base_height * tile_down

addr_pins = [board.MTX_ADDRA, board.MTX_ADDRB, board.MTX_ADDRC, board.MTX_ADDRD]
rgb_pins = [
    board.MTX_R1,
    board.MTX_G1,
    board.MTX_B1,
    board.MTX_R2,
    board.MTX_G2,
    board.MTX_B2,
]
clock_pin = board.MTX_CLK
latch_pin = board.MTX_LAT
oe_pin = board.MTX_OE

displayio.release_displays()
matrix = rgbmatrix.RGBMatrix(
                width=width,
                height=height,
                bit_depth=bit_depth,
                rgb_pins=rgb_pins,
                addr_pins=addr_pins,
                clock_pin=clock_pin,
                latch_pin=latch_pin,
                output_enable_pin=oe_pin,
                tile=tile_down, serpentine=serpentine,
            )
display = framebufferio.FramebufferDisplay(matrix)

We'll focus on the effect of these 3 settings:

  • chain_across
  • tile_down
  • serpentine

Note how chain_across is used to calculate the width from the base_width and similarly that tile_down is used to calculate the height from the base_height.

The total number of displays is chain_across * tile_down.

The top-right panel (before rotation) is always the one that has the MatrixPortal or incoming ribbon cable attached to it.

Purely horizontal arrangements

  • chain_across = 1
  • tile_down = 1
  • serpentine doesn't matter

Uses a single panel, size is 64x32

  • chain_across = 2
  • tile_down = 1
  • serpentine doesn't matter

Uses two panels, total display size is 128x32

  • chain_across = 4
  • tile_down = 1
  • serpentine doesn't matter

Uses four panels, total display size is 256x32

Purely vertical arrangements

The value called "serpentine" controls whether every alternate row of panels is rotated 180 degrees. This is generally more convenient, due to the positions of the connectors. The approximate path of the ribbon cables are shown with the arrows.

  • chain_across = 1
  • tile_down = 4
  • serpentine = True

Uses four panels, total display size is 64x128. Notice how displays 2 and 4 are rotated 180 degrees to minimize the length of ribbon cables required.

  • chain_across = 1
  • tile_down = 4
  • serpentine = False

Uses four panels, total display size is 64x128. Note how the ribbon cables are longer than with serpentine=True. This is usually less convenient.

Rectangular arrangements

  • chain_across = 2
  • tile_down = 2
  • serpentine = True

Uses four panels, total display size is 128x64. Note how displays 3 and 4 are rotated 180 degrees to minimize the length of ribbon cables required.

  • chain_across = 2
  • tile_down = 2
  • serpentine = False

Uses four panels, total display size is 128x64.

Note how long the ribbon cable is from panel 2 to 3. This is why the "serpentine" arrangement is usual preferable to the non-serpentine arrangement.

The effect of display rotation

All of the above examples show a display with rotation=0. You can change the rotation of a screen by passing in a rotation= parameter to the FramebufferDisplay constructor, or by setting the .rotation property of the display object at any time.

This rotation, which can be any of 0, 90, 180, or 270 degrees counterclockwise, affects the whole display rather than the individual panels.

display.rotation = 90

display.rotation = 180

display.rotation = 270

This guide was first published on Apr 20, 2020. It was last updated on Dec 18, 2021.

This page (Advanced: Multiple Panels) was last updated on Jan 28, 2021.

Text editor powered by tinymce.