Using the Arduino to control musical Christmas lights from Vixen is easy with serial but has it's limitations. If it misses a step it can't correct itself and everything will be out of sync. It seems that the best solution would be to use the Renard Protocol as it has built in error correction but I can't seem to find any help on programming the Arduino to read the data stream. Unfortunately I'm too new to all of this to program it myself, though if I can't get help I may try. The grand idea would be to figure out how to utilize the Renard protocol and use daisy chained shift registers to run 50+ channels. Any help with programming would be greatly appreciated.
If it misses a step...
My suspicion is that it would be much less work to determine why "it" is missing steps and fix that problem.
Link?
It isn't currently but if it were to for any reason it would never resync. That is, from what I can tell, the largest drawback of running a Vixen + Arduino + Serial system. If that can be eliminated by writing some code for Arduino to read a Renard stream (renard has a start and stop byte) that seems to be the best way to go and I think there are a lot of people that would use it. Unfortunately I don't know how to code well enough to write it.
Mat er daddy claims to have done what you want...
Have you searched for his work?
I have searched everywhere I could think of for his work and tried to get ahold of him. He refers to it as "slightly more complex" but never really goes into any details on how.
You were right, after digging for awhile I did find this code by Mat er daddy. Right now I'm playing with modifying it to dump the color part because my lights are not RGB pixels.
#define XMAS_PIN 8
#define xmas_color_t uint16_t
#define XMAS_LIGHT_COUNT (50)
#define XMAS_CHANNEL_MAX (0xF)
#define XMAS_DEFAULT_INTENSITY (0xCC)
#define XMAS_COLOR(r,g,b) ((r)+((g)<<4)+((b)<<8))
#define XMAS_COLOR_WHITE XMAS_COLOR(XMAS_CHANNEL_MAX,XMAS_CHANNEL_MAX,XMAS_CHANNEL_MAX)
#define XMAS_COLOR_BLACK XMAS_COLOR(0,0,0)
bool sync;
void xmas_begin(uint8_t pin);
void xmas_one(uint8_t pin);
void xmas_zero(uint8_t pin);
void xmas_end(uint8_t pin);
void xmas_begin(uint8_t pin)
{
digitalWrite(pin,1);
delayMicroseconds(7);
digitalWrite(pin,0);
}
void xmas_one(uint8_t pin)
{
digitalWrite(pin,0);
delayMicroseconds(11); //This results in a 20 uS long low
digitalWrite(pin,1);
delayMicroseconds(7);
digitalWrite(pin,0);
}
void xmas_zero(uint8_t pin)
{
digitalWrite(pin,0);
delayMicroseconds(2);
digitalWrite(pin,1);
delayMicroseconds(20-3);
digitalWrite(pin,0);
}
void xmas_end(uint8_t pin)
{
digitalWrite(pin,0);
delayMicroseconds(40); // Can be made shorter
}
void xmas_set_color(uint8_t led,uint8_t intensity,xmas_color_t color, uint8_t pin)
{
uint8_t i;
cli(); //Disable interrupts while we write to GECEs
xmas_begin(pin);
//6-Bit bulb address (MSB first)
for(i=6;i;i--,(led<<=1))
{
if(led&(1<<5))
xmas_one(pin);
else
xmas_zero(pin);
}
//8-Bit brightness (MSB first)
for(i=8;i;i--,(intensity<<=1))
{
if(intensity&(1<<7))
xmas_one(pin);
else
xmas_zero(pin);
}
//12 bit Color (Blue, Green, Red) (MSB first)
for(i=12;i;i--,(color<<=1))
{
if(color&(1<<11))
xmas_one(pin);
else
xmas_zero(pin);
}
xmas_end(pin);
sei(); //Re-enable interrupts now that we're done writing to GECEs
}
void xmas_set_all_one_address(uint8_t pin)
{
for (int i = 0; i < XMAS_LIGHT_COUNT; ++i)
xmas_set_color(0,XMAS_DEFAULT_INTENSITY,XMAS_COLOR_BLACK,pin);
}
void setup()
{
delay(10);
Serial.begin(57600);
delay(10);
pinMode(5, OUTPUT);
digitalWrite(5, LOW);
pinMode(XMAS_PIN, OUTPUT);
digitalWrite(XMAS_PIN, 0);
xmas_set_all_one_address(XMAS_PIN);
sync = false;
}
void wait_for_serial()
{
while ( ! Serial.available() > 0 ) { }
}
int renardReadBytes( uint8_t *bytes, uint8_t bytes_size )
{
int in_byte = 0;
int bytes_read;
for ( bytes_read = 0; bytes_read < bytes_size; )
{
wait_for_serial();
in_byte = Serial.read();
switch (in_byte)
{
case(0x7E): // We saw the sync byte, start over!
sync = true;
return bytes_read;
case(0x7D): // Skip the pad byte
continue;
case(0x7F): // Escape character, we need to read one more byte to get our actual data
wait_for_serial();
in_byte = Serial.read();
switch (in_byte)
{
case(0x2F): // renard wants an 0x7D
in_byte = 0x7D;
case(0x30): // renard wants an 0x7E
in_byte = 0x7E;
case(0x31): // renard wants an 0x7F
in_byte = 0x7F;
}
}
bytes[bytes_read++] = in_byte;
}
return bytes_read;
}
int renardRead( uint8_t *bytes, uint8_t byte_count )
{
int in_byte = 0;
while ( ! sync )
{
wait_for_serial();
in_byte = Serial.read();
if ( in_byte == 0x7E ) // Sync byte signifies start of packet
sync = true;
}
if ( sync )
{
sync = false;
wait_for_serial();
in_byte = Serial.read();
if ( in_byte == 0x80 ) // Read from here
{
return renardReadBytes(bytes, byte_count);
}
}
return 0;
}
void loop()
{
uint8_t bytes[4], bytes_read;
bytes_read = renardRead(&bytes[0], 4);
if ( bytes_read == 4 )
{
// We have now received 4 bytes of data per string, do something with them!
uint8_t red = bytes[0];
uint8_t green = bytes[1];
uint8_t blue = bytes[2];
uint8_t white = bytes[3];
red = ( red+(white/3) >= (XMAS_CHANNEL_MAX<<4) ? (XMAS_CHANNEL_MAX<<4) : red+(white/3) );
green = ( green+(white/3) >= (XMAS_CHANNEL_MAX<<4) ? (XMAS_CHANNEL_MAX<<4) : green+(white/3) );
blue = ( blue+(white/3) >= (XMAS_CHANNEL_MAX<<4) ? (XMAS_CHANNEL_MAX<<4) : blue+(white/3) );
xmas_set_color(0,XMAS_DEFAULT_INTENSITY,XMAS_COLOR((red>>4),(green>>4),(blue>>4)),XMAS_PIN);
}
}
Did you get the code figured out? I just came across this in a google search.
If anybody comes back to this post, I found a bug in my code not allowing more than 255 channels (I used a uint8_t for channel count).
See updated code where the original code was posted:
Hi I am looking for this:
The idea is to create 6-8 channel controlled EL wire, so that I can make some chore on it. Many of people has already done it, but I am not getting any to the point solution, may be I am not able to understand because I am an artist not a technician. But I believe I can handle the project with some help and guidence.
Please people out there, help me.!
Thank you!!
choreographernik@gmail.com