0
votes

I am trying to send information to an Arduino Mega 2560 using serial data in order to control both LED Pixel Strips and conventional christmas light strings. I am also using VIXEN lighting software.

I can control one strip of LED pixels from Vixen using this code in the Arduino loop() function;

          Serial.readBytes((char*)leds, NUM_LEDS * 3);//buffer to store things in, length (number of bytes to read)
          FastLED.show();//refresh the pixel LED's

I can also control a relay (or multiple relays) for the conventional lights using this code;

#define CHANNEL_01 7 //Pin #7 on the Arduino Mega board

   void setup()
    {
      // Begin serial communication
      Serial.begin(BAUD_RATE);
      #define CHANNEL_COUNT 1 

    int channels[] = {CHANNEL_01}
    int incomingByte[16];
    // Define baud rate. This figure must match that of your profile configuration in Vixen!
    #define BAUD_RATE 9600 


      // Set up each channel as an output
      for(int i = 0; i < CHANNEL_COUNT; i++)
      {
        pinMode(channels[i], OUTPUT);
      }
    }

void loop()
{
  if (Serial.available() >= CHANNEL_COUNT)
  {
    // Read data from Vixen, store in array
    for (int i = 0; i < CHANNEL_COUNT; i++)
    {
      incomingByte[i] = Serial.read();
    }
    // Write data from array to a pin on Arduino
    for (int i = 0; i < CHANNEL_COUNT; i++)
    {
      digitalWrite(channels[i], incomingByte[i]);
    }
  }
}

The problem is that I cannot do both of these things. I can either assign the 150 bytes of LED data to the LED strip and it works fine, OR, I can run the relays and they work fine. I have not been able to figure out how to chop up the bytes from the serial data and send it to the appropriate pin. For example, maybe I want to control a relay using pin 7 and a strip of LED pixels using pin 6.

The strip of pixel LED's consumes the first 150 bytes of data from the serial data. But how can I get the next one byte that controls a relay that turns on and off the conventional christmas light string? The byte that controls the light string would be the 151'st in the serial data. Is there a way to specify the 151'st byte? Serial.read() does nothing more than read the first byte (I think). How can a user iterate through the bytes of serial data and select only the ones they want?

2

2 Answers

0
votes

When you do the Serial.readBytes((char*)leds, NUM_LEDS * 3); you read the first 150 bytes, assuming you have 50 LEDs. So the next byte pending in the serial buffer would be the 151'st byte, therefore if you call Serial.read() after Serial.readBytes((char*)leds, NUM_LEDS * 3); you would get that byte. Note that you can use one byte to controle 8 relays if you want, one bit per relay, by using bitRead() An example.

bool relayState[8];

Serial.readBytes((char*)leds, NUM_LEDS * 3);

byte relays = Serial.read();

for(byte i=0;i<8;i++){
  relayState[i] = bitRead(relays, i);
}

for(byte i=0;i<8;i++) {
  digitalWrite(relay[i], relayState[i]);
}

Then a value of 1 would turn on relay 0, a value of 2 would turn on relay 1, a value of 3 would turn on relay 0 and relay 1, etc.

0
votes

To solve this problem I bought an Arduino Uno to run the standard (non-LED) lights separate from the LED lights which run off an Arduino MEGA 2560. The non-LED lights are run on one controller in the Vixen Lights software. The controller has 4 outputs (channels), one for each of the non-LED light sets. Each channel will control one line on a solid state relay. The Arduino Uno runs the relays using this code;

#define PIN1 7 //Pin number seven
#define PIN2 6 //Pin number six
#define PIN3 5 //Pin number five
#define PIN4 4 //Pin number four

#define BAUD_RATE 9600 //just running 4 relay switches so we don't need much speed
#define CHANNEL_COUNT 4 //there are 4 channels coming from the Vixen controller

int bt[4]; //a variable we will use in the loop section of code
int x; //another variable we will use in the loop section of code

void setup() {
    delay(1000); //a little delay to give Uno some time on startup
    Serial.begin(BAUD_RATE); //set the baud rate of the serial stream
    pinMode(PIN1, OUTPUT); //set the four pins on the Arduino Uno to output
    pinMode(PIN2, OUTPUT);
    pinMode(PIN3, OUTPUT);
    pinMode(PIN4, OUTPUT);

}

void loop() {
    if (Serial.available() >= CHANNEL_COUNT) { 
        for (X = 0; x < CHANNEL_COUNT; x++) { //for every channel...
            bt[x] = Serial.read(); //we read a byte from the serial stream buffer and store it in an array for later use
        }

        digitalWrite(PIN1, bt[0]);  //we tell the pins on the arduino what to do... 
        digitalWrite(PIN2, bt[1]);  //using the array of integers that holds the byte values from the serial stream...
        digitalWrite(PIN3, bt[2]); 
        digitalWrite(PIN4, bt[3]);

    }   

}

The LED's run off a second controller in the Vixen Lights software. I have two 12 volt, 50 pixel LED strips of type WS2811. The Arduino uses the FastLED library that can be downloaded for free from FastLED.io. What I found was that there is one byte of garbage data that comes in the serial stream for the LED strips and I had to move past that byte of data in order for the LED's to receive the correct bytes of data to control their color, position etc. I use this code to run my LED's off the Arduino MEGA 2560;

#include <FastLED.h> //include the FastLED library in the Arduino project
#define LED_PIN1 7 //I am going to run one strip of 50 LEDs off of pin 7 on the MEGA
#define LED_PIN2 6 //I am going to run a second strip of 50 LEDs off of pin 6 on the MEGA
#define BAUD_RATE 115200 
#define NUM_LEDS 50

//It took me some time to figure out that my two pixel strips are set 
//to different color codes. Why? I don't know, but they are.  
#define RGB_ORDER RGB //one of my pixel strips is set to use RGB color codes
#define BRG_ORDER BRG //the second strip came from the factory with BRG color codes

#define LED_TYPE WS2811 //what type of LEDs are they? Mine are WS2811, yours may be different.

//create an array to hold the FastLED CRBG code for each of the 50 pixels in the 
//first strip.
CRGB leds1[NUM_LEDS]; 

//create another array to hold the FastLED CRBG codes for each of the 50 pixels in 
//the second strip.
CRGB leds2[NUM_LEDS]; 

int g; //a variable we will use in the loop section

int bufferGarbage[1]; //THIS IS THE KEY TO MAKING THIS WHOLE THING WORK. WE NEED TO 
 //GET PAST THE FIRST MYSTERY BYTE THAT IS SENT TO THE ARDUINO MEGA FROM THE VIXEN 
 //LIGHTS SOFTWARE. So we create a variable we will use in the loop section of code. 

void setup() {
    delay(1000);
    Serial.begin(BAUD_RATE);
    pinMode(LED_PIN1, OUTPUT); //set our pins to output. PIN1 is pin 6 on the Arduino board.
    pinMode(LED_PIN2, OUTPUT); //set our pins to output. PIN2 is pin 7 on the Arduino board.

     //This line sets up the first pixel strip to run using FastLED
    FastLED<LED_TYPE, LED_PIN1, RGB_ORDER>(leds1, NUM_LEDS).setCorrection(TypicalLEDStrip); 

    //This line sets up the second pixel strip to run using FastLED
    FastLED<LED_TYPE, LED_PIN2, BRG_ORDER>(leds2, NUM_LEDS).setCorrection(TypicalLEDStrip); 
}

void loop() {
    if (Serial.available() >= 0) { //if there is data in the serial stream
           //bufferGarbage is to capture the first byte of garbage that comes across.
           //Without this the LED's are out of sync. 
           //In my case if I didn't capture this byte the first pixel on my 
           //second LED strip would match the color code that should be on the last 
           //pixel of the first strip. We don't do anything with this byte.
           //but we need to read it from the serial stream so we can move to the 
           //next byte in the stream.
           bufferGarbage[0] = Serial.read();  

        //then we need to populate the leds1 array so FastLED can tell the pixels what to do.
        //We have 50 pixels in the strip and each pixel has a CRGB property that uses 
        //a red, green, and blue attribute. So for each LED we need to capture 3
        //bytes from the serial stream. 50 LEDs * 3 bytes each means we need to read
        //150 bytes of data from the serial stream.
        for (g = 0; g < NUM_LEDS; g++) {
            Serial.readBytes( ( char*)(&leds1[g], 3);
        }
        for (g = 0; g < NUM_LEDS; g++) {//then we read the next 150 bytes for the second strip of LEDs
            Serial.readBytes( ( char*)(&leds2[g], 3);
        }

        FastLED.show(); //then we tell FastLED to show the pixels!

    }
}