Four Universe DMX Library

I am using the four universe DMX library to receive a DMX signal on a Duemilanove with the MAX485 transceiver. I am trying to set it up so when it is receiving a DMX signal, it runs one set of code and when the DMX signal is lost, it runs another set of code. The ultimate goal is to control LED pixels.

I am using the led on pin 13 to tell me when it is receiving a DMX signal. The code below sort of works. The LED does come on when the signal is present but does not stay on. Randomly, the if statement will no longer be true when signal is present and the LED will shut off.

#include <lib_dmx.h>
#define    DMX512     (0)    // (250 kbaud - 2 to 512 channels) Standard USITT DMX-512
const int ledPin =  13;      // the number of the LED pin
volatile unsigned long lastframe = 0;
unsigned long now = 0;

void setup() 
{ 
  //****** set function called when all channels received
  ArduinoDmx0.attachRXInterrupt  (frame_received);  
  ArduinoDmx0.set_control_pin (2);    // control pin for max485 not used  
  ArduinoDmx0.set_rx_address(1);      // set rx0 dmx start address
  ArduinoDmx0.set_rx_channels(12);     // number of rx channels
  ArduinoDmx0.init_rx(DMX512);        // starts universe 0 as rx, NEW Parameter DMX mode
  pinMode (ledPin, OUTPUT);  //status LED set to Output 
}  //end setup()
 
void loop()
{
 now = millis();  //store current time
  
  if(now - lastframe < 5000) //calculate difference between times.  If less than 5 seconds we are receiving DMX
  {
   digitalWrite(ledPin, HIGH); //turn LED on if receiving DMX
  }
  else
  {
  digitalWrite(ledPin, LOW); //turn off if not receiving DMX
  delay(1000); //pause to show that LED is off
  }
  
}  //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
  {
    lastframe = millis(); //store time all channels are received 
  }
}  // end of ISR

Any help would be appreciated. Thanks!

  static uint8_t led;

What is this for?

Randomly, the if statement will no longer be true when signal is present and the LED will shut off.

How do you know this?

static uint8_t led;

I'm not exactly sure what this is for. It is part of the DMX library so I just left it in.

Randomly, the if statement will no longer be true when signal is present and the LED will shut off.

Something is causing the LED to shut off at seemingly random times when the DMX signal is present. The LED stays off for 1 second due to the delay I have written in the code and then comes back on. If I remove the DMX signal, the LED goes out and stays out like it should.

Not sure if it's your problem but you don't stop interrupts to read lastframe and as it's 32 bits it could change part way through a read. Stopping interrupts may have on the DMX library but you could make the interrupt service routine just increment a byte value and then check in the main code if the value has changed in the last 5 seconds and reset the countdown if it has or turn the LEd on if it has not. As your reading a byte value there is no real need to disable interrupts as an interrupt won't stop a instruction (read memory) part way though.

Thank you. I’m not exactly sure how to code that. Am I on the right track?

#include <lib_dmx.h>
#define    DMX512     (0)    // (250 kbaud - 2 to 512 channels) Standard USITT DMX-512
const int ledPin =  13;      // the number of the LED pin
//volatile unsigned long lastframe = 0;
unsigned long now = 0;
//const int whiteled = 9;
//int ledstate = LOW;
int currentcounter = 0;
int previouscounter = 0;






void setup() 
{ 
  //****** set function called when all channels received
  ArduinoDmx0.attachRXInterrupt  (frame_received);  
  ArduinoDmx0.set_control_pin (2);    // control pin for max485 not used  
  ArduinoDmx0.set_rx_address(1);      // set rx0 dmx start address
  ArduinoDmx0.set_rx_channels(12);     // number of rx channels
  ArduinoDmx0.init_rx(DMX512);        // starts universe 0 as rx, NEW Parameter DMX mode
  pinMode (ledPin, OUTPUT);  //status LED set to Output 
  //pinMode(whiteled, OUTPUT);
  
}  //end setup()
 
void loop()
{
  if(currentcounter > previouscounter) //has the value increased?
  {
    now = millis(); //store the time since the value has increased 
  }
  if(now < 5000) //time less than 5 seconds 
  {
   digitalWrite(ledPin, HIGH); //turn LED on 
   previouscounter = currentcounter;
  }
  else
  {
  digitalWrite(ledPin, LOW); //turn LED off
  delay(1000); //pause to show that LED is off
  }
  
}  //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
  {
    currentcounter++;  //increase counter by 1 each time through 
  }
}  // end of ISR

djred2000:
Thank you. I’m not exactly sure how to code that. Am I on the right track?

Yes you are, currentcounter still needs to be volatile though as its used in interrupt code. It also needs to be byte size so can be read in a single (machine code) instruction.
The check between values has changed to not equal (!=) instead of greater than (>) because the byte will wrap around to zero after its incremented beyond 255 and cause the LED to go out.
The code is untested as my arduino is doing other things ATM.

#include <lib_dmx.h>
#define    DMX512     (0)    // (250 kbaud - 2 to 512 channels) Standard USITT DMX-512
const int ledPin =  13;      // the number of the LED pin
//volatile unsigned long lastframe = 0;
unsigned long now = 0;
//const int whiteled = 9;
//int ledstate = LOW;
volatile byte currentcounter = 0;
byte previouscounter = 0;

void setup() 
{ 
  //****** set function called when all channels received
  ArduinoDmx0.attachRXInterrupt  (frame_received);  
  ArduinoDmx0.set_control_pin (2);    // control pin for max485 not used  
  ArduinoDmx0.set_rx_address(1);      // set rx0 dmx start address
  ArduinoDmx0.set_rx_channels(12);     // number of rx channels
  ArduinoDmx0.init_rx(DMX512);        // starts universe 0 as rx, NEW Parameter DMX mode
  pinMode (ledPin, OUTPUT);  //status LED set to Output 
  //pinMode(whiteled, OUTPUT);
  
}  //end setup()

void loop()
{
  if(currentcounter != previouscounter) //has the value changed?
  {
    now = millis(); //store the time since the value has increased 
    previouscounter = currentcounter;
  }
  
  if((millis() - now) > 5000) //time greater than 5 seconds 
  {
    digitalWrite(ledPin, LOW); //turn LED off
    delay(1000); //pause to show that LED is off
  }
  else
  {
    digitalWrite(ledPin, HIGH); //turn LED on 
  }
  
}  //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
  {
    currentcounter++;  //increase counter by 1 each time through 
  }
}  // end of ISR

Thank you very much. That works perfectly. I understand how it works now. I will post the final code once I test it with the LED pixels.