dmx code errors :/

Firstly i’m new to Arduino but i’va got the following code;

//----code from http://arduino.cc/playground/DMX/Ardmx ----// 



//----variables----// 

#define RX_STATUS_PIN 2
 
volatile uint8_t  DmxRxField[8]; //array of DMX vals (raw)
volatile uint16_t DmxAddress;    //start address
 
enum {IDLE, BREAK, STARTB, STARTADR}; //DMX states
 
volatile uint8_t gDmxState;

//----setup----//

void setup() {

Serial.begin(250000); //Enable serial reception with a 250k rate
pinMode(RX_STATUS_PIN, OUTPUT); //RX STATUS LED pin, blinks on incoming DMX data
gDmxState= IDLE; // initial state
DmxAddress = 3; // The desired DMX Start Adress

}

ISR(USART0_RX_vect) {
  //mod 
  #define rxStatusPin = 13;
  //mod   
        digitalWrite(rxStatusPin, HIGH);
        static  uint16_t DmxCount;
        uint8_t  USARTstate= UCSR1A;    //get state before data!
        uint8_t  DmxByte   = UDR1;          //get data
        uint8_t  DmxState  = gDmxState; //just load once from SRAM to increase speed
 
        if (USARTstate &(1<<FE1))               //check for break
        {
                DmxCount =  DmxAddress;         //reset channel counter (count channels before start address)
                gDmxState= BREAK;
        }
 
        else if (DmxState == BREAK)
        {
                if (DmxByte == 0) gDmxState= STARTB;  //normal start code detected
                else                      gDmxState= IDLE;
        }
 
        else if (DmxState == STARTB)
        {
                if (--DmxCount == 0)    //start address reached?
                {
                        DmxCount= 1;            //set up counter for required channels
                        DmxRxField[0]= DmxByte; //get 1st DMX channel of device
                        gDmxState= STARTADR;
                }
        }
 
        else if (DmxState == STARTADR)
        {
                DmxRxField[DmxCount++]= DmxByte;        //get channel
                if (DmxCount >= sizeof(DmxRxField)) //all ch received?
                {
                        gDmxState= IDLE;        //wait for next break
                }
        }
        digitalWrite(rxStatusPin, LOW);                                                
}

//----the code----//

void loop() {

analogWrite(14, DmxRxField[0]);
  
}

but it gives me the following errors;

version_2.cpp: In function ‘void USART0_RX_vect()’:
version_2:30: error: expected primary-expression before ‘=’ token
version_2:30: error: expected primary-expression before ‘,’ token
version_2:30: error: expected ;' before ')' token version_2:32: error: 'UCSR1A' was not declared in this scope version_2:33: error: 'UDR1' was not declared in this scope version_2:36: error: 'FE1' was not declared in this scope version_2:66: error: expected primary-expression before '=' token version_2:66: error: expected primary-expression before ',' token version_2:66: error: expected ;’ before ‘)’ token

I’ve added some code to remove an error in the //mod comments. But i have no idea where to start with the other errors.

but i'va got the following code

Which version of the IDE are you using? Which board do you have?

version 1.0 and looking to use code on uno and maybe mega.

Line 30, just like the error said,

#define rxStatusPin = 13;

This is not valid code.
Defines are compile-time only, you want to use a variable like 'DmxAddress' is, or just put 13 until you can understand defines.

you will need to include something to provide the definitions for 'UCSR1A' and the other 2 names.

#define was bad so

digitalWrite(rxStatusPin, LOW);

is also bad

updated code;

//----code from http://arduino.cc/playground/DMX/Ardmx ----// 



//----variables----// 

#define RX_STATUS_PIN 2
 
 
volatile uint8_t  DmxRxField[8]; //array of DMX vals (raw)
volatile uint16_t DmxAddress;    //start address
 
enum {IDLE, BREAK, STARTB, STARTADR}; //DMX states
 
volatile uint8_t gDmxState;

//----setup----//

void setup() {

Serial.begin(250000); //Enable serial reception with a 250k rate
pinMode(RX_STATUS_PIN, OUTPUT); //RX STATUS LED pin, blinks on incoming DMX data
gDmxState= IDLE; // initial state
DmxAddress = 3; // The desired DMX Start Adress

}

ISR(USART0_RX_vect) {
        digitalWrite(13, HIGH);
        static  uint16_t DmxCount;
        uint8_t  USARTstate= UCSR1A;    //get state before data!
        uint8_t  DmxByte   = UDR1;          //get data
        uint8_t  DmxState  = gDmxState; //just load once from SRAM to increase speed
 
        if (USARTstate &(1<<FE1))               //check for break
        {
                DmxCount =  DmxAddress;         //reset channel counter (count channels before start address)
                gDmxState= BREAK;
        }
 
        else if (DmxState == BREAK)
        {
                if (DmxByte == 0) gDmxState= STARTB;  //normal start code detected
                else                      gDmxState= IDLE;
        }
 
        else if (DmxState == STARTB)
        {
                if (--DmxCount == 0)    //start address reached?
                {
                        DmxCount= 1;            //set up counter for required channels
                        DmxRxField[0]= DmxByte; //get 1st DMX channel of device
                        gDmxState= STARTADR;
                }
        }
 
        else if (DmxState == STARTADR)
        {
                DmxRxField[DmxCount++]= DmxByte;        //get channel
                if (DmxCount >= sizeof(DmxRxField)) //all ch received?
                {
                        gDmxState= IDLE;        //wait for next break
                }
        }
        digitalWrite(13, LOW);                                                
}

//----the code----//

void loop() {

analogWrite(14, DmxRxField[0]);
  
}

but i still get the following errors;

version_2.cpp: In function ‘void USART0_RX_vect()’:
version_2:30: error: ‘UCSR1A’ was not declared in this scope
version_2:31: error: ‘UDR1’ was not declared in this scope
version_2:34: error: ‘FE1’ was not declared in this scope

I’m not sure how to define these or what they do. Any ideas?

Had a look at this - UCSR1A only exists on Arduino Megas. The author of that page got it wrong, the first UART is numbered 0, not 1. Standard Arduinos have only one UART (numbered 0). The Mega Arduinos have 4 UARTS, numbered 0,1,2,3

Should i change it to UART0 then?

That depends on whether you want it to run on a non-Mega Arduino :wink:

ideally yeah i would like to use in on uno as that's the platform i own.

i think this is where i've got lost

To avoid a redefinition error upon compile, you have to slightly modify your HardwareSerial.cpp when compiling the DMX receiver code. Don't forget to save the original one before! Now just do a search for "ISR(USARTn_RX_vect)" where n should be replaced by the number of the USART you actually use, e.g. "USART0_RX_vect". When you found the definition, just comment the whole block between the {..} out (it should be about 5 lines long or so).

i'm running version 1.0 but i can't find this code in the file - C:\Program Files\arduino-1.0\hardware\arduino\cores\arduino\hardwareserial.cpp

Any ideas on this change that i should make?

USART_RX_vect - not numbered since only one

ahh - wicked that works for mega -

//----code from http://arduino.cc/playground/DMX/Ardmx ----// 
//change1//-- UCSR1A; for mega to UART0; for uno. 


//----variables----// 

#define RX_STATUS_PIN 2
 
 
volatile uint8_t  DmxRxField[8]; //array of DMX vals (raw)
volatile uint16_t DmxAddress;    //start address
 
enum {IDLE, BREAK, STARTB, STARTADR}; //DMX states
 
volatile uint8_t gDmxState;

//----setup----//

void setup() {

Serial.begin(250000); //Enable serial reception with a 250k rate
pinMode(RX_STATUS_PIN, OUTPUT); //RX STATUS LED pin, blinks on incoming DMX data
gDmxState= IDLE; // initial state
DmxAddress = 3; // The desired DMX Start Adress

}

ISR(USART_RX_vect) {
        digitalWrite(13, HIGH);
        static  uint16_t DmxCount;
        uint8_t  USARTstate= UCSR1A;  //change1//  //get state before data!
        uint8_t  DmxByte   = UDR1;          //get data
        uint8_t  DmxState  = gDmxState; //just load once from SRAM to increase speed
 
        if (USARTstate &(1<<FE1))               //check for break
        {
                DmxCount =  DmxAddress;         //reset channel counter (count channels before start address)
                gDmxState= BREAK;
        }
 
        else if (DmxState == BREAK)
        {
                if (DmxByte == 0) gDmxState= STARTB;  //normal start code detected
                else                      gDmxState= IDLE;
        }
 
        else if (DmxState == STARTB)
        {
                if (--DmxCount == 0)    //start address reached?
                {
                        DmxCount= 1;            //set up counter for required channels
                        DmxRxField[0]= DmxByte; //get 1st DMX channel of device
                        gDmxState= STARTADR;
                }
        }
 
        else if (DmxState == STARTADR)
        {
                DmxRxField[DmxCount++]= DmxByte;        //get channel
                if (DmxCount >= sizeof(DmxRxField)) //all ch received?
                {
                        gDmxState= IDLE;        //wait for next break
                }
        }
        digitalWrite(13, LOW);                                                
}

//----the code----//

void loop() {

analogWrite(14, DmxRxField[0]);
  
}

but i have no idea what to change the UCSR1A to as it doesn’t seem to like UART0 or UART ither. (for uno board that is)(or the 2 lines after that).

Find the include/avr/iom328p.h include file... All these defines are in there. On ubuntu this ends up at /usr/share/avr/include/avr/iom328p.h, don't know about other platforms.

UCSR0A, UCSR0B, UCSR0C are present there...

ok code for uno; (it verify’s but still not 100% sure on it)

//----code from http://arduino.cc/playground/DMX/Ardmx ----// 
//changes for uno. 
/*
pin out 
0 - dmx in from 75176 TI
1
2
3
4

11 - output to led.
12
13 - led status pin
*/




//----variables----// 

#define RX_STATUS_PIN 13
 
 
volatile uint8_t  DmxRxField[8]; //array of DMX vals (raw)
volatile uint16_t DmxAddress;    //start address
 
enum {IDLE, BREAK, STARTB, STARTADR}; //DMX states
 
volatile uint8_t gDmxState;

//----setup----//

void setup() {

Serial.begin(250000); //Enable serial reception with a 250k rate
pinMode(RX_STATUS_PIN, OUTPUT); //RX STATUS LED pin, blinks on incoming DMX data
gDmxState= IDLE; // initial state
DmxAddress = 1; // The desired DMX Start Adress

pinMode(11, OUTPUT); //pin for led output
}

ISR(USART_RX_vect) {
        digitalWrite(13, HIGH);
        static  uint16_t DmxCount;
        uint8_t  USARTstate= UCSR0A;  //get state before data! (UCSR0A for uno)
        uint8_t  DmxByte   = UDR0;          //get data //usart data register //(UDR0 for uno) 
        uint8_t  DmxState  = gDmxState; //just load once from SRAM to increase speed
 
        if (USARTstate &(1<<FE0))               //check for break //(FE0 for uno)
        {
                DmxCount =  DmxAddress;         //reset channel counter (count channels before start address)
                gDmxState= BREAK;
        }
 
        else if (DmxState == BREAK)
        {
                if (DmxByte == 0) gDmxState= STARTB;  //normal start code detected
                else                      gDmxState= IDLE;
        }
 
        else if (DmxState == STARTB)
        {
                if (--DmxCount == 0)    //start address reached?
                {
                        DmxCount= 1;            //set up counter for required channels
                        DmxRxField[0]= DmxByte; //get 1st DMX channel of device
                        gDmxState= STARTADR;
                }
        }
 
        else if (DmxState == STARTADR)
        {
                DmxRxField[DmxCount++]= DmxByte;        //get channel
                if (DmxCount >= sizeof(DmxRxField)) //all ch received?
                {
                        gDmxState= IDLE;        //wait for next break
                }
        }
        digitalWrite(13, LOW);                                                
}

//----the code----//

void loop() {

analogWrite(11, DmxRxField[0]);
  
}

also i’ve modified the hardwareserial.cpp in the following way;

/******************* COMMENTED OUT FOR DMX RECEPTION ************

#if !defined(USART0_RX_vect) && defined(USART1_RX_vect)
 do nothing - on the 32u4 the first USART is USART1
#else
#if !defined(USART_RX_vect) && !defined(SIG_USART0_RECV) && \
    !defined(SIG_UART0_RECV) && !defined(USART0_RX_vect) && \
	!defined(SIG_UART_RECV)
  #error "Don't know what the Data Received vector is called for the first UART"
#else
  void serialEvent() __attribute__((weak));
  void serialEvent() {}
  #define serialEvent_implemented
#if defined(USART_RX_vect)
//SIGNAL(USART_RX_vect)
#elif defined(SIG_USART0_RECV)\
  SIGNAL(SIG_USART0_RECV)
#elif defined(SIG_UART0_RECV)
  SIGNAL(SIG_UART0_RECV)
#elif defined(USART0_RX_vect)
  SIGNAL(USART0_RX_vect)
#elif defined(SIG_UART_RECV)
  SIGNAL(SIG_UART_RECV)
#endif
  {
 #if defined(UDR0)
    unsigned char c  =  UDR0;
  #elif defined(UDR)
    unsigned char c  =  UDR;
  #else
    #error UDR not defined
  #endif
    store_char(c, &rx_buffer);
  }
#endif
#endif

******************** END COMMENT ***************/

I think that’s it - have i missed anything?

Did you ever get this working?
I (newbie) tried as above and some variants thereof without success.. Looks like ISR(USART_RX_vect) isn't getting called at all(?)
Also using an Uno and 1.0

Michael

Each interrupt vector can be "masked out" (ie disabled) by a bit in some control register, so if its not being called that's the first thing to check. Datasheet(s) has all the grizzly details of course!

Well, thanks :sweat_smile:
The DS has 567 pages and although I read it, I probably won’t get the one missing Bit - at least in combination with all the magic the Arduino libs etc do behind the scenes…

I like it really (the whole Arduino thing), because it makes many things much less freaky using an AVR (only to start thinking about fuses, ISP etc. creates headache)
And I understand this is a corner-case (re)creating the ISR for the USART to cleanly recv DMX - if there are other/better, reliable options using built-in functions I’d be happy also to learn about.

Michael

I’m still stuck after some hours, it looks like whatever I try the ISR isnt called at all :frowning:
Seeing the DMX-signal on Pin0/RXD clearly but none of my debug-pins ever reacts; tried from another code here now from screatch:

#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>


// ********************* local definitions *********************
#define DMX_CHANNELS    (32)		//Define the number of DMX values to store

#define RX_STATUS_PIN 2

enum {IDLE, BREAK, STARTB, STARTADR};	//DMX states

uint8_t  gDmxState;
uint16_t DmxCount;

uint8_t  DmxRxField[DMX_CHANNELS];     //array of DMX vals (raw)
uint16_t DmxAddress;			 //start address

int ledPin = 4;			     // LED connected to digital pin 13
boolean rxled=false;

void setup()				   // run once, when the sketch starts
{
  // sets the digital pin as output
  pinMode(ledPin, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(RX_STATUS_PIN, OUTPUT); //RX STATUS LED pin, blinks on incoming DMX data
  digitalWrite(RX_STATUS_PIN, LOW);
  
  // Disable interrupts
  cli();

  // 250kbps baud - only works for 16MHz clock frequency. See the ATMega8 datasheet if you are using a different clock speed
  UBRR0H = 0;
  UBRR0L = 3;

  // enable rx and interrupt on complete reception of a byte
  UCSR0A |= (1<<RXC0);
  UCSR0B = (1<<RXEN0)|(1<<RXCIE0);
  UCSR0C = (1<<UMSEL01)|(3<<UCSZ00)|(1<<USBS0);

  // Enable interrupts
  sei();

  gDmxState= IDLE;

  uint8_t i;
  for (i=0; i<DMX_CHANNELS; i++)
  {
    DmxRxField[i]= 0;
  }

  DmxAddress= 10;  //Set the base DMX address. Could use DIP switches for this.
}

void loop()			   // run over and over again
{
  digitalWrite(3, HIGH);   // set the LED on
  if(DmxRxField[0] >=127)
  {
    digitalWrite(ledPin, HIGH);   // sets the LED on
  }
  else
  {
    digitalWrite(ledPin, LOW);    // sets the LED off
  }
  digitalWrite(3, LOW);   // set the LED on
}

// *************** DMX Reception ISR ****************
ISR(USART_RX_vect) {
      digitalWrite(RX_STATUS_PIN, HIGH);
      static  uint16_t DmxCount;
      uint8_t  USARTstate= UCSR0A;    //get state before data!
      uint8_t  DmxByte   = UDR0;          //get data
      uint8_t  DmxState  = gDmxState; //just load once from SRAM to increase speed
 
      if (USARTstate &(1<<FE0))               //check for break
      {
              DmxCount =  DmxAddress;         //reset channel counter (count channels before start address)
              gDmxState= BREAK;
      }
 
      else if (DmxState == BREAK)
      {
              if (DmxByte == 0)
                gDmxState= STARTB;  //normal start code detected
              else
                gDmxState= IDLE;
      }
 
      else if (DmxState == STARTB)
      {
              if (--DmxCount == 0)    //start address reached?
              {
                  DmxCount= 1;            //set up counter for required channels
                  DmxRxField[0]= DmxByte; //get 1st DMX channel of device
                  gDmxState= STARTADR;
              }
      }
 
      else if (DmxState == STARTADR)
      {
              DmxRxField[DmxCount++]= DmxByte;        //get channel
              if (DmxCount >= sizeof(DmxRxField)) //all ch received?
              {
                      gDmxState= IDLE;        //wait for next break
              }
      }
      digitalWrite(RX_STATUS_PIN, LOW);
}

(and 10 variations thereof)

Still nothing… Any working ISR-code for the Uno would be highly apprecated :~

Michael

I think i did get it working at some point but my uni studies have taken over and the project has slowed up (to a stop).

I think I had it working nearly - at some point today also, seeing the PIN in the ISR getting toggled but with a much to low level (mV instead of 0/5V) and while messed up again, I thought to post the rather initial code which should be right after reading and verifying each bit against the Atmega-DS… (As I might also have measured wrong, having a DSO doesn’t mean to control it…)

My assumption is, something changed in avr-libc or Arduino since I last tried this and the ArDMX-Guide was written (without any problems back then!) some months ago with a 2009…
But I also don’t want to go back and hack old versions with new libs, better to find out the source - but there I’m stuck right now. I’d be happy to provide an updated guide once it works, goal is to interface shift-register LED-drivers (which works fine, standalone without DMX…)
Maybe someone has a hint…
BTW, just to be complete: Arduino 1.0 on Ubuntu 11.10, Uno, nothing else hacked in…

Makki