// This code was written by Victor Perez for doityourselfchristmas.com based on the code from Zparticle, Si_champion and Neil Tapp.
// To adapt the code to your case, just change this top section, with the #define lines.
// Includes the watchdog timer library
#include <avr/wdt.h>
// This sets how many channels will vixen be sending. Can be set to any number from 1 to 48 for Arduino Mega, and 1 to 18 for Arduino Uno.
#define CHANNEL_COUNT 36
// speed for the com port for talking with vixen. From 9600 to 115200. Use the same speed as set in Vixen.
#define VIXEN_COM_SPEED 57600
// Timeout waiting for serial input before going to random mode (in milliseconds).
#define TIME_OUT 100
#define MODE_2_SPEED 500
// If the relays turn On and Off opposite to Vixen sequence, change "#define MODE NOT_INVERTED" for "#define MODE INVERTED"
#define NOT_INVERTED 1
#define INVERTED 0
//Change Below
#define MODE NOT_INVERTED
//Switch Mode
#define mode_switch1 7 //GND for ALL ON
#define mode_switch2 8 //GND for slow random
// which pins control which channels
// You can change these assignment to use different pins, but be very careful to not repeat the same pin number for 2 channels.
// DO NOT use pings 0 and 1, as those are for the serial port to talk to the computer.
#define CH01 22
#define CH02 23
#define CH03 24
#define CH04 25
#define CH05 26
#define CH06 27
#define CH07 28
#define CH08 29
#define CH09 30
#define CH10 31
#define CH11 32
#define CH12 33
#define CH13 34
#define CH14 35
#define CH15 36
#define CH16 37
#define CH17 38
#define CH18 39
#define CH19 40
#define CH20 41
#define CH21 42
#define CH22 43
#define CH23 44
#define CH24 45
#define CH25 46
#define CH26 47
#define CH27 48
#define CH28 49
#define CH29 50
#define CH30 51
#define CH31 52
#define CH32 53
#define CH33 02
#define CH34 03
#define CH35 04
#define CH36 05
int channels[] = {CH01,CH02,CH03,CH04,CH05 ,CH06,CH07,CH08,CH09,
CH10,CH11,CH12,CH13,CH14,CH15,CH16,CH17,CH18,CH19,CH20,CH21,CH22,
CH23,CH24,CH25,CH26,CH27,CH28,CH29,CH30,CH31,CH32,CH33,CH34,CH35,CH36};
int incomingByte[CHANNEL_COUNT];
int i = 0; // Loop counter
volatile unsigned long timer_a = 0; // new line
//setup the pins/ inputs & outputs
void setup(){
// enable the watchdog timer with a time of 1 second. If the board freezes, it will reset itself after 1 second.
wdt_enable(WDTO_1S);
// specifically for the UNO
sei();
// initalize PWM Channels / Pins
pinMode(mode_switch1, INPUT_PULLUP); // Connect Pin7 to GROUND for All on, Open for Flicker.
for (i=0; i < CHANNEL_COUNT; i++){
pinMode(channels[i], OUTPUT);
}
pinMode(mode_switch2, INPUT_PULLUP); // Connect Pin8 to GROUND for Mode 1, Open for Flicker.
for (i=0; i < CHANNEL_COUNT; i++){
pinMode(channels[i], OUTPUT);
}
// set all the realys to off to start with
if (MODE == NOT_INVERTED) {
for (i=0; i < CHANNEL_COUNT; i++){
digitalWrite(channels[i], LOW);
}
}
else {
for (i=0; i < CHANNEL_COUNT; i++){
digitalWrite(channels[i], HIGH);
}
}
testSequence();
// set up Serial according to the speed defined above.
Serial3.begin(VIXEN_COM_SPEED);
}
void loop()
{
if (Serial3.available() >= (CHANNEL_COUNT+20)) {
wdt_reset(); // resets the watchdog
timer_a = millis (); // new line
int uno = Serial3.read();
if (uno == 126){
int dos = Serial3.read();
if (dos == 33){
for (i=0; i < CHANNEL_COUNT; i++) {
// read each byte
incomingByte[i] = Serial3.read();
}
if (MODE == NOT_INVERTED) {
for (i=0; i < CHANNEL_COUNT; i++){
int value = incomingByte[i];
if (value <= 127) {
digitalWrite(channels[i], LOW);
}
else {
digitalWrite(channels[i], HIGH);
}
}
}
else {
for (i=0; i < CHANNEL_COUNT; i++){
int value = incomingByte[i];
if (value < 127) {
digitalWrite(channels[i], HIGH);
}
else {
digitalWrite(channels[i], LOW);
}
}
}
}
}
}
// Random mode code. Random mode starts if no serial input has been received in TIME_OUT millisenconds
else {
wdt_reset(); // resets the watchdog
// If the switch is connected to ground, keep all the lights on when Vixen is not running.
///move twinkle here
if (digitalRead (mode_switch1) == LOW) {
//MODE 1 - TWINKLE 1-24
unsigned long diff = millis() - timer_a;
if (diff >= TIME_OUT) {
timer_a = millis ();
int random_a = 0;
for (i=0; i < CHANNEL_COUNT; i++){
random_a = random(0, 20); //(MIN, MAX) sets the odds of hitting 0 to turn channel off
if (random_a == 0) {
digitalWrite(channels[i], LOW);
} else {
digitalWrite(channels[i], HIGH);
}
}
for (i=24; i < 36; i++){ //start at channel 24 and turn on remander up to 36
digitalWrite(channels[i], HIGH);
}
}
} else if (digitalRead (mode_switch2) == LOW){
//MODE2 SLOW RANDOM 1-24
unsigned long diff = millis() - timer_a;
if (diff >= MODE_2_SPEED) {
timer_a = millis ();
int random_a = 0;
for (i=0; i < 24; i++){ //set to max out at channel 24 not 36 (CHANNEL _COUNT)
random_a = random(0, 2); //(MIN, MAX) sets the odds of hitting 0 to turn channel off
if (random_a == 0) {
digitalWrite(channels[i], LOW);
} else {
digitalWrite(channels[i], HIGH);
}
}
for (i=24; i < 36; i++){ //start at channel 24 and turn on remander up to 36
digitalWrite(channels[i], HIGH);
}
}
//FLICKER
} else { // ALL ON
unsigned long diff = millis() - timer_a;
if (diff >= TIME_OUT) {
timer_a = millis ();
if (MODE == NOT_INVERTED) {
for (i=0; i < CHANNEL_COUNT; i++){
wdt_reset(); // resets the watchdog
digitalWrite(channels[i], HIGH);
}
} else {
for (i=0; i < CHANNEL_COUNT; i++){
wdt_reset(); // resets the watchdog
digitalWrite(channels[i], LOW);
}
}
}
}
}
}
void testSequence(){
if (MODE == NOT_INVERTED) {
for (i=0; i < CHANNEL_COUNT; i++){
wdt_reset(); // resets the watchdog
digitalWrite(channels[i], HIGH);
delay (250);
digitalWrite(channels[i], LOW);
}
}
else {
for (i=0; i < CHANNEL_COUNT; i++){
wdt_reset(); // resets the watchdog
digitalWrite(channels[i], LOW);
delay (500);
digitalWrite(channels[i], HIGH);
}
}
}