DMX + Shiftbrites

I would like to control a large set of Shiftbrites (or simmilar lights) using DMX512.

My initial plan is to build the arduino DMX receiver http://blog.wingedvictorydesign.com/2009/03/20/receive-dmx-512-with-an-arduino/

and then process the values received to send to the shiftbrite string.

Any reason this would not work?

My backup plan would be to receive the DMX values on a PC and then have software translate them to serial values I can send to the arduino.

I haven't tested the DMX receive code, mainly because I don't have anything that sends DMX commands. But it looks like it will work fine; it doesn't use the hardware SPI pins that the ShiftBrite Shield uses. The only conflict I can think of would be some kind of timing issue. The current hardware SPI implementation shouldn't interfere with the DMX code's interrupts, and the ShiftBrite chain isn't too timing sensitive. If hardware SPI does cause problems, there is also a pretty fast software method.

Yeah this is what I was figuring so far. I haven't done the calculations to figure out the processing cost of running all of these things at the same time (especially if I want to use 120 shiftbrites) but hopefully it is not bogged down.

By software I assume you mean shifting using bit bashing instead of the spi port?

Right, bit banged with port writes instead of using the slow digitalWrite or shiftOut methods.

It's one of the application examples on the documentation site: start [macetech documentation]

cool I have tried that before and it was pretty fast.

I think someone did something similar to this and was able to get 25fps.

Did you ever get this working intellijel? I am looking to control some shiftbrites fvia dmx rom my dmx controller that is part of my light controllers.

-jds

Hi Chaps.
I have adapted some code I found on this site and have been able to run
some shiftbrites. I managed to run 20 (thats all I have :slight_smile: )without any problems. My code is a bit crude, and a bit light on comments. The code here runs 10 Shiftbrights. I have run them next to a professional LED lighting fixture and they worked very well.
Cheers

// The DMX reciver
// DMX reciver code for arduino with ATmega 168
// It is based on Hendrik Hoelschers dmx code from http://www.hoelscher-hi.de/hendrik/
// This code was adapted for the ATmega 8 by big_mark_h
// And finaly Gustaf Gagge adapted it for ATmega 168 with lots of help from big_mark_h and Grumpy_Mike
// Simon Howarth then adapted it and added the code to control a number of ShiftBright's


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


// ********************* local definitions *********************
#define DMX_CHANNELS    (30)            //Define the number of DMX values to store. 3 for each ShiftBright

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

uint8_t  gDmxState;
uint8_t  *gDmxPnt;
uint16_t DmxCount;

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

int datapin  = 9; // DI
int latchpin = 10; // LI
int enablepin = 11; // EI
int clockpin = 12; // CI
int Count;
int Tred;  // Temp value red
int Tgreen;  // Temp value green
int Tblue;  // Temp value blue

void setup()                           // run once, when the sketch starts
{
  // sets the digital pin as output
  pinMode(datapin, OUTPUT);
  pinMode(latchpin, OUTPUT);
  pinMode(enablepin, OUTPUT);
  pinMode(clockpin, OUTPUT);
  digitalWrite(latchpin, LOW);
  digitalWrite(enablepin, 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
  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++)
  {
    DmxField[i]= 0;
  }

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

void SB_SendPacket(int SB_CommandMode, int SB_RedCommand, int SB_GreenCommand, int SB_BlueCommand) {
  unsigned long SB_CommandPacket;
  SB_CommandPacket = SB_CommandMode & B11;
  SB_CommandPacket = (SB_CommandPacket << 10)  | (SB_BlueCommand & 1023);
  SB_CommandPacket = (SB_CommandPacket << 10)  | (SB_RedCommand & 1023);
  SB_CommandPacket = (SB_CommandPacket << 10)  | (SB_GreenCommand & 1023);

  shiftOut(datapin, clockpin, MSBFIRST, SB_CommandPacket >> 24);
  shiftOut(datapin, clockpin, MSBFIRST, SB_CommandPacket >> 16);
  shiftOut(datapin, clockpin, MSBFIRST, SB_CommandPacket >> 8);
  shiftOut(datapin, clockpin, MSBFIRST, SB_CommandPacket);
}


void SB_Make_It_So() {
  delay(1); // adjustment may be necessary depending on chain length
  digitalWrite(latchpin,HIGH); // latch data into registers
  delay(1); // adjustment may be necessary depending on chain length
  digitalWrite(latchpin,LOW);
}

void loop()                     // run over and over again
{
   for (Count = 1; Count<= 10; Count++){ // set ShiftBrights to full
    SB_SendPacket(B01,127,127,127);
  }
  SB_Make_It_So();
  for (Count = 0; Count<=27; Count +=3){
    Tred = DmxField[Count] * 4; //Times by 4 because dmx is only 8 bit
    Tgreen = DmxField[Count+1] * 4;
    Tblue = DmxField[Count+2] * 4;
    SB_SendPacket(B00, Tred, Tgreen, Tblue);
  }
  SB_Make_It_So();

}

// *************** DMX Reception ISR ****************
SIGNAL(SIG_USART_RECV)
{
uint8_t USARTstate= UCSR0A;                              //get state
uint8_t DmxByte= UDR0;                                    //get data
uint8_t DmxState= gDmxState;                              //just get once from SRAM!!!

if (USARTstate &(1<<FE0))                              //check for break
      {
      UCSR0A &= ~(1<<FE0);                              //reset flag
      DmxCount= DmxAddress;                              //reset frame counter
      gDmxState= BREAK;
      }

else if (DmxState == BREAK)
      {
      if (DmxByte == 0)
            {
            gDmxState= STARTB;                        //normal start code detected
            gDmxPnt= ((uint8_t*)DmxField +1);
            }
      else gDmxState= IDLE;
      }

else if (DmxState == STARTB)
      {
      if (--DmxCount == 0)                              //start address reached?
            {
            gDmxState= STARTADR;
            DmxField[0]= DmxByte;
            }
      }

else if (DmxState == STARTADR)
      {
      uint8_t *DmxPnt;
      DmxPnt= gDmxPnt;
      *DmxPnt= DmxByte;
      if (++DmxPnt >= (DmxField +DMX_CHANNELS))             //all ch received?
            {
            gDmxState= IDLE;
            }
      else gDmxPnt= DmxPnt;
      }
}