Polychrome
Blinkenlights Polychrome light and sound installation in Mildenberg, Germany, 2023
Contributing Content
There are several ways to contribute to polychrome.
- Submit an animation in the WebP format with the dimensions
242x8
. WebP animations go intooctopus/priv/webp
. - Write an application in elixir to generate dynamic content. See our example app.
- Write a standalone program that sends Protobuf packets over UDP. See our protobuf schema.
Please send us pull requests!
Components
Name | Description | Documentation |
---|---|---|
octopus | Central hub for the project. Manages apps, mixes pixel streams, shows previews. |
Readme |
protobuf | Protobuf schema files for the data packets | schema.proto |
blinkenleds | ESP32 firmware that drives the LED panels | Readme |
calibration | Tooling to create color calibration tables for the Leds | Readme |
beak | Audio engine that drives the sound output | Readme |
Architecture
Protobuf is used everywhere as the wire format. All messages are wrapped in the Packet
message to ensure save decoding. See the schema for more details.
Data flow for pixel and sound outputs
flowchart LR
external_1[External Source] --> |UDP| udp_server_1
external_2[External Source] --> |UDP| udp_server_2
subgraph Octopus
udp_server_1["Octopus.UDPServer [Port 2342]"] --> mixer
udp_server_2["Octopus.UDPServer [Port 2343]"] --> mixer
app_1[Octopus.Apps.Foo] --> mixer
app_2[Octopus.Apps.Baa] --> mixer
mixer["Octopus.Mixer"]-->broadcast[Octopus.Broadcaster]
mixer --> |pubsub| manager[OctobusWeb.ManagerLive]
end
subgraph "Blinkenled panel (10x)"
broadcast-->|UDP Broadcast|esp32[ESP32]
esp32-->LEDS
end
broadcast --> |UDP Broadcast| sim
sim[Simulator]-->|live_view| live[HTML]
subgraph "Beak (sound)"
broadcast --> |UDP Broadcast| beak
beak--> Speakers
end
Data flow for input events
---
title: "Input events"
---
flowchart LR
controllers --> |UDP| input_adapter
subgraph Octopus
input_adapter[Octopus.InputAdapter] --> mixer["Octopus.Mixer"]
manager[OctobusWeb.ManagerLive] --> mixer
mixer --> udp_server_1["Octopus.UDPServer [Port 2342]"]
mixer --> udp_server_2["Octopus.UDPServer [Port 2343]"]
mixer --> app_1[Octopus.Apps.Foo]
mixer --> app_2[Octopus.Apps.Baa]
end
udp_server_1 --> |UDP| external_1[External Source]
udp_server_2 --> |UDP| external_2[External Source]