magnify
Home Arduino projects Arduino four universes DMX 512 library
formats

Arduino four universes DMX 512 library

After searching the web for Arduino DMX libraries, and test, we find no library allowing the use of multiple DMX universes and that did not use the timers of the arduino, so finally decided to create it.

*** UPDATED 07/07/2012 ***

Download current version: Arduino four universes dmx library version 0.3


The wiring diagram you can find it at:

Schematic Arduino shield four DMX 512 universes.

Version 0.3 CHANGES
– Not needed anymore to disable and enable interrupts during configuration.
– Not needed anymore to modify the Arduino IDE file HarwareSerial.cpp.
– Experimental support for non-standard DMX modes, faster and with more channels per universe:

  • DMX512  (250 kbaud  – 2 to 512  channels) Standard USITT DMX-512 1990
  • DMX1024 (500 kbaud  – 2 to 1024 channels) Completely non standard – TESTED ok
  • DMX2048 (1000 kbaud – 2 to 2048 channels) called by Manufacturers DMX1000K ?

– Removed leds tx – rx for speedup, if required shall be implemented in the program
– Interrupts on frame transmitted and frame received by each universe, user callback functions.

Known issues:
When we compile get the error: ‘ArduinoDmxN’ was not Declared In This scope:
Check if you have configured the correct type of board in the Arduino IDE, menu tools > board
(with Arduino nano can only use one USART = ArduinoDmx0 = USART0)
Errors while programing Arduino:
Will be necessary to remove the DMX shield, and put it back once programmed.

Flicker when controlling LEDs:
If we are dealing with LED lights, flicker may appear due to a refresh rate too low, we use fewer channels per universe (eg 200 instead of 512, to increase the frequency) and / or use less universes. This is a well known problem that affects all consoles and controllers that send all 512 channels, even when the maximum DMX refresh rate (around 44 Hz) is used.

Note about the refresh time:
The Arduino Mega and Arduino Nano use a microcontroller Atmel AVR 8-bit at 16 Mhz, which imposes a limitation of resources.
For example, 4 buffers in DMX1000K mode at 2048 channels each, will consume ALL the memory on an Arduino Mega 2560, so it must be clear what we are doing.
We should note that in practice we will probably not use all universes with all channels if we keep up the refresh rate of the DMX inputs and outputs.

Instructions for library setup – version 0.3:
Copy deskontrol library folder “Dmx” to arduino-XX.XX/libraries/

Instructions for library use:
There are four objects already created called “ArduinoDmx0”, “ArduinoDmx1”, “ArduinoDmx2”, “ArduinoDmx3”, each of these objects using a USART of the Arduino Mega, with Arduino nano can only use “ArduinoDmx0” because there is only one USART.

When compiling your programs, in order to economy Arduino resources, should comment in the “lib_dmx.h” lines with “# define USE_UARTN” of USARTs not going to use (only Arduino Mega).

The library usage is very easy, the functions that you have to use are:

ArduinoDmxN.set_control_pin (PIN_NUMBER);  // if not used -1

A call to this function we assign the pin number to be used to control the MAX485 driver, if it works as a universe of input or output. (Arduino pin that connects to pins 2 and 3 of the MAX485), can be any Arduino digital output pin.

ArduinoDmxN.set_rx_address (DMX_RX_ADDRESS);

Calling this function assign the DMX INPUT start address for this universe, can be any value between 1 and 510 (2046)*.

ArduinoDmxN.set_tx_address (DMX_TX_ADDRESS);

Calling this function assign the DMX OUT start address for this universe, can be any value between 1 and 510 (2046)*.

ArduinoDmxN.set_rx_channels (NUMBER_OF_CHANNELS);

A call to this function we assign the number of channels of DMX INPUT for this universe, can be any value between 2 and 512 (2048)*.

ArduinoDmxN.set_tx_channels (NUMBER_OF_CHANNELS);

A call to this function we assign the number of DMX OUT channels for this universe, can be any value between 2 and 512 (2048)*.

If you want to use sincronous mode:

ArduinoDmxN.attachTXInterrupt (my_TX_ISR_name);

A call to this function we assign the name of the user callback function that is activated each time that finish sending a DMX frame in a DMX universe. (avoid loss of time in the main program loop)

ArduinoDmxN.attachRXInterrupt (my_RX_ISR_name);

A call to this function we assign the name of the user callback function that is activated each time that finish receiving a DMX frame in a DMX universe. (avoid loss of time in the main program loop)

To begin transmitting or receiving a DMX universe (currently not possible simultaneously in the same universe), use one of the following functions:

ArduinoDmxN.init_rx (DMX_MODE);   // *** new parameter DMX_MODE ***

A call to this function (once called the above functions) starts this universe to DMX RECEIVE.

ArduinoDmxN.init_tx (DMX_MODE);   // *** new parameter DMX_MODE ***

A call to this function (once called the above functions) starts this universe to DMX TRANSMIT.

To write DMX output values:  ArduinoDmxN.TxBuffer [CHANNEL – 1] = Data;
To read DMX input values:    Data = ArduinoDmxN.RxBuffer [CHANNEL – 1]; // channel is 0 indexed

* This library does not use any Arduino timer, remaining free for other uses.

Thus we can use up to four universes simultaneously, each functioning as an input or output DMX.

In the examples of the library have as:
– Receive one DMX universe.
– Mix 2 DMX inputs (2 universes) in one, with patched channels. 200 + 200 input channels, output 400 channels.
– Mix 2 DMX inputs (2 universes) in one, with higher value priority (HTP)
– Use interrupts to send or receive in synchronous mode.
– Use non-standard fast DMX modes.

* 2048 channels with DMX1000K – 512 with DMX512

Download OLD version: Arduino four DMX 512 universes library version 0.1

 

Application example: Dimmerino – Inexpensive modular dimmer for Arduino.

Any suggestions or improvements are welcome.

Toni Merino

 
 Share on Facebook Share on Twitter Share on Reddit Share on LinkedIn
32 Comments  comments 

32 Responses

  1. ardufreak

    Successful tested on Arduino IDE 1.0

    • ahd71

      I tried to compile the demosketches with the board setting to Arduino Uno (and Nano) but got compilation errors while it was working fine for Mega2560. I made this small change in the lib_dmx.cpp file and it was compiling successfully also for Uno.

      from: UCSRB &= ~((1<<RXCIE) | (1<<TXCIE) | (1<<RXEN) | (1<<TXEN));
      to: UCSR0B &= ~((1<<RXCIE0) | (1<<TXCIE0) | (1<<RXEN0) | (1<<TXEN0));

      I haven't tested it with hardware yet, but the library sure looks promissing and clear and intuitive API and I'm looking forward to use it. Thanks!

      BR/ahd71

      • Toni Merino

        Thanks for your modification, he change in the library.
        > Mistake from Saturday night update…
        I ordered an Arduino Uno to test the library and art-net node, but still have not received it.

        Regards

  2. Anders

    Hi,

    The library used alone seems to work great, have also tried it with some hardware now 🙂

    I’m having one problem though when integrating my project with the AndroidAccessory.h where I get the following error when compiling, even if i comment all but one of the “USE_UARTx” in the lib_dmx.h

    core.a(HardwareSerial.cpp.o): In function `__vector_36′:
    C:\data\arduino-dev-env\hardware\arduino\cores\arduino/HardwareSerial.cpp:127: multiple definition of `__vector_36′
    DMX\lib_dmx.cpp.o:C:\data\arduino-dev-env\libraries\DMX/lib_dmx.cpp:205: first defined here

    Clearly both libraries seems to define the ISR (direct or indirect via HardwareSerial.cpp)

    If I comment out the following info from HardwareSerial.cpp it compiles fine again.

    // SIGNAL(USART1_RX_vect)
    // {
    // unsigned char c = UDR1;
    // store_char(c, &rx_buffer1);
    // }

    So what’s the best solution? I don’t know, but someway to redefine the ISR’s instead of asuming they aren’t defined I guess.

    • Toni Merino

      I’ve been looking for a solution, and the best I think it would be, on files hardwareserial.h and hardwareserial.cpp add directives such as:

      # if defined USE_HARDSERIAL_USARTx

      hardwareserial code related to USARTn

      # endif

      This would prevent definition of interrupt vectors and code that are not used later.

      If we are using Arduino Mega, when initializing any USART with SerialX.begin(baud), not only is defined code and interrupt vectors for that USART, but is defined for all USARTs.

      If anyone knows any other solution, please post them.

  3. Andrew Nagy

    Thank you! I’ve had a Arduino Mega Board since February and I could never get any DMX libs to work until I came across this one! Now it finally works. Thank you so much!

  4. tolunay gul

    Thank you very much! I was looking for DMX receiving that used no timers so that i could use an 4×4 RGB led matrix made with 3x TLC5940 in series.
    First one controls the red led’s, the second one the green led’s and the third one is for blue led’s. With this library i now created an 16 channel RGB controller! for more info you can contact me. tolunay_gul93{@}hotmail{dot}com

  5. Hi! would it work on a Teensy++ 2.0?

    thanks!

    • Toni Merino

      I have not tested, but probably work with small modifications.
      I think the libraries for Arduino, are almost equal for Teensy. But I’m not sure …

      Regards.

  6. Ken

    Has any one got this working on the Leonardo yet?

    Seems have compilation errors with the UART names.

    Great work by the way.

    Ken

    • Toni Merino

      Hi Ken.
      Sorry, I forgot to answer …

      > Has any one got this working on the Leonardo yet?
      > Seems have compilation errors With The UART names.

      Currently not supported on ATmega32U4, support in future revision.
      Regards.

  7. andrea

    hi
    I tried your code with one universe rx with UNO and it works fine.
    How can I implement “rx led” in your program?
    thanks
    Andrea

    • Toni Merino

      Hi Andrea.

      > I tried your code with one universe rx with UNO and it works fine.
      > How can I implement “rx led” in your program?

      In the current version of the library indicators have been removed, to be implemented in the main loop.
      You can include the code for indicator where do the reading or writing of the buffers (by example).

      // point where process data:
      
      int handle_dmx(artnet_dmx_t *packet)
      {
        //LED indicator. 
        //to slow down ON/OFF, one time is ON and next is OFF
      
        static uint8_t led_status;
        if(led_status == 1)
        {
          led_status = 0;
          digitalWrite(LEDPIN,led_status);
        }
        else
        {
          led_status = 1;
          digitalWrite(LEDPIN,led_status);
        }
      
        if(packet->universe == 0)
        {   
          memcpy (ArduinoDmx0.TxBuffer, packet->data, ARTNET_DMX_LENGTH);
        }
      }
      

      Regards.

  8. andrea

    thanks for the reply… I am newbie.
    I did some tests but I can not figure it out.
    I’d like to see if the dmx signal is being received.
    This is my simple sketch:

    #include "lib_dmx.h"
    
    #define    DMX512     (0)    // (250 kbaud - 2 to 512 channels) Standard USITT DMX-512
    /*************************************************************************************************************
     * Title			    : dmx receiver set 1 led intensity with led test dmx
      **************************************************************************************************************/
    // assegnazione pin
    
    // led pin 
    const int ledPin1 = 5;
    
    // dmx test led
    const int ledDmxPin =  13;
    
    
    void setup() 
    { 
      ArduinoDmx0.set_control_pin (-1);    // control pin for max485 not used
      ArduinoDmx0.set_rx_address(1);      // set rx0 dmx start address
      ArduinoDmx0.set_rx_channels(8);     // number of rx channels
      ArduinoDmx0.init_rx(DMX512);        // starts universe 0 as rx, NEW Parameter DMX mode
    
    
      // dmx test led
      pinMode (ledDmxPin, OUTPUT);
    
    
    }  //end setup()
    
    void loop()
    {
    
      analogWrite(ledPin1, ArduinoDmx0.RxBuffer[0]);
    
    
    
    }  //end loop()
    

    can you help me?
    thank you very much

    • Toni Merino

      Hi Andrea.

      You can use function “ArduinoDmx0.attachRXInterrupt (function_name);”
      regards.

      #include <lib_dmx.h>
      
      #define    DMX512     (0)    // (250 kbaud - 2 to 512 channels) Standard USITT DMX-512
      /*************************************************************************************************************
       * Title			    : dmx receiver set 1 led intensity with led test dmx
        **************************************************************************************************************/
      // assegnazione pin
      
      // led pin 
      const int ledPin1 = 5;
      
      // dmx test led
      const int ledDmxPin =  13;
      
      void setup() 
      { 
        //****** set function called when all channels received
        ArduinoDmx0.attachRXInterrupt  (frame_received);  
      
        ArduinoDmx0.set_control_pin (-1);    // control pin for max485 not used  
        //*** remember if not used: 
        //put pins 2 and 3 from max485 to GND for DMX RX or
        //put pins 2 and 3 from max485 to +5v for DMX TX ***
      
        ArduinoDmx0.set_rx_address(1);      // set rx0 dmx start address
        ArduinoDmx0.set_rx_channels(8);     // number of rx channels
        ArduinoDmx0.init_rx(DMX512);        // starts universe 0 as rx, NEW Parameter DMX mode
      
      
        // dmx test led
        pinMode (ledDmxPin, OUTPUT);
      
      
      }  //end setup()
      
      void loop()
      {
      
        //analogWrite(ledPin1, ArduinoDmx0.RxBuffer[0]); //see next function
      
      }  //end loop()
      
      // Custom ISR: fired when all channels in one universe are received
      void frame_received(uint8_t universe) 
      {
        static uint8_t led;
      
        if (universe == 0) // USART0
        {
          if(led == 0)	//blink led
          {
            digitalWrite  (ledDmxPin,  HIGH); 
            led = 1;
          }
          else
          {
            digitalWrite  (ledDmxPin,  LOW);
            led = 0;
          }
          // write outputs here using interrupts (don't waste time in main loop) **************
          analogWrite(ledPin1, ArduinoDmx0.RxBuffer[0]);
        }
      }  // end of ISR
      
  9. andrea

    I tried, and it works!
    and now I will study interrupts…

    thank you, very much

  10. Hi Toni

    Any plans to port this library and the arduino code to the new Arduino Due board?
    The new board have more RAM and a more powerfull processor, also with 4 UART’s.

    Merry Christmas

    Regards
    A. Caneira

  11. Tonnie Wittenaar

    Hi Nice project, thanks for that.

    Is a mega2560 fast enough to create a HTP merger with 3x 512 inputs and 1x 512 output?

    Do you know the frame delay caused by the merger?

    Or is it better to wait for a future Duo implementation as A. Caneira suggests?

    Regards
    Tonnie

    • Toni Merino

      Hi Tonnie

      Is a mega2560 fast enough to create a HTP merger with 3x 512 inputs and 1x 512 output?

      Do you know the frame delay caused by the merger?

      The output will be too slow with mega 🙁

      Or is it better to wait for a future Duo implementation as A. Caneira suggests?

      I have to test the DUO Arduino to see if it gives good results with four full universes…
      Regards

  12. […] “After searching the web for Arduino DMX libraries, and test, we find no library allowing the use of multiple DMX universes and that did not use the timers of the arduino, so finally decided to create it:”2 […]

  13. vijaya

    i am trying to convert it for atmega8 but i am not getting can any one help me? please…………..

  14. hydrus

    Have been using this library successfully on Arduino Uno, Mega2560 with ethernet shield and Arduino Ethernet now.

    I understand why you give the possibility of half duplex in some cases but in most cases simplex is all you need. (so no control pin and only one wire Rx or Tx from atmega to MAX485, makes single layer PCB design easier as well)

    Now, seen the UART’s on an atmega can handle full duplex, shouldn’t it be possible to make two simplex connections from one uart? So one Rx universe and one Tx universe per UART.
    You would of course still need 2 MAX485 but an Arduino Uno could have an input and an output universe at the same time this way.
    And I know there are limits to memory and speed but a Uno should be able to handle a single universe in and out no?

    Tried to do this by both initializing ArduinoDmx0 as Tx and Rx but it doesn’t seem to work to copy the Rx buffer to the Tx of the same UART.
    Is this possible at all or can’t the atmega do dual simplex over one UART?

    • Toni Merino

      Hi.
      The problem for use TX/RX at one time is the mode which have implemented the “BREAK” in TX mode. (This affect to RX)
      In order to generate break, USART speed is changed at beginning of each DMX frame (slow down for break generation, and after break = 250 kbaud for DMX frame)
      For implement TX/RX you need another mechanism to generate break (timer based, or asm).
      Regards.

      • hydrus

        Hello Toni,

        Thanks for this wonderful answer.
        I now even have more respect for the work you did.

        I also finally understand (roughly 😉 ) how you did this without using timers. Nice work!

  15. Florian

    Hi,

    I have been trying to use one of you’re example programs wich includes the DMX library, on my Arduino Uno. But when i try to compile i get the same error over and over again,

    Dmx_Receive.pde: In function ‘void loop()’:
    Dmx_Receive:37: error: ‘ArduinoDmx0’ was not declared in this scope

    I have no idea what to do about it (or what it exactly means).
    I am a bit of a arduino beginner and dont know alot about the whole arduino programming stuff.

    • Toni Merino

      Hi Florian.

      Be sure that:
      – You have “#include <lib_dmx.h> ” at the begining of program.
      – Folder of dmx library named (“Dmx”), is correctly copied on libraries folder of your Arduino IDE (normally arduino-XX.XX/libraries/)
      – You have selected correct board type on Arduino IDE.
      – You are not using Hardware serial.

      If this not work for you, what version of Arduino IDE are you using?, Windows or Linux?

      Regards.

Leave a Reply

Your email address will not be published. Required fields are marked *