Trouble with DMX512 using MAX485 and DmxSerial.h Library

I'm currently working on a project involving the MAX485 module, DMX512 communication, and the DmxSerial.h library on Arduino. I've successfully transmitted DMX512 data using the MAX485 module and the DmxSimple.h library, and everything works as expected. I've attached pictures (Picture Number 1) to illustrate the successful transmission setup.

However, I'm encountering difficulties when trying to receive DMX512 data from a lighting board. It's important to note that receiving DMX requires different wiring than transmitting. I've wired the system differently for the reception part (see Picture Number 2), but unfortunately, I can't get the microcontroller to read the signal. Here are some specifics about my setup:

I am using the DmxSerial.h library for receiving DMX, and I've tried the standard example "DmxSerialRecv" from the library's GitHub repository.

If you have any thoughts on what might be causing the problem or tips on how to resolve it, I would love to hear them!

Thank you for your help!

I’m not sure Incan see a difference between your two drawings…

Moreover, there shouldn’t be any difference other than sorting out your use of i/o pins., you simply swap the tx/rx enable states,

Please also post your code in code tags.

A different processor with extra hardware serial will help, otherwise you have to mess around with pins 0/1 when debugging or programming, Software serial won’t be reliable for DMX

Currently, for transmitting, enable pins are connected to +5V. For receiving, they are connected to GND (I do this manually) .
For Transmitting (Connected to Mega 2560 Tx pin 1): GitHub link

For Receiving (Connected to Mega 2560 Rx pin 0):: GitHub link

Based on your suggestion for a processor with extra hardware serial, which specific processor or Arduino model would you recommend? Is the Arduino Due a suitable choice in your opinion?

If your codes reasonable size I’d say a MEGA 2560 (4 hardware uarts) or similar.

If you need a lot more memory, then jump up to a bigger processor.

The MEGA1284 has a lot of memory and 2x uarts. Other options can be found.

Fritzing is always hugely unclear, but i think it looks OK, (except maybe for the connection between GND & XLR 1 which on a DMX chain should not be there, but this will not be your issue.

Please post an actual schematic if possible.

A 328P processor will easily suffice, debug messages are usually not required, but yes uploading may mean that the MAX485 needs to be disconnected.

I use Nanos, pro-minis or UNOs (as well as assorted ESP8266's ) for receiving DMX.
SocftwareSerial just won't work at 250Kbps, not even for transmission and for sure not for reception, but if debug messages are really needed it could be used for that icw a USB to TTL converter.

Still DMX reception can be confirmed with use of just 2 leds, one to ping when receiving a frame and one to show a channel value.

is this the example you are referring to ?

I have never used that library, but it should work, again please make a schematic with how you have connected it up.

I have always used a different method on an AVR, which involves looking for the break using a timer, and then reading the incoming byte from the UDR0 register in the USART_RX_vect ISR.

I haven't looked at the code for AVR for a while though. As always there are a few examples flying around in my sketch folder, and i'd have to test to confirm which is actually the right one.

Oh eh, how many channels does that lighting board transmit ? Older simpler boards that i have used for testing tend to send just a limited amount of channels, i am not sure DMXSerial.h accounts for that.

That’s a really important factor l.

You only need to transmit as many channels as you are using,. increasing the cycle speed to refresh the target devices.

I am using Chamsys MagicqDMX usb dongle.
But can try different lighting consoles as well.

Not all libraries allow for that. Mind you with a framelength of less than 26ms for a complete frame, that being nearly 40Hz, DMX is already in the range that the human eye can perceive. even at half speed there is no problem to most VJ's

That is not a lighting board.

The most obvious is to use the DMXSimple sketch on a board. You can transmit, you know for sure, you have received it. Now can you receive what you transmit.

There are a few libraries that i have used, Conceptinetics.h being my favorite for transmission (DMXSimple use a bit-banged method)

This is a thread i started when doing reception without any library and found there were some bytes there i couldn't explain.

I think this is the final code i ended up with

#define PWM_LED_PIN 5
#define DMX_PING 13
#define MAX_DMX_CHANNELS 512

#define NUMBER_OF_CHANNELS 510

#define BAUDDMX 250000UL

#define RECEIVE_FORMAT 0x06 // 8N1 (could be 8N2 aswell.

#define UBDMX ((F_CPU / (8 * BAUDDMX)) - 1)



volatile uint16_t dmxaddress = 1;
volatile uint16_t i = 0;
volatile uint8_t dmxreceived = 0;
volatile uint16_t dmxcurrent = 0;
volatile uint8_t dmxvalue[NUMBER_OF_CHANNELS];

volatile uint8_t dmxnewvalue = 0;
volatile uint8_t zerocounter = 0;
volatile bool storeSerial = false;

void setup() {

  pinMode(PWM_LED_PIN, OUTPUT); // first dmxchannel LED value
  pinMode(DMX_PING, OUTPUT); //ping LED
  init_uart();
  SetupTimerRegisters();
}

void loop()  {
  ReceiveDMX();
  Processing();

}

void ReceiveDMX() {
  dmxnewvalue = 0;
  dmxcurrent = 0;
  zerocounter = 0;
  i = 0;
  UCSR0C = RECEIVE_FORMAT; //0x06; // 8N1
  bitSet(UCSR0B, RXCIE0);   // enable RX ISR
  bitSet(TIMSK2, OCIE2A);
  while (dmxnewvalue != 1);
}

void Processing() {  // main processing
  static bool pin = true;
  pin = !pin;
  analogWrite(5, dmxvalue[0]);
  digitalWrite(13, pin);
  if (dmxvalue[0] > 200) {
    digitalWrite(13, HIGH);
  }
  else {
    digitalWrite(13, LOW);
  }
}

void init_uart() {
  DDRD |=  (1 << PORTD1); // set TX pin  to output
  DDRD &= ~(1 << PORTD0); // set RX pin to input
  UCSR0A = 0x02; // 1<<U2X | 0<<MPCM;
  UCSR0B = 1 << RXCIE0 | 0 << TXCIE0 | 0 << UDRIE0 | 1 << RXEN0 | 1 << TXEN0 | 0 << UCSZ02; // Enable TX & RX, disable RX interrupt
  UCSR0C = RECEIVE_FORMAT; // 8N1
  UBRR0H = (UBDMX >> 8);  // set baud rate
  UBRR0L = (UBDMX & 0xFF); // HL register
}

void SetupTimerRegisters() {  // Sets up Timer2 to fire every 4us
  cli();
  bitClear(TCCR2A, COM2A1);
  bitClear(TCCR2A, COM2A0);
  bitClear(TCCR2A, COM2B1);
  bitClear(TCCR2A, COM2B0);
  bitSet(TCCR2A, WGM21);
  bitClear(TCCR2A, WGM20);
  bitClear(TCCR2B, FOC2A);
  bitClear(TCCR2B, FOC2B);
  bitClear(TCCR2B, WGM22);
  bitClear(TCCR2B, CS22);
  bitClear(TCCR2B, CS21);
  bitSet(TCCR2B, CS20);
  OCR2A = 64;
  bitClear(TIMSK2, OCIE2B);
  bitSet(TIMSK2, OCIE2A);
  bitClear(TIMSK2, TOIE2);
  sei();
}

ISR(TIMER2_COMPA_vect) {
  if (bitRead(PIND, PIND0)) {  // checks if the pin has gone HIGH
    zerocounter = 0;
  }
  else {
    zerocounter++;
    if (zerocounter == 20)  // if 80us have passed 'Break' has been detected
    {
      bitClear(TIMSK2, OCIE2A);  // disable Timer2 Interrupt
      storeSerial = true;

    }
  }
} //end Timer2 ISR

ISR(USART_RX_vect) {
  /* The receive buffer (UDR0) must be read during the reception ISR, or the ISR will just
     execute again immediately upon exiting. */
  //static uint8_t dummies = 3;  // somehow the ISR gets fired 3 times after re-enabling
  dmxreceived = UDR0;
  /*if (dummies) {
    dummies--;
  }
  else */
  if (storeSerial) {
    dmxcurrent++;     //increment address counter starts at 0
    // this skips the start code
    if (dmxcurrent > dmxaddress) {        //check if the current address is the one we want.
      dmxvalue[i] = dmxreceived;
      i++;
      if ((i == NUMBER_OF_CHANNELS) || (dmxcurrent > MAX_DMX_CHANNELS - 2)) {
        bitClear(UCSR0B, RXCIE0);                   // disable RX ISR
        //dummies = 3;                             // reset number of dummy values
        storeSerial = false;                      // set the flag to false
        dmxnewvalue = 1;                        //set newvalue, so that the main code can be executed.
      }
    }
  }
} // end ISR

Just post the schematic also, and confirm that pin 6 on the MAX485 transceiver actually connects to XLR pin 3
You got transmission going so i do not think you would have gotten it wrong, as with the other pins of the XLR plug, but you never know.

Good news!

After trying one NANO for transmitting and another for receiving, everything works!
Later connected to the real DMX output (magicDMX dongle for my testing) that worked too.

Used for transmitting and receiving DmxSerial libraries and example codes

Maybe the problem was in some bad connection? But at least everything works and learned something new from your comments. Thanks, everyone!

1 Like

Ok just a small note and the modules you are using. They contain a 120R resistor on them. a terminator. In a DMX chain there should be a terminator after the last device on the chain. These modules have them on all of them also when they are used as master.

You should remove that resistor ! It is marked R7 on the module. If you want to have a terminator at the end of the chain, you are better off using a Male XLR plug and soldering a 120R resistor between pins 2 & 3

Having to many terminators in a chain can and will cause issues and can cause damage.

Also within a DMX chain, the GND from the master is used for shielding the twisted pair of the data line, but this GND should not be connected to all of the other devices in the chain. There should be no common GND between devices ! This will prevent any accidental transfer of shortcircuits through the GND lines.
Also there really is no need since the reference voltage of the data lines are each-other. The potential difference between the data+ & data- lines (A & B) determines the logic level of the RI.

Good you got it working !

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.