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?
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.
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 )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;
}
}