# LED Matrix FIFA World Cup Scoreboard

## Overview

![](https://cdn-learn.adafruit.com/assets/assets/000/144/016/medium800thumb/led_matrices_twoGames.jpg?1777391828)

You can build a large RGB LED matrix display to follow along with the FIFA World Cup. A Matrix Portal S3 running CircuitPython requests data from the ESPN API to show the tournament gameplay data alongside country flags that are resized and gamma corrected to look crisp and bright on the matrices.&nbsp;

## Hardware and Power Requirements

The ESPN API generates a JSON response that is _huge_. It also takes a lot of processing power to interface with not one, not two, but four 64x32 RGB LED matrices. Luckily the ESP32-S3 on the Matrix Portal S3 is able to handle the JSON and the matrices with its 8MB of flash and 2MB of SRAM. Previously this project would not have been possible with less powerful chips, like the SAMD51 on the original Matrix Portal. **TL;DR: make sure you are using a Matrix Portal S3 for this project**.

Warning: 

On top of processing power, four RGB LED matrices require a good power supply to ensure top pixel performance. In working on this project, the **best results were seen using two 5V 4A power supplies** : one for the two top panels and one for the two bottom panels. In this scenario, the Matrix Portal S3 is powered via its USB-C port, separately from the matrices.

Warning: 

## Parts
Featured
### Adafruit Matrix Portal S3 CircuitPython Powered Internet Display

[Adafruit Matrix Portal S3 CircuitPython Powered Internet Display](https://www.adafruit.com/product/5778)
Folks love our [wide selection of RGB matrices](https://www.adafruit.com/category/327) and accessories&nbsp;for making custom colorful LED displays... and our RGB Matrix Shields and FeatherWings can be quickly soldered together to make the wiring much easier. But what if we made it...

Out of Stock
[Buy Now](https://www.adafruit.com/product/5778)
[Related Guides to the Product](https://learn.adafruit.com/products/5778/guides)
![Video of Adafruit Matrix Portal S3 linked up to a matrix displaying the "Adafruit Matrix Portal" in white letters and red, green and blue circles jumping around. ](https://cdn-shop.adafruit.com/product-videos/640x480/5778-06.jpg)

Featured
### USB Type A to Type C Cable - approx 1 meter / 3 ft long

[USB Type A to Type C Cable - approx 1 meter / 3 ft long](https://www.adafruit.com/product/4474)
As technology changes and adapts, so does Adafruit. This&nbsp;&nbsp; **USB Type A to Type C** cable will help you with the transition to USB C, even if you're still totin' around a USB Type A hub, computer or laptop.

USB C is the latest industry-standard connector for...

In Stock
[Buy Now](https://www.adafruit.com/product/4474)
[Related Guides to the Product](https://learn.adafruit.com/products/4474/guides)
![Angled shot of a coiled black, USB-C to USB-A cable.](https://cdn-shop.adafruit.com/640x480/4474-02.jpg)

### Four 64x32 RGB LED Matrices:
Featured
### 64x32 RGB LED Matrix - 4mm pitch

[64x32 RGB LED Matrix - 4mm pitch](https://www.adafruit.com/product/2278)
Bring a little bit of Times Square into your home with this sweet 64 x 32 square RGB LED matrix panel. These panels are normally used to make video walls, here in New York we see them on the sides of busses and bus stops, to display animations or short video clips. We thought they looked...

In Stock
[Buy Now](https://www.adafruit.com/product/2278)
[Related Guides to the Product](https://learn.adafruit.com/products/2278/guides)
![Two white hands hold out an assembled and powered on 64x32 RGB LED Matrix Panel - 4mm pitch. The matrix displays "Adafruit Industries LED MATRIX! 32x64 *RGB*"](https://cdn-shop.adafruit.com/640x480/2278-00.jpg)

### Four Acrylic Panels:
Featured
### Black LED Diffusion Acrylic Panel - 10.2" x 5.1"

[Black LED Diffusion Acrylic Panel - 10.2" x 5.1"](https://www.adafruit.com/product/4749)
&nbsp;nice whoppin' rectangular slab of some lovely black acrylic to add some extra diffusion to your LED Matrix project. This material is 2.6mm (0.1") thick and is made of special cast acrylic that makes it perfect for glowy projects, especially matrices or NeoPixels.

Unlike...

In Stock
[Buy Now](https://www.adafruit.com/product/4749)
[Related Guides to the Product](https://learn.adafruit.com/products/4749/guides)
![LED RGB matrix 10.2" x 5.1" with "Adafruit Industries LED Matrix" text showing, and LED acrylic slowly covering to make it nicely diffused](https://cdn-shop.adafruit.com/product-videos/640x480/4749-02.jpg)

### Two 5V 4A Power Supplies:
Featured
### 5V 4A (4000mA) switching power supply - UL Listed

[5V 4A (4000mA) switching power supply - UL Listed](https://www.adafruit.com/product/1466)
Need a lot of 5V power? This switching supply gives a clean regulated 5V output at up to **4 Amps** (4000mA). 110 or 240 input, so it works in any country. The plugs are "US 2-prong" style so you may need a plug adapter, but you can pick one up at any hardware store for $1 or so,...

In Stock
[Buy Now](https://www.adafruit.com/product/1466)
[Related Guides to the Product](https://learn.adafruit.com/products/1466/guides)
![Angled shot of 5V 4A switching power supply brick with power cable.](https://cdn-shop.adafruit.com/640x480/1466-10.jpg)

### Two Female DC Jack to Screw Terminal Block Adapters:
Featured
### Female DC Power adapter - 2.1mm jack to screw terminal block

[Female DC Power adapter - 2.1mm jack to screw terminal block](https://www.adafruit.com/product/368)
If you need to connect a DC power wall wart to a board that doesn't have a DC jack - this adapter will come in very handy! There is a 2.1mm DC jack on one end, and a screw terminal block on the other. The terminals are labeled with positive/negative assuming a positive-tip configuration...

Out of Stock
[Buy Now](https://www.adafruit.com/product/368)
[Related Guides to the Product](https://learn.adafruit.com/products/368/guides)
![Angle shot Female DC Power adapter - 2.1mm jack to screw terminal block](https://cdn-shop.adafruit.com/640x480/368-03.jpg)

### Clear Adhesive Squares - 6 pack

quantity: 3
[Clear Adhesive Squares - 6 pack](https://www.adafruit.com/product/4813)
 **UGlu Dashes** &nbsp;are perfect for a variety of small projects. These adhesive squares provide a stronger bond to most surfaces and are cleaner and easier to remove&nbsp;without the wait, mess, or hassle.

Adheres to a wide variety of surfaces, including, but not limited...

In Stock
[Buy Now](https://www.adafruit.com/product/4813)
[Related Guides to the Product](https://learn.adafruit.com/products/4813/guides)
![ 6 pack of Clear Adhesive Squares](https://cdn-shop.adafruit.com/640x480/4813-01.jpg)

### Black Nylon Machine Screw and Stand-off Set – M3 Thread

[Black Nylon Machine Screw and Stand-off Set – M3 Thread](https://www.adafruit.com/product/4685)
Totaling **420 pieces** , this **M3 Screw Set** &nbsp;is a must-have for your workstation.&nbsp;You'll have enough screws, nuts, and hex standoffs to fuel your maker tendencies&nbsp;for days on end! M3 size screws fit a number of&nbsp;Adafruit breakout/dev board...

In Stock
[Buy Now](https://www.adafruit.com/product/4685)
[Related Guides to the Product](https://learn.adafruit.com/products/4685/guides)
![Opened box showing many nylon screws](https://cdn-shop.adafruit.com/640x480/4685-01.jpg)

# LED Matrix FIFA World Cup Scoreboard

## 3D Printing

![](https://cdn-learn.adafruit.com/assets/assets/000/124/411/medium800/led_matrices_edited_P1410429.jpg?1694713812)

You can 3D print brackets to hold the matrices together. Note that these have been designed to fit the [4mm pitch matrices](https://www.adafruit.com/product/2278). You'll print one center bracket and six of the smaller 1x2 brackets. The parts can be downloaded from Printables or directly below.

[Printables Download](https://www.printables.com/model/582588-brackets-for-rgb-led-matrices-4mm-pitch)
[RGB_LED_Matrix_Brackets_4mm_Pitch.zip](https://cdn-learn.adafruit.com/assets/assets/000/124/414/original/RGB_LED_Matrix_Brackets_4mm_Pitch.zip?1694714174)
Info: 

A plus sign shaped bracket fits over the intersection in the middle of the four matrices. It is secured with four M3 screws.

![led_matrices_edited_P1410430.jpg](https://cdn-learn.adafruit.com/assets/assets/000/124/412/medium640/led_matrices_edited_P1410430.jpg?1694713822)

Small 1x2 brackets secure the matrices together along the seams with M3 screws.

![led_matrices_edited_P1410432.jpg](https://cdn-learn.adafruit.com/assets/assets/000/124/413/medium640/led_matrices_edited_P1410432.jpg?1694713870)

# LED Matrix FIFA World Cup Scoreboard

## Install CircuitPython

[CircuitPython](https://github.com/adafruit/circuitpython) is a derivative of [MicroPython](https://micropython.org) designed to simplify experimentation and education on low-cost microcontrollers. It makes it easier than ever to get prototyping by requiring no upfront desktop software downloads. Simply copy and edit files on the **CIRCUITPY** drive to iterate.

## Set up CircuitPython Quick Start!

Follow this quick step-by-step for super-fast Python power :)

Info: 

[Download the latest version of CircuitPython for this board via circuitpython.org](https://circuitpython.org/board/adafruit_matrixportal_s3/)
## Further Information

For more detailed info on installing CircuitPython, check out [Installing CircuitPython](https://learn.adafruit.com/welcome-to-circuitpython/installing-circuitpython).

 **Click the link above and download the latest UF2 file.**

Download and save it to your desktop (or wherever is handy).

![led_matrices_Save_to_Desktop.png](https://cdn-learn.adafruit.com/assets/assets/000/095/075/medium640/led_matrices_Save_to_Desktop.png?1601050695)

Plug your MatrixPortal S3 into your computer using a known-good USB cable.

**A lot of people end up using charge-only USB cables and it is very frustrating! So make sure you have a USB cable you know is good for data sync.**

Click the **Reset** button (indicated by the green arrow) on your board. When you see the NeoPixel RGB LED (indicated by the magenta arrow) turn purple, press it again. At that point, the NeoPixel should turn green. If it turns red, check the USB cable, try another USB port, etc.

If double-clicking doesn't work the first time, try again. Sometimes it can take a few tries to get the rhythm right!

![led_matrices_Buttons.jpg](https://cdn-learn.adafruit.com/assets/assets/000/126/017/medium640/led_matrices_Buttons.jpg?1699492993)

Info: 

You will see a new disk drive appear called **MATRXS3BOOT**.

Drag the **adafruit\_circuitpython\_etc.uf2** file over to **MATRXS3BOOT****.**

![led_matrices_matrix.png](https://cdn-learn.adafruit.com/assets/assets/000/126/018/medium640/led_matrices_matrix.png?1699493436)

The LED will flash. Then, the **MATRXS3BOOT** &nbsp;drive will disappear and a new disk drive called **CIRCUITPY** will appear.

That's it, you're done! :)

![led_matrices_CircuitPy.png](https://cdn-learn.adafruit.com/assets/assets/000/122/618/medium640/led_matrices_CircuitPy.png?1689369656)

# LED Matrix FIFA World Cup Scoreboard

## Create Your settings.toml File

CircuitPython works with WiFi-capable boards to enable you to make projects that have network connectivity. This means working with various passwords and API keys. As of [CircuitPython 8](https://circuitpython.org/downloads), there is support for a **settings.toml** file. This is a file that is stored on your **CIRCUITPY** drive, that contains all of your secret network information, such as your SSID, SSID password and any API keys for IoT services. It is designed to separate your sensitive information from your **code.py** file so you are able to share your code without sharing your credentials.

CircuitPython previously used a **secrets.py** file for this purpose. The **settings.toml** file is quite similar.

Warning: Your **settings.toml** file should be stored in the main directory of your **CIRCUITPY** drive. It should not be in a folder.

## CircuitPython **settings.toml** File

This section will provide a couple of examples of what your **settings.toml** file should look like, specifically for CircuitPython WiFi projects in general.

The most minimal **settings.toml** file must contain your WiFi SSID and password, as that is the minimum required to connect to WiFi. Copy this example, paste it into your **settings.toml** , and update:

- `your_wifi_ssid`
- `your_wifi_password`

```auto
CIRCUITPY_WIFI_SSID = "your_wifi_ssid"
CIRCUITPY_WIFI_PASSWORD = "your_wifi_password"
```

Many CircuitPython network-connected projects on the Adafruit Learn System involve using Adafruit IO. For these projects, you must _also_ include your Adafruit IO username and key. Copy the following example, paste it into your settings.toml file, and update:

- `your_wifi_ssid`
- `your_wifi_password`
- `your_aio_username`
- `your_aio_key`

```auto
CIRCUITPY_WIFI_SSID = "your_wifi_ssid"
CIRCUITPY_WIFI_PASSWORD = "your_wifi_password"
ADAFRUIT_AIO_USERNAME = "your_aio_username"
ADAFRUIT_AIO_KEY = "your_aio_key"
```

Some projects use different variable names for the entries in the **settings.toml** file. For example, a project might use `ADAFRUIT_AIO_ID` in the place of `ADAFRUIT_AIO_USERNAME`. **If you run into connectivity issues, one of the first things to check is that the names in the settings.toml file match the names in the code.**

Warning: Not every project uses the same variable name for each entry in the **settings.toml** file! Always verify it matches the code.

## **settings.toml** File Tips
Here is an example **settings.toml** file.

```auto
# Comments are supported
CIRCUITPY_WIFI_SSID = "guest wifi"
CIRCUITPY_WIFI_PASSWORD = "guessable"
CIRCUITPY_WEB_API_PORT = 80
CIRCUITPY_WEB_API_PASSWORD = "passw0rd"
test_variable = "this is a test"
thumbs_up = "\U0001f44d"
```

In a **settings.toml** file, it's important to keep these factors in mind:

- Strings are wrapped in double quotes; ex: `"your-string-here"`
- Integers are _ **not** _ quoted and may be written in decimal with optional sign (`+1`, `-1`, `1000`) or hexadecimal (`0xabcd`).
  - Floats (decimal numbers), octal (`0o567`) and binary (`0b11011`) are not supported.

- Use `\u` escapes for weird characters, `\x` and `\ooo` escapes are not available in **.toml** files
  - Example: `\U0001f44d` for 👍 (thumbs up emoji) and `\u20ac` for € (EUR sign)

- Unicode emoji, and non-ASCII characters, stand for themselves as long as you're careful to save in "UTF-8 without BOM" format

&nbsp;

&nbsp;

When your&nbsp; **settings.toml&nbsp;** file is ready, you can save it in your text editor with the **.toml** &nbsp;extension.

![adafruit_products_dotToml.jpg](https://cdn-learn.adafruit.com/assets/assets/000/117/071/medium640/adafruit_products_dotToml.jpg?1671034293)

## Accessing Your **settings.toml** Information in **code.py**
In your **code.py** file, you'll need to `import` the `os` library to access the **settings.toml** file. Your settings are accessed with the `os.getenv()` function. You'll pass your settings entry to the function to import it into the **code.py** file.

```python
import os

print(os.getenv("test_variable"))
```

![](https://cdn-learn.adafruit.com/assets/assets/000/117/072/medium800/adafruit_products_tomlOutput.jpg?1671034496)

In the upcoming CircuitPython WiFi examples, you'll see how the **settings.toml&nbsp;** file is used for connecting to your SSID and accessing your API keys.

# LED Matrix FIFA World Cup Scoreboard

## Code the Scoreboard

Once you've finished setting up your Matrix Portal S3 with CircuitPython, you can access the code and necessary libraries by downloading the Project Bundle.

To do this, click on the **Download Project Bundle** button in the window below. It will download to your computer as a zipped folder.

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Matrix_Portal/FIFA_World_Cup_Display/code.py

## Upload the Code and Libraries to the Matrix Portal S3

After downloading the Project Bundle, plug your Matrix Portal S3 into the computer's USB port with a known good USB data+power cable. You should see a new flash drive appear in the computer's File Explorer or Finder (depending on your operating system) called **CIRCUITPY**. Unzip the folder and copy the following items to the Matrix Portal S3's **CIRCUITPY** drive.

- **lib** folder
- **team\_logos** folder
- **code.py**

Your Matrix Portal S3 **CIRCUITPY** drive should look like this after copying the **lib** folder, **team\_logos** folder and the **code.py** file.

![CIRCUITPY drive](https://adafruit.github.io/Adafruit_Learning_System_Guides/Matrix_Portal_FIFA_World_Cup_Display.png )

## Add Your **settings.toml** File

As of CircuitPython 8.0.0, there is support for [Environment Variables](https://docs.circuitpython.org/en/latest/docs/environment.html). Environment variables are stored in a **settings.toml** file. Similar to **secrets.py** , the **settings.toml** file separates your sensitive information from your main **code.py** file. Add your **settings.toml** file as described in the [Create Your settings.toml File page](https://learn.adafruit.com/led-matrix-sports-scoreboard/create-your-settings-toml-file) earlier in this guide. You'll need to include your `CIRCUITPY_WIFI_SSID` and `CIRCUITPY_WIFI_PASSWORD`.

```python
CIRCUITPY_WIFI_SSID = "your-ssid-here"
CIRCUITPY_WIFI_PASSWORD = "your-ssid-password-here"
```

## How the CircuitPython Code Works

At the top of the code are a few variables that are used throughout:

- `font_color` - the color of the font used for all of the text on the Matrix. It defaults to white (`0xFFFFFF`)
- `timezone_info` - your timezone UTC offset and timezone name. Edit these if needed to match your timezone
- `fetch_timer` - how often the ESPN API should be pinged to update the display (defaults to 5 minutes (300 seconds))
- `display_timer` - how often the display should update to rotate through the different games (defaults to 30 seconds)

```python
# font color for text on matrix
font_color = 0xFFFFFF
# your timezone UTC offset and timezone name
timezone_info = [-4, "EDT"]
# how often the API should be fetched
fetch_timer = 300 # seconds
# how often the display should update
display_timer = 30 # seconds
```

### Matrix

An `RGBMatrix` object is instantiated to be 128 pixels wide by 64 pixels high. It is then passed to be a `FramebufferDisplay`.

```python
# matrix setup
base_width = 64
base_height = 32
chain_across = 2
tile_down = 2
DISPLAY_WIDTH = base_width * chain_across
DISPLAY_HEIGHT = base_height * tile_down
matrix = rgbmatrix.RGBMatrix(
    width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, bit_depth=4,
    rgb_pins=[
        board.MTX_R1,
        board.MTX_G1,
        board.MTX_B1,
        board.MTX_R2,
        board.MTX_G2,
        board.MTX_B2
    ],
    addr_pins=[
        board.MTX_ADDRA,
        board.MTX_ADDRB,
        board.MTX_ADDRC,
        board.MTX_ADDRD
    ],
    clock_pin=board.MTX_CLK,
    latch_pin=board.MTX_LAT,
    output_enable_pin=board.MTX_OE,
    tile=tile_down, serpentine=True,
    doublebuffer=False
)
display = framebufferio.FramebufferDisplay(matrix)
```

### API URL

The `SPORT_URL` is the API URL for accessing the scoreboard data for the World Cup. The `games` array will hold a dictionary with information from the API requests and the `groups` array will hold displayio groups to show on the matrix.

```python
# connect to WIFI
wifi.radio.connect(os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD"))
print(f"Connected to {os.getenv('CIRCUITPY_WIFI_SSID')}")

# add API URLs
SPORT_URL = "https://site.api.espn.com/apis/site/v2/sports/soccer/fifa.world/scoreboard"

context = ssl.create_default_context()
pool = socketpool.SocketPool(wifi.radio)
requests = adafruit_requests.Session(pool, context)

# arrays for games and display groups
# the length and entries for both will vary depending on API response
games = []
groups = []
```

### UTC to Your Time Zone

The `convert_date_format()` function is used to reformat the time that is fetched from the ESPN API. It rearranges the string to be formatted as "MM/DD - HH:MM AM/PM TZ" and converts the time from UTC to your defined time zone.

```python
# takes UTC time from JSON and reformats how its displayed
def convert_date_format(date, tz_information):
    # Manually extract year, month, day, hour, and minute from the string
    year = int(date[0:4])
    month = int(date[5:7])
    day = int(date[8:10])
    hour = int(date[11:13])
    minute = int(date[14:16])
    # Construct a datetime object using the extracted values
    dt = datetime(year, month, day, hour, minute)
    # Adjust the datetime object for the target timezone offset
    dt_adjusted = dt + timedelta(hours=tz_information[0])
    # Extract fields for output format
    month = dt_adjusted.month
    day = dt_adjusted.day
    hour = dt_adjusted.hour
    minute = dt_adjusted.minute
    # Convert 24-hour format to 12-hour format and determine AM/PM
    am_pm = "AM" if hour < 12 else "PM"
    hour_12 = hour if hour <= 12 else hour - 12
    minute = f"{minute:02}"
    # Determine the timezone abbreviation based on the offset
    time_zone_str = tz_information[1]
    return f"{month}/{day} - {hour_12}:{minute} {am_pm} {time_zone_str}"
```

### Fetch the Data

The `get_data()` function handles making a request to the ESPN API and populating the `games` list with a dictionary from the returned JSON feed. The following information is used for the display:

- Name of the match (`shortName`)
  - The team names are extracted from this string

- Date
- Score
- Game clock
- Location (City)
- Game status

You can update this function to get different information from the API depending on what matters most to you.&nbsp;

```python
def get_data(data, dictionary):
    dictionary.clear()
    pixel.fill((0, 0, 255))
    print(f"Fetching data from {data}")
    # make the request to the API
    resp = requests.get(data)
    # json
    json_data = resp.json()
    for i in range(len(json_data["events"])):
        match_name = json_data["events"][i]["shortName"]
        print(match_name)
        date = json_data["events"][i]["date"]
        date = convert_date_format(date, timezone_info)
        home_team = match_name[0:3]
        away_team = match_name[6:9]
        score_home = json_data["events"][i]["competitions"][0]["competitors"][0]["score"]
        score_away = json_data["events"][i]["competitions"][0]["competitors"][1]["score"]
        clock = json_data["events"][i]["status"]["displayClock"]
        location = json_data["events"][i]["competitions"][0]["venue"]["address"]["city"]
        status = json_data["events"][i]["status"]["type"]["shortDetail"]
        dictionary.append({"home": home_team, "away": away_team, "score_home": score_home,
                           "score_away": score_away, "date": date, "clock": clock, "status": status,
                           "location": location})
    # debug printing
    # print(dictionary)
    got_data = True
    return dictionary, got_data
```

### Show the Data

The `make_gfx()` function takes the dictionary and creates text labels with the information from the API. The country flag is loaded in as a bitmap depending on who is playing in the game. All of the graphics elements are pushed to a group that is then added to the groups list to be accessed for showing on the matrix.

```python
def make_gfx(dictionary, grps): # pylint: disable=too-many-locals
    grps.clear()
    for i in range(len(dictionary)):
        # check if it's pre-game
        if dictionary[i]["status"] == "Scheduled":
            status = "pre"
            print("match, pre-game")
        else:
            status = dictionary[i]["status"]
        # make a display group
        grp = displayio.Group()
        # load in logos
        logo0 = "/team_logos/" + dictionary[i]["home"] + ".bmp"
        bitmap0 = displayio.OnDiskBitmap(logo0)
        grid0 = displayio.TileGrid(bitmap0, pixel_shader=bitmap0.pixel_shader, x = 2)
        grp.append(grid0) # index 0
        logo1 = "/team_logos/" + dictionary[i]["away"] + ".bmp"
        bitmap1 = displayio.OnDiskBitmap(logo1)
        grid1 = displayio.TileGrid(bitmap1, pixel_shader=bitmap1.pixel_shader, x = 94)
        grp.append(grid1) # index 1
        home_text = adafruit_display_text.label.Label(terminalio.FONT, color=font_color,
                                                  text=" ")
        home_text.text=dictionary[i]["home"]
        home_text.anchor_point = (0.0, 0.5)
        home_text.anchored_position = (10, 32)
        grp.append(home_text) # index 2
        away_text = adafruit_display_text.label.Label(terminalio.FONT, color=font_color,
                                                      text=" ")
        away_text.text=dictionary[i]["away"]
        away_text.anchor_point = (1.0, 0.5)
        away_text.anchored_position = (120, 32)
        grp.append(away_text) # index 3
        vs_text = adafruit_display_text.label.Label(terminalio.FONT, color=font_color,
                                                    text=" ")
        vs_text.anchor_point = (0.5, 0.0)
        vs_text.anchored_position = (DISPLAY_WIDTH / 2, 14)
        grp.append(vs_text) # index 4
        info_text = adafruit_display_text.label.Label(terminalio.FONT, color=font_color,
                                                    text=" ")
        info_text.anchor_point = (0.5, 1.0)
        info_text.anchored_position = (DISPLAY_WIDTH / 2, DISPLAY_HEIGHT)
        grp.append(info_text) # index 5
        location_text = adafruit_display_text.label.Label(terminalio.FONT, color=font_color,
                                                    text=f"{dictionary[i]['location']}")
        location_text.anchor_point = (0.5, 1.0)
        location_text.anchored_position = (DISPLAY_WIDTH / 2, DISPLAY_HEIGHT - 12)
        grp.append(location_text) # index 6
        if status == "pre":
            vs_text.text="VS"
            info_text.text=dictionary[i]["date"]
        # if it's active or final show score
        else:
            info_text.text=f"Clock: {dictionary[i]['clock']}"
            vs_text.text=f"{dictionary[i]['score_home']} - {dictionary[i]['score_away']}"
        grps.append(grp)
    return grps
```

### Clocks and First Fetch

Before the loop, the `get_data()` and `make_gfx()` functions are called to get the initial API info and graphics. `ticks` is used in the loop for timekeeping. The `fetch_clock` and `display_clock` are setup as `ticks` clocks.

```python
# clock for fetching
fetch_timer = fetch_timer * 1000
# index and clock for updating display
display_index = 0
display_timer = display_timer * 1000

# initial data fetch
try:
    games, just_fetched = get_data(SPORT_URL, games)
    groups = make_gfx(games, groups)
    display.root_group = groups[display_index]
# pylint: disable=broad-except
except Exception as Error:
    print(f"Error: {Error}")
    time.sleep(10)
    gc.collect()
    time.sleep(5)
    microcontroller.reset()
# start clocks
fetch_clock = ticks_ms()
display_clock = ticks_ms()
```

### The Loop

Two processes are happening concurrently in the loop with the help of `ticks`. The matrices are cycling through the display groups by advancing through the `groups` array. The API is fetched on a different timer. The `make_gfx()` function is called immediately after, which allows for the graphics being shown to be updated.

```python
while True:
    try:
        if not just_fetched:
            # garbage collection for display groups
            gc.collect()
            # fetch the json for the next team
            games, just_fetched = get_data(SPORT_URL, games)
            groups = make_gfx(games, groups)
            # reset clocks
            fetch_clock = ticks_add(fetch_clock, fetch_timer)
            display_clock = ticks_add(display_clock, display_timer)
        # update display seperate from API request
        if ticks_diff(ticks_ms(), display_clock) >= display_timer:
            print("updating display")
            display.root_group = groups[display_index]
            display_index = (display_index + 1) % len(games)
            info_clock = ticks_ms()
            display_clock = ticks_add(display_clock, display_timer)
        # cleared for fetching after time has passed
        if ticks_diff(ticks_ms(), fetch_clock) >= fetch_timer:
            just_fetched = False
    # pylint: disable=broad-except
    except Exception as Error:
        print(f"Error: {Error}")
        time.sleep(10)
        gc.collect()
        time.sleep(5)
        microcontroller.reset()
```

# LED Matrix FIFA World Cup Scoreboard

## Wiring and Assembly

![](https://cdn-learn.adafruit.com/assets/assets/000/124/415/medium800/led_matrices_editedWithAnotation_P1410435.jpg?1694715310)

Making sure your matrices are laid out in the correct order can be confusing. Before plugging in any cables, lay them out to make sure they are oriented properly. Each matrix has arrow markings which you can use to help during layout.

- Matrix 1 - This matrix will have the Matrix Portal S3 plugged into its IDC port on the left. Its arrow markings will be pointing up and to the right.
- Matrix 2 - This matrix is placed to the right of Matrix 1. Its arrow markings will be pointing up and to the right.
- Matrix 3 - This matrix is placed below Matrix 2. Its arrow markings will be pointing down and to the left.
- Matrix 4 - This matrix is placed to the left of Matrix 3 and below Matrix 1. Its arrow markings will be pointing down and to the left.

Once you have your four matrices laid out in the correct order you can start plugging in the IDC cables.

Plug an IDC cable into the right-hand port on Matrix 1 and the left-hand port on Matrix 2.

![led_matrices_editedAnotated_P1410436.jpg](https://cdn-learn.adafruit.com/assets/assets/000/124/416/medium640/led_matrices_editedAnotated_P1410436.jpg?1694715749)

Plug an IDC cable into the right-hand port on Matrix 2 and the right-hand port on Matrix 3.

![led_matrices_editedAnotated_P1410437.jpg](https://cdn-learn.adafruit.com/assets/assets/000/124/417/medium640/led_matrices_editedAnotated_P1410437.jpg?1694715843)

Plug the last IDC cable into the left-hand port on the Matrix 3 and the right-hand port on the Matrix 4. This completes the data wiring for the matrices.

![led_matrices_editedAnnotated_P1410438.jpg](https://cdn-learn.adafruit.com/assets/assets/000/124/418/medium640/led_matrices_editedAnnotated_P1410438.jpg?1694715918)

## 3D Printed Brackets
Place the center bracket over the intersection in the middle of the four matrices. Use the bracket to make sure that the matrices are aligned with each other. Secure it with four M3 screws.

![led_matrices_editedAnnotated_P1410439.jpg](https://cdn-learn.adafruit.com/assets/assets/000/124/419/medium640/led_matrices_editedAnnotated_P1410439.jpg?1694716056)

Use four 2x1 brackets to join the matrices together to the left and right of the center bracket. Secure the brackets with M3 screws.

![led_matrices_editedAnnotated_P1410441.jpg](https://cdn-learn.adafruit.com/assets/assets/000/124/421/medium640/led_matrices_editedAnnotated_P1410441.jpg?1694716181)

Use two 2x1 brackets to secure the matrices above and below the center bracket. Secure the brackets with M3 screws.

![led_matrices_editedAnnotated_P1410442.jpg](https://cdn-learn.adafruit.com/assets/assets/000/124/422/medium640/led_matrices_editedAnnotated_P1410442.jpg?1694716258)

## Power
Gather two power cables that came with your matrices. Plug one of the cables into the two power inputs on the top two matrices. Plug the other cable into the two power inputs on the bottom two matrices.

![led_matrices_editedAnnotated_P1410444.jpg](https://cdn-learn.adafruit.com/assets/assets/000/124/423/medium640/led_matrices_editedAnnotated_P1410444.jpg?1694716348)

Each power cable connector will be secured in a DC jack terminal block adapter.

![led_matrices_edited_P1410446.jpg](https://cdn-learn.adafruit.com/assets/assets/000/124/424/medium640/led_matrices_edited_P1410446.jpg?1694716410)

Secure the positive cable (red wire) into the positive terminal on the DC jack adapter (labeled with a raised +). Secure the ground cable (black wire) into the negative terminal on the DC jack adapter (labeled with a raised -). Repeat this for the second power cable.

![led_matrices_edited_P1410455.jpg](https://cdn-learn.adafruit.com/assets/assets/000/124/425/medium640/led_matrices_edited_P1410455.jpg?1694716443)

Now you can plug both sets of two matrices into 5V 4A power supplies.

## LED Acrylic
Remove the protective film from the shiny side of the LED acrylic.

![led_matrices_edited_P1410463.jpg](https://cdn-learn.adafruit.com/assets/assets/000/124/452/medium640/led_matrices_edited_P1410463.jpg?1695043441)

Place mounting tabs in the four corners of the acrylic.

![led_matrices_edited_P1410464.jpg](https://cdn-learn.adafruit.com/assets/assets/000/124/453/medium640/led_matrices_edited_P1410464.jpg?1695043512)

Attach the acrylic to one of the RGB LED panels, lining it up with the edges of the panel.

![led_matrices_edited_P1410465.jpg](https://cdn-learn.adafruit.com/assets/assets/000/124/454/medium640/led_matrices_edited_P1410465.jpg?1695043533)

Repeat this process for the three remaining RGB LED panels. Remove the protective film from the acrylic sheets.

![led_matrices_edited_P1410468.jpg](https://cdn-learn.adafruit.com/assets/assets/000/124/455/medium640/led_matrices_edited_P1410468.jpg?1695043581)

# LED Matrix FIFA World Cup Scoreboard

## Use

![](https://cdn-learn.adafruit.com/assets/assets/000/144/017/medium800/led_matrices_edited_P1490600.jpg?1777391840)

### Update Your Time Zone

The ESPN API stores the timestamp for games in UTC. There is a function in the code that converts the UTC time to your defined time zone. You'll add your time zone UTC offset and time zone name into the&nbsp;`timezone_info` array at the top of the code:

```python
# your timezone UTC offset and timezone name
timezone_info = [-4, "EDT"]
```

## Boot Up
Power up the Matrix Portal S3 via USB and the LED matrices with their power supplies. You'll see CircuitPython boot up, followed by showing the first result from the API request.

![](https://cdn-learn.adafruit.com/assets/assets/000/144/018/medium640thumb/led_matrices_boot.jpg?1777391880)

As the World Cup progresses, you'll see different games show up on the display. The code is written so that the display assets can dynamically update depending on how many games are active in the schedule.

![](https://cdn-learn.adafruit.com/assets/assets/000/144/019/medium640/led_matrices_edited_P1490598.jpg?1777391911)


## Guide Products

### Adafruit Matrix Portal S3 CircuitPython Powered Internet Display

[Adafruit Matrix Portal S3 CircuitPython Powered Internet Display](https://www.adafruit.com/product/5778)
Folks love our [wide selection of RGB matrices](https://www.adafruit.com/category/327) and accessories&nbsp;for making custom colorful LED displays... and our RGB Matrix Shields and FeatherWings can be quickly soldered together to make the wiring much easier. But what if we made it...

Out of Stock
[Buy Now](https://www.adafruit.com/product/5778)
[Related Guides to the Product](https://learn.adafruit.com/products/5778/guides)
### USB Type A to Type C Cable - approx 1 meter / 3 ft long

[USB Type A to Type C Cable - approx 1 meter / 3 ft long](https://www.adafruit.com/product/4474)
As technology changes and adapts, so does Adafruit. This&nbsp;&nbsp; **USB Type A to Type C** cable will help you with the transition to USB C, even if you're still totin' around a USB Type A hub, computer or laptop.

USB C is the latest industry-standard connector for...

In Stock
[Buy Now](https://www.adafruit.com/product/4474)
[Related Guides to the Product](https://learn.adafruit.com/products/4474/guides)
### 64x32 RGB LED Matrix - 4mm pitch

[64x32 RGB LED Matrix - 4mm pitch](https://www.adafruit.com/product/2278)
Bring a little bit of Times Square into your home with this sweet 64 x 32 square RGB LED matrix panel. These panels are normally used to make video walls, here in New York we see them on the sides of busses and bus stops, to display animations or short video clips. We thought they looked...

In Stock
[Buy Now](https://www.adafruit.com/product/2278)
[Related Guides to the Product](https://learn.adafruit.com/products/2278/guides)
### Black LED Diffusion Acrylic Panel - 10.2" x 5.1"

[Black LED Diffusion Acrylic Panel - 10.2" x 5.1"](https://www.adafruit.com/product/4749)
&nbsp;nice whoppin' rectangular slab of some lovely black acrylic to add some extra diffusion to your LED Matrix project. This material is 2.6mm (0.1") thick and is made of special cast acrylic that makes it perfect for glowy projects, especially matrices or NeoPixels.

Unlike...

In Stock
[Buy Now](https://www.adafruit.com/product/4749)
[Related Guides to the Product](https://learn.adafruit.com/products/4749/guides)
### 5V 4A (4000mA) switching power supply - UL Listed

[5V 4A (4000mA) switching power supply - UL Listed](https://www.adafruit.com/product/1466)
Need a lot of 5V power? This switching supply gives a clean regulated 5V output at up to **4 Amps** (4000mA). 110 or 240 input, so it works in any country. The plugs are "US 2-prong" style so you may need a plug adapter, but you can pick one up at any hardware store for $1 or so,...

In Stock
[Buy Now](https://www.adafruit.com/product/1466)
[Related Guides to the Product](https://learn.adafruit.com/products/1466/guides)
### Female DC Power adapter - 2.1mm jack to screw terminal block

[Female DC Power adapter - 2.1mm jack to screw terminal block](https://www.adafruit.com/product/368)
If you need to connect a DC power wall wart to a board that doesn't have a DC jack - this adapter will come in very handy! There is a 2.1mm DC jack on one end, and a screw terminal block on the other. The terminals are labeled with positive/negative assuming a positive-tip configuration...

Out of Stock
[Buy Now](https://www.adafruit.com/product/368)
[Related Guides to the Product](https://learn.adafruit.com/products/368/guides)
### Clear Adhesive Squares - 6 pack

[Clear Adhesive Squares - 6 pack](https://www.adafruit.com/product/4813)
 **UGlu Dashes** &nbsp;are perfect for a variety of small projects. These adhesive squares provide a stronger bond to most surfaces and are cleaner and easier to remove&nbsp;without the wait, mess, or hassle.

Adheres to a wide variety of surfaces, including, but not limited...

In Stock
[Buy Now](https://www.adafruit.com/product/4813)
[Related Guides to the Product](https://learn.adafruit.com/products/4813/guides)
### Black Nylon Machine Screw and Stand-off Set – M3 Thread

[Black Nylon Machine Screw and Stand-off Set – M3 Thread](https://www.adafruit.com/product/4685)
Totaling **420 pieces** , this **M3 Screw Set** &nbsp;is a must-have for your workstation.&nbsp;You'll have enough screws, nuts, and hex standoffs to fuel your maker tendencies&nbsp;for days on end! M3 size screws fit a number of&nbsp;Adafruit breakout/dev board...

In Stock
[Buy Now](https://www.adafruit.com/product/4685)
[Related Guides to the Product](https://learn.adafruit.com/products/4685/guides)

## Related Guides

- [Adafruit MatrixPortal S3](https://learn.adafruit.com/adafruit-matrixportal-s3.md)
- [May Pad Macropad with the KB2040, KMK, and CircuitPython](https://learn.adafruit.com/maypad-macropad-with-the-kb2040-kmk-and-circuitpython.md)
- [Blurry Analog Clock](https://learn.adafruit.com/blurry-analog-clock.md)
- [No-Code IoT Pool Monitor](https://learn.adafruit.com/iot-pool.md)
- [RGB LED Matrix Cube with 25,000 LEDs](https://learn.adafruit.com/rgb-led-matrix-cube-for-pi.md)
- [RPi Stock Alert Alarm](https://learn.adafruit.com/rpi-stock-alert-alarm.md)
- [DIY Pico Mechanical Keyboard with Fritzing and CircuitPython](https://learn.adafruit.com/diy-pico-mechanical-keyboard-with-fritzing-circuitpython.md)
- [Stick Person Costume with Neon LED Strips](https://learn.adafruit.com/led-neon-stick-person-costume.md)
- [Sailor Moon Star Locket](https://learn.adafruit.com/sailor-moon-star-locket.md)
- [Wireless Dual Stepper Control with Adafruit IO, Raspberry Pi and Python](https://learn.adafruit.com/wireless-stepper-control-with-adafruit-io-circuitpython-raspberry-pi-python.md)
- [Commodore Keyboard to USB HID with CircuitPython](https://learn.adafruit.com/commodore-keyboard-to-usb-hid-with-circuitpython.md)
- [I2S Microphones with CircuitPython](https://learn.adafruit.com/i2s-microphones-with-circuitpython.md)
- [Remote Control Candy Dispenser Ghost](https://learn.adafruit.com/ble-claw.md)
- [Tombstone Prop-Maker RP2040](https://learn.adafruit.com/tombstone-prop-maker-rp2040.md)
- [PyPortal IoT Weather Station](https://learn.adafruit.com/pyportal-iot-weather-station.md)
- [Apple //e Emulator on Fruit Jam](https://learn.adafruit.com/apple-e-emulator-on-fruit-jam.md)
