Arduino Playground is read-only starting December 31st, 2018. For more info please look at this Forum Post

DMX Serial - Send DMX data without assembler programming

This code was developped to show how you can send DMX packages without using any assembler code. It works because the ATmega chips of the Arduino support the 250.000 baud rate used by the DMX protocol.

You can find a Arduino compatible library and 2 sample applications at http://www.mathertel.de/Arduino/DMXSerial.aspx .

This library does not use the built-in Serial object but modifies the hardware registers directly.

Well, there are 3 stumbling blocks arround:

First, there is a problem with the standard Arduino library to access the hardware base serial interface because the serial kind of parity and stop bit handling is not set at all and the standard values are used. The trick is to patch the hardware register after initializing everything else to no parity and 2 stop bits.

The other problem is the starting break block that have to be sent before the channel data bytes. This 88 usec low signal cannot be sent by using the 250.000 baut rate so for sending the break a slower baud rate is initialized, a 0-byte is sent and the baud rate is reset to the correct 250.000 baud.

When trying to receive DMX packages you will have to implement a function for handling the receive interrupt. This will conflict with the built-in Serial library object that also implements this interrupt. The workaround that was used by several libraries is to patch the HardwareSerial.cpp implementation. I discovered that when not using the standard Serial library at all this conflict disapears because the standard Serial code is not included in the sketch. Therefore the library handles all hardware registers by itself.

You can find a more detailed documentation about that topic at http://www.mathertel.de/Arduino/DMXSerial.aspx.

Proof of concept Code

This Sketch is just for analysis and demo purpose here.

  1. /*
  2.  A Simple DMX Fader implementation using the hardware serial interface.
  3. */
  4.  
  5.  
  6. // The color fading pattern
  7.  
  8. int RedList[]   = {255, 128,   0,   0,   0, 128};
  9. int GreenList[] = {  0, 128, 255, 128,   0,   0};
  10. int BlueList[]  = {  0,   0,   0, 128, 255, 128};
  11.  
  12. int RedLevel, GreenLevel, BlueLevel;
  13.  
  14. int RedNow = 0;
  15. int GreenNow = 0;
  16. int BlueNow = 0;
  17.  
  18. int state = 0;
  19.  
  20. const int RedPin =    9;  // PWM output pin for Red Light.
  21. const int GreenPin = 10;  // PWM output pin for Green Light.
  22. const int BluePin =   5;  // PWM output pin for Blue Light.
  23.  
  24.  
  25. #define DMX_MAX 128 // max. number of DMX data packages.
  26.  
  27. uint8_t DMXBuffer[DMX_MAX];
  28.  
  29. void DMXstart()
  30. {
  31.   // DMX is a 250000 baud serial data
  32.   Serial.begin(25000);
  33.   UCSR0C = (1<<USBS0)|(3<<UCSZ00);
  34.  
  35.   // initialize the DMX buffer
  36.   for (int n = 0; n < DMX_MAX; n++)
  37.     DMXBuffer[n] = 0;
  38.  
  39. } // DMXstart
  40.  
  41.  
  42. void DMXwrite(int channel, uint8_t value)
  43. {
  44.   // press parameters to allowed range
  45.   if (channel < 1) channel = 1;
  46.   if (channel > DMX_MAX) channel = DMX_MAX;
  47.   if (value < 0)   value = 0;
  48.   if (value > 255) value = 255;
  49.   // store value for later sending
  50.   DMXBuffer[channel-1] = value;
  51. } // DMXwrite
  52.  
  53.  
  54. void DMXflush()
  55. {
  56.   // send the break by sending a slow 0 byte
  57.   Serial.begin(125000);
  58.   Serial.write((uint8_t)0);
  59.  
  60.   // now back to DMX speed: 250000baud
  61.   Serial.begin(250000);
  62.   // write start code
  63.   Serial.write((uint8_t)0);
  64.   // write all the values from the array
  65.   Serial.write(DMXBuffer, sizeof(DMXBuffer));
  66. } // DMXflush
  67.  
  68.  
  69. void setup() {
  70.   DMXstart();
  71.  
  72.   pinMode(RedPin,   OUTPUT); // sets the digital pin as output
  73.   pinMode(GreenPin, OUTPUT);
  74.   pinMode(BluePin,  OUTPUT);
  75. } // setup
  76.  
  77. void loop() {
  78.   // int sensorValue = analogRead(analogInPin);            
  79.  
  80.   RedLevel = RedList[state];
  81.   GreenLevel = GreenList[state];
  82.   BlueLevel = BlueList[state];
  83.  
  84.   if ((RedLevel == RedNow) && (GreenLevel == GreenNow) && (BlueLevel == BlueNow)) {
  85.     state += 1;
  86.     if (state == 6)
  87.       state = 0;
  88.  
  89.   } else {
  90.     if (RedNow < RedLevel)  RedNow++;
  91.     if (RedNow > RedLevel)  RedNow--;
  92.     DMXwrite(1, RedNow);
  93.     analogWrite(RedPin,   RedNow);
  94.  
  95.     if (GreenNow < GreenLevel)  GreenNow++;
  96.     if (GreenNow > GreenLevel)  GreenNow--;
  97.     DMXwrite(2, GreenNow);
  98.     analogWrite(GreenPin, GreenNow);
  99.  
  100.     if (BlueNow < BlueLevel)  BlueNow++;
  101.     if (BlueNow > BlueLevel)  BlueNow--;
  102.     DMXwrite(3, BlueNow);
  103.     analogWrite(BluePin,  BlueNow);
  104.   } // if
  105.  
  106.   DMXflush();
  107.   // delay(0);                  // wait for next color
  108. } // loop