You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The **LED Matrix Painter** example provides a web-based tool for designing frames and animations for the Arduino UNO Q 8×13 LED matrix. You can create individual frames, organize them into animations, preview them in real-time on the board, and export them as C++ code.
3
+
The **LED Matrix Painter** example transforms your Arduino UNO Q into a design tool for the built-in LED Matrix. It features a web-based pixel editor that allows you to draw frames, create animations, and export the results as ready-to-use C++ code.
This example allows you to design LED matrix frames using an interactive web interface. Each frame can have custom brightness levels (0-7) for each LED pixel. You can:
9
+
This App provides a complete workflow for designing LED matrix visuals. It uses the `web_ui` Brick to host a graphical editor where you can draw pixels with 8 levels of brightness. Changes are reflected instantly on the UNO Q's physical matrix.
10
10
11
-
-**Design frames** with pixel-by-pixel control using an interactive grid
12
-
-**Preview in real-time** on the Arduino UNO Q LED matrix
13
-
-**Save and organize** multiple frames with a persistent database
14
-
-**Create animations** by sequencing multiple frames together
15
-
-**Export code** as C++ arrays ready to use in your Arduino sketches
16
-
-**Transform frames** with operations like invert, rotate, and flip
11
+
The application uses the `dbstorage_sqlstore` Brick to persist your designs in a database, allowing you to save multiple frames, reorder them via drag-and-drop, and organize them into animations. Finally, the "Export .h" feature generates the exact C++ code needed to use your designs in standalone Arduino sketches.
17
12
18
-
The application uses the Router Bridge to communicate between the web interface (running on Linux) and the Arduino sketch (running on the microcontroller), enabling real-time updates to the physical LED matrix.
13
+
Key features include:
14
+
-**Real-time Preview:** Drawing on the web interface updates the UNO Q matrix instantly.
15
+
-**8-bit Grayscale:** Support for 8 brightness levels per pixel (0-7 in the editor, mapped to 0-255).
16
+
-**Frame Management:** Create, delete, and reorder frames using a persistent database.
17
+
-**Transform Tools:** Quickly invert, rotate, or flip your designs.
18
+
-**Animation Mode:** Sequence frames to create and preview animations on the board.
19
+
-**Code Generation:** Export frames or animations as `uint32_t` arrays compatible with the `Arduino_LED_Matrix` library.
19
20
20
21
## Bricks Used
21
22
22
-
-`web_ui`: Provides the web server and HTTP API endpoints for the interactive frame designer interface.
23
-
-`dbstorage_sqlstore` (implicit): Stores frame data persistently in a SQLite database.
23
+
The LED Matrix Painter example uses the following Bricks:
24
+
25
+
-`web_ui`: Brick to create the interactive grid editor and manage API endpoints.
26
+
-`dbstorage_sqlstore`: Brick to persist frames and animation sequences using a SQLite database.
24
27
25
28
## Hardware and Software Requirements
26
29
@@ -35,127 +38,131 @@ The application uses the Router Bridge to communicate between the web interface
35
38
36
39
## How to Use the Example
37
40
38
-
1. Launch the App by clicking the **Play** button in the top-right corner. Wait until the App has launched.
39
-
2.**Design a frame:**
40
-
- Click on individual pixels in the 8×13 grid to toggle them on/off
41
-
- Use the brightness slider to adjust LED intensity (0-7)
42
-
- Click on pixels with different brightness values to paint with varying intensities
43
-
3.**Save your frame:**
44
-
- Click the **Save Frame** button to persist the current design
45
-
- Frames are automatically saved to a database and appear in the sidebar
46
-
4.**Create animations:**
47
-
- Save multiple frames
48
-
- Switch to **Animations** mode in the sidebar
49
-
- Create a new animation and add frames to it
50
-
- Use **Play** to preview the animation on the board
51
-
5.**Export code:**
52
-
- Select the frames or animations you want to export
53
-
- Click **Export** to generate C++ code
54
-
- Copy the generated arrays into your Arduino sketch
55
-
56
-
## How it Works
57
-
58
-
The LED Matrix Painter consists of three main components working together:
59
-
60
-
-**Web Interface (Frontend)**: An interactive grid editor built with HTML/CSS/JavaScript that sends pixel data to the backend via HTTP API calls.
61
-
62
-
-**Python Backend**: Handles frame storage in a SQLite database, manages frame transformations, and communicates with the Arduino via Router Bridge.
63
-
64
-
-**Arduino Sketch**: Receives frame data over Router Bridge and displays it on the physical LED matrix using the `Arduino_LED_Matrix` library.
65
-
66
-
High-level data flow:
67
-
68
-
```
69
-
Web Browser → HTTP API → Python Backend → Router Bridge → Arduino LED Matrix
70
-
↓
71
-
SQLite Database
72
-
```
73
-
74
-
The workflow:
75
-
1. User edits a frame in the web interface
76
-
2. Changes are sent to Python backend via HTTP POST
77
-
3. Backend validates and stores the frame in SQLite
78
-
4. Backend sends frame data to Arduino via Bridge
79
-
5. Arduino sketch renders the frame on the LED matrix
80
-
81
-
## Understanding the Code
82
-
83
-
### 🔧 Backend (`main.py`)
84
-
85
-
The Python application manages the HTTP API, database operations, and communication with the Arduino.
41
+
1.**Run the App**
42
+
Launch the App from Arduino App Lab.
86
43
87
-
-**`designer = FrameDesigner()`**: Initializes the frame designer utility from `arduino.app_utils`, which provides transformation operations (invert, rotate, flip).
44
+
2.**Access the Editor**
45
+
Open the App in your browser at `<UNO-Q-IP-ADDRESS>:7000`.
88
46
89
-
-**`store.init_db()`**: Creates the SQLite database and tables for storing frames if they don't exist.
47
+
3.**Draw Frames**
48
+
-**Click** a cell in the grid to toggle it on.
49
+
-**Click again** (or hover and wait) to open the brightness slider and adjust the intensity (0-7).
50
+
- The design appears immediately on the UNO Q LED Matrix.
90
51
91
-
-**`ui.expose_api('POST', '/persist_frame', persist_frame)`**: Exposes an HTTP endpoint that saves or updates frames in the database.
52
+
4.**Manage Your Session**
53
+
-**Auto-save:** Changes are automatically saved to the database as you draw.
54
+
-**Create:** Use the **+** button in the sidebar to create new empty frames.
55
+
-**Reorder:** Drag and drop frames in the list to change their sequence.
56
+
-**Transform:** Use the toolbar buttons to **Invert**, **Rotate 180°**, or **Flip** the current frame.
92
57
93
-
-**`ui.expose_api('POST', '/load_frame', load_frame)`**: Loads a frame from the database by ID or retrieves the last edited frame.
58
+
5.**Create Animations**
59
+
- Switch the radio button in the sidebar to **Animations**.
60
+
- Select multiple frames by clicking on them in the sidebar.
61
+
- Click **Play Animation** to see the sequence run on the UNO Q.
94
62
95
-
-**`ui.expose_api('GET', '/list_frames', list_frames)`**: Returns all saved frames for display in the sidebar.
63
+
6.**Export Code**
64
+
- Click **Export .h** to download a C++ header file containing your designs.
65
+
- Copy the generated code (displayed in the right column) directly into your Arduino sketch.
96
66
97
-
-**`ui.expose_api('POST', '/play_animation', play_animation)`**: Sends a sequence of frames to the Arduino to play as an animation.
98
-
99
-
-**`ui.expose_api('POST', '/export_frames', export_frames)`**: Generates C++ code arrays from selected frames for use in Arduino sketches.
67
+
## How it Works
100
68
101
-
-**`Bridge.call("draw", frame_bytes)`**: Sends frame data to the Arduino sketch to update the LED matrix display.
69
+
The LED Matrix Painter consists of three main components working together:
102
70
103
-
-**`AppFrame` class**: Custom extension of `arduino.app_utils.Frame` that adds metadata like frame name, position, duration, and database persistence methods.
71
+
1.**Web Interface**: An interactive grid editor that captures user input and sends pixel data to the backend.
72
+
2.**Python Backend**: Manages the database, handles frame transformations, and communicates with the hardware.
73
+
3.**Arduino Sketch**: Receives raw data and renders it on the physical matrix.
104
74
105
-
### 💻 Frontend (`app.js` + `index.html`)
75
+
**High-level data flow:**
106
76
107
-
The web interface provides an interactive pixel grid editor and frame management tools.
77
+
```
78
+
Web Browser ──► HTTP API ──► Python Backend ──► Router Bridge ──► Arduino Sketch
79
+
│ │
80
+
▼ ▼
81
+
SQLite Database LED Matrix Display
82
+
```
108
83
109
-
-**Pixel Grid**: An 8×13 canvas that responds to mouse clicks and drag operations for painting pixels.
84
+
## Understanding the Code
110
85
111
-
-**Brightness Control**: A slider (0-7) that controls the current brush brightness level.
86
+
### 🔧 Backend (`main.py` & `store.py`)
112
87
113
-
-**Frame List**: Displays all saved frames in a sidebar with options to load, delete, or reorder them.
88
+
The Python backend acts as the controller, managing the API and database interactions.
114
89
115
-
-**Animations Mode**: Allows creating and managing animation sequences by dragging frames into animation containers.
90
+
-**Persistence**: The application uses `SQLStore` to manage a `frames` table. This allows frames to be loaded, reordered, and updated efficiently.
-**Export Modal**: Generates and displays C++ code for selected frames or animations.
96
+
defsave_frame(frame: AppFrame) -> int:
97
+
# Logic to calculate position and insert record
98
+
record = frame.to_record()
99
+
db.store("frames", record, create_table=False)
100
+
# ...
101
+
```
120
102
121
-
-**HTTP API calls**: Uses `fetch()`to communicate with the Python backend for all frame operations (save, load, delete, transform, export, play).
103
+
-**Bridge Communication**: When a frame is loaded or edited, it is sent to the board. The `AppFrame` class handles the conversion of pixel data into the specific byte format required by the sketch.
122
104
123
-
### 🔧 Hardware (`sketch.ino`)
105
+
```python
106
+
# main.py
107
+
defapply_frame_to_board(frame: AppFrame):
108
+
"""Send frame bytes to the Arduino board."""
109
+
frame_bytes = frame.to_board_bytes()
110
+
Bridge.call("draw", frame_bytes)
111
+
```
124
112
125
-
The Arduino code handles LED matrix control and Router Bridge communication.
113
+
-**Code Export**: The `AppFrame` class includes logic to generate C++ source code strings (`uint32_t` arrays), which are returned to the frontend for display.
126
114
127
-
-**`matrix.begin()`**: Initializes the Arduino_LED_Matrix library for controlling the UNO Q LED matrix.
115
+
```python
116
+
# app_frame.py
117
+
defto_c_string(self) -> str:
118
+
c_type ="uint32_t"
119
+
parts = [f"const {c_type}{self.name}[] = {{"]
120
+
# ... formats array data as hex/int ...
121
+
parts.append("};")
122
+
return"\n".join(parts)
123
+
```
128
124
129
-
-**`matrix.setGrayscaleBits(8)`**: Configures the matrix to accept 8-bit brightness values (0-255) for each pixel.
125
+
### 🔧 Arduino Component (`sketch.ino`)
130
126
131
-
-**`Bridge.begin()`**: Initializes Router Bridge for receiving commands from the Python application.
127
+
The sketch initializes the matrix and registers Bridge functions to receive data from Python.
132
128
133
-
-**`Bridge.provide("draw", draw)`**: Registers the `draw` function to be callable from Python, which accepts frame data and renders it on the matrix.
129
+
-**Matrix Configuration**: The matrix is configured to accept 8-bit values, allowing for smooth gradients (0-255) rather than just on/off.
134
130
135
-
-**`Bridge.provide("play_animation", play_animation)`**: Registers the animation playback function that accepts multiple frames and plays them sequentially.
131
+
```cpp
132
+
voidsetup() {
133
+
matrix.begin();
134
+
// configure grayscale bits to 8 so the display can accept 0..255 brightness
135
+
matrix.setGrayscaleBits(8);
136
+
Bridge.begin();
137
+
// ...
138
+
}
139
+
```
136
140
137
-
-**`matrix.draw(frame.data())`**: Renders a single frame on the LED matrix using raw byte data.
141
+
-**Drawing Frames**: The `draw` function receives a vector of bytes, which represents the frame data, and passes it to the matrix driver.
138
142
139
-
-**`matrix.loadWrapper()` + `matrix.playSequence()`**: Loads an animation sequence and plays it on the LED matrix.
143
+
```cpp
144
+
voiddraw(std::vector<uint8_t> frame) {
145
+
// Direct draw of received bytes
146
+
matrix.draw(frame.data());
147
+
}
148
+
```
140
149
141
-
## Frame Data Format
150
+
- **Playing Animations**: The `play_animation` function receives a stream of bytes representing multiple frames and durations. It reconstructs them into `uint32_t` arrays (the native format for the matrix library) and plays the sequence.
142
151
143
-
Frames are stored as 8×13 arrays where each value represents LED brightness (0-255):
152
+
### 🔧 Frontend (`app.js`)
144
153
145
-
```cpp
146
-
// Example frame in C++ format
147
-
constuint8_t frame[][12] = {
148
-
{255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255},
149
-
{0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0},
150
-
// ... 6 more rows
151
-
};
152
-
```
154
+
The JavaScript frontend handles the interactive grid logic.
153
155
154
-
For animations, frames are stored as `uint32_t` arrays compatible with the Arduino_LED_Matrix library:
156
+
- **Brightness Control**: It supports multi-level brightness by managing a dataset attribute `data-b` on each cell.
157
+
- **Auto-Persist**: To ensure a smooth user experience, changes are debounced and automatically sent to the backend via `schedulePersist()`, which updates both the database and the physical board simultaneously.
0 commit comments