Clueless. Expanding on existing code! (Serial Lighting and manual overrides)

Hello All

This code is being run on 1 of 10 arduinos, controlling 320 relays on a Monster Truck.

The standard code takes input from Vixen 3 (Light Control Software) via serial, and does the relevant outputs.

Additionally on this particular arduino I need two additional functions, and I suck at writing additional code, as I'm an auto sparky by trade.

Feature 1:) If serial data is coming in, turn output on. (used for status monitor in cab)

Feature 2:) If input is high, turn output on. (These are used for manual overrides for work lighting / strobes etc whilst not in show mode). I am taking 12v inputs down to 5v using an optoisolator board to sense the input. eBay Link to Optoisolators

The code base has been borrowed from DIY Christmas forum and works perfectly. I've initialled my edits in the comments with DS.

I'm not going to lie, I've tried reading various pages and guides and coming up blank. Can someone help me out.

cheers

// 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 32

 // 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 1000
 
 // If the relays turn On and Off opposite to Vixen sequence, change "#define MODE NOT_INVERTED" for "#define MODE INVERTED"
 #define NOT_INVERTED 0
 #define INVERTED 1
 #define MODE INVERTED

 // 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
// Up to here for Arduino uno.
 #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
 
 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};

 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
 for (i=0; i < CHANNEL_COUNT; i++){
    pinMode(channels[i], OUTPUT);
  }
// DS ATTEMPTING TO SETUP INPUT PIN MODES
pinMode(2, INPUT); // SWITCHING OUTPUT PIN 33
pinMode(3, INPUT); // SWITCHING OUTPUT PIN 34
pinMode(4, INPUT); // SWITCHING OUTPUT PIN 35
pinMode(5, INPUT); // SWITCHING OUTPUT PIN 36
pinMode(6, INPUT); // SWITCHING OUTPUT PIN 37
pinMode(7, INPUT); // SWITCHING OUTPUT PIN 38
pinMode(8, INPUT); // SWITCHING OUTPUT PIN 30
pinMode(9, INPUT); // SWITCHING OUTPUT PIN 31&32



// 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.
  Serial.begin(VIXEN_COM_SPEED);
}

void loop()
{
   if (Serial.available() >= (CHANNEL_COUNT+2)) {
     wdt_reset(); // resets the watchdog
     timer_a = millis (); // new line
     int uno = Serial.read();
     if (uno == 126){
       
       int dos = Serial.read();
       if (dos == 33){

   
         for (i=0; i < CHANNEL_COUNT; i++) {
             // read each byte
          incomingByte[i] = Serial.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);
      }
 // DS Setting Switch modes for output. Additional lines for other switches needing added.
     }
if (digitalRead(8) == HIGH)
{digitalWrite(30, LOW);
}
       }
     }

     //DS Setting relay output for Green indicator
      if (Serial.available() >= (CHANNEL_COUNT+2)) 
        digitalWrite (channels[CH16], LOW); }
   }

   
// Random mode code. Random mode starts if no serial input has been received in TIME_OUT millisenconds
   else {
     wdt_reset(); // resets the watchdog
     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, 2);
         if (random_a == 0) {
           digitalWrite(channels[i], LOW);
         }
         else {
           digitalWrite(channels[i], HIGH);
         }
       }
     }
   }
}

void testSequence(){

if (MODE == NOT_INVERTED) {
 for (i=0; i < CHANNEL_COUNT; i++){
   wdt_reset(); // resets the watchdog
   digitalWrite(channels[i], HIGH);
   delay (500);
   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);
   }
 }
}

Feature 1:) If serial data is coming in, turn output on. (used for status monitor in cab)

Turn what output on?

Feature 2:) If input is high, turn output on.

Which input should drive which output?

Can someone help me out.

With what? The code does something that may, or may not, be what you want.

Hi Paul

Quote
Feature 1:) If serial data is coming in, turn output on. (used for status monitor in cab)
Turn what output on?

In setup

// DS ATTEMPTING TO SETUP INPUT PIN MODES
pinMode(2, INPUT); // SWITCHING OUTPUT PIN 33
pinMode(3, INPUT); // SWITCHING OUTPUT PIN 34
pinMode(4, INPUT); // SWITCHING OUTPUT PIN 35
pinMode(5, INPUT); // SWITCHING OUTPUT PIN 36
pinMode(6, INPUT); // SWITCHING OUTPUT PIN 37
pinMode(7, INPUT); // SWITCHING OUTPUT PIN 38
pinMode(8, INPUT); // SWITCHING OUTPUT PIN 30
pinMode(9, INPUT); // SWITCHING OUTPUT PIN 31&32

and in the loop I have done this:

 // DS Setting Switch modes for output. Additional lines for other switches needing added.
     }
if (digitalRead(8) == HIGH)
{digitalWrite(30, LOW);
}

The Serial status part I have done the following:

     //DS Setting relay output for Green indicator
      if (Serial.available() >= (CHANNEL_COUNT+2)) 
        digitalWrite (channels[CH16], LOW); }
   }

The bit I need help with is that none of it gives me any reaction at all on my relays. If I was getting odd results I could work through it. Im thinking either my code is crap (likely) and/or I have inserted it into a place I shouldn't have (also likely)

DuncanS:
and in the loop I have done this:

 // DS Setting Switch modes for output. Additional lines for other switches needing added.

}
if (digitalRead(8) == HIGH)
{digitalWrite(30, LOW);
}

I am not sure if that will actually do what you want it to, but for what i think you want to do, a hardware solution (another relay connected directly to the override switch) might be much more straightforward and more what you actually want on a car.

DuncanS:
The Serial status part I have done the following:

     //DS Setting relay output for Green indicator

if (Serial.available() >= (CHANNEL_COUNT+2))
        digitalWrite (channels[CH16], LOW); }
  }

is definitely in the wrong spot and should be near the start of the function when the same test is executed, by the time you do it the second time all serial bytes have been read, and the condition will nearly always return false unless vixen sends new data before this data has been fully processed, but then you are actually testing the update rate which is not what you want. Just turning the LED on is also not going to give you a visual expression of what you want, so i suggest.
within loop()

void loop()
{
  static bool ledpin=LOW;  // or false 
  if (Serial.available() >= (CHANNEL_COUNT+2)) {
     wdt_reset(); // resets the watchdog
     ledpin=!ledpin;  
     digitalWrite (channels[CH16], ledpin);  // is that really writing to the right pin ?
     timer_a = millis (); // new line
     int uno = Serial.read();
     if (uno == 126){

DuncanS:
The bit I need help with is that none of it gives me any reaction at all on my relays. If I was getting odd results I could work through it. Im thinking either my code is crap (likely) and/or I have inserted it into a place I shouldn't have (also likely)

i figure a bit of both, but mainly your explanation of what you want really sucks ! (sorry)

Apologies regarding the sucky explanations! My brain doesn't translate this project well onto text.

The serial monitor is one part of a two part system. On the dashboard there are two green lights, one for main power coming into the "brain" (the box housing all the relays and arduinos) and the second one I want to indicate when the system is "show ready" i.e Vixen3 is connected, and the arduinos are recieving data.

The eight switches are for controlling auxiliary work lighting, strobes for site movement etc. I already have all these lights integrated as part of the Vixen3 show system, but I would like to be able to control these functions without having to boot the laptop. Normally I would just do this with diodes and relays, but I just don't have any physical space left, and with plenty of spare software controlled relays, it made sense to attempt to integrate them!

DuncanS:
On the dashboard there are two green lights, one for main power coming into the "brain" (the box housing all the relays and arduinos) and the second one I want to indicate when the system is "show ready" i.e Vixen3 is connected, and the arduinos are recieving data.

And this second light is connected to the pin referenced by channels[CH16] ? Is that connected via a relay (active high or low ?) ? maybe the best solution would be in this case to do a timeout on the reception of the next Vixen 'frame'

void loop()
{
  static uint32_t timeout=millis(); 
  if (milllis()-timeout>1000) {   // meaning no reception for a second
    digitalWrite (channels[CH16], HIGH);
  }
  if (Serial.available() >= (CHANNEL_COUNT+2)) {
     wdt_reset(); // resets the watchdog
     timeout=millis(); // reset the timeout for the light  
     digitalWrite (channels[CH16], LOW);  // assuming active-low
     timer_a = millis (); // new line
     .... etc etc

Try if that works for the light.

Hi All

Apologies for the slow reply. Not been able to get to the truck for a week or so as its been nuts at work. I've just tried that code, and whilst it compiles fine I'm not seeing any output from it. I have checked the channel assignment, checked the state high/low and checked the relays are outputting in random mode (which they are) Any further thoughts?

Well the code was just for lighting up the dashlight if you are receiving frames of data from vixen, doesn't it do that ? try setting the built-in LED on pin 13 (also available as LED_BUILTIN ) and swap the polarity (meaning where it is set HIGH now set it LOW and vice versa.

void loop()
{
  static uint32_t timeout=millis(); 
  if (milllis()-timeout>1000) {   // meaning no reception for a second
    digitalWrite (13, LOW);
  }
  if (Serial.available() >= (CHANNEL_COUNT+2)) {
     wdt_reset(); // resets the watchdog
     timeout=millis(); // reset the timeout for the light  
     digitalWrite (13, HIGH);  // assuming active-low
     timer_a = millis (); // new line
     .... etc etc

Assuming that you aren't using that pin for anything else.