DMX over RS485 with an Arduino

Arduino DMX breadboard example

Having a travelingย Tesla coil show means having to understand other stage technologies. One often encountered issue is the effect that our machine’s EMI can have on DMX stage lighting. Before we can understand ways of mitigating these problems, we must first become familiar with RS485.

RS485 is so common that you have likely heard the term at least a few times. But what is it even, and what does it have to do with DMX? I’ll go into the details in this article and use what I learned to build a little DMX512 thingy with an Arduino. If you are looking for a complete solution for DMX lighting, check out our open-source MIDI to DMX converter.

What is RS485?

RS485 is a serial communication standard. It outlines what voltage levels and timings data should have when using it. Just like RS232, it uses asynchronous serial communication.

As you can see in the scope trace, there are three distinct phases of a byte:

  1. The “Start bit”: this is always 0 and allows the receiver to synchronize to the timing of the transmitter.
  2. The Data (8 bits): this is the content of the Message. The device reads the data at a fixed frequency, called the baud rate.
  3. The “Stop bit”: this is always 1 and allows the receiver to detect if its timing is wrong. It just checks if the stop bit is “1”. If it isn’t, it will give out an error.
RS485 scope

The stop bit error detection can be unreliable when the receiver’s baud rate is higher than that of the incoming data. In this situation, there is a data bit where the receiver expects a stop bit. If this is “1” by coincidence, the receiver won’t know that it made a mistake as the data looks just like a stop bit. For this reason, some protocols use two stop bits. It is much less likely for two data bits to be “1” after each other, so an error is more likely to be detected.

Balanced signal with RS485

Unlike RS232, RS485 is a symmetrical bus. This means that we have two data lines instead of one. The second one transmits the inverse of the main data line. The receiver detects the difference between the two and ignores absolute voltages. What this means is that it is much more immune to noise.

If some interference produces 2.5V on data lines, an RS232 transceiver would think the signal is always “1”. But with a symmetrical bus, the 2.5V would be induced similarly on both conductors, with the difference remaining the same. The receiver would have no issue decoding the data despite the interference. That’s why it’s used so much in industrial applications.

Another thing the standard outlines is the driver output impedance. At the high baud rates, transmission line effects start to cause problems with signal reflections on cable ends. With a known output impedance, it’s easy to design cables with a matching impedance that negates those effects. Those reflection problems are also why DMX networks are supposed to have a 120 ohm terminator at the end.

What RS485 doesn’t define is what data gets sent over the bus or what format it should have. You can send normal strings over it just as well as some complicated data packets.

So what does DMX512 have to do with this?

DMX512 is one of the protocols using RS485. It’s probably the most common standard for controlling stage lighting in use right now. If you buy any sort of controllable stage light, it probably supports DMX. When it was invented, computer hardware was slow, and ram was small, so it was designed to be as simple as possible. It’s also using RS485 because of its noise immunity, which is why I’m talking about it now ๐Ÿ˜‹

Let’s look at another scope trace to understand how it works:

  1. The Break (or line-break): This is how DMX signals the start of a packet. Its long zero level guarantees that any receiver gets a “Stop bit, not zero” error.ย 
  2. The Start code: For normal DMX data, this will always be a zero. It’s there as a way to signal package types.
  3. The Data itself: these bytes contain the values for the individual channels.
DMX Protocol on scope

The amount of bytes sent differs between lighting desks/interfaces. The cheap Chinese ones, for example, may only send out 192 channels because their CPUs can’t keep up with anything more. The official spec puts a limit on the time between one break and the next. This limits the number of bytes to 513 slots (1 Start code and 512 Channels), hence DMX512. This is also sent with two stop bits for added fault tolerance.

Another thing to keep in mind is that many cheap DMX interfaces won’t adhere closely to the spec. Especially the length of the break if often shortened or not accurate in cheap lighting desks. Other controllers might have a lot of variance in the timing of the data. Most cheap lights also don’t check the second stop bit because it works and only reduces fault tolerance. But since all of those just impact the resilience to faults, it’s not that big a deal for hobby use. ๐Ÿ˜„

DMX Packet

One other thing to talk about is the connector. The DMX standard specifies a 5pin XLR connector but only uses three pins. And since 3pin XLR is cheaper and more common, many cheap lights use them instead.
This brings some problems with it, though. Audio cables don’t have a controlled impedance and are thus not matched to RS485 drivers. But since they are sometimes cheaper, people tend to use them for lights that have 3pin sockets too. This can cause signal reflections and make the entire DMX network go haywire. Some 3pin cables can also have some nasty voltages on them from certain audio equipment. Keep this in mind when you choose what connector to use. Even though I have never had any of those issues with the three-pin variant myself ๐Ÿ˜€

Using an Arduino to receive DMX

Now that we are experts in RS485 communications, we can get to the fun part:
making some LEDs blink over DMX with an Arduino ๐Ÿ˜Ž

First, we’ll need the hardware. To receive RS485 properly, the Arduino needs some help from a transceiver chip. I used an sn75176 differential bus transceiver, probably the most common one you’ll find anywhere. Since it can be a transmitter too, we need to tell it to receive. We’d risk damaging the transmitter on the other side if we tried to transmit ๐Ÿ˜‰ We do this by pulling the two config pins !RE and WE to ground. We’ll also need a connector for the DMX data. I had a three-pin one lying around, so I soldered a pin header to it and plugged it into the breadboard.

Arduino DMX RGB example
RS485 to Serial pin diagram

You’ll need to connect the output of the SN75176 to pin0 of the Arduino if you’re using an UNO. This is because the data rate is too high for a software serial port. The library uses the hardware UART module. That means that you won’t be able to upload code with the transceiver connected as well.

Oh, and don’t forget to put a couple of LEDs onto the breadboard to control ๐Ÿ˜ Then all we need is the software that receives the data. I just used the Conceptinetics DMX library.ย I used the following code to output three channels of PWM data depending on DMX addresses.
				
					#include <Conceptinetics.h>

DMX_Slave dmx_slave (3);

void setup() {  
  dmx_slave.enable();  
  dmx_slave.setStartAddress(1);
  
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
}

void loop() 
  analogWrite(9, dmx_slave.getChannelValue(0));
  analogWrite(10, dmx_slave.getChannelValue(1));
  analogWrite(11, dmx_slave.getChannelValue(2));
}
				
			

And that’s it!ย 

I hope this helped you understand RS485 and DMX a little better. If you have any feedback, we’d love to hear it ๐Ÿ˜€

Share this post

Share on facebook
Share on twitter
Share on email