Welcome back! Today I'm going to be discussing the long awaited Art-Net backbone, an essential piece of processing for my Java projects involving stage lighting. I'll be taking a look at how it functions, the different data types and what they do, and how it all fits together to push lighting data to Art-Net.
External Libraries
Since I am not experienced enough to be writing my own Art-Net communication library from scratch, I'm building upon Artnet4J, a library written by Cansik (GitHub page here). This library is the final interface between Java and Art-Net, and what is doing the heavy lifting in terms of communicating with my lights.
What is Art-Net?
Art-Net is a protocol for sending DMX data over IP networking. An Art-Net network is built up of standard IP infrastructure like routers and switches, along with nodes, which are responsible for actually turning the Art-Net data into DMX that the lights can interpret. The Art-Net node I am using is an ELC DMXLan Buddy, which is capable of outputting 2 universes independently (a universe being a chain of 512 DMX channels).
<Photo of DMXLan Buddy>
The reason I am using Art-Net rather than something like USB to DMX conversion is because Art-Net is easier to support, since you don't have to worry about compatibility with all different USB to DMX dongles. With Art-Net, all you have to do is specify an IP address and universe, and any node that supports it will be able to read and convert the data.
Using Artnet4J
The basic thing to understand about Artnet4j is how data is packaged before being sent to Art-Net. The data takes the form of an array of 512 bytes containing values between 0 and 255. Each index position specifies a DMX channel, and each value is the value that gets pushed to that channel. From there all you have to do is create a client to handle the communications side of things, and push the array to an IP address and universe.
This is a very easy library to use, but because the software I am building is going to be relatively complex, I needed to build upon it to make things as solid as possible for use in the future. This includes creating objects for each universe to save things like IP address and universe ID, and defining different data objects for my software to work with.
Data Types
There are four main data types that my software is able to use, which are commands, frames, scenes, and stacks. These are essentially containers for each other, and the way they are encapsulated in the following way: each frame contains several commands, each scene contains several frames, and each stack contains several scenes. While I haven't yet created a project that utilizes scenes or stacks, every experiment with Art-Net in Java has extensively utilized frames.
Commands are simple, lightweight data types containing an address, universe, and data value. In essence, it is there to say "this channel at this value on this universe". By itself it simply controls a single light, but when there are many commands encapsulated in a single frame, things become more interesting.
Frames are what are actually sent to Art-Net, since they contain an array of commands which need to be read and sent out to each universe. The cool thing here is that frames are not universe specific, so you can control any lights in any universe together in a single frame.
One more step up the chain, we see that each scene contains a series of frames, much like a video contains a whole bunch of still images that it combines to create the illusion of video. This is going to be important in future projects where I need to worry about different scenes stepping through commands in sequential order, but for now it's just there for future implementation.
Finally, there is what is called a stack, which is a bunch of scenes meant to play side-by-side with each other. Once again, this is here for future implementation and isn't utilized currently.
Universes
The next thing I needed to do was to create an ArtnetUniverse object so I can reference each universe independently without worrying about specifying an IP address each time. I also store a Universe ID, which is a unique identifier that my software can use to figure out which universe to send data to. The class also contains methods for writing data to the universe, and also for sending the universe data out to Art-Net.
Art-Net Router
The Art-Net router is an object that takes data and routes it to each universe, depending on the desired universe ID. When sending data to Art-Net, the data is encapsulated in a frame, and a router 'opens' a frame, reads each command, and sends it to the correct universe depending on the universe address in the command. This is essentially the link between the Art-Net part of Java and the rest of a program, as it serves as a hub for routing commands. However, unlike IP routers in the real world, this is merely an object in a Java program and not a physical router.
Putting it all Together
The last step is to combine all of these steps into a final project. For sake of example, I'll be explaining how I use this in my last project, the simple dimmer and color controller (see that project here).
First is to create and initialize all of the objects we need for Art-Net to work.
![]() |
| Initialization code |
The next step is to create a frame object. We only need one since this is a basic controller and isn't working with saved scenes and frames.
![]() |
| Creating and assigning the frames to the fader banks |
Next is the code to write data to each frame. This is a simple method call for the frame object.
| Code for adding a command to a frame |
The last step is to send the frame to the router, which is done each cycle through the main loop.
![]() |
| Commands for sending Art-Net data |
And there you have it! This is the Art-Net framework I will be using in future projects since it offers simple functionality that builds upon existing Java Art-Net libraries. Thanks to Cansik for making the library exist so I don't have to start from scratch!
That's all for now, thanks for reading! Keep on making things!
-Will



No comments:
Post a Comment