Scheduling DMX events

Hi Everyone,

I'm currently using the DMXSimple library to control lights on dimmer for a piece I'm developing.

I would like to control to lights in a linear way so that when I turned the arduino on the piece started.

What is best/easiest strategy to schedule events, I had considered writing the numbers to an audio file and then reading them as DMX integers is that feasible or just a hassle?

I am very new to arduino but enjoying it!

Thanks in advance

Jack

Hi Jack,

  • By scheduling events, you mean something like a lighting cue, where at certain times the levels change. do you want the level go to 0% to 100% over a time period? flash on? ramp up and down in a sin wave?

-use a look table, aka a giant array and maybe loop through your code accessing the table each itteration through, you could time the loop so you only send a DMX event every 0.25sec? then your dmx values could be precisely controlled and timed.

don't go too fast on the changes. you'll have to look up the DMX timing rate for your dimmer, error on the slower side.

don't run out of memory with too big of an array, i bet 1000 lines would be okay. you could get creative with excel to build the list.

good luck.

Hi Jonny,

Thats great thank you.

Using a look up table sounds perfect. Are there anything online you could point me towards to help get started?

first big question... can you send a single value to your dimmer via dmx to turn on a light? if you have the communication step done, then the rest is staightforward. here is an example of a what i mean by look-up table, aka array... (in very rough pseudo-code, this will not compile)

i think the arduino will be able to spit out data faster than your dimmers will react, and if you are using conventional lights, then the lamps themselves are very slow.

///-----
//lookup table
int dmxvalues[5] = {20, 40, 80, 30, 60, 100};

setup(){
//dmx stuff, communication stuff
}//setup

loop(){ 
//read the next spot in the lookup table
i++;

//but make sure we don't read past the end of the array
if (i > 5)
{i=0;}

//send out the value
dmxout = dmxvalues[i];

//how fast do you want to change the lights? new value every second
delay(1000);


}//loop
//------

Hi Jonny,

At the moment I can control individual channels. Just no in horizontal way. I think changing dmx values every second would be fine. This would also make calculating the length of the piece easy.

Could I use a separate look up table for each DMX channel?

Jack

Hi Jack,

Great, the control portion was the unknown part of this project for me. Professional lighting boards have a massive database of channels and levels, after that, what separates them is how you control and access that database. some allow you to have direct, intuitive control, others you have to jump through hoops to get just to get a light to turn on. for your project, you are going to build a very small database, as i don't think the arduino can replicate a GrandMa and unfortunately your going to have to jump through hoops to change a value.

each channel is an array
each channel will be updated each time through the loop
does each channel change each time through the loop, not necessarily - that's your design

how many channels do you want to run?? i would suggest starting small, and finding out where "the adruino lighting desk" stops working.
how often do you want to update your channel database? real-time, or once a month?

looking below at your tiny database, you could view the horizontal rows as channels, and the vertical columns are 'cues', if you see the patten of numbers, there will be a ramp up on channel 0-3, with an offset of one cue (sort of like a wave effect) channel 4-7 will pop-on at a different value in the same cue. channel 8-9 will do sort of a combination of both.

(i suggest using excel/openoffice to color code you chart so you have a better look at what your numbers are doing, text on a screen is rough)

(and for you experienced coders out there, yes i know there at x-dimension arrays, simple is better in this case :slight_smile: )

_Jon

//pseudo-code  (check array bounds)
int arraysize = 20;

//database array...
int ch0[] {0,10,20,30,20,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
int ch1[] {0,0,10,20,30,20,10,0,0,0,0,0,0,0,0,0,0,0,0,0}
int ch2[] {0,0,0,10,20,30,20,10,0,0,0,0,0,0,0,0,0,0,0,0}
int ch3[] {0,0,0,0,10,20,30,20,10,0,0,0,0,0,0,0,0,0,0,0}

int ch4[] {0,0,0,0,0,0,40,0,0,0,0,0,50,0,0,0,0,0,0}
int ch5[] {0,0,0,0,0,0,30,0,0,0,0,0,50,0,0,0,0,0,0}
int ch6[] {0,0,0,0,0,0,20,0,0,0,0,0,50,0,0,0,0,0,0}
int ch7[] {0,0,0,0,0,0,10,0,0,0,0,0,50,0,0,0,0,0,0}

int ch8[] {0,20,30,40,50,60,0,0,0,0,0,0,50,0,0,0,0,0,0}
int ch9[] {0,0,20,30,40,50,60,0,0,0,0,0,50,0,0,0,0,0,0}

//...

setup(){
(setup dmx stuff)
(setup input / output stuff)
}


loop(){
i++
//careful, if you try to read out side of your array, you will crash.

if (i>arraysize)
{i=0;
}

dmx0 = ch0[i];
delay(5);

dmx1 = ch1[i]
delay(5);

dmx2 = ch2[i]
delay(5);

dmx3 = ch3[i]
delay(5);

dmx4 = ch4[i]
delay(5);

dmx5 = ch5[i]
delay(5);

dmx6 = ch6[i]
delay(5);

dmx7 = ch7[i]
delay(5);

dmx8 = ch8[i]
delay(5);

dmx9 = ch9[i]
delay(5);

//and here's a hint for real-time control
dmx10 = analogRead(knob_pin);

}

Hi Jon,

Thank you for the help its really appreciated.

Thought I should post where I've gotten to in case it helps anybody else but also hoped I could get some advice. How long does delay take to step through the numbers. How would I get to a point where I was stepping through every second or half a second?

Thanks

Jack

int timer = 1000;

int chan1[] = {0, 10, 100, 0, 0, 0, 255, 255, 0, 255, 255, 60, 255, 0, 15, 100, 170, 190, 200, 255};
int chan2[] = {0, 10, 100, 0, 0, 0, 255, 255, 100, 255, 255, 60, 255, 0, 15, 100, 170, 190, 200, 255};

int pinCount = 20;

#include <DmxSimple.h>

void setup() {
DmxSimple.usePin(3);
DmxSimple.maxChannel(2);

}

void loop() {

for (int thisPin = 0; thisPin < pinCount; thisPin++) {

DmxSimple.write(1, chan1[thisPin]);
DmxSimple.write(2, chan2[thisPin]);
delay(timer);
}
}

HI Jack,

Does it work in your example? if so great... here is a minor tweak to your code, using some descriptive names of what the code is doing verus how it's wired. also, i've had weird issues calling an array from inside a function call, so that's why there's an extra variable just before the dmx update. hope this helps..

you have it exactly right, using the delay(1000) at the end of the loop - it will wait 1 sec before going to the next spot in the array.

i've always seen #include as the first few lines in code, not sure why, but there seems to be a reason.

#include <DmxSimple.h>

int timer = 1000;

  int chanValues1[] = {0, 10, 100, 0, 0, 0, 255, 255, 0, 255, 255, 60, 255, 0, 15, 100, 170, 190, 200, 255};
  int chanValues2[] = {0, 10, 100, 0, 0, 0, 255, 255, 100, 255, 255, 60, 255, 0, 15, 100, 170, 190, 200, 255};

int arraySize = 20;

//use names, avoid 'magic' numbers
int dmxChan1 = 1;
int dmxChan2 = 2; 

void setup() {
  DmxSimple.usePin(3);
  DmxSimple.maxChannel(2);

}//setup

void loop() {
int dmxValue = 0;

    for (int i = 0; i < arraySize; i++) { 
   
      dmxValue = chanValues1[i];
      DmxSimple.write(dmxChan1, dmxValue);
    
      //not sure how fast you can write new data on the DMX bus, lets delay a small bit. you may be able to remove this??
      delay(20);    
     
      dmxValue = chanValues2[i];
      DmxSimple.write(dmxChan2, dmxValue);
    
    delay(timer);

  }//for

}//loop

Thanks Jon,

It works in my example but I'm going to go through your changes and put them in to help me understand.

Cheers

Jack

Hi Jon,

The code you gave me is definitely more reliable, maybe its extra delay you put in.

So far controlling two DMX channels with separate arrays works well with array sizes towards 400 elements.

Ideally I wanted my piece to be around 12 minutes long so this would mean only having the flexibility to change numbers around every two seconds which feels a bit restrictive.

On the DMX shield that I bought ( http://www.skpang.co.uk/catalog/arduino-dmx-shield-p-663.html ) there is a micro SD card slot and I do have a spare card so I wondered if it was possible to read the the array from the SD?

Although I'm a little confused as I think my program is quite small as it says this when I load it "Binary sketch size: 3014 bytes (of a 30720 byte maximum)"

Thanks

Jack

Although I'm a little confused as I think my program is quite small as it says this when I load it "Binary sketch size: 3014 bytes (of a 30720 byte maximum)"

That tells you how much flash memory is being used. Arrays are stored in SRAM - a different kind of memory. On a Duemilanove and UNO, SRAM is 2048 bytes. That is what limits your array sizes.

So it should be straight forward to store the array on on the SD? If so how should I go about doing it?

So it should be straight forward to store the array on on the SD? If so how should I go about doing it?

If it is so straightforward, why do you have to ask?

Good point! I guess I'm asking cus it might be straightforward for somebody who knows and might like to point me in the right direction...

Hi Jack,

The SD card route looks to be the way to go, then you can write you lighting programs on your PC/Mac then run them from the Arduino. I took a quick look at the SD card library, and it looks straightforward. One issue that i could see, say you want to read only a portion of the file, the first 1000 bytes, how do you keep track of where you are in the file, how do you tell the read/write function only to read the first 1000 bytes? or do you read line by line in the text file - immediately outputting it on the dmx line - this is a design question - that i hope someone else could answer this, constructively... :.

read in "chunks" or read line-by-line?

Hi Jack,

when i get back i'm going to get one of those shields you have... they look neat. until then, here is some pseudo code, let me know if you come up with anything.

//includes
//defines

int i //file size keeper

setup 
filesize = get file size


loop 
for (int i=0; i<filesize; i++){

file open for first channel
file position i
dmx value = file read at position i
dmx out
file close

file open for second channel 
file position i
dmx value = file read at position i
dmx out
file close

}

//what is needed to start / check sd communication?
//serial library needed?
//need to strip out extra characters being read from the file?
//output back to serial monitor to verify?