AddressableLED - dekay/vpinball-wiki GitHub Wiki
The control of Addressable LEDs is offloaded from the primary pincab controllers (Pinscape, Pinscape Pico, Dudescab, etc) to inexpensive microcontrollers loaded with firmware dedicated to the task. These include:
- the Wemos D1 Mini: lowest price. Performs well but animations on HD LED Matrices may lag.
- the Wemos S2 Mini: a fraction more expensive than the D1 Mini but has higher performance (Reference).
- the PJRC Teensy: most expensive but highest performance. This and the S2 Mini should be preferred for Pincabs using HD LED Matrices.
You'll find these microcontrollers built into products from PJRC, Cleveland Software Designs and the Arnoz Shop if you'd prefer somebody else do all the soldering.
Important
Just because a device is advertised as being able to control LED's doesn't necessarily mean that it can control addressable LEDs. For example, devices like Cleveland Software Design's PinOne, GroovyGameGear's LED-Wiz, and mjr's PinScape Pico are able to drive individual LEDs only.
The Wemos D1 Mini has been produced in a number of versions over the years. There are also many clones of it available built with different components, colors, flash memory sizes, and silkscreen markings. The V4 version is the newest one at time of writing and features a USB-C port. The previous V3 version with its micro USB port is still readily available if that is your preference. The important thing to know is that they are all based on the ESP8266 microcontroller and their pinouts are all compatible. The extra memory and external antenna features provided by the Wemos D1 mini Pro are unnecessary in this application: a standard Wemos D1 mini with 4MB of flash and on-board antenna will do the job just fine and will do it cheaper.
The LED string connections to a bare D1 Mini are shown in this modified image from Random Nerd Tutorials. Beware of incorrect pinouts like this one at microcontrollerslab.com that show the WAKE
, SCLK
, etc pins shifted up a row starting at ADC0
.
The Wemos D1 Mini can drive up to eight separate LED strings. The mapping of each string to physical Wemos D1 Pin to DOF Port number is shown in the table below. Note the following:
- "DOF Port Number" is the Port number label in the DOF Config Tool. The numbers increment by three because each LED string logically uses one port per R, G, and B channel.
- the LED String #'s and the Wemos Pin #'s are not in order
- The D0 output on the Wemos is not used for driving LEDs
LED String # | Wemos Pin | DOF Port Number |
---|---|---|
1 | D5 | 1 |
2 | D6 | 4 |
3 | D7 | 7 |
4 | D8 | 10 |
5 | D1 | 13 |
6 | D2 | 16 |
7 | D3 | 19 |
8 | D4 | 22 |
The firmware for the Wemos D1 controller is open source and available on Github if your are interested in checking it out or want to flash the firmware directly using the Arduino toolchain.
TODO Finish
There are two firmwares that are used on the Wemos S2 Mini. If you are using Cleveland Software Design's Addressable LED Controller, it comes preflashed with their custom firmware. If not, the firmware for the Wemos D1 controller will also work on the S2.
Important
The Teensy firmware is set for RGB
color ordering internally, and because the WS2812/13/15 used in addressable LED strips and matrices are GRB
chipsets, it has to be setup correctly in the cabinet. That means that whenever you are using a Teensy with these LEDs and have a choice between RGB
and GBR
(e.g. Arnoz Tiny Tools firmware selection, Arnoz Tiny Tools Cacabinet Configurator), be sure to select GRB
. Otherwise things won't work. WOTW has more on this here.
The WeMos firmwares don't have this restriction. They are compiled with the correct internal color ordering for each version of LED chipset, so RGB
can be be specified in firmware selection and configuration tools if you like. Just be consistent with the ordering between the two (e.g. use RGB
firmware and specify RGB
in the cabinet.xml
configuration tools.
TODO Finish
The firmware for the Teensy controller is open source and available on Github if your are interested in checking it out or want to flash the firmware directly using the Arduino toolchain.
The website for the DOF Config Tool provides numerous references on how DOF works, as well as Downloads & Links to other key files and resources. They aren't listed there, but these Way of the Wrench videos do an excellent job of describing the setup of addressable LEDs and should be considered Must Watches
- How to make a cabinet.xml file and install the teensy strip controller
- How to install Direct Output Framework.
Other videos in his Virtual Pinball Cabinet playlist covering the installation and testing of addressable LEDs are also well worth a watch.
The LED configuration and DOF support is spread across various .xml
and .ini
files. You'll need these four files at a bare minimum to get addressable LED strips working under DOF (you'll need two more if you are using a LED Matrix as well):
-
tablemappings.xml
contains a mapping between the full text name of a table (e.g. "Tales of the Arabian Nights") to the abbreviatedRomName
of that table (e.g. "totan"). It is generated by the online DOF Config Tool every time you select "Generate config". It seems that not all tables need this file for addressable LED effects to work properly, but some of them do so there is no point to skipping it. -
directoutputconfig30.ini
contains color definitions, macros, and LED effects per table. If LED effects are working on some tables but not others, it might be that the non-working tables are not listed in this configuration file. Here is a sample file to get you started, though beware that it will become stale over time as it won't contain new tables or fixes. It is better to use the fresh file that is generated every time "Generate config" is selected from the online DOF Config Tool. -
cabinet.xml
/CabinetConfig.xml
/whatever.xml
: the output file created by tools like Cleveland Software Design's Cabinet File Generator or Arnoz Tiny Tools (Google Translated version). This file defines things like the connection settings to your microcontroller and the specific details of the LED strings and matrices you have connected to it. You can call this file whatever you like (we'll usecabinet.xml
througout this page) but the name must match that defined inGlobalConfig_B2SServer.xml
discussed next. No sample file provided here because there is such wide variation in hardware and setups. -
GlobalConfig_B2SServer.xml
contains several settings for logging that you can set to eithertrue
orfalse
. But perhaps more importantly, it also contains the name of the config file describing the detailed LED configuration mentioned above, so these two things need to match. A sampleGlobalConfig_B2SServer.xml
file is provided below. It tells DOF that you've named the file detailing your LED setup discussed previously in a config file namedcabinet.xml
.
<?xml version="1.0" encoding="utf-8"?>
<GlobalConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<DOFPath />
<CabinetConfigFilePattern>{GlobalConfigDirectory}/cabinet.xml</CabinetConfigFilePattern>
<EnableLogging>true</EnableLogging>
<LoggingEnabled>true</LoggingEnabled>
<ClearLogOnSessionStart>true</ClearLogOnSessionStart>
<LogLevel>0</LogLevel>
</GlobalConfig>
On Windows, place all config files in the directory C:\DirectOutput\config
. On Linux / Mac, they go into ~/.vpinball/directoutputconfig
. Create the directory if need be. Remember that directory names on Linux / Mac are case sensitive.
Windows users have it pretty easy. Install DOF and put your config files in c:\DirectOutput\Config
.
But... can't connect to your Wemos-based controller for some unknown reason? If you see an error message something like this in your directoutput.log
file...
EXCEPTION: Could not put the controller on com-port 'COM3' into the commandmode. Will not send data to the controller.
then you are likely running into this issue discussed on the VPUniverse forums. There are two possible solutions for this.
First, ensure your Wemos driver is updated and that you disable Modem Handshake on the port used by the Wemos. (Image credit: The Arnoz Shop)
If the problem persists, try disabling any addressable LED strips on your motherboard and disabling Windows Dynamic Lighting. Apparently, this service can hijack a com port or the Wemos when initialized.
DOF capability is built-in to the 10.8.1 Standalone version of VPinball that runs on Linux and Mac since late June, 2025. There are no additional plugins that are separately downloaded and installed. However, there is more setup that you're going to need to do.
Some of the online tools out there that generate the cabinet.xml
file assume you are running Windows and that means they'll assume your microcontroller is hooked up to a COM port like COM3
. There will be a line in the file that looks like this:
<ComPortName>COM3</ComPortName>
Linux and Mac will set up a port somewhere in the /dev
directory. Find out which one by plugging in your controller and running sudo dmesg
. In the example shown below for a Wemos D1 mini, dmesg
reports that the device is attached to ttyUSB0
.
$ sudo dmesg
<snip>
[ 6152.514481] usb 1-2.2: new full-speed USB device number 12 using xhci_hcd
[ 6152.756412] usb 1-2.2: New USB device found, idVendor=1a86, idProduct=7523, bcdDevice= 2.64
[ 6152.756420] usb 1-2.2: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[ 6152.756421] usb 1-2.2: Product: USB Serial
[ 6152.787503] ch341 1-2.2:1.0: ch341-uart converter detected
[ 6152.788034] usb 1-2.2: ch341-uart converter now attached to ttyUSB0
The full path to the device is /dev
+ ttyUSB0
to give /dev/ttyUSB0
. The corresponding update to the ComPortName
in the cabinet.xml
file would look like this:
<ComPortName>/dev/ttyUSB0</ComPortName>
Note that this example is for Linux. A Mac user might see something a little more complicated, like /dev/cu.usbserial-02G5PBVF
. The entry in the cabinet.xml
file would then look like this:
<ComPortName>/dev/cu.usbserial-02G5PBVF</ComPortName>
There is an equivalent problem for Linux / Mac users to the one that Windows have that is documented above: the Wemos may fail to connect even if the ComPortName
is set properly. The equivalent solution is to add the line <ComPortDtrEnable>true</ComPortDtrEnable>
within the <WemosD1MPStripController>
section of the cabinet.xml
file. In other words...
<WemosD1MPStripController>
<snip>
<ComPortDtrEnable>true</ComPortDtrEnable>
<snip>
</WemosD1MPStripController>
TODO Document setting up permissions so a regular user can access the microcontroller. It will look something like this
Edit the VPinballX.ini
file in your $HOME/.vpinball
directory and make sure that these two items are enabled within the [Standalone]
section of the file
B2SPlugins = 1
DOFPlugin = 1
You've got your .ini
and .xml
files in place, your LEDs are all hooked up, but you want to try a simple test to make sure everything is connected and configured properly before trying to test on an actual table. If you've compiled VPinball yourself, you'll have access to a program called dof_test
. From within the directory containing all of the VPinball files, do:
$ ./external/linux-x64/Release/libdof/libdof/build/dof_test ij_l7
The program will print an extensive set of debugging messages that will let you know if it has been able to find and connect to your LED controller, etc. When it gets to the S10
test, the LEDs will come on for a few seconds solid and then fade in & out for a few more seconds. If you see this, congratulations! You are ready to try your setup out with a real VPX table. If you don't see this, scroll back through the debug output for clues on what might be wrong.
Using a LED matrix on your cab, either standard density or HD? If so, there are a couple of other files generated by the DOF Config Tool that you need to know about: DirectOutputShapes.png
& DirectOutputShapes.xml
. TerryRed explains these two files in detail but basically:
- The
DirectOutputShapes.png
file is an array of small images that are basic building blocks for animations like sparkle effects and flashers, as well as three sets of letters and numbers in different sizes and weights. - The
DirectOutputShapes.xml
file is the "roadmap" used by DOF to name & describe the individual elements in the image. That image looks like this.
DOF depends on these files for animating LED Matrix displays so you'll want these files in place if you have one. Remember that on Windows, they go in C:\DirectOutput\config
. On Linux / Mac, they go into ~/.vpinball/directoutputconfig
.
Conventional LED Matrices used in VPinball are built from individual WS2812B LEDs that are in the "5050" form factor (5.0mm x 5.0mm) arranged in grids of 8 * 8 or 8x16. HD LED Matrices also use WS2812B LEDs but in the "2020" (2.0mm x 2.0mm) form factor arranged in grids of 16x16 or 16x32. The current recommended HD matrix from the creators of the HD effects that run on them are these units available from AliExpress.
These 16 * 32 displays are 80mm high x 160mm wide and are also available in 16 * 16 sizes that are 80mm x 80mm. The LEDs are mounted on a stiff PCB substrate that makes for easier mounting in a pincab vs. a flexible display. The separation between the LEDs makes for a taller display that looks a little more "matrix-y" than if the LEDs were packed tighter.
AliExpress vendors come and go, but the "WS2812 full color LED screen RGB color dot matrix 16 * 32 dot matrix SPI protocol 2020 small light beads" display from YiFei LED Store is a reputable vendor with good pricing that gets better as quantities go up. If you can't find an AliExpress vendor that will ship to your region or you'd prefer the LEDs more tightly packed, consider the displays from L'atelier d'Arnoz or Cleveland Software Design.
You might be wondering if the standard density matrix effects will display properly on HD LED Matrices and the answer is definitely Yes. As the DirectOutput documentation explains...
DOF can display a part of a bitmap image on a matrix toy. The defined part of the bitmap is scaled to the size of the matrix, so the actual resolution of the matrix does not matter.
In addition, other matrix effects are positioned and sized as a percentage of the size of the matrix and not in terms of an absolute number of LED's. Thanks to this, standard density matrix effects look fine on an HD matrix. But HD matrix effects designed specifically for HD LED displays take full advantage of the additional resolution and look that much better.
To take advantage of these higher resolutions, it turns out that there is a lot more to do than just specifying a higher resolution in your cabinet.xml
file, although you definitely need to do that too.
First off, the DOF Config Tool has special fields for HD matrix effects named PF Back Effects MX HD
and PF Back Flashers MX HD
. If you think that you'd need to ensure these fields are filled in to take advantage of your HD matrix display, you'd be wrong. The problem is that a table needs to be specifically coded to take advantage of these fields, and very few are. Just because the HD fields are filled in in DOF doesn't mean its being used by the table unless the table script actually makes the call. It is best to forget about the MX HD fields in DOF: there was a project in 2024 that copied a lot of code to the HD fields but that fizzled out and was never completed.
Instead, HD matrix support works using custom DOF code to replace the regular PF Back Effects MX
... TODO Finish.
DOF supports the ideas of "combos", where the same toy (in our case, an HD matrix) can be used for multiple things. If you have an HD Matrix, the following combo is recommended:
PF Back Effects MX
PF Back Flashers MX
Custom MX 1
In the DOF Config tool, that combo setup would look like the one outlined in red below.
That combo can be named whatever you like, but that is the name that you will want to use when setting up DOF's Port Assignments for your Teensy or Wemos LED controller in the DOF Config Tool. It is strongly recommended that you don't include PF Back Strobe MX
or PF Back Beacon MX
into this combo as they tend to interfere with other HD effects (more on this in a bit).
Once you've got the combo defined, it can be used within the DOF Config Tool from the port assignments menu. This example shows three combos mapped to the first three outputs of a WS2811 device (in actual fact a Wemos D1 Mini).
The HD effects created by the Virtual Pinball Custom LED Effects (VPCLE) group are now available from within the DOF Config Tool that you'll want to download by clicking the link shown below on the DOF home page to get mx.rar
. This is a .rar
archive of all the HD effects. You can also get it directly at this link.
The DOF Config Tool now supports automatically updating all supported tables to HD effects at the click of the button in the image shown below. There is also a filter in the DOF Config tool that lets you show only those tables that have HD effects. This is a real time saver, but note that you'll still need to download the mx.rar
file linked above if you use this feature. The archive includes all of the .png
and .gif
files that represent the HD effects that you'll need to save to your PC. The "Apply MX Configuration to All Tables" only copies over the text strings that detail how the HD effects are applied.
By looking at the files in the mx.rar
archive, you can get an idea of the approach taken by the VPCLE group in setting up these effects. Here is an example from Cactus Canyon
{
"table": "Cactus Canyon",
"type": "table_config",
"rom": "cc",
"rom_aliases": "",
"config": {
"74": {
"toy": "PF Left Flashers MX",
"user": "S28 Red AT10 AH10 L1 "
},
"80": {
"toy": "PF Left Effects MX",
"user": "W13 Golden_rod 2000 AFDEN30 AFMIN100 AFMAX150\/W18 Golden_rod AT80 AH20 APCRed\/W67 Golden_rod 250 AT0 AH50 ADU AS250\/W67 Golden_rod 250 AT50 AH50 ADD AS250\/W51 Golden_rod 250 AT60 AH40\/W16 Orange_red 250 AT80 AH20 ADD AS200\/W35 Red 250 W250 FD250 AT0 AH100 ADD AS400\/W86|W87 Golden_rod 250 AT60 AH20\/W46 Dark_orange 250 AT40 AH10\/W85 Turquoise 250 AT20 AH80 ADD AS250\/S6 Sienna 250 AT0 AH30 ADU AS250\/W82 Golden_rod Blink 490 BPW15 W250 AT0 AH100 ADD AS200"
},
"76": {
"toy": "PF Back Flashers MX",
"user": ""
},
"83": {
"toy": "PF Back Effects MX",
"user": "W13 White 500 F500 ABL0 ABW44 ABT0 ABH11 L20\/W13 White 1000 W500 F500 ABL0 ABW44 ABT11 ABH11 L19\/
...
<snip>
}
}
}
You'll notice that they update the standard density "MX" effects rather than populate the "HD" effects. You'll also see that they deliberately blank out the PF Back Flashers MX
field: the back flashers tend to interfere with HD DOF effects created by this group.
TODO Write up that the images in mx.rar
need to be extracted. I think they'd go into the directoutput config directory but need to confirm.
You're using an HD Matrix built up from multiple HD panels and so you're going to want them to update as fast as possible. The problem is that the addressable LED's are commanded in a serial bitstream at a fixed data rate, so the more LEDs in your matrix, the longer it takes for the last LED in the line to be commanded and the slower the update rate.
The solution is to break up the serial addressing of the entire display into pieces by connecting the Data In connection of each panel to its own port on the LED controller. Each LED on each panel is still commanded in series, but each of the panels can be commanded in parallel. This makes the entire display built up from multiple panels update about as fast as a single panel can be updated. Nice.
Getting this to work is straightforward. The key is that individual panels each connected to a different LED Controller output that have the same names will be combined into one. The Cleveland Software Design's Cabinet File Generator and the Arnoz Tiny Tools Cacabinet Generator (not a typo BTW) take different approaches and create different XML files, but the result is the same in the end. Let's look at each in turn.
Cleveland Software Design's Cabinet File Generator sets the same name for each output to the matrix automatically for you in their preconfigured setups.
A snippet of its output is below. Note that the size of the entire Back Panel matrix gets specified as the size of the individual 64 * 16 HD panel that they sell. Note also how the OutputName
's for each output to the matrix has the same name. That is the key that tells DOF to combine each of the individual 64 * 16 panels into one display. The OutputNumber
's corresponding to the DOF Port Assignments increment automatically by three in the predefined setup as well. This is different from the Arnoz approach as we'll see later but the end result is the same.
<LedStrip>
<Name>Back Panel</Name>
<Width>64</Width>
<Height>16</Height>
...
</LedStrip>
<LedWizEquivalent>
<Name>LedWizEquivalent 30</Name>
<LedWizNumber>30</LedWizNumber>
<Outputs>
...
<LedWizEquivalentOutput>
<OutputName>Back Panel</OutputName>
<LedWizEquivalentOutputNumber>7</LedWizEquivalentOutputNumber>
</LedWizEquivalentOutput>
<LedWizEquivalentOutput>
<OutputName>Back Panel</OutputName>
<LedWizEquivalentOutputNumber>10</LedWizEquivalentOutputNumber>
</LedWizEquivalentOutput>
<LedWizEquivalentOutput>
<OutputName>Back Panel</OutputName>
<LedWizEquivalentOutputNumber>13</LedWizEquivalentOutputNumber>
...
Each LED controller output in the cabinet.xml
file will need its own set of three port assignments (one each for R, G, and B) in the DOF config tool. So a display made up of four HD panels will require 4 * 3 = 12 port assignments in the DOF Config Tool with the same name given to each. Here's an example of how you'd then set this up in the DOF Config tool.
Example: I am using the Cleveland Software Design Cabinet File Generator and have a pincab with a left playfield LED strip, a right playfield LED strip, and an HD matrix built up from four 16 * 64 panels. Each are built up from combo's already set up in DOF named PF Left Combo
, PF Right Combo
, and PF Back Combo
respectively. The Port Assignments set up in DOF for my addressable LED controller would be as follows:
P:001: PF Left Combo
P:004: PF Right Combo
P:007: PF Back Combo
TODO. Not sure if the three outputs that follow need to be setup up in the online config tool. Need to verify somehow.
P:010: PF Back Combo
P:013: PF Back Combo
P:016: PF Back Combo
There is a great video on the L'atelier d'Arnoz YouTube channel that shows exactly how to use the Arnoz Tiny Tools Cacabinet Generator that is available for download here (Google Translated version) to work with an HD Display made from a number of panels. The trick here is to use the Split
field and increment the number in that field by one for each output driving the matrix, with the first panel in the matrix having a Split
value of 1
.
Unlike the Cleveland Software Design online tool, there is no preconfigured template that sets a number of HD Matrix parameters for you. It is up to you to make sure that the name of each Addressable Toy is the same for each output to the matrix (PF Matrix
in this example), that the Split
number increments by one as you go, that the DofOutputPort
is the same number for all of them, that the dimensions of each Addressable Toy in the matrix are the same dimensions, etc. Fortunately there is a good amount of error checking, and an error in the setup of a Toy will be shown in the GUI. Hovering your mouse over the error will show the rules you need to follow. Here, Output 5 and 6 were both assigned a Split
of 3
. Changing the second one to 4
clears the error.
Here is a snippet of the XML created by the tool for a matrix with four 16 x 32 panels. Note how the XML shows the width and height as that of the entire HD Display of 16 x 128 vs that of a single panel shown in the Cleveland Software Design XML. And unlike the Cleveland Software Design tool, the XML generated by the Arnoz tool only specifies a single DOF output port (7
in this example) in the XML, so a display made up of four HD panels will require just 1 * 3 = 3 port assignments in the DOF Config Tool. However, the end result is the same in both cases: merge the physical individual panels into one logical HD Matrix and and split the works across multiple outputs on the controller.
<LedStrip>
<Name>PF Matrix</Name>
<Width>128</Width>
<Height>16</Height>
...
</LedStrip>
<LedWizEquivalent>
<Name>LedWizEquivalent 30</Name>
<Outputs>
...
<LedWizEquivalentOutput>
<OutputName>PF Matrix</OutputName>
<LedWizEquivalentOutputNumber>7</LedWizEquivalentOutputNumber>
</LedWizEquivalentOutput>
</Outputs>
<LedWizNumber>30</LedWizNumber>
</LedWizEquivalent>
</Toys>
</Cabinet>
Here's an example of how you'd then set this up in the DOF Config tool.
Example: I am using the Arnoz Cacabinet File Generator and have a pincab with a left playfield LED strip, a right playfield LED strip, and an HD matrix built up from four 16 * 32 panels. Each are built up from combo's already set up in DOF named PF Left Combo
, PF Right Combo
, and PF Back Combo
respectively. The Port Assignments set up in DOF for my addressable LED controller would be as follows:
P:001: PF Left Combo
P:004: PF Right Combo
P:007: PF Back Combo
- The COM port (Windows) or device (Linux / Windows) is incorrect
- (Wemos devices) You haven't checked the "Disable Modem Handshake" on that COM port (Windows) or you don't have the line
<ComPortDtrEnable>true</ComPortDtrEnable>
in yourcabinet.xml
file (Linux / Mac)
- You forgot to put
DirectOutputShapes.png
andDirectOutputShapes.xml
in the config directory - You've specified the wrong LED order in your configuration tool. These are the valid arrangements
The usual default in the cabinet.xml
file has the AutoConfigEnabled
parameter set to true
. That setting is necessary for PinOne devices but isn't for Teensy or Wemos devices. Try setting this parameter to false
for faster startup time whenever a table is started.