Difference between revisions of "Arduino and the mechanical relay"

From diychristmas.org wiki
Jump to navigation Jump to search
Line 2: Line 2:
  
 
  <nowiki>
 
  <nowiki>
// *** diychristmas.org free software so long as this line remains in sketch!  
+
// *** diychristmas.org free software so long as this line remains in sketch!
 
// Vixen/xLights "generic" serial mechanical relay sketch
 
// Vixen/xLights "generic" serial mechanical relay sketch
 
//  - Uses digitalWrite as this outputs LOW or HIGH no pwm values
 
//  - Uses digitalWrite as this outputs LOW or HIGH no pwm values
Line 12: Line 12:
 
int channels[] = {2, 3, 4, 5, 6, 7, 8, 10};
 
int channels[] = {2, 3, 4, 5, 6, 7, 8, 10};
  
// Vixen information
+
// Vixen/xLights information
//  - CHANNEL_COUNT is number of channels it will listen for from Vixen
+
// speed for the com port for talking with player
const int CHANNEL_COUNT = 8;
 
// speed for the com port for talking with vixen
 
 
const long SERIAL_COM_SPEED = 115200L;
 
const long SERIAL_COM_SPEED = 115200L;
 
// Generic Serial controller config - must be present, must match controller setup
 
// Generic Serial controller config - must be present, must match controller setup
const int VIXEN_HEADER[3] = {33, 34, 35}; // This is character !"# (hard to replicate in Vixen sequence)
+
const int CONTROLLER_HEADER[3] = {33, 34, 35}; // This is character !"# (hard to replicate in sequencer)
 +
 
 
// Relays
 
// Relays
 
//  - most mechanical relays turn on when pin is low, off on high
 
//  - most mechanical relays turn on when pin is low, off on high
Line 25: Line 24:
  
 
// these are program variables we need to use in multiple places
 
// these are program variables we need to use in multiple places
const int SIZE_OF_HEADER = sizeof(VIXEN_HEADER) / sizeof(int); // no need to change
+
const int SIZE_OF_HEADER = sizeof(CONTROLLER_HEADER) / sizeof(int); // no need to change
 +
const int CHANNEL_COUNT = sizeof(channels) / sizeof(int); // no need to change
 
int buffer[CHANNEL_COUNT]; // no need to change going to hold relay output values
 
int buffer[CHANNEL_COUNT]; // no need to change going to hold relay output values
  
Line 31: Line 31:
 
{
 
{
 
   Serial.begin(SERIAL_COM_SPEED);
 
   Serial.begin(SERIAL_COM_SPEED);
  Serial.write("Setup");
 
  
 
   // set the channel pins to output mode
 
   // set the channel pins to output mode
Line 44: Line 43:
 
void loop()
 
void loop()
 
{
 
{
   waitForVixenHeader(VIXEN_HEADER);
+
   waitForControllerHeader(CONTROLLER_HEADER);
   readFromVixen();
+
   readSequenceData();
 
   outputToLights();
 
   outputToLights();
 
}
 
}
Line 72: Line 71:
 
}
 
}
  
void readFromVixen()
+
void readSequenceData()
 
{
 
{
 
   char buffer2[CHANNEL_COUNT];
 
   char buffer2[CHANNEL_COUNT];
Line 86: Line 85:
 
}
 
}
  
void waitForVixenHeader(int header[])
+
void waitForControllerHeader(int header[])
 
{
 
{
 
   for (int i = 0; i < SIZE_OF_HEADER; i++) {
 
   for (int i = 0; i < SIZE_OF_HEADER; i++) {
 
     // wait for serial available
 
     // wait for serial available
 
     while (!Serial.available()) {}
 
     while (!Serial.available()) {}
     // Check the byte until it matches the VIXEN_HEADER byte
+
     // Check the byte until it matches the CONTROLLER_HEADER byte
 
     int inByte = Serial.read();
 
     int inByte = Serial.read();
     if (inByte != VIXEN_HEADER[i]) {
+
     if (inByte != CONTROLLER_HEADER[i]) {
 
       i = -1; // wrong data set to "zero"
 
       i = -1; // wrong data set to "zero"
 
     }
 
     }
Line 118: Line 117:
 
   turnLightsOff();
 
   turnLightsOff();
 
}
 
}
 +
 
</nowiki>
 
</nowiki>
  

Revision as of 17:54, 1 July 2018

First, here's the program code -- comments follow later!

// *** diychristmas.org free software so long as this line remains in sketch!
// Vixen/xLights "generic" serial mechanical relay sketch
//  - Uses digitalWrite as this outputs LOW or HIGH no pwm values
//  - This is what is needed for a mechanical relay

// Hookup the relay in order of channel definition
// Define as many as you need
// put channels (pins) in an array so we can use looping structures to control
int channels[] = {2, 3, 4, 5, 6, 7, 8, 10};

// Vixen/xLights information
// speed for the com port for talking with player
const long SERIAL_COM_SPEED = 115200L;
// Generic Serial controller config - must be present, must match controller setup
const int CONTROLLER_HEADER[3] = {33, 34, 35}; // This is character !"# (hard to replicate in sequencer)

// Relays
//  - most mechanical relays turn on when pin is low, off on high
const int ON  = LOW;
const int OFF = HIGH;

// these are program variables we need to use in multiple places
const int SIZE_OF_HEADER = sizeof(CONTROLLER_HEADER) / sizeof(int); // no need to change
const int CHANNEL_COUNT = sizeof(channels) / sizeof(int); // no need to change
int buffer[CHANNEL_COUNT]; // no need to change going to hold relay output values

void setup()
{
  Serial.begin(SERIAL_COM_SPEED);

  // set the channel pins to output mode
  for (int channelIndex = 0; channelIndex < CHANNEL_COUNT; channelIndex++) {
    pinMode(channels[channelIndex], OUTPUT);
  }

  turnLightsOff();
  powerOnSelfTest(); // watch your lights to make sure they are all going on in order
}

void loop()
{
  waitForControllerHeader(CONTROLLER_HEADER);
  readSequenceData();
  outputToLights();
}

void turnLightsOff()
{
  //turn them all off
  for (int channelIndex = 0; channelIndex < CHANNEL_COUNT; channelIndex++) {
    digitalWrite(channels[channelIndex], OFF);
  }
}

void outputToLights()
{
  for (int channelIndex = 0; channelIndex < CHANNEL_COUNT; channelIndex++) {
    // we should only be seeing 255 and 0 but in case someone tried a fade
    // 48 is used for debug purposes. You can use the serial monitor to test
    // send this string !"#01010101 to turn on every other relay as 0 == dec(48) 1 == dec(49)
    if (buffer[channelIndex] > 48) {
      digitalWrite(channels[channelIndex], ON);
    }
    else {
      digitalWrite(channels[channelIndex], OFF);
    }
  }
}

void readSequenceData()
{
  char buffer2[CHANNEL_COUNT];
  int index = 0;

  while (Serial.available() < CHANNEL_COUNT) {}
  // We have enough data!
  for (int i = 0; i < CHANNEL_COUNT; i++) {
    int inByte = Serial.read();
    buffer[i] = inByte;
    Serial.write(inByte);
  }
}

void waitForControllerHeader(int header[])
{
  for (int i = 0; i < SIZE_OF_HEADER; i++) {
    // wait for serial available
    while (!Serial.available()) {}
    // Check the byte until it matches the CONTROLLER_HEADER byte
    int inByte = Serial.read();
    if (inByte != CONTROLLER_HEADER[i]) {
      i = -1; // wrong data set to "zero"
    }
  }
  // found the header!
}

// powerOnSelfTest - does a couple of checks to make sure everything turns on and off
//  - watch your lights, they should go on in order
void powerOnSelfTest()
{
  // This routines turns on and off each relay in order
  for (int channelIndex = 0; channelIndex < CHANNEL_COUNT; channelIndex++) {
    digitalWrite(channels[channelIndex], ON); // turn on one channel at a time
    delay(2000);
    digitalWrite(channels[channelIndex], OFF);
  }
  // This routines turns on each relay in order leaving them all on for .5 seconds
  for (int channelIndex = 0; channelIndex < CHANNEL_COUNT; channelIndex++) {
    digitalWrite(channels[channelIndex], ON); // all on test
    delay(500); // wait .5 seconds
  }
  delay(2000); // slight pause to check all on
  turnLightsOff();
}


Let's talk about the code... At the top of the sketch, you will find the definitions of how you are going to use the Arduino with Vixen, xLights or any other serial output. These things are self explanatory but for the "I've never seen an Arduino or Vixen setup" people, here is another try to explain them.

Things you might have to change

int channels[] = {2, 3, 4, 5, 6, 7, 8, 10};

This line assigns pins from the arduino to specific "channels". The order of definition is the order the pins will be turned on or off. In your software, you would assign channel one to Shrub1, channel two to Shrub2, etc. This is done in the element to controller mapping in Vixen or in model definition in xLights. You will need to map these through the Arduino pins to the specific relay on your relay board and out to the lights. It might look like this:

Description Channel Pin Relay
Shrub1Left 1 2 In1
Shrub2 2 3 In2
Shrub3 3 4 In3
Shrub4Right 4 5 In4
Post1Left 5 6 In5
Post2 6 7 In6
Post3 7 8 In7
Post4Right 8 10 In8


const int CHANNEL_COUNT = 8; const long SERIAL_COM_SPEED = 115200L; const int VIXEN_HEADER[3] = {33, 34, 35}; const int ON = LOW; const int OFF = HIGH;