A search on the associated open-lighting discussion group indicated that various people had talked about this, been told it wouldn't work, and not actually tried it. Given that quite a lot of similar adaptors using the FTDI USB-serial chip to send DMX exist (and are supported in OLA), this didn't seem a logical position. The fact that the Raspberry Pi UART is integrated at a much lower level than a USB converter (with hardware interrupts and DMA available) should give it much better performance. So I decided to carry on and build such a system so the actual results could be measured.
Why DMX-512 is HardThere are a number of reasons why producing direct DMX-512 output from a computer is considered hard, and software developers want to hand the task off to an external microcontroller running bare metal code. The key ones seem to be:
- DMX-512 runs a a non-standard (for PC) baud rate of 250kbaud. Many computer UARTs cannot run at this speed, which makes them a non-starter.
- DMX-512 uses serial break signals (periods when the line is held continuously in the '1' (non-idle state) to demarcate successive frames of data. These cannot be sent by just writing characters out of the serial port.
- DMX-512 has relative tight timing requirements for various elements of the signal – if your computer suddenly stops sending data for a while, then the lights you are controlling may go out or flicker randomly.
Hardware DMX OutputThe hardware side of sending DMX-512 is relatively simple – it uses simplex RS-485 (I am ignoring optional extensions like RDM). Simplex means that data only goes one way – the controller sends data, and everything else in the system just listens to it, with no answering back! RS-485 is a common standard for industrial serial communications, using a screened, twisted, pair of wires. Because RS-485 is common industrially, there are lots of integrated circuits which can translate from the transmit pin coming out of the Raspberry Pi (at 3.3V TTL levels) to the standard (higher) RS-485 levels. I used a Maxim MAX3158 line driver, because it provides isolation between the DMX control line (which will be connected to lighting ground) and the Pi (which will be connected to audio ground). For a simple project like this, isolation isn't required, but it can be very useful in avoiding humming audio and flickering lights on larger projects. I also had got hold of some at a good price!
|RS-485 output schematic (pdf | svg)|
R3 is the DMX line terminator, to minimise reflections on the DMX cable, and needs to be the ½ W part because it gets quite a lot of current through it when the full output voltage is being driven.
|C1, C2||100 nF 100 V|
|R1||100 Ω ¼ W|
|R2||47 kΩ ¼ W|
|R3||120 Ω ½ W|
This all worked straightforwardly – each byte sent out of the Pi's serial port was translated through to RS-485 levels on the DMX output connector, with no sign of ringing or waveform distortion.
DMX Output Plug-inSo back to those things which make software developers avoid direct DMX output. Before we try to start, we need to stop the default Raspbian image from using the serial port as a text mode login screen, by following these instructions. With that done and rebooted, I no longer got random data coming out of the UART.
The first software challenge was to get the UART outputting data at 250kbaud. The maximum speed seemed to be limited to 115.2kbaud, until I found a post on how to run the Pi UART at 1Mbaud which explained how to increase the clock speed of the UART. So do as it says, and add the line
to /boot/config.txt and reboot your Pi (again). This raises the clock limit, but we can still only get the “standard” speeds of 230.4kbaud, 460.8k, 500k and 576k – no joy at 250k. The setserial utility seems to support custom rates, but they don't work in practice. There is a plaintive little message in
the system log
Feb 22 18:55:02 lightingpi kernel: [ 4519.973048] seterial sets custom speed on ttyAMA0. This is deprecated.
What it doesn't say is that setting the custom speed also doesn't work on the Pi UART! After much puzzling, I found a stack overflow post describing how to use the Linux-only termios2 interface to set arbitrary baud rates (this is what you are supposed to use in place of the depreciated setserial method, if you can find out about it). This works, although writing a C program to use the termios2 API has several more “surprises” in store for the unwary.
With the proof of concept in place, on to using it in OLA. OLA has pretty good developer documentation and a detailed log of creating another OLA output plug-in. Between these, it was fairly easy to work out that most of what I was doing could be copied from the existing plug-ins, mostly that FTDIchip output driver I found near the start.
After all messing to get the correct speed, integration into OLA was very smooth, once I did all the things listed in the instructions to register my new plug-in, there it was in the output of the ola_plugin_info command:
Id Plugin Name
11 E1.31 (sACN)
10000 UART native DMX
(10000 is the dummy ID for testing, it will only get a “proper” ID when the code is accepted back into upstream OLA development). The source code to my forked copy of OLA with the Pi UART plug-in added can be found on Github here. commit a4959cc46d is the version which was used at the trail, although there has subsequently been a new version of OLA released upstream (which I need to update to).
Once OLA was compiled with the Pi output plug-in, it needed to be enabled (the plug-in is deliberately disabled by default), by creating the configuration file /var/lib/ola/conf/ola-uartdmx.conf
which contains just two lines:
device = /dev/ttyAMA0
enabled = true
(there are some other advanced options, but you probably don't need them).
Moment of TruthYou should now have the UART native DMX output device visible in the OLA web GUI, so you can connect it to Universe 0, and use the web DMX console to start sending some output. With any luck, you should be able to fade up your light(s)! The fade won't be very smooth, because the faders only update from the browser a few times per second, but it proves you have control. You can get more detailed control (and timed fades) with the ola_dmxconsole command line tool which is included with OLA.
Next time, I will look at the how I created audio and lighting files to play back through this system.