Step 2: The Raspi

1. raspi-tize yourself

The bulk of the work on this project is to get your raspi ready for business. You can purchase the raspi from several sources, but our preference is from the great folks at Adafruit industries - they have been and continue to be a strong supporter of makers everywhere. You can purchase a raspi from this link:


2. get jacked

The raspi by itself is just a card, so to make it into a fully functioning computer you'll need a few components that you most likely already have lying around. It is well worth the effort to build your raspi into a fully functioning computer because it really is great machine for building any "smart" project you have in mind down the road. The Raspberri Pi foundation website is a great resource for getting or raspi up and running. Please read this page for information on what you need to get your raspi computing:


3. get loaded

This project is using the stock Raspian "wheezy" operating system, which you can download for free from the Raspberry Pi Foundation website. This page has complete details on how to get the OS to your SD card - its very straightforward procedure, and in less than 20 minutes you should be able to plug the SD card into your raspi and have it booted and ready for business.


4. hello raspi!

Once you've got the SD card prepared and cabling connected, simply insert it into the SD card slot, and hit the juice to the raspi. To your amazement a computer will appear on the screen. The stock wheezy distribution contains a window manager ( LXDE ) that you will use to log in ( Username: pi , Password: raspberry ) and begin your raspi adventure. As per the boot instructions, you can type "startx" to get the LXDE window manager running. Take a few minutes to explore the system. BTW, if you want to have your raspi boot into the windows environment every time you plug it in, you can follow these instructions:


5. get wheelin'

The software that creates the color wheel interface and talks to the DMX converter can be downloaded for free in both binary and source format directly to your raspi. To get started, download the free DMXWheel application code from here:

dmxwheel source code (zip file)

Launch Midori ( from your desktop icon ), and enter this URL. Click on the paperclip, and save the file to your desktop when prompted; this will create an icon labeled DMXWheel.tar.gz" on your desktop. Next, open up a terminal window to get a command line interface by selecting the icon on the lower left of the tool bar -> Accessories -> LXTerminal. In the terminal window, type these two commands:

<strong>cd Desktop

tar xvzf DMXWheel.tar.gz</strong>

This will unpack the DMXWheel application code on your desktop to a folder named "DMXWheel". You can open this folder to find the code that is referred to in the rest of this instructable.

6. get the extra bits

Although not needed to run the programs, to make changes and build the source code two additional software packages should be installed. These two packages contain Linux-native code to communicate with USB (libusb-dev), and develop user interface windows (gtk+3.0) respectively. These packages are installed using the linux application management program called "apt-get". In the terminal, type these commands and follow the proceeding prompts:

<strong>sudo apt-get install libusb-dev

sudo apt-get install gtk+3.0

7. raspi-ready

At this point you should have the raspi ready to go for the rest of the project. The software you will be using will be found in the DMXWheel folder on your desktop. Take a minute to look through this folder and read the README file - it provides valuable information on what the code is, what is does, and how to run it. We will go through some of the basics, but this README file can serve as your local reference documentation. There is a huge amount of coolness to explore on the raspi, so when you have some time explore the Raspberry Pi foundation forum to get some great ideas as well as support from the raspi community.

<p>Hello, I recently ran into a problem that I have not been having before, when trying to run DMXWheel.bin as normal, i am getting an error that states</p><p>&quot;** (DMXWheel.bin:1609): WARNING **: Error retrieving accessibility bus address: org.freedesktop.DBus.Error.ServiceUnknown: The name org.a11y.Bus was not provided by any .service files&quot;<br></p><p>I have not changed any of my hardware and it has been working properly before. Does anyone know what could cause this error?</p><p>Thanks!</p>
<p>Well done mate! You've done a great job.</p><p>I've been playing with the PI for a few years, but my knowledge is still pretty limited. Have you any idea how I go about making this kind of thing work with a different usb to dmx adaptor. My hope was that 'under-the-hood' mine would be the same as the velleman one, but when I execute the daemon I get an error about USB device not found. I guess it can't be that complicated! I feel up for a challenge!</p><p>Well done. Amazed more people haven't done this. My application is basically for static LED architectural lighting in our church building, without having a lighting desk that fingers can twiddle! Then when we have events I can use a full desk or PC (freestyler) for more ambitious lighting (chases etc).</p>
<p>Hi, </p><p>Nice project as well, but i'm having the same issue described here:</p><p>// acastellano-e 2 years ago<br><br>// Hi!!<br>// First of all, this is an amazing project.<br>// I'm playing with the code and i can't control more than 6 <br>// channels at the same time, when i set values for 6 channels<br>// if i set a value to 7th it doesn't changue. If i start to <br>// set values from the 7th chanel it works but only for the <br>// first 6 channels that i set, any idea?</p><p>Could anyone help me?</p><p>THansk in advance. </p><p>P.:s. I'm rewriting as I cannot hit the reply botton to commit my comment to the existing entry .</p><br>
<p>Or just install QLC+.</p>
<p>I'm still trying to speak with the deamon via a python program. I have the deamon running. But nothing is happening on the DMX bus when I start the python script. </p><p>import sysv_ipc</p><p>memory=sysv_ipc.SharedMemory(0x56444D58 , 0666, 512) </p><p>print memory</p><p>shm=sysv_ipc.attach(491527)</p><p>print shm</p><p>for i in range(512):</p><p> shm.write(str(unichr(100)),i)</p>
<p>Could anybody help me, to get me a hint, how I can use or integrate this module in python?</p>
<p>This project is really great. Thank you very much!.</p><p>My whole application is written in Python.</p><p>Can anybody help me with a python example sending only a single DMX value on one channel to the running deamon?</p><p>This would help me very very much to create my own application in Python.</p>
<p>&quot;To get started, download the free DMXWheel application code from here using this page.</p><p>Launch Midori ( from your desktop icon ), and enter this URL.&quot;</p><p>Which page ? Which URL ? Why is this broken ? </p><p>What a shame ! It's otherwise very well written !</p>
I'm sorry for that, nano dust. I had originally posted it on the intractable as an attachment but it looks like that's not available now. I have updated the link to point to an external site that is hosting the source file. Please let me know if you have any other problems. Have fun!
<p>Thanks flashular! I was indeed able to download and compile without problems ! </p>
<p>Hi there,</p><p>Where can i download all this soft.</p><p>Links are broken?</p><p>Thanks </p><p>Johan</p>
Sorry about that. Should be there now.
<p>Sorry, Johan. I lost my web hosting account and am currently reconstructing it. However, you should be able to download the attached ZIP file until the links are fixed. Sorry for the trouble.</p>
<p>If you send me the zip file to michelle@sorbs.net (make the subject good so I don't think it's spam) I'll put it on a public site for you.</p>
<p>Hi, can't download DMXWheels, can you put the sourcecode here please ?</p>
<p>Hey I uncovered a couple bugs in dmxd.c. The loop that fills the header 2 array to be written to the usb device does not contain the write statement, thus only the last seven channels will be written after the first packet is sent. Also, the terminating condition for the loop &quot;curChanIdx &lt; ( numChans - 7 )&quot; leaves the possibility that some of the end channels will not be written. My modifications are shown below. This replaces the code in dmxd.c from line 221 to the #else around line 256. </p><p>Note that these fixes allow for the possibility of writing more than 512 channels if your MaxChannels is high enough. It also will at times fill the tail end of the last array to be written with uninitialized data. This won't be a problem though if there is nothing in your lighting system listening to anything beyond your specified max channels.</p><p>The same makfile flashular provided will still compile the deamon even with these changes. Just edit dmxd.c in the DMXWheel/dmx/src folder.</p><p>This really was a great project, so thank you to flashular for doing the bulk of the work to provide the PC to DMX interface. WIth the provided function calls I was able to build my own working light board for use in a 24 channel system in my High School's auditorium. It has all the functionality of the current board with the addition of wireless control so I can actually turn lights off and on while climbing around in the catwalks.</p><p>Hope this helps.</p><p>// after the first packet additional packets are sent that contain seven</p><p> // channels each up to 512.</p><p> // while ( curChanIdx &lt; ( numChans - 7 ) ) {</p><p> while ( curChanIdx &lt; numChans ) {</p><p> data[0] = 2; // start packet header (2)</p><p> data[1] = chanData [ curChanIdx++ ]; // next chan data</p><p> data[2] = chanData [ curChanIdx++ ]; // next chan data</p><p> data[3] = chanData [ curChanIdx++ ]; // next chan data</p><p> data[4] = chanData [ curChanIdx++ ]; // next chan data</p><p> data[5] = chanData [ curChanIdx++ ]; // next chan data</p><p> data[6] = chanData [ curChanIdx++ ]; // next chan data</p><p>data[7] = chanData [ curChanIdx++ ]; // next chan data</p><p>success = writeUSB ( data , 8 );</p><p>if ( !success ) {</p><p>printf ( &quot;%s: error sending DMX bulk packet\n&quot; , ProgName );</p><p>return ( 0 );</p><p>}</p><p> }</p><p> /*</p><p> success = writeUSB ( data , 8 );</p><p> if ( !success ) {</p><p> printf ( &quot;%s: error sending DMX bulk packet\n&quot; , ProgName );</p><p> return ( 0 );</p><p> }</p><p> if ( curChanIdx &gt;= numChans ) return ( 0 );</p><p> */</p>
<p>Hi </p><p> I would like to install DMXWheel however the download link is broken. Anyone have any idea where I can download the install file? Thanks</p>
<p>Where do you send de RGB-values to the dmx controller?</p>
DMX is a really, really simple protocol, provided you can generate the BREAK signal it requires. Other than that, it is just a one-way, 250kbps, 8N2 serial interface. The additional circuit would be a 3.3V RS485 transceiver. It could be used as a Art-net to DMX converter (or other DMX-over-network protocol), allowing any other computer to use it from the network.
Yeah, I'm surprised that nobody has offered a project that uses an RS485 circuit. I would be interested in helping develop the software side if someone has a schematic that could eventually be developed into a shield for the pi. I see the opportunity for a full featured lighting control rig with HDMI user interface that could fit into the palm of your hand ( and be under $60! )
<p>Better late than never:</p><p><a href="http://www.jonshouse.co.uk/rpidmx512.cgi" rel="nofollow">http://www.jonshouse.co.uk/rpidmx512.cgi</a></p>
<p>Can I control two different lights (or two banks of multiple lights) so that both are displaying different colors and patterns?</p>
Yes, as long as you have DMX compatible features and configure them according to the setup you create in the code. If you are new to DMX you might need to do some reading on what the channel and values mean in the DMX protocol.
<p>Hi!!<br><br>First of all, this is an amazing project.<br><br>I'm playing with the code and i can't control more than 6 channels at the same time, when i set values for 6 channels if i set a value to 7th it doesn't changue. If i start to set values from the 7th chanel it works but only for the first 6 channels that i set, any idea?</p>
Hi djMaxM. The Velleman is a USB to DMX controller, and is powered by the USB connection from the Raspberry Pi. The output of the Velleman is a low voltage DMX signal that is fed to a DMX compatible light fixture that itself has mains power.
I just bought one of these: http://www.wiedamark.com/icolorflexslx4-2.aspx (Color Kinetics iColor Flex) - other than the Pi and the Velleman, do I need anything else? Like a power source, or does that come from the Velleman (don't see how given the load)?
Hi flashular, this is a great project, nice work! Just wondering how to access/download the dmxd.c program? thanks
Hi omeguanut. The source can be downloaded here:<br><br>http://www.engeldinger.com/services/latest-project/dmxwheel<br><br>Let me know if you run into any problems getting it working.
dmx.c:<br> <br> // ==========================================================================<br> // Velleman K8062 DMX controller library for VM116/K8062<br> // ==========================================================================<br> <br> #include &lt;stdio.h&gt;<br> #include &lt;sys/types.h&gt;<br> #include &lt;sys/ipc.h&gt;<br> #include &lt;sys/shm.h&gt;<br> #include &lt;errno.h&gt;<br> <br> #include &quot;dmx.h&quot;<br> <br> <br> int&nbsp;&nbsp; * maxChanAddr;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // control register for # of channels to update<br> ubyte * exitAddr;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // control register to exit deamon<br> ubyte * chanData;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 512 byte array of channel data<br> <br> ubyte * shm;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // shared memory segment containing data &amp; ctrl regs<br> int&nbsp;&nbsp;&nbsp;&nbsp; shmid = -1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // handel to shared memory segment<br> <br> <br> // ==========================================================================<br> // open the DMX connection<br> // ==========================================================================<br> <br> int dmxOpen()<br> {<br> <br> &nbsp; // get the shared memory created by the deamon<br> <br> &nbsp;&nbsp;&nbsp; shmid = shmget ( 0x56444D58 , sizeof ( ubyte ) * 515 , 0666 );<br> <br> &nbsp;&nbsp;&nbsp; if ( shmid == -1 ) {<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf ( &quot;error[%d] - is dmxd running?\n&quot; , errno );<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return ( errno );<br> &nbsp;&nbsp;&nbsp; }<br> <br> &nbsp;&nbsp;&nbsp; // set up control and data registers<br> <br> &nbsp;&nbsp;&nbsp; shm = ( ubyte *) shmat ( shmid, NULL, 0 );<br> <br> &nbsp;&nbsp;&nbsp; maxChanAddr&nbsp; = ( int * ) shm;<br> &nbsp;&nbsp;&nbsp; exitAddr&nbsp;&nbsp;&nbsp;&nbsp; = ( ubyte * ) maxChanAddr + 2;<br> &nbsp;&nbsp;&nbsp; chanData&nbsp;&nbsp;&nbsp;&nbsp; = ( ubyte * ) maxChanAddr + 3;<br> }<br> <br> // ==========================================================================<br> // close the DMX connection<br> // ==========================================================================<br> <br> void dmxClose()<br> {<br> &nbsp; if ( shmid != -1 ) shmdt ( shm );<br> }<br> <br> // ==========================================================================<br> // dmxSetMaxChannels -- set the maximum # of channels to send<br> // ==========================================================================<br> <br> void dmxSetMaxChannels ( int maxChannels )<br> {<br> &nbsp; *maxChanAddr = maxChannels;<br> }<br> <br> // ==========================================================================<br> // dmxSetValue -- set the value for a DMX channel<br> // ==========================================================================<br> <br> void dmxSetValue ( ubyte channel , ubyte data )<br> {<br> &nbsp; chanData[channel] = data;<br> }
dmx.h:<br> <br> // ==========================================================================<br> // Velleman K8062 DMX controller library for VM116/K8062<br> // ==========================================================================<br> <br> typedef unsigned char ubyte;<br> <br> int&nbsp; dmxOpen&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ();<br> void dmxClose&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ();<br> void dmxSetMaxChannels ( int maxChannels );<br> void dmxSetValue&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( ubyte channel , ubyte value );
dmxd.c:<br> <br> // ==========================================================================<br> // Velleman K8062 DMX controller Deamon for VM116/K8062<br> // ==========================================================================<br> //<br> // Modified from code from Denis Moreaux 2008 ( &lt;vapula@endor.be&gt; )<br> //<br> //<br> // This program should be run as a background process and continously updates<br> // a shared memory segment created by the application to control DMX channels<br> // sent through the DMX controller. The DMX channels can be accessed through<br> // a shared memory block that is allocated as:<br> //<br> // 0&nbsp;&nbsp;&nbsp;&nbsp; = max # of channels to send&nbsp; ( 0 - 512 )<br> // 1&nbsp;&nbsp;&nbsp;&nbsp; = exit deamon control flag&nbsp;&nbsp; ( 0 = run, 1 = exit )<br> // 2-514 = dmx channel data<br> //<br> // ==========================================================================<br> //<br> // Prerequisites ( USB lib ):<br> //&nbsp;&nbsp; sudo apt-get install libusb-dev<br> //<br> //<br> // ==========================================================================<br> //<br> <br> #include &lt;usb.h&gt;<br> #include &lt;unistd.h&gt;<br> #include &lt;stdio.h&gt;<br> #include &lt;sys/types.h&gt;<br> #include &lt;sys/time.h&gt;<br> #include &lt;sys/ipc.h&gt;<br> #include &lt;sys/shm.h&gt;<br> #include &lt;string.h&gt;<br> #include &lt;errno.h&gt;<br> <br> <br> // dmx data and control registers<br> <br> typedef unsigned char ubyte;<br> <br> int&nbsp;&nbsp; * maxChanAddr;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // control register for # of channels to update<br> ubyte * exitAddr;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // control register to exit deamon<br> ubyte * chanData;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 512 byte array of channel data<br> <br> <br> ubyte *shm;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // shared memory segment containing data &amp; ctrl regs<br> int shmid;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // handel to shared memory segment<br> <br> <br> // constants and defs<br> <br> #define ProgName &quot;dmxd&quot;&nbsp; // name of this program<br> #define VendorID 0x10cf&nbsp; // K8062 USB vendor ID<br> #define ProdID&nbsp;&nbsp; 0x8062&nbsp; // K8062 USB product ID<br> <br> #define UpdateInt 100000 // update interval ( microseconds )<br> #define DefMaxChans&nbsp;&nbsp; 16 // default number of maximum channels<br> <br> // internal structures<br> <br> struct usb_bus *bus;&nbsp;&nbsp;&nbsp; // pointer to the USB bus<br> struct usb_device *dev; // pointer to the K8062 USB device<br> usb_dev_handle *udev;&nbsp;&nbsp; // access handle to the K8062 device<br> <br> <br> // function delcarations<br> <br> int&nbsp; main();<br> <br> int sendDMX();<br> <br> <br> int&nbsp; initUSB();<br> int&nbsp; writeUSB ( ubyte *data , int numBytes );<br> void exitUSB();<br> <br> int&nbsp; initSHM();<br> void exitSHM();<br> <br> void timediff ( struct timeval *res, struct timeval *a, struct timeval *b );<br> void timeadd&nbsp; ( struct timeval *res, struct timeval *a, struct timeval *b );<br> <br> <br> // ==========================================================================<br> // main -- dmx deamon<br> // ==========================================================================<br> <br> int main() {<br> <br> &nbsp;&nbsp;&nbsp; struct timeval now,next,diff,delay;<br> &nbsp;&nbsp;&nbsp; int success;<br> <br> &nbsp;&nbsp;&nbsp; printf ( &quot;%s: starting dmx deamon\n&quot; , ProgName );<br> <br> <br> &nbsp;&nbsp;&nbsp; // intialize USB device<br> <br> &nbsp;&nbsp;&nbsp; success = initUSB();<br> <br> &nbsp;&nbsp;&nbsp; if ( !success ) {<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf ( &quot;%s: error initializing USB interface\n&quot; , ProgName );<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return ( -1 );<br> &nbsp;&nbsp;&nbsp; }<br> <br> &nbsp;&nbsp;&nbsp; // initialize shared memory segment<br> <br> &nbsp;&nbsp;&nbsp; success = initSHM();<br> <br> &nbsp;&nbsp;&nbsp; if ( !success&nbsp; ) {<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf ( &quot;%s: error initializing shared memory\n&quot; , ProgName );<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return ( -2 );<br> &nbsp;&nbsp;&nbsp; }<br> <br> <br> &nbsp;&nbsp;&nbsp; // start timer<br> <br> &nbsp;&nbsp;&nbsp; delay.tv_sec = 0;<br> &nbsp;&nbsp;&nbsp; delay.tv_usec= UpdateInt;<br> <br> &nbsp;&nbsp;&nbsp; gettimeofday ( &amp;next , NULL );<br> <br> <br> <br> &nbsp;&nbsp;&nbsp; // loop until commanded to shutdown<br> <br> &nbsp;&nbsp;&nbsp; while( !*exitAddr ) {<br> <br> <br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // send DMX data<br> <br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; success = sendDMX();<br> <br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( !success ) {<br> <br> printf&nbsp; ( &quot;%s: DMX send error\n&quot; , ProgName );<br> *exitAddr++;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br> <br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // wait for update interval<br> <br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeadd ( &amp;next , &amp;next , &amp;delay );<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gettimeofday ( &amp;now , NULL );<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timediff ( &amp;diff, &amp;next , &amp;now );<br> <br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (diff.tv_sec || diff.tv_usec) {<br> <br> select ( 0, NULL, NULL, NULL, &amp;diff );<br> gettimeofday ( &amp;now, NULL );<br> timediff ( &amp;diff, &amp;next, &amp;now );<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br> <br> &nbsp;&nbsp;&nbsp; }<br> <br> &nbsp;&nbsp;&nbsp; printf ( &quot;%s: dmx deamon is shutting down\n&quot; , ProgName );<br> <br> <br> &nbsp;&nbsp;&nbsp; // on shutdown reset all DMX channels<br> <br> &nbsp;&nbsp;&nbsp; memset ( chanData , 0, 512 * sizeof (ubyte) );<br> <br> &nbsp;&nbsp;&nbsp; sendDMX();<br> <br> <br> &nbsp;&nbsp;&nbsp; // exit the system<br> <br> &nbsp;&nbsp;&nbsp; exitUSB();<br> &nbsp;&nbsp;&nbsp; exitSHM();<br> <br> &nbsp;&nbsp;&nbsp; return ( 0 );<br> }<br> <br> <br> // ==========================================================================<br> // sendDMX -- send current DMX data<br> // ==========================================================================<br> <br> int sendDMX ()<br> {<br> &nbsp; ubyte data[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };<br> &nbsp; int numChans = *maxChanAddr;<br> &nbsp;<br> <br> #if 1<br> <br> &nbsp; // find out how many consecutive zeroes are in the data - the start<br> &nbsp; // packet can indicate this to avoid sending a bunch of leading<br> &nbsp; // zeroes<br> <br> &nbsp; int curChanIdx = 0;<br> &nbsp;<br> &nbsp; for ( curChanIdx = 0; curChanIdx &lt; numChans; curChanIdx++ ) {<br> &nbsp;&nbsp;&nbsp; if ( chanData[ curChanIdx ] != 0 ) break;<br> &nbsp; }<br> <br> &nbsp; // build starting packet. this packet specifies how many channels have<br> &nbsp; // zero data from the start and then contains the next 6 channels of<br> &nbsp; // data<br> <br> &nbsp; data[0] = 4;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // start packet header (4)<br> &nbsp; data[1] = curChanIdx;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // number of zeroes ( not sent )<br> &nbsp;<br> &nbsp; data[2] = chanData [ curChanIdx++ ];&nbsp; // first ( non-zero ) chan data<br> &nbsp; data[3] = chanData [ curChanIdx++ ];&nbsp; // next chan data<br> &nbsp; data[4] = chanData [ curChanIdx++ ];&nbsp; // next chan data<br> &nbsp; data[5] = chanData [ curChanIdx++ ];&nbsp; // next chan data<br> &nbsp; data[6] = chanData [ curChanIdx++ ];&nbsp; // next chan data<br> &nbsp; data[7] = chanData [ curChanIdx++ ];&nbsp; // next chan data<br> &nbsp;<br> &nbsp; int success = writeUSB ( data , 8 );<br> <br> &nbsp; if ( !success ) {<br> &nbsp;&nbsp;&nbsp; printf ( &quot;%s: error sending DMX start packet\n&quot; , ProgName );<br> &nbsp;&nbsp;&nbsp; return ( 0 );<br> &nbsp; }<br> <br> &nbsp; if ( curChanIdx &gt;= numChans ) return ( 1 );<br> <br> &nbsp;<br> <br> &nbsp; // after the first packet additional packets are sent that contain seven<br> &nbsp; // channels each up to 512.<br> <br> &nbsp; while ( curChanIdx &lt; ( numChans - 7 ) ) {<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br> &nbsp;&nbsp;&nbsp; data[0] = 2;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // start packet header (2)<br> &nbsp;&nbsp;&nbsp; data[1] = chanData [ curChanIdx++ ];&nbsp; // next chan data<br> &nbsp;&nbsp;&nbsp; data[2] = chanData [ curChanIdx++ ];&nbsp; // next chan data<br> &nbsp;&nbsp;&nbsp; data[3] = chanData [ curChanIdx++ ];&nbsp; // next chan data<br> &nbsp;&nbsp;&nbsp; data[4] = chanData [ curChanIdx++ ];&nbsp; // next chan data<br> &nbsp;&nbsp;&nbsp; data[5] = chanData [ curChanIdx++ ];&nbsp; // next chan data<br> &nbsp;&nbsp;&nbsp; data[6] = chanData [ curChanIdx++ ];&nbsp; // next chan data<br> <br> &nbsp; }<br> <br> &nbsp; success = writeUSB ( data , 8 );<br> <br> &nbsp; if ( !success ) {<br> &nbsp;&nbsp;&nbsp; printf ( &quot;%s: error sending DMX bulk packet\n&quot; , ProgName );<br> &nbsp;&nbsp;&nbsp; return ( 0 );<br> &nbsp; }<br> <br> &nbsp; if ( curChanIdx &gt;= numChans ) return ( 0 );<br> <br> #else<br> <br> &nbsp; data[0] = 5;&nbsp;&nbsp; // packet header for single channeld data<br> <br> &nbsp; printf ( &quot;sending %d channels\n&quot; , numChans );<br> &nbsp;<br> <br> &nbsp; for ( int chIdx = 0; chIdx &lt; numChans; chIdx++ )<br> &nbsp;&nbsp;&nbsp; {<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; data[1] = chanData [ chIdx ];<br> <br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int success = writeUSB ( data , 8 );<br> <br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( !success ) {<br> printf ( &quot;%s: error sending DMX data packet\n&quot; , ProgName );<br> return ( 0 );<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br> &nbsp;&nbsp;&nbsp; }<br> <br> #endif&nbsp;<br> <br> &nbsp;<br> &nbsp; return ( 1 );<br> <br> }<br> <br> // ==========================================================================<br> // initUSB -- intialize the USB interface for the device<br> // ==========================================================================<br> <br> int initUSB()<br> {<br> &nbsp; int success;<br> &nbsp;<br> <br> &nbsp; // open the usb library<br> <br> &nbsp; usb_init();<br> <br> <br> &nbsp; // find the usb device for DMX controller<br> <br> &nbsp; usb_find_busses();<br> &nbsp; usb_find_devices();<br> <br> &nbsp; usb_device_descriptor *descr = 0x0;<br> <br> &nbsp; for ( bus = usb_busses; bus; bus = bus -&gt; next ) {<br> <br> &nbsp;&nbsp;&nbsp; for ( dev = bus-&gt;devices; dev; dev = dev -&gt; next ) {<br> <br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf ( &quot;%s: checking device [%s]\n&quot; , ProgName , dev -&gt; filename );<br> <br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; descr = &amp; dev-&gt;descriptor;<br> <br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( descr -&gt; idVendor == VendorID )<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;&amp; ( descr -&gt; idProduct == ProdID&nbsp; ) ) break;<br> &nbsp;&nbsp;&nbsp; }<br> &nbsp; }<br> <br> &nbsp; if ( !dev ) {<br> printf ( &quot;%s: DMX device not found on USB\n&quot; , ProgName );&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br> return ( 0 );<br> &nbsp; }<br> &nbsp;<br> <br> &nbsp; // open the device<br> <br> &nbsp; printf ( &quot;%s: opening device [%s] ... &quot; , ProgName , dev -&gt; filename );<br> <br> &nbsp; udev = usb_open ( dev );<br> <br> &nbsp; if ( udev == 0x0 ) {<br> &nbsp;&nbsp;&nbsp; printf ( &quot;%s: error opening device\n&quot; , ProgName );<br> &nbsp;&nbsp;&nbsp; return ( 0 );<br> &nbsp; }<br> &nbsp; else {<br> &nbsp;&nbsp;&nbsp;&nbsp; printf ( &quot;ok\n&quot; );<br> &nbsp; }<br> <br> <br> &nbsp; // claim the interface<br> <br> <br> #if&nbsp;&nbsp;&nbsp;&nbsp; defined(LIBUSB_HAS_GET_DRIVER_NP) \<br> &nbsp;&nbsp;&nbsp;&nbsp; &amp;&amp; defined(LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP)<br> <br> &nbsp; usb_detach_kernel_driver_np( udev, 0);<br> <br> #endif<br> <br> <br> &nbsp; // set configuration<br> <br> <br> &nbsp; usb_set_debug(4);<br> <br> &nbsp; success = usb_set_configuration ( udev, 1 );<br> <br> &nbsp; if ( success != 0 ) {<br> &nbsp;&nbsp;&nbsp; printf ( &quot;%s: configuration error [%d]\n&quot; , ProgName , success );<br> &nbsp;&nbsp;&nbsp; return ( 0 );<br> &nbsp;&nbsp;&nbsp;<br> &nbsp; }<br> <br> <br> &nbsp; // claim the interface<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br> &nbsp; success = usb_claim_interface ( udev, 0 );<br> <br> &nbsp; if ( success != 0 ) {<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br> &nbsp;&nbsp;&nbsp; printf ( &quot;%s: error claiming interface [%d]\n&quot; , success );<br> &nbsp;&nbsp;&nbsp; return ( 0 );<br> &nbsp; }<br> <br> &nbsp; return ( 1 );<br> }<br> <br> // ==========================================================================<br> // writeUSB -- write a command to the USB interface<br> // ==========================================================================<br> <br> int writeUSB ( ubyte *data , int numBytes )<br> {<br> &nbsp; int nSent;<br> <br> &nbsp; //&nbsp; printf ( &quot;%s: writing [%d] bytes &quot; , ProgName , numBytes );<br> &nbsp; //&nbsp; for ( int b = 0; b &lt; numBytes; b++ ) printf ( &quot;[%d]&quot; , data[b] );<br> &nbsp; //&nbsp; printf ( &quot;\n&quot; );<br> <br> &nbsp; // write the data<br> <br> &nbsp; nSent = usb_interrupt_write ( udev ,<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1,<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (char *) data,<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; numBytes,<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 200 );<br> <br> &nbsp; if ( nSent != numBytes ) {<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br> &nbsp;&nbsp;&nbsp; printf ( &quot;%s: error writing [%d] bytes [%d]\n&quot; , numBytes , nSent );<br> &nbsp;&nbsp;&nbsp; return ( 0 );<br> &nbsp; }<br> <br> &nbsp; return ( 1 );<br> &nbsp;<br> }<br> <br> <br> // ==========================================================================<br> // exitUSB -- terminate USB connection<br> // ==========================================================================<br> <br> void exitUSB()<br> {<br> &nbsp;&nbsp;&nbsp; usb_close(udev);<br> }<br> <br> // ==========================================================================<br> // initSHM -- initialize shared memory segment<br> // ==========================================================================<br> <br> int initSHM()<br> {<br> <br> &nbsp; printf ( &quot;%s: creating shared memory segment ... &quot; , ProgName );<br> <br> <br> &nbsp; // create the shared memory segment<br> <br> &nbsp; shmid = shmget ( 0x56444D58 , sizeof ( ubyte ) * 515 , IPC_CREAT | 0666 );<br> <br> &nbsp; if ( shmid == -1 ) {<br> &nbsp;&nbsp;&nbsp; printf ( &quot;error creating shared memory segment [%d]\n&quot; , errno );<br> &nbsp;&nbsp;&nbsp; return ( 0 );<br> &nbsp; }<br> &nbsp; else<br> &nbsp;&nbsp;&nbsp; printf ( &quot;ok\n&quot; );<br> <br> <br> &nbsp; // attach to segment and initialize<br> <br> <br> &nbsp; printf ( &quot;%s: intitalizing segment [0x%x] ... &quot; , ProgName , shmid );<br> <br> &nbsp; shm = ( ubyte * ) shmat ( shmid , NULL , 0 );<br> <br> &nbsp; if ( shm == 0x0 ) {<br> &nbsp;&nbsp;&nbsp; printf ( &quot;error connecting to segment [%d]\n&quot; , errno );<br> &nbsp;&nbsp;&nbsp; return ( 0 );<br> &nbsp; }<br> &nbsp; else<br> &nbsp;&nbsp;&nbsp; printf ( &quot;ok\n&quot; );<br> <br> <br> &nbsp; memset ( shm , 0 , sizeof ( ubyte ) * 515 );<br> <br> <br> &nbsp; // set up command &amp; data registers<br> <br> &nbsp; maxChanAddr&nbsp; = ( int * ) shm;<br> &nbsp; *maxChanAddr = DefMaxChans;<br> <br> &nbsp; exitAddr&nbsp;&nbsp;&nbsp;&nbsp; = ( ubyte * ) maxChanAddr + 2;<br> &nbsp; chanData&nbsp;&nbsp;&nbsp;&nbsp; = ( ubyte * ) maxChanAddr + 3;<br> <br> &nbsp; return ( 1 );<br> }<br> <br> // ==========================================================================<br> // exitSHM -- terminate shared memory segment<br> // ==========================================================================<br> <br> void exitSHM()<br> {<br> &nbsp;&nbsp;&nbsp; shmdt(shm);<br> &nbsp;&nbsp;&nbsp; shmctl(shmid,IPC_RMID,NULL);<br> }<br> <br> // ==========================================================================<br> // timediff | timeadd -- timing functions<br> // ==========================================================================<br> <br> void timediff ( struct timeval *res, struct timeval *a, struct timeval *b)<br> {<br> &nbsp;&nbsp;&nbsp; long sec,usec;<br> &nbsp;&nbsp;&nbsp; sec=a-&gt;tv_sec-b-&gt;tv_sec;<br> &nbsp;&nbsp;&nbsp; usec=a-&gt;tv_usec-b-&gt;tv_usec;<br> <br> &nbsp;&nbsp;&nbsp; while (usec&lt;0) {<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; usec+=1000000;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sec--;<br> &nbsp;&nbsp;&nbsp; }<br> &nbsp;&nbsp;&nbsp; if (sec&lt;0) {<br> res-&gt;tv_sec=0;<br> res-&gt;tv_usec=0;<br> &nbsp;&nbsp;&nbsp; } else {<br> res-&gt;tv_sec=sec;<br> res-&gt;tv_usec=usec;<br> &nbsp;&nbsp;&nbsp; }<br> }<br> <br> void timeadd(struct timeval *res, struct timeval *a, struct timeval *b)<br> {<br> &nbsp;&nbsp;&nbsp; res-&gt;tv_usec=a-&gt;tv_usec+b-&gt;tv_usec;<br> &nbsp;&nbsp;&nbsp; res-&gt;tv_sec=a-&gt;tv_sec+b-&gt;tv_sec;<br> &nbsp;&nbsp;&nbsp; while (res-&gt;tv_usec &gt;= 1000000) {<br> res-&gt;tv_usec-=1000000;<br> res-&gt;tv_sec++;<br> &nbsp;&nbsp;&nbsp; }<br> }
Makefile: <br> <br>CC=g++ <br>DEAMONOBJS=dmxd.o <br>LIBOJBS=dmx.o <br>OBJS=$(LIBOBJS) $(DEAMONOBJS) <br>DEAMONBIN=dmxd.bin <br>LIB=libdmx.a <br>CFLAGS+= <br>LDFLAGS+=-lusb -lm <br>INCLUDES+=-I./ <br> <br>all: $(LIB) $(DEAMONBIN) $(TESTBIN) <br> <br>%.o: %.c <br> @rm -f $@ <br> $(CC) $(CFLAGS) $(INCLUDES) -g -c $&lt; -o $@ -Wno-deprecated-declarations <br> <br>dmxd.bin: $(DEAMONOBJS) <br> $(CC) -o $@ -Wl,--whole-archive $(DEAMONOBJS) $(LDFLAGS) -Wl,--no-whole-archive -rdynamic <br> mv dmxd.bin ../deamon <br> <br> <br>%.a: $(LIBOJBS) <br> $(AR) r $@ $^ <br> mv $(LIB) ../lib <br> cp dmx.h ../include <br> <br>clean: <br> for i in $(OBJS); do (if test -e &quot;$$i&quot;; then ( rm $$i ); fi ); done <br> @rm -f dmxd.bin $(LIB)
Hey, thanks for the swift reply. I've actually got the project running great as is. I have it set up on my pi controlling a light and i have set up a vnc to control the pi remotely via my work mac which has been real fun. I'm just having trouble opening up the dmxd.c that you mention checking out at the end of your instructions and wondered if you had any tips/issue advice. My end goal is to be able to monitor twitter for a specific hashtag which will be interfaced with the vcn to change the LED lights colour via twitter!
I got it on a blowout sale at Musicians Friend. I see you get them normally priced for about $120.
may I ask where you got the color splash so cheap?
As a lighting/sound guy, this looks like a neat little project. I already use that interface and I just got a pi so I'll look into this
as a lighting/ sound guy I should probably invest in something DMX controlled for when my PI comes in
Would this work with the Enttec USB-to-DMX adapter too?
This is great, we are in the lighting business and will probably rig something like this up. <br>What would make it even more useful would be able to use a smartphone to be able to control it. My preference is for Android but I believe there is another popular mobile OS out there too.
Combining this project with a web interface would not be too tough, check out (https://www.instructables.com/id/Raspberry-Pi-GPIO-home-automation/) for an idea how to do it. The Raspberry Pi is perfect for this type of application - and instead of writing an application for Android and iOS, you could just use the web browser.
Sorry, can't reply to posts because of bug on the website... <br> <br>Certainly would be interesting, but the interface side would take a great deal of work and thinking to be useful (perhaps something using a touchscreen could be done, not the cheapest but it would be less complicated in hardware terms). I had talked about a much simpler converter, but of course that does not need all the power of a Pi. <br> <br>Sorry, I could not help with this project (don't own a Pi), but it really is surprising that this has not been done before.
I got all excited there looking for a cheap way to make a small self contained controller, think some of the things from this would work but been avoiding USB to DMX controllers because for some reason &Acirc;&pound;100 seems to be awfully expensive...
I agree. Even the $60 for the kit is pretty expensive, but when I considered the complexity of using the GPIO and the development time and cost of additional circuitry this was the path of least resistance. The other thing that swayed my decision was that the controller can also be used by any other PC and in my case allows me to use it for other purposes. <br> <br>Thanks for your comment.
Hmm maybe a better way to look at it...

About This Instructable




Bio: I am a multidisciplinary engineer actively interested in new technology and how it can be used to further interest in science, technology, engineering, and mathematics.
More by flashular:babbletron -  an interactive exploration of computer generated speech plugduino - Arduino based 120 Volt outlet controller Raspberry Pi as a DMX light controller 
Add instructable to: