January 1

Using OpenDMX in Linux

Enttec makes a handy little USB to DMX converter called OpenDMX. (DMX is the standard theatrical lighting control protocol – a serial protocol where up to 512 lights are daisy chained together). Several people have made Linux kernel drivers for this device – for example: the DMX4Linux project and Erwin Rol – however, at the time I got one of these dongles, they either didn’t work with the 2.6.x kernels or required compiling a kernel module (irritating when apt-get keep installing new ones requiring a module recompile…). So, I set about using another approach – using just the stock Linux serial drivers.

The OpenDMX device actually uses a standard FTDI USB to Serial IC that is well supported by Linux. The main tricky bit is persuading Linux to use the unusual baud rate used by DMX (250Kbits/sec). Handily recent linux kernels (the earliest I’ve tried is 2.6.17) allow you to set the data rate of a serial port to the required value.

The second tricky bit is that DMX requires that the lighting data is sent out continuously. The OpenDMX has no data buffer of it’s own so it relies on the PC software to keep spitting out all of the DMX data. I knocked together a crude daemon that memory maps a file that stores the lighting levels and keeps spitting the values out to the OpenDMX device.

Here it is the code – admittedly lacking error checking, or configuration parameters – but, you get the idea:

/*
 * $Id: dmx_server.cpp,v 1.2 2008/10/04 17:05:22 anthony Exp $
 */

using namespace std;

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <iostream>
#include <sys/mman.h>

#include <termios.h>
#include <linux/serial.h>
#include <termio.h>

#define DMXDEVICE "/dev/ttyUSB0"

int main(int argc, char* argv[])
{
	int mcr=0;
	struct termios newtio;
	struct serial_struct advsettings;
	unsigned char *buffer;

	int res;
	int fd;
	int statefd;
	cout << "Opening state file..." << endl;
	statefd=open("/var/dmx/state",O_RDONLY);
	cout << "mmap'ing state file..." << endl;
	buffer = static_cast<unsigned char *>(mmap(0, 513, PROT_READ, MAP_SHARED, statefd, 0));

	cout << "Opening output device... " << endl;
	// Open write-only, not controlling TTY
	fd = open(DMXDEVICE,O_WRONLY | O_NOCTTY);
        if (fd < 0) {
    	perror("open");
		exit(-1);
	}

	// Now setup serial port as required:
	// First setup custom baud rate
	ioctl(fd,TIOCGSERIAL,&advsettings);
        printf("Before: Baudbase: %i Divisor: %i \n",advsettings.baud_base,advsettings.custom_divisor);

	advsettings.flags = (advsettings.flags & ~ASYNC_SPD_MASK) | ASYNC_SPD_CUST;
	advsettings.custom_divisor = advsettings.baud_base / 250000;

	printf("After: Baudbase: %i Divisor: %i \n",advsettings.baud_base,advsettings.custom_divisor);

	ioctl(fd,TIOCSSERIAL,&advsettings);

	// First zero all fields in struct:
	bzero(&newtio, sizeof(newtio));

	// 8bit, 2stopbits, ignore modem signals
	newtio.c_cflag = CS8 | CSTOPB | CLOCAL | B38400;

	tcflush(fd,TCIFLUSH);
	tcsetattr(fd,TCSANOW,&newtio);

	// Set RTS High:
	ioctl(fd, TIOCMGET, &mcr);
        mcr &= ~TIOCM_RTS;
        ioctl(fd, TIOCMSET, &mcr);

	cout << "Running." << endl;
	while(1) {
		// Wait for TX buffer to empty:
		tcdrain(fd); 

		// 88us break
		ioctl(fd,TIOCSBRK);
		usleep(88);
		ioctl(fd,TIOCCBRK);
		usleep(8);

		res = write(fd, buffer, 513);

		if (res < 0){
			perror("write");
			exit(-1);
		}

	}

	close(fd);

	munmap(buffer, 513);
	close(statefd);

	return 0;
}

Tags:
Copyright 2020. All rights reserved.

Posted January 1, 2009 by anthony in category "Open-source software

3,173 COMMENTS :

  1. By Steph Reed on

    Thanks loads for this! After problems with both the Erwinrol and DMX4Linux drivers I actually came up with the same idea.. it’s great someone’s already done it!

    Reply
  2. By Peter on

    Dear Anthony,
    can I use your Code as open-source in my DMX project? I am planning to extend it a little more, add a socket for network control.

    Reply
  3. By ajgreen (Post author) on

    @Peter
    Sure Peter, you are welcome to use the code on this page in your open-source project. If you release it on the web, let me know and I’ll put up a link.

    Reply
  4. By MattaLor on

    Nicely put. With thanks! compare rx prices online pharmacy drugstore

    Reply
  5. By MattaLor on

    You’ve made the point. canadian pharmacy cialis 20mg cialis online pharmacy

    Reply
  6. By MattaLor on

    Thanks. A good amount of posts!
    canadadrugsonline best online canadian pharmacy

    Reply
  7. By MattaLor on

    Cheers, Plenty of data.
    medical pharmacy north west pharmacy canada

    Reply
  8. By MattaLor on

    You have made your position quite well!! canadian pharmacy without prescription northwest pharmacy/com

    Reply
  9. By MattaLor on

    You mentioned that terrifically. cvs pharmacy online most reliable canadian pharmacies

    Reply
  10. By CorezDumma on

    You expressed that adequately. pain meds online without doctor prescription canadian pharmacy online viagra

    Reply
  11. By MattaLor on

    Regards. Numerous forum posts.
    canada pharmaceuticals online my canadian pharmacy

    Reply