Arduino and the mechanical relay

From diychristmas.org wiki
Revision as of 19:51, 21 June 2018 by MikeKrebs (talk | contribs) (Add code to page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
// 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 information
//  - CHANNEL_COUNT is number of channels it will listen for from Vixen
const int CHANNEL_COUNT = 8;
// speed for the com port for talking with vixen
const long VIXEN_COM_SPEED = 115200L;
// 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)
// 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(VIXEN_HEADER) / sizeof(int); // no need to change
int buffer[CHANNEL_COUNT]; // no need to change going to hold relay output values

void setup()
{
  Serial.begin(VIXEN_COM_SPEED);
  Serial.write("Setup");

  // 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()
{
  waitForVixenHeader(VIXEN_HEADER);
  readFromVixen();
  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 readFromVixen()
{
  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 waitForVixenHeader(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 VIXEN_HEADER byte
    int inByte = Serial.read();
    if (inByte != VIXEN_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();
}