The concept is to design and create a portable dimmer.


  • DMX512 Controllable
  • 4 Channels
  • Portable
  • Easy to use

I proposed this idea to my professor at WSU because I wanted to combine my passions for theatre and computers. This project acted a little like my senior project in the theatre department. If you have any comments or question, I would love to help.

Future development could include more channels, 5 pin DMX connector, DMX passthrough, 8 dip switches to change the channel, printed circuit board.

I have migrated this project from http://danfredell.com/df/Projects/Entries/2013/1/6_DMX_Dimmer.html because it is still popular, I guess. Also I lost my iWeb seed file so I can't easily update it anymore. It would be nice to allow people to share their questions on the project with each other.

Step 1: Gathering the Hardware

Hardware Used: Most of it was ordered from Tayda Electronics. I like them better than DigiKey because of the smaller and easier to understand selection.

  1. ATMEGA328, Micro-controller
  2. MOC3020, TRIAC Optocoupler. Not ZeroCross.
  3. MAX458 or SN75176BP, DMX Receiver
  4. ISP814, AC Optocoupler
  5. 7805, 5v Regulator
  6. BTA24-600, 600V 25A TRIAC
  7. 20MHz Crystal
  8. 9V Power supply

A few hurdles and lessons learned along the way

  • If you are not a register expert, stick with a ATMEGA328P
  • Wrong optocouplers. You do not want Zero Cross
  • High channels were unstable. Switching from 16MHz to 20MHz solved this issue
  • Unable to have a DMX status light because the interrupt call had to be very fast
  • DC power has to be extremely stable, any ripple will cause the DMX signal to become very noisy

The TRIAC design came from MRedmon, thank you.

Step 2: Circuit Design

I used Fritzing 7.7 on Mac to design my circuit.

The MAX485 at the top is used to convert the DMX signal into something the Arduino can read.

The 4N35 on the left is used to detect the zero cross of the AC signal so the Arduino will know at what time to dim the Sine wave output. More about how the hardware and software interact in the software section.

I have gotten the question will this project work in Europe with 230V and 50Hz? I don't live in Europe, nor do I travel there often to be able to test this design. It should work, you would just have to modify the brightness timing line of code for the different frequency time delay.

Step 3: Kovari Circuit Design

Through the process of having my website up I was able to have a few email conversations. One was with Kovari Andrei who did a circuit design based on this project and wanted to share his design. I'm no circuit board designer but it is an Eagle project. Let me know how it works for you if you use it.

Step 4: Software

I'm a software engineer by trade so this part is the most detailed.

Summery:When the Arduino first boots the setup() method is called. In there I set up a few of the variables and output locations to be used later. zeroCrossInterupt() is called/ ran every time the AC crosses from positive to negative voltage. It will set the zeroCross flag for every channel and start the timer. The loop() method is called continually forever. To turn on the output, the TRIAC only has to be triggered for 10 microseconds. If it is time to trigger he TRIAC and zeroCross has happened the output will turn on until the end of the AC phase.

There were a few examples online that I used to get this project started. The main thing that I could not find was having multiple TRIAC outputs. Others used the delay function to PWM the output, but that would not work in my case because the ATMEGA has to be listening to DMX all the time. I solved this by pulsing the TRIAC at so many ms after zero-cross. By pulsing the TRIAC closer to zero-cross the more of the sin wave is output.

Here is what the half 120VAC sin wave looks like on an oscilloscope, above.

The ISP814 is connected to interrupt 1. So when it receives signal that the AC transitions from positive to negative or vise versa it sets the zeroCross for each channel to true and starts the stopwatch.

In the loop() method, it checks every channel if zeroCross is true and the time for it to activate has passed it will pulse the TRIAC for 10 microseconds. This is enough to turn the TRIAC on. Once a TRIAC is turned on it will stay on until zeroCross. The light would flicker when the DMX was around 3% so I added the truncating in there to prevent it. This was caused the Arduino being too slow, and the pulse would some times trigger the next sin wave instead of the last 4% of the wave.

Also in the loop() I set the PWM value of the status LEDs. These LEDs can use the internal PWM generated by the Arduino because we do not have to worry about the zeroCross of AC. Once the PWM is set the Arduino will continue at that brightness until told other wise.

As noted in the top comments in order to use a DMX interrupt on pin 2 and run at 20MHz you will have to edit some of the Arduino application files. In HardwareSerial.cpp a chunk of code must be deleted, this allows us to write our own interrupt call. This ISR method is at the bottom of the code to handle the DMX interrupt. If you are going to use an Arduino as an ISP programmer, be sure to revert your changes to HardwareSerial.cpp otherwise the ATMEGA328 on the bread board will be unreachable. The second change is an easer one. The boards.txt file has to be changed to the new 20MHz clock speed.


Brightness maps to 8000 because that is the amount of microseconds of 1/2 an AC sine wave at 60hz. So at full brightness 256 DMX the program will leave 1/2 the AC sine wave ON for 8000us. I came up with 8000 via guess and check. Doing the math of 1000000us/60hz/2 = 8333 so that might be a better number, but having the extra 333us over head allows for the TRIAC to open and any jitter in the program is probably a good idea.

On Arduino 1.5.3 that they moved the location of the HardwareSerial.cpp file. It is now /Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/HardwareSerial0.cpp You will need to comment out this whole if block starting with line 39: #if defined(USART_RX_vect)

Otherwise you will end up with this error: core/core.a(HardwareSerial0.cpp.o): In function `__vector_18':

Step 5: Packaging It Up

I picked up the gray project box at Menards in their electrical section. I used a reciprocating saw to cut out the electrical plug holes. The case got a theatre c-clamp attached to the top for hanging purposes. Status lights for every input and output to help diagnose if there is ever a problem. A label maker was used to explain the different ports on the device. The numbers next to each plug represents the DMX channel number. I affixed the circuit board and transformer with some hot glue. The LEDs are stuck in place with led holders.

<p>Can this take a 220v input (europe)?</p>
<p>Yes this will work just fine up to 600V as that is the rating of the TRIACs I bought. The bigger concern is the frequency difference. Here in America our AC mains are at 60Hz. I believe Europe is at 50Hz. So the brightness map will need to change values. For 60Hz I have it at 8000us, 50Hz will be more around 10000us or a hair under. You will have to test the max and min brightness to verify. Let me know if that works out. There are a lot of people wondering about using this in Europe. </p>
<p>One more question, could you use an Arduino (with an atmega328 chip nonetheless) so that it's made easier to program?</p>
<p>Ya, I used the Arduino bootloader and Arduino IDE software to program this chip. I didn't have an Arduino Uno shield with the detachable IC. So, I used https://www.arduino.cc/en/Tutorial/ArduinoISP to program an atmega328 on a breadboard that had a 20MHz crystal. </p>
<p>Great. Really looking forward to try this out since I need some dimmer packs but they cost a fortune.</p>
<p>Thank you for this tutorial</p>
<p>Thank you for this tutorial, I will use this as a start for making a dmx reciever.</p>
<p>Great tutorial!</p>

About This Instructable




More by Dan Fredell:4 Ch DMX Dimmer 
Add instructable to: