Arduino UNO Q Elf Detector Series - Part 2: LED Matrix

In Part 1 of this Arduino UNO Q Elf Detector Series, we mastered the simple dual-core architecture by blinking a single LED. But let’s be honest: a single blinking light isn't going to scare off a determined elf. They make toys; they know how LEDs work. To truly secure the workshop, we need "shock and awe."

We are moving to a more sophisticated use case: controlling the Arduino UNO Q’s built-in 13x8 LED matrix display. That is 104 individually controllable LEDs; enough to turn my workbench into a blinding disco of deterrence.

Prerequisites

Before proceeding, you must have completed Part 1: Blinking an LED.

  • An Arduino UNO Q powered and connected to the internet.
  • A FoundriesFactory™ platform account with a created Factory.
  • The fioup daemon running and managing updates automatically.
  • Git configured with your Factory repository cloned.
  • The arduino-led-webui application successfully removed from your device.

The Application Architecture

This project takes the dual-core communication pattern we learned in Part 1 and applies it to a more complex display system.

The Arduino UNO Q features a 13×8 red LED matrix (104 individually controllable LEDs) built into the board. This matrix is controlled through dedicated hardware on the STM32U5 MCU.

The Challenge: Unlike simple GPIO LEDs, the matrix uses a packed binary format where all 104 LED states are stored in just 128 bits (4 × 32-bit integers)

The Solution:

  • Qualcomm DragonwingTM (MPU): Runs a Flask web server serving an interactive 13x8 grid interface.
  • The Bridge: Transmits coordinate data (x, y) from the web app to the MCU in real-time.
  • STM32U5 (MCU): Receives the coordinates, converts them to the packed binary format, and updates the hardware with precise timing.

This entire "Browser → Cloud → Linux → Bridge → MCU → Hardware" round trip happens in less than 30ms.

Step 1: Understanding the Application

Before we deploy, let's look at what we are building

The LED Matrix Interface

While our previous app toggled individual LEDs, this project controls a complete display. The web interface presents a 13×8 clickable grid that mirrors the physical matrix:

13 columns × 8 rows = 104 LEDs

  • Click a square: The corresponding LED lights up on the board.
  • Click again: The LED turns off.
  • Clear All: Resets the entire display.

Inside the arduino-matrix-webui directory, we have:

  • index.html: The interactive grid UI
  • main.py: The Flask server managing state and Bridge communication.
  • sketch.ino: The MCU firmware that handles the binary frame buffer.
  • Dockerfile: The container build definition including arduino-cli and OpenOCD

Step 2:Deploying the Matrix Application

Since we already set up the repository in Part 1, deployment is straightforward. We will fetch the new code from our demo remote and push it to your Factory.

Navigate to your containers.git folder on your host machine and run:

  1. Add the demo remote (if you removed it in Part 1):
host:~$ git remote add arduino-demo https://github.com/foundriesio/containers.git
host:~$ git fetch arduino-demo arduino-demo-25Q4
  1. Checkout the application folder:
host:~$ git checkout arduino-demo/arduino-demo-25Q4 -- arduino-matrix-webui
  1. Commit and Push to your Factory:
host:~$ git add arduino-matrix-webui
host:~$ git commit -m "Adding Arduino LED Matrix WebUI demo"
host:~$ git push

What Just Happened?

FoundriesFactory detected the push, triggered a CI/CD build job, compiled the container, and published it to your private registry. You can monitor the build progress in your Targets dashboard at:

Factory targets

Step 3: Enabling the Application

In Part 1, we manually updated the device using the CLI. This time, we will use the FoundriesFactory Web UI to manage our fleet. This demonstrates how you can remotely configure which applications run on your devices without touching the device terminal.

  1. Navigate to your Devices page: https://app.foundries.io/factories/<FACTORY-NAME>/devices/
  2. Select your Arduino UNO Q device from the list
  3. Click on Update tags & apps
  4. Drag and Drop: Move arduino-matrix-webui from the left (Available) to the right (Selected).
Update tags

5. Click "Apply"

The Update Process: Your device's fioup daemon (which polls for updates automatically) will detect this configuration change, download the new container, stop any old apps, and start the new Matrix Controller.

You can verify this is happening by checking the logs on your device:

device:~$ journalctl -f -u fioup

Expected output:

Nov 22 20:30:15 raul fioup[5003]: [1/6] Checking ... new update from 2 [] to 3 [arduino-matrix-webui]
Nov 22 20:30:15 raul fioup[5003]: [2/6] Initializing ... fetch size: 652.3 MiB, 24 blobs; add: [arduino-matrix-webui]
Nov 22 20:30:15 raul fioup[5003]: [3/6] Fetching ...
Nov 22 20:30:45 raul fioup[5003]:          100%  [=========================]  652.3 MiB / 652.3 MiB | 24/24 blobs
Nov 22 20:30:45 raul fioup[5003]: [4/6] Stopping ... done
Nov 22 20:30:45 raul fioup[5003]: [5/6] Installing ...
Nov 22 20:30:45 raul fioup[5003]:         Installing app hub.foundries.io/<FACTORY>/arduino-matrix-webui@sha256:...
Nov 22 20:30:52 raul fioup[5003]:         Image loaded: hub.foundries.io/<FACTORY>/arduino-matrix-webui@sha256:...
Nov 22 20:30:52 raul fioup[5003]:       Done
Nov 22 20:30:52 raul fioup[5003]: [6/6] Starting ...
Nov 22 20:30:53 raul fioup[5003]:         starting arduino-matrix-webui --> hub.foundries.io/<FACTORY>/arduino-matrix-webui@sha256:... done
Nov 22 20:30:53 raul fioup[5003]:       Done

Step 4: Testing the Matrix Drawing Interface

Once the logs show "Done" and "Starting...", your application is live!

1. Verify the Container:

Check the device logs to ensure the container started successfully:

device:~$ docker ps -a

You should see arduino-led-webui with the status Up.

- - - - Output Example - - -
CONTAINER ID   IMAGE                                                COMMAND           CREATED         STATUS         PORTS     NAMES
6fc4c458764e   hub.foundries.io/advent2025_2/arduino-matrix-webui   "/app/start.sh"   2 minutes ago   Up 2 minutes             arduino-matrix-webui-arduino-matrix-webui-1

2. Access the Interface: From any computer on the same network, open a browser and navigate to: http://<device-IP>:8000

device:~$ docker logs arduino-matrix-webui-1

3. Start Drawing: Click on the grid squares in your browser. You will see the LEDs on your Arduino UNO Q light up instantly to match your design. Try drawing a smiley face, your initials, or a simple pattern.

Web UI
Board smiley

Step 5:Removal and Clean up

To prepare for the next part of this series, we should remove this application to keep our device clean. We will use the Web UI again.

  1. Go back to your Devices page at: https://app.foundries.io/factories/<FACTORY-NAME>/devices/ and select your device
Devices
  1. Click Update tags & apps.
Update tags
  1. Move arduino-matrix-webui from Selected back to Available.
  2. Click Apply

The fioup daemon will detect the change and remove the container automatically. You can verify this by running docker ps -a on the device once again; the container should be gone.

Conclusion

In this part, we deployed a sophisticated application that controls a complete LED matrix display through an interactive web interface. We leveraged the same CI/CD workflow as before, but this time we utilized the FoundriesFactory UI for fleet management.

We have demonstrated that with the FoundriesFactory platform we can iterate quickly, test locally, push to the cloud, and deploy complex hardware controls to edge devices string with a simple git push.

In the next part of this series, we will take a major leap forward: integrating Edge Impulse machine learning models. We will build a voice-controlled system that responds to audio commands, combining everything we've learned with AI at the edge.

Resources

For a deeper dive, explore the repository to gain a better understanding of the code:

Related posts