DIY DMX

I’ve had a DMX project on the back burner for some time now. A year or so ago I managed to trade a bottle of scotch for a box of 8 RGB PAR cans, call them disco lights. These lights contain an array of RGB LEDs in a rugged commercial housing. You can control the intensity of each of the RGB LEDs individually using a commercial standard protocol known as DMX-512.

DMX is a serial bus operating at RS-485 levels with a simple framing mechanism. The protocol is inherently simplex, the sender just sends. There is no error detection or correction. DMX devices such lights, strobes etc. are connected in parallel to the serial bus.  Each device receives the same digital signal. Individual devices are configured with an address that indicates the starting channel number.

Each DMX-512 frame contains data for up to 512 channels. Each channel is a single, 8 bit byte. The channel number is implied by its position in the frame. The first byte following the frame header is the data for channel 1, the second byte is for channel 2 etc. In cases where an 8 bit value is not sufficient, for example the rotational position of a spotlight, a 16 bit value can be created by using two adjacent channels. The convention is to place the most significant byte first, in say channel 1, and then place the least significant byte after, in channel 2.

In my case, the RGB lights are 4 channel types. This is hard wired into the lights themselves. Three channels correspond to the intensity of the red, green and blue LEDs. The fourth channel is used to control effects such as strobe. Each light has a series of switches to configure the address. If I set the address to say 1, this means the light will take its data from channels 1, 2, 3 and  4 of the DMX frame. If I set the address to say 8 then channels 8, 9, 10 and 11 will be used.

Project Hardware

A simple serial interface can be created with an FT232R chip from FTDI. Being a surface mount device it’s easier to buy a premade breakout board than create a circuit from scratch. I used a Sparkfun  USB to RS-485 breakout board (BOB-09822) as this also includes the RS-485 transceiver chip. To make testing and installation easier I soldered a 3 screw terminal block to the board.

As supplied, the RS-485 transceivers enable signal is driven by the TXDEN pin. TXDEN is generated by the FT232R and goes high whenever data is about to be transmitted (and during the transmission). Once data transmission is complete the pin goes low again. Whilst this behaviour is useful when using half-duplex RS-485, it can cause problems with  a simplex protocol such as DMX due to the bus ‘floating’. Sometimes an RS-485 receiver can interpret the floating bus as a start bit, the receiver will then generate framing errors. If you’re interested in more information on why, Google ‘RS-485 failsafe’.

I decided to wire the RS-485 transceiver so that it operates in a ‘Tx only’ mode. This requires cutting the track between pins 2&3 of the transceiver and pin 13 (TXDEN) of the FT232R. Fortunately the track is easily accessible on the bottom side of the board. Image 1 below shows the cut location, to the right, just below the text ‘RX-I’.

Once cut, the  solder mask can be scraped from the top side, just near pins 2 & 3 of the transceiver. This can then be jumpered to the 3.3V pad adjacent to the FT232R (JP-5 in the schematic). See the green wire in Image 2 below.

After a bit of trial and error it was determined that the DMX ‘+’ signal should be connected to the ‘A’ and DMX ‘-‘ to ‘B’. It helps to have documentation for your DMX devices.

I also discovered a bug with the Sparkfun board, the TX and RX LEDs have been reversed. If this kind of thing annoys you read the comments on the Sparkfun website. Someone has posted instructions on how to work around this annoyance by reprogramming the device settings.

Software

As I am the author of yad2xx, an open source Java to D2XX driver binding project, it makes sense to build on top of the functionality provided there. There are two main tasks, one time device initialisation and periodic transmission of the DMX frame. Let’s start with initialisation.

The DMX protocol is based around a stream of asynchronous characters. Each byte is 8 bits long, there are two stop bits and no parity. The baud rate is high, 250k/bits per second. The initialisation code goes like this:

Device[] devices = FTDIInterface.getDevices();

if (devices.length == 0) {
    out.println("*** No FTDI devices found. Possible driver problem. ***");
    return;
}

device = devices[0];
device.open();
device.reset();
delay(10);

device.setDataCharacteristics((byte) 8, (byte) 2,
                              FTDIConstants.FT_PARITY_NONE);
device.setBaudRate(250000);
delay(10);

The DMX protocol sends data blocks framed by BREAK conditions. A BREAK condition is where the line is driven to the start bit state and then held for a period longer than a single character transmission (including any stop bits). Due to the invalid stop bits, the receiving UART will report a NUL (ASCII 0) character received plus a framing error. Receipt of a BREAK effectively ‘resets’ the receiver.

The first byte following the BREAK is known as the START code. When communicating with fixtures this is set to NULL (ASCII 0). Channel data follows the START code. The channel portion of the frame is variable length, up to 512 bytes can be sent. The receiver knows when a short frame is encountered due to the BREAK. In summary, the DMX frame consists of 1) BREAK 2) START code 3) channel data. This repeats continuously.

For testing I decided to use 192 channels, this is represented by a constant and a byte array:

private static final int CHANNEL_COUNT = 192 + 1;

private byte[] channels;

The CHANNEL_COUNT has an extra byte to allow for the START code. Java indexes arrays starting from zero, which conveniently locates the DMX channel 1 value in channels[1]. The START code is found in channels[0].

Initialisation goes like this:

channels = new byte[CHANNEL_COUNT];

for (int i = 0; i < CHANNEL_COUNT; i++) {
    channels[i] = (byte) 0;
}

channels[1] = (byte) 0xff;    // Strobe/Intensity channel
channels[2] = (byte) 0xff;    // RED channel

Once the data has been set up we need to periodically send a complete DMX frame. The code for that goes like this:

private void sendDmxFrame() throws FTDIException {
    device.setBreak(true);     // BREAK indicates new DMX frame
    device.setBreak(false);
		
    device.write(channels);    // send START code plus 192 channel bytes
}

Final Thoughts

Both hard and software were a breeze to put together. This is the first time I’d used yad2xx to drive an FTDI chip in UART mode and the library worked well with no fixes required.

The main problem I encountered was not having a technical manual for the lights. I had made the assumption that the channel order would be R/G/B/strobe. As it turned out they are actually Intensity-Strobe/R/G/B. To complicate things even further values between 0-140 on the intensity-strobe channel control the intensity (it appears to max out between 127-140). Values between 140-190 make the light strobe. Values above that set it to maximum intensity (again). Go figure!

Whilst you can use yad2xx for basic testing I found a better option was to download the Q Light Controller from Source Forge. After a little bit of experimentation I found that by editing the ‘Outputs’ options and selecting ‘ENTEC USB DMX Output’ I was able to get the software working. Operating a bunch of on screen sliders is MUCH easier that messing about with a Mickey Mouse sample program.

Anyway I now have a bunch of DMX cables to make.

 

Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s