Receive DMX-512 with an Arduino
Part I: ProloguePart II: InstructionsPart III: Known Limitations, Notes, and the Code
You Will Need:
- A copy of the latest release and the modified wiring_serial.c or HardwareSerial.cpp file. See the instructions for what to do with the files.
- An Arduino with an Atmega168 processor (such as the latest Duemilanove version). Because of the timing-sensitive nature of DMX-512, some of the code had to be optimized by referring to particular registers on the Atmega168. The code can easily be adapted to other processors, though.
- An RS-485 to Serial Transceiver, such as the MAX485 or the TI 75176. They’ll run you about $1, the MAX485 is a little more but it apparently has some kind of fancy overvoltage protection, so I used that.
- A breadboard and some wires, also a 150Ω resistor to terminate the DMX line if necessary.
Instructions:
DMX uses a twisted pair of signal wires with opposite polarity to transmit information per RS-485. However, your Arduino needs a serial signal, with a pin brought high for one and low for zero. To convert between these protocols, you’ll need to wire up your MAX485 or 75176 in the following way:
Here are some pictures which may help you:
Note 1: Starting with Rev11 of the software, I adjusted the pin layout slightly for better routing on the DMX I/O Shield. The two gray wires in the above photos that are plugged into pins 3 and 4 should be plugged into pins 2 and 3, respectively, if you’re using the latest software.
Note 2: I’m using the Arduino protoshield here, which I highly recommend, they’re handy. If you don’t have one, the pin layout is the same as if you ran directly into the Arduino board.
Note 3: if you want to retain the use of pins 1, 4, and 5, at the cost of being able to transmit as well as receive, you can connect the corresponding pins on the MAX485 to the ground on the Arduino board. I’ve done it this way for possible future RDM functionality ;).
One Dumb Hack is necessary: rename your currently installed HardwareSerial.cpp file to HardwareSerial.cpp.backup, and put the modified HardwareSerial.cpp from this site in the same directory. It’s located in:
(Arduino Install Directory)/hardware/cores/arduino/
The reason for this is that the Arduino software defines the USART_RX_vect serial reception interrupt, and includes it in your compiled code, even if you don’t use any serial functions. This will, I hope, be fixed in a future release, but until it is this is the work-around. You can read more about the issue here. Once you’ve uploaded the sketch and it’s working to your satisfaction, you can undo this part to regain your normal serial library functionality.
Finally, fire up the Arduino software, and put what you want the Arduino to do with the received values in the action() loop. The received values are stored in the dmxvalue[] array. The downloaded sketch contains example code to print out each of the values to the serial port, and set PWM pins 5 and 6 to the first and second value in the array, respectively, but this can of course be changed to anything you want.
That’s it, let me know how it works for you! You may want to keep reading for the Known Limitations, etc.
Go to Section:
- Part I: Prologue
- Part II: Instructions
- Part III: Known Limitations, Notes, and the Code
- View All




December 20th, 2009 at 1:21 pm
Hi. Very interesting project thanks! can be used in various applications. I would like to add encoder and managed using several DMX channel setting motor speed and position
December 21st, 2009 at 4:52 pm
Firstly, thanks and well done for cracking this, I’ve wanted to be able to add DMX to my lighting projects for a long time now but sussing it out myself is currently beyond my ability. I’m totally building one of these! :D
Something I’m unsure about though, Rapid Electronics don’t have a “MAX485″, but they do have “MAX485CPA+” and “MAX485CSA+”. Are either of those suitable for this? I don’t know what the difference is.
Thanks again for publishing your work,
Dan
December 22nd, 2009 at 2:08 pm
Hi Daniel,
The difference is the package. The CPA is a through hole package, whereas the CSA is the surface mount. You’ll want the CPA. Best of luck with your project!
January 5th, 2010 at 3:45 pm
Hi there,
Any update on the code? Will there be a future version that does not need to modify the Arduino lib?
January 9th, 2010 at 3:40 pm
Incredible work!
I am having trouble getting things to work for me.
I am using Arduino 0017.
Do you have any more recent builds of your project?
Thanks so much!
January 11th, 2010 at 9:23 am
Hi All,
I will put together an update for IDE 0017 or verify that the current version works. If you don’t want to wait, you could just take a look at what I’ve done to the hardware.cpp file and do the same to the IDE 0017 version.
Note that the hack to the Arduino library files is necessary due to code on the Arduino side, not my software, so I have no control over when/if this will be fixed.
January 29th, 2010 at 6:38 am
For everyone else using 0017:
The mod you need to make to the hardwareserial.cpp is this:
Change line 115 from:
uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre)
to:
uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x)
and it should compile.
February 25th, 2010 at 8:57 am
The fix given by BlueFusion does work. One note for a little more clarity: you should do this as an additional modification in the already modified hardwareserial.cpp file (the one included in the download from this site).
Thanks anyway for the work already done on this, I will be constructing a centerpiece for a disco with this which will have 8 pinspots, mirrors and servo’s! (and maybe we will abuse it every now and then with our band :))
February 27th, 2010 at 3:39 pm
Can your modifications send and receive or not?
March 1st, 2010 at 3:58 pm
Doing research.
Looking for a solution.
I Need to manipulate 2000+ 3w-5w LED’s for my art project.
http://www.TheBallofLight.com
Your project seems like it would allow for it. Each of the 2000 lights would need to be able to be driven by a central DMX console. As I read each of your units can manipulate 512 individual lights. That sounds astounding. That would mean I would need to make only 4 of these units. That would also mean 4 Universes I believe. I think I would also need 4 optical splitters to lead to these units. Then back to the Console.
I have many questions on this topic and am just getting started on a two and half year project.
If you are interested at all interested I would love to tell all and pick your brain some you seem extremely knowledgeable on this subject.
March 2nd, 2010 at 12:25 am
I actually would not use DMX for this application– I would try to get your LEDs to take a video input. That way, you’ll be able to program it from a VJ software (such as Arkaos, there are dozens) rather than a theatrical lighting console, which will give you a more intuitive and flexible programming paradigm. Also, I would try to source your LED drivers from commercially available hardware such as the driver boards for LED billboards. By the time you buy the components for 2,000 DIY drivers, you won’t be saving any money, and the soldering involved gives me the creeping horrors. I mean, why spend all your time reinventing the wheel, when you could be focusing on the art? My $.02
April 1st, 2010 at 9:54 am
This is amazing! I’m trying to build a DMX-controlled moving light, and your code should be very helpful! However, in Arduino 0018, the project won’t compile: it says “(location)/HardwareSerial.cpp:185: error: no matching function for call to ‘HardwareSerial::HardwareSerial((ring_buffer*, volatile uint8_t*, volatile uint8_t*, volatile uint8_t*, volatile uint8_t*, volatile uint8_t*, int, int, int, int)’”. I’ve tried the modification suggested by BlueFusion, which fixed another compiler error but not this one. Any suggestions for an Arduino 0018 user?
May 21st, 2010 at 1:05 am
I’m having a hard time getting this code to work on my arduino mega, IDE 0018.
Additional problem is that I want it to connect to serial3, so I have serial available to talk to the PC.
With some simple code, I can detect (and copy) data received on serial3 to serial0, so all electronics work nicely. I just can’t get this DMX program to work, and I have no clue what all the timer configurations etc, hacks to harwareserial, etc mean…
May 24th, 2010 at 1:06 am
lampmaker, how did you get it to work on a mega? I have tried for ages bu no matter what i do all i get is errors
May 25th, 2010 at 3:00 pm
I am likewise unable to compile this on 0018. Game over.
May 28th, 2010 at 6:39 pm
Hi: I want to build a DMX-driven 8*8 LED array and was hoping to use your code and a TLC5940 (using the http://students.washington.edu/acleone/codes/tlc5940arduino/html_r8/ library) but your library and their library use the same pins (specifically 3 and 11). Is there a way to move those functions to other pins?
Also, I’m trying to compile under IDE 0018 and even with the Bluefusion mods to hardwareserial.cpp it comes up with errors (it’s still complaining about that line 115).
Thanks.
\dmc
May 30th, 2010 at 8:37 am
Hi Dave,
That might be do-able. You’ll need to move either my DMX code or the tlc5940 clock timer over to timer1. See the discussion in earlier comments about timers and trying to output two data protocols at the same time. As I understand it, the TLC5940 has an asynchronous serial input, so it doesn’t need constant updates, all the time, right?
May 30th, 2010 at 10:20 am
Max: Thanks for your thoughts.
In my application I won’t be needing to do RDM, so I won’t need the timer on Pin 3 … it’s just the Pin 11 timer I’ll need to move (and the guy who wrote the tlc5490 library isn’t interested in telling me how to move his pins around).
I’m still learning about the 5940, so I can’t say yet whether it’s asynch or synch … when I get more eddiecated on the topic, I’ll be back.
Also, I tried downloading IDE 0017 and moving in the new HardwareSerial.cpp with Bluefusion’s mods and the sketch still won’t compile …
Thanks again.
\dmc
June 16th, 2010 at 5:59 am
I think I might’ve figured out this whole 0018 issue. All I did was comment out the section of code in the IDE-native HardwareSerial.cpp that was commented out in the version provided here, and now it at least appears able to compile. I haven’t tried getting it to run on an Arduino yet.
June 22nd, 2010 at 6:27 pm
Grody: Just ran across your theory … tried it out and got this:
>>error: no matching function for call to ‘HardwareSerial::HardwareSerial(ring_buffer*, volatile uint8_t*, volatile uint8_t*, volatile uint8_t*, volatile uint8_t*, volatile uint8_t*, int, int, int, int)’
Thanks for your thoughts, though.
\dmc
June 23rd, 2010 at 4:12 pm
Gregory Haley: I say the suggested “feeding video” into that 2000 nodes will be “interesting” (say the least).
But you might want to look at ARTNET or E1.31 for your driving protocols (rather than basic DMX512).
Your backend/desk will need to support it of course, but it will get over you 512/universe limitations.
There are examples you can have a look at where they are using > 3000 lights in an awesome christmastree driven by madrix: http://www.response-box.com/rgblights/ (be prepared to sell your kids to get one, and own a nuclear powerstation to light it of course ;).
good luck!
July 18th, 2010 at 9:15 pm
I’ve got an interesting anomaly someone may have encountered — the outputted DMX values don’t map correctly from my input values. Here’s how they map:
0 –> 254
…
64 –> 2
65 –> 254
…
128 –> 2
129 –> 254
…
191 –> 2
192 –> 254
…
255 –> 2
I’m sure it has something to do with my home-made el cheapo FTDI-based DMX transmitter, but my professional DMX lights don’t seem to mind. Any ideas where I should look to see if I can adapt the code? I’m running Arduino 0018, using the standard action() loop.
Great software! Thanks!
August 15th, 2010 at 5:57 pm
Success!
In recent weeks I hadn’t bothered to read the text of the blog, just the comments and so I didn’t notice that Rev14 was out. That has solved all my problems.
I am successfully processing a DMX signal (which is from a USB converter designed by a friend of mine that is still in beta).
In my first few minutes of fiddling with the action loop, I found the need to make the output of the serial monitor more meaningful and neater. You can see my rewritten action loop and its output at
http://www.dmcole.net/wp-content/uploads/2010/08/Arduino-DMX-receiver-Action.png
Thanks so much Max. Now, on to the not insignificant process of making the serial chips work …
\dmc
August 20th, 2010 at 1:31 pm
Hi,
I came across this the other day and would like to ask you if you still have a copy of the code lying around somewhere although it shouldn’t be too difficult to implement an LCD and a rotary encoder.
Would be great if you can share the code with us.
Thanks.
Sincerely,
Siliconsoul.
August 28th, 2010 at 2:40 pm
Hi,
Thanks for posting all this so beautifully. I am a LD from NY and have been using Arduino for some small scale embedded systems projects / mock ups. My next quest is to try and make a small, maybe 1′, LED strip light that is driven by an arduino and controlled by a dmx console. I am also new to code writing and my question is… once you get the Arduino to receive DMX what is the best way to map the dmx channel to a digital output?
-seb
August 28th, 2010 at 7:38 pm
Hi Seb,
If your power needs are pretty minimal, you could just drive the LEDs directly via the PWM outputs. Otherwise, you’ll need the Arduino to output whatever the control protocol is for your LED drivers– probably 0-10V. Although, it doesn’t seem to me that you save any time/money here by building your own strip– there are RGB strips available at dirt cheap prices, e.g.:
http://www.enttec.com/?main_menu=Products&pn=72001&show=description
(or even Ikea!)
The very best and highest performing RGB strips will run you in the $250/ft range, e.g.:
http://www.lumenpulse.com/en/products.php?model=324
But you won’t match the performance/durability of these commercial products unless you have the tooling and engineering skills to make good optical components (miniature lenses and reflectors) and thermally manage the diodes so they don’t overheat and burn out.
I don’t want to sound discouraging because it sounds like a really fun project, but it’s a way to go if you decide you’d like to outsource some of it.
September 6th, 2010 at 8:13 am
New to Arduino and DMX, but recently buyed shield parts from CuteDigi, three questions:
I have 3 pin led bars, its compatible?
How to connect 3 to 5 and viceversa?
Need to make any change on code(for 3 pin compatibility and/or atmega 328 Duemilanove)?
Mani thanks, nice project!!!