Help with multiple functions controlling one output

Im having a very hard time figuring out whats wrong with a piece of code. I have multiple functions that can control a variable frequency drive. 2 of the 3 functions work correctly while the third does not. If I take the tablesaw function out of the program the jointer function works but with the tablesaw function in it seams the VFD output is being turned on and off everytime through the code. The LED on the 16 channel relay is lit but I think because of the cycling the VFD does not turn on.

Here are the 3 functions

void tablesaw(){


  if (TSIState == LOW){
    if(BIState == HIGH){
      if(CBIState == HIGH){
        if(JLIState == HIGH){
          if(PLIState == HIGH){
            if(DPIState == HIGH){
              if(SHIState == HIGH) {
           

   unsigned long currentTSMillis = millis();
    digitalWrite(DC, LOW);
    digitalWrite(TS, LOW);
    if (currentTSMillis - TimerTSON >= 1000){
    digitalWrite(VFD, LOW);
    TimerPLOFF = millis();
    TimerJLOFF = millis();
    TimerTSOFF = millis();
    TimerCBOFF = millis();
    TimerDPOFF = millis();
    TimerBOFF = millis();
    TimerSHOFF = millis();
       }
       }
       }
       }
       }
       }
       }
  }

  else if (DPIState == LOW){
    if(JLIState == LOW){
     if(CBIState == LOW){
        if(BIState == LOW){
         if(SHIState == LOW){
          if(PLIState == LOW){
        }
        }
        }
        }
        }
  }



  else {
    digitalWrite(VFD, HIGH);
    unsigned long currentTSMillis = millis();
    if (currentTSMillis - TimerTSOFF >= 5000){
    digitalWrite(DC, HIGH);
    }
    if (currentTSMillis - TimerTSOFF >= 30000){
    digitalWrite(TS, HIGH);
    TimerTSON = millis();
  }
  }
}
  


 


void jointer(){
    
  if (JLIState == LOW){
    if(PLIState == HIGH){
      if(DPIState == HIGH){
        if(CBIState == HIGH){
          if(BIState == HIGH){
            if(SHIState == HIGH){
              if(TSIState == HIGH) {
                
    // turn Planer relay on and Turn on Inverter
    unsigned long currentJLMillis = millis();
    digitalWrite(DC, LOW);
    digitalWrite(JL, LOW);
    if (currentJLMillis - TimerJLON >= 1000){
    digitalWrite(VFD, LOW);
    TimerPLOFF = millis();
    TimerJLOFF = millis();
    TimerTSOFF = millis();
    TimerCBOFF = millis();
    TimerDPOFF = millis();
    TimerBOFF = millis();
    TimerSHOFF = millis();
    
    }
    }
    }
    }
    }
    }
    }
  }
   
  
  
  else if (DPIState == LOW){
    if(PLIState == LOW){
      if(CBIState == LOW){
        if(BIState == LOW){
          if(SHIState == LOW){
            if(TSIState == LOW){
      }
      }
      }
      }
      }
  }
  else {
    digitalWrite(VFD, HIGH);
    unsigned long currentJLMillis = millis();
    if (currentJLMillis - TimerJLOFF >= 5000){
    digitalWrite(DC, HIGH); 
    }
    if (currentJLMillis - TimerJLOFF >= 20000){
    digitalWrite(JL, HIGH);
    TimerJLON = millis();
  
  }
  }
}

void planer(){

  if (PLIState == LOW){
   if(DPIState == HIGH){
     if(JLIState == HIGH){
      if(CBIState == HIGH){
        if(BIState == HIGH){
           if(SHIState == HIGH){
            if(TSIState == HIGH) {
        
    // turn Planer relay on and Turn on Inverter
    unsigned long currentPLMillis = millis();
    digitalWrite(DC, LOW);
    digitalWrite(PL, LOW);
    if (currentPLMillis - TimerPLON >= 1000){
    digitalWrite(VFD, LOW);
    TimerPLOFF = millis();
    TimerJLOFF = millis();
    TimerTSOFF = millis();
    TimerCBOFF = millis();
    TimerDPOFF = millis();
    TimerBOFF = millis();
    TimerSHOFF = millis();
      }
      }
      }
      }
      }
      }
      }
  }
    
  else if (DPIState == LOW){
    if(JLIState == LOW){
      if(CBIState == LOW){
        if(BIState == LOW){
          if(SHIState == LOW){
          if(TSIState == LOW){
        }
        }
        }
        }
        }
  }
  else {
    digitalWrite(VFD, HIGH);
    unsigned long currentPLMillis = millis();
    if (currentPLMillis - TimerPLOFF >= 5000){
     digitalWrite(DC, HIGH); 
    }
    if (currentPLMillis - TimerPLOFF >= 20000){
    digitalWrite(PL, HIGH);
    TimerPLON = millis();
  
  }
  }
}

I think that the this part of the code is causing the VFD to be turned back off the LED on the 16 channel relay is lit but the VFD does not turn on (if I put a jumper across the terminals on the relay the VFD comes on). The tablesaw function works correctly.

  else {
    digitalWrite(VFD, HIGH);
    unsigned long currentTSMillis = millis();
    if (currentTSMillis - TimerTSOFF >= 5000){
    digitalWrite(DC, HIGH);
    }
    if (currentTSMillis - TimerTSOFF >= 30000){
    digitalWrite(TS, HIGH);
    TimerTSON = millis();

I also left all the tablesaw code and and just commented out //digitalWrite(VFD, HIGH); in the else statement and the jointer code works... so this tells me the code is running the else statement in the tablesaw code but I dont think it should be..

I have this part in so that if any of the functions are being called for it should skip the final else statement in each function.

  else if (DPIState == LOW){
    if(JLIState == LOW){
     if(CBIState == LOW){
        if(BIState == LOW){
         if(SHIState == LOW){
          if(PLIState == LOW){
        }
        }
        }
        }
        }
  }

Any help is greatly appreciated Im tired of banging my head against the wall. Its probably something silly I just cant find it.

Thanks

I'm not sure what your problem is. But I can tell you that having a dense nested block of if's that do absolutely nothing, is not helping your case.

Perhaps you are confused about how the if statement works. That could definitely throw a monkey wrench in your logic.

else if (DPIState == LOW) {
  if (JLIState == LOW) {
    if (CBIState == LOW) {
      if (BIState == LOW) {
        if (SHIState == LOW) {
          if (PLIState == LOW) {
          }
        }
      }
    }
  }
}

By the way, the compiler has an optimizer that will look at this code, probably understand that it does nothing, and just throw it away as if it doesn't exist.

I think you are using cascaded 'if' statements to implement a logical AND. That doesn't work quite the same, especially if you use 'else' clauses. For example:

  else if (DPIState == LOW) {
    if (JLIState == LOW) {
      if (CBIState == LOW) {
        if (BIState == LOW) {
          if (SHIState == LOW) {
            if (TSIState == LOW) {
            }
          }
        }
      }
    }
  }
  else {

works the same as

  else if (DPIState == LOW) {
  }
  else {

I suspect you want:

  else if (DPIState == LOW && JLIState == LOW && CBIState == LOW && 
   BIState == LOW && SHIState == LOW) && TSIState == LOW) {
 }
 else {

and similar for other cascaded 'if' statements.

Ironically, he did it that way before, and was advised to change to nested ifs in this thread.

aarg:
Ironically, he did it that way before, and was advised to change to nested ifs in this thread.

Exactly, I started a new thread since I was asking different questions, i got the debounce working... I want the && operator I will put it back in and try for the else if. Maybe there is a completely different way I should be doing this?

Actually I want ||

else if (DPIState == LOW || PLIState == LOW || JLIState == LOW || CBIState == LOW || BIState == LOW || SHIState == LOW){

thats how I used to have it. Maybe leave the first If statements nested and the else if statements with the || operator?

Sorry for all the newbie questions I am still very new to programming.

The nesting is a form of AND. If you want OR (||) the nesting is even more wrong.

There is almost certainly a better way to do it but without seeing all of the code and knowing how the hardware works it is hard to make a guess about what you intended. For example if only one of these "state" inputs is HIGH at any time you could use a number to represent which input is HIGH. If multiple inputs can be HIGH you can encode up to eight inputs into a single byte and use masking and comparison to test any combinations you need to act on.

@ ScottDamman, why didn't you just continue with your other Thread so that everyone can see all the information?

...R

If you indent your code carefully it is much easier to make sense of it and spot errors - for example

void tablesaw(){

    if (TSIState == LOW){
        if(BIState == HIGH){
            if(CBIState == HIGH){
                if(JLIState == HIGH){
                    if(PLIState == HIGH){
                        if(DPIState == HIGH){
                            if(SHIState == HIGH) {
                                unsigned long currentTSMillis = millis();
                                digitalWrite(DC, LOW);
                                digitalWrite(TS, LOW);
                                if (currentTSMillis - TimerTSON >= 1000){
                                    digitalWrite(VFD, LOW);
                                    TimerPLOFF = millis();
                                    TimerJLOFF = millis();
                                    TimerTSOFF = millis();
                                    TimerCBOFF = millis();
                                    TimerDPOFF = millis();
                                    TimerBOFF = millis();
                                    TimerSHOFF = millis();
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    else if (DPIState == LOW){
        if(JLIState == LOW){
            if(CBIState == LOW){
                if(BIState == LOW){
                    if(SHIState == LOW){
                        if(PLIState == LOW){
                        }
                    }
                }
            }
        }
    }
    else {
        digitalWrite(VFD, HIGH);
        unsigned long currentTSMillis = millis();
        if (currentTSMillis - TimerTSOFF >= 5000){
            digitalWrite(DC, HIGH);
        }
        if (currentTSMillis - TimerTSOFF >= 30000){
            digitalWrite(TS, HIGH);
            TimerTSON = millis();
        }
    }
}

It does not seem to me to make sense to have the test if(DPIState == HIGH){ 5 layers down in the first section and then have else if (DPIState == LOW){ at the top of the next section. Why wouldn't it be at the top of both sections?

You should use a single value of millis() for all of TimerPLOFF to TimerSHOFF in case the value changes while you are updating all the variables.

The whole business seems extraordinarily complex. Can it not be greatly simplified?

All those things like BIState and CBIState may mean something to you but they are completely meaningless to me. And I suspect they will be a problem for you in 6 months from now.

...R

Does look like the situation where there are a number of exclusive alternatives, not separate boolean states...

Perhaps the OP could explain what all those variables represent?

With such complex logic, I would abandon the algorithmic implementation, and use tables instead. I also believe that the variable names are confusing.

Sorry for starting 2 thread I thought it would keep things separated since I was asking more question.

So what I am trying to do,

I have 7 woodworking machines that require 3 phase power, to run them when there is no 3 phase available a rotary phase converter can be used of a variable frequency drive. In this case I am using the arduino to allow 1 VFD to run all of the machines albeit 1 at a time.

So how I think the program should work,

a switch at each machine coming to the inputs on the arduino. When I need to use a machine I flip the switch at that machine. The arduino then turns on a low voltage relay (16 channel relay board) that powers a larger 3 phase relay connecting the specified machine to the VFD. After waiting 1 sec for the relay to close, the arduino sends another output for the VFD to turn on, this is on another of the 16 channel relays. The arduino also turns on the dust collection when it turns on the VFD.

The VFD is not powerful enough to run more than 1 machine at a time so I would like it so that the program can only initiate one at a time, now it is just me in the shop but I want to make sure something silly doesnt happen.

When the switch is turned off at the machine that is being used, the arduino disconnects the relay for the VFD control wire and then waits for the motor to come to a stop before disconnecting the 3 phase relay. This is done through a millis timer.

To combat EMI issues caused by the VFD I have added in debounce to the input switches. I also have opto isolators for the inputs just havent put them in yet.

I have been removing parts of code to make it easier to troubleshoot so my code currently only has the Table Saw, Jointer, Planer in it. However the other machines are, Crescent Bandsaw, Oliver Bandsaw, Drill Press, Shaper.

Here is my code, the rest will follow

// Initialize Inputs:
const int DPI = 22; //Drill Press
const int PLI = 23; //Planer
const int JLI = 24; //Jointer
const int CBI = 25; //Crescent Bandsaw
const int BI = 26; //Oliver Bandsaw
const int DCI = 27; //Dust collection
const int ACPI = 28; //Air Compressor
const int TI = 29; //No longer doing transformer on the arduino pin 29 is available 
const int SHI = 30; // Oliver Shaper
const int TSI = 31; // Oliver Table Saw



// Intialize Outputs:
const int AC = 35; // Relay 1 Air Compressor
const int DC = 37; // Relay 2 Dust Collection 
const int DP = 39; // Relay 3 Drill Press
const int PL = 41; // Relay 4 Planer
const int JL = 43; // Relay 5 Jointer
const int CB = 45; // Relay  6 Crescent Bandsaw
const int B = 47; // Relay 7 Oliver Bandsaw
const int VFD = 48; // Relay 16 VFD end switch 
const int SH = 36; // Relay 9 Oliver Shaper
const int TS = 38; // Relay 10 Oliver Table Saw
const int T = 40; // No longer doing transformer on the arduino pin 40 available for output 
const int EStop = 42; // Estop to VFD
const int SLed = 13; // stop function LED


// Variables that will change:
int DPIState = HIGH; // drill press switch state
int ButtonDPIState;
int LastDPIState = HIGH;

int PLIState = HIGH; // planer switch state
int ButtonPLIState;
int LastPLIState = HIGH; 

int JLIState = HIGH; // jointer switch state
int ButtonJLIState;
int LastJLIState = HIGH; 

int CBIState = HIGH; // crescent bandsaw switch state
int ButtonCBIState;
int LastCBIState = HIGH;

int BIState = HIGH; // oliver bandsaw switch state
int ButtonBIState;
int LastBIState = HIGH;

int DCIState = 0; //manual dust collection button


int SHIState = HIGH; // shaper input state
int ButtonSHIState;
int LastSHIState = HIGH;

int TSIState = HIGH; // Table Saw input state
int ButtonTSIState; 
int LastTSIState = HIGH; 

unsigned long TimerDPON = 0;
unsigned long TimerDPOFF = 0;
unsigned long TimerPLON = 0;
unsigned long TimerPLOFF = 0;
unsigned long TimerJLON = 0;
unsigned long TimerJLOFF = 0;
unsigned long TimerCBON = 0;
unsigned long TimerCBOFF = 0; 
unsigned long TimerBON = 0;
unsigned long TimerBOFF = 0;
unsigned long TimerSHON = 0;
unsigned long TimerSHOFF = 0; 
unsigned long TimerTSON = 0;
unsigned long TimerTSOFF = 0;

//Intialize analog signals

unsigned long previousMillis = 0;
unsigned long interval = 10000;



long lastdebounceDPTime = 0;
long lastdebouncePLTime = 0;
long lastdebounceJLTime = 0;
long lastdebounceTSTime = 0; 
long lastdebounceCBTime = 0;
long lastdebounceBTime = 0;
long lastdebounceSHTime = 0;
long debouncedelay = 1000;

void setup(){  
 
//Drive all relays to High to begin
digitalWrite(T, HIGH);
digitalWrite(DC, HIGH);
digitalWrite(AC, HIGH);
digitalWrite(DP, HIGH);
digitalWrite(PL, HIGH);
digitalWrite(JL, HIGH);
digitalWrite(CB, HIGH);
digitalWrite(B, HIGH);
digitalWrite(VFD, HIGH);
digitalWrite(SH, HIGH);
digitalWrite(TS, HIGH);
digitalWrite(SLed, LOW); //Make sure the LED is turned off


// Pin Outputs to Ouputs
pinMode(T, OUTPUT);
pinMode(DC, OUTPUT);
pinMode(AC, OUTPUT);
pinMode(DP, OUTPUT);
pinMode(PL, OUTPUT);
pinMode(JL, OUTPUT);
pinMode(CB, OUTPUT);
pinMode(B, OUTPUT);
pinMode(VFD, OUTPUT);
pinMode(SH, OUTPUT);
pinMode(TS, OUTPUT);
pinMode(SLed, OUTPUT);

  // Pin Inputs to Inputs:
pinMode(DPI, INPUT_PULLUP);
pinMode(PLI, INPUT_PULLUP);
pinMode(JLI, INPUT_PULLUP);
pinMode(CBI, INPUT_PULLUP);
pinMode(BI, INPUT_PULLUP);
pinMode(DCI, INPUT_PULLUP);
pinMode(ACPI, INPUT_PULLUP);
pinMode(TI, INPUT_PULLUP); // transformer input no longer needed for use on the arduino 
pinMode(SHI, INPUT_PULLUP);
pinMode(TSI, INPUT_PULLUP);



}
void loop() 
{


int readingDPI = digitalRead(DPI);
int readingPLI = digitalRead(PLI);
int readingJLI = digitalRead(JLI);
int readingCBI = digitalRead(CBI);
int readingBI = digitalRead(BI);
int readingDCI = digitalRead(DCI);
int readingSHI = digitalRead(SHI);
int readingTSI = digitalRead(TSI);

//Shaper Debounce
if (readingSHI != LastSHIState){
  lastdebounceSHTime = millis();
}
if((millis()-lastdebounceSHTime)>debouncedelay){
  ButtonSHIState = readingSHI;
  SHIState = readingSHI;
}

//Oliver Bandsaw debounce
if (readingBI !=LastBIState){
  lastdebounceBTime = millis();
}
if((millis()-lastdebounceBTime)>debouncedelay){
  ButtonBIState = readingBI;
  BIState = readingBI;
}

//Drill Press Debounce
if (readingDPI !=LastDPIState){
  lastdebounceDPTime = millis();
}
if((millis()-lastdebounceDPTime)> debouncedelay){
  if(readingDPI !=ButtonDPIState){
    ButtonDPIState = readingDPI;
    DPIState = readingDPI;
  }
}

//Planer Debounce
if (readingPLI != LastPLIState){
  lastdebouncePLTime = millis();
}
 if((millis()-lastdebouncePLTime) > debouncedelay){
  if(readingPLI != ButtonPLIState){
    ButtonPLIState = readingPLI;
      PLIState = readingPLI;
 }
 }
LastPLIState = readingPLI;

 //Jointer Debounce
 if (readingJLI !=LastJLIState){
  lastdebounceJLTime = millis();
 }
 if((millis()-lastdebounceJLTime) > debouncedelay){
  if(readingJLI !=ButtonJLIState){
    ButtonJLIState = readingJLI;
      JLIState = readingJLI;
 }
 }
 LastJLIState = readingJLI;
 

//Table Saw Debounce
if (readingTSI != LastTSIState){
  lastdebounceTSTime = millis();
}

if((millis()-lastdebounceTSTime) > debouncedelay){
  if(readingTSI !=ButtonTSIState){
  ButtonTSIState = readingTSI;
  TSIState = readingTSI;
}
}
LastTSIState = readingTSI;

// drillpres();
 planer();
 jointer();
// cbandsaw();
 //obandsaw();
 //shaper();
 tablesaw();
 
}

void tablesaw(){


  if (TSIState == LOW){
    if(BIState == HIGH){
      if(CBIState == HIGH){
        if(JLIState == HIGH){
          if(PLIState == HIGH){
            if(DPIState == HIGH){
              if(SHIState == HIGH) {
           

   unsigned long currentTSMillis = millis();
    digitalWrite(DC, LOW);
    digitalWrite(TS, LOW);
    if (currentTSMillis - TimerTSON >= 1000){
    digitalWrite(VFD, LOW);
    TimerPLOFF = millis();
    TimerJLOFF = millis();
    TimerTSOFF = millis();
    TimerCBOFF = millis();
    TimerDPOFF = millis();
    TimerBOFF = millis();
    TimerSHOFF = millis();
       }
       }
       }
       }
       }
       }
       }
  }

  else if (DPIState == LOW || PLIState == LOW || JLIState == LOW || CBIState == LOW || BIState == LOW || SHIState == LOW){
    
  }

  else {
    digitalWrite(VFD, HIGH);
    unsigned long currentTSMillis = millis();
    if (currentTSMillis - TimerTSOFF >= 5000){
    digitalWrite(DC, HIGH);
    }
    if (currentTSMillis - TimerTSOFF >= 30000){
    digitalWrite(TS, HIGH);
    TimerTSON = millis();
  }
  }
}
  


 


void jointer(){
    
  if (JLIState == LOW){
    if(PLIState == HIGH){
      if(DPIState == HIGH){
        if(CBIState == HIGH){
          if(BIState == HIGH){
            if(SHIState == HIGH){
              if(TSIState == HIGH) {
                
    // turn Planer relay on and Turn on Inverter
    unsigned long currentJLMillis = millis();
    digitalWrite(DC, LOW);
    digitalWrite(JL, LOW);
    if (currentJLMillis - TimerJLON >= 1000){
    digitalWrite(VFD, LOW);
    TimerPLOFF = millis();
    TimerJLOFF = millis();
    TimerTSOFF = millis();
    TimerCBOFF = millis();
    TimerDPOFF = millis();
    TimerBOFF = millis();
    TimerSHOFF = millis();
    
    }
    }
    }
    }
    }
    }
    }
  }
   
  
  
  else if (DPIState == LOW || PLIState == LOW || CBIState == LOW || BIState == LOW || SHIState == LOW || TSIState == LOW){
    
  }
  else {
    digitalWrite(VFD, HIGH);
    unsigned long currentJLMillis = millis();
    if (currentJLMillis - TimerJLOFF >= 5000){
    digitalWrite(DC, HIGH); 
    }
    if (currentJLMillis - TimerJLOFF >= 20000){
    digitalWrite(JL, HIGH);
    TimerJLON = millis();
  
  }
  }
}

void planer(){

  if (PLIState == LOW){
   if(DPIState == HIGH){
     if(JLIState == HIGH){
      if(CBIState == HIGH){
        if(BIState == HIGH){
           if(SHIState == HIGH){
            if(TSIState == HIGH) {
        
    // turn Planer relay on and Turn on Inverter
    unsigned long currentPLMillis = millis();
    digitalWrite(DC, LOW);
    digitalWrite(PL, LOW);
    if (currentPLMillis - TimerPLON >= 1000){
    digitalWrite(VFD, LOW);
    TimerPLOFF = millis();
    TimerJLOFF = millis();
    TimerTSOFF = millis();
    TimerCBOFF = millis();
    TimerDPOFF = millis();
    TimerBOFF = millis();
    TimerSHOFF = millis();
      }
      }
      }
      }
      }
      }
      }
  }
    
  else if (DPIState == LOW || JLIState == LOW || CBIState == LOW || BIState == LOW || SHIState == LOW || TSIState == LOW){
    
 }
  else {
    digitalWrite(VFD, HIGH);
    unsigned long currentPLMillis = millis();
    if (currentPLMillis - TimerPLOFF >= 5000){
     digitalWrite(DC, HIGH); 
    }
    if (currentPLMillis - TimerPLOFF >= 20000){
    digitalWrite(PL, HIGH);
    TimerPLON = millis();
  
  }
  }
}

If I understand correctly you have lots of variables that keep track of which machine is using the vfd.
And that is what is causing the long if chain?

How about using just one variable, call it vfdAvailable .

Hutkikz:
If I understand correctly you have lots of variables that keep track of which machine is using the vfd.
And that is what is causing the long if chain?

How about using just one variable, call it vfdAvailable .

Ok after changing the else if statement back to how I originally had it the program works on all the machines and limits the use to just one machine.

However I am very interested to learn and clean up the program so I wont have issues in the future. Any help to that end if very appreciated.

So if I understand you correctly just do the check once to confirm the VFD is available then the IF statements in each function can get alot shorter?

Yes, when you use a machine it marks vfdAvailable =false and when finished marks it =true.
Then when you start another it just needs to check to see if it is available or not.

I think your project actually calls for a statemachine. But that might be a bit much work for now.

Note in advance: I do not exactly understand what all your code is doing (but I understand the nested ifs ;)); so I might have some misunderstanding of what certain parts do.

To simplify your conditions, you can make use of a struct of bitfields and function pointers. I have possibly not based the the below on your latest code, but it should give you the idea.

// flags structure
struct Flags
{
  unsigned int TSIState: 1; // tablesaw
  unsigned int BIState: 1;  // Oliver bandsaw
  unsigned int CBIState: 1; // Crescent bandsaw
  unsigned int JLIState: 1; // jointer
  unsigned int PLIState: 1; // planer
  unsigned int DPIState: 1; // drill press
  unsigned int SHIState: 1; // shaper
  //unsigned int Timer0State: 1;
};

The above defines a structure with 7 bitfields; one for each input. In the code, it will reflect the status of the inputs. Commented out is a bitfield for the state of a timer. Be aware that TSIState is bit 0, BIState bit 1 and so on.

The definition uses an 16 bit variable; you can change to unsigned char if you're sure that that is sufficient for all your flags or to unsigned long if you need space for more.

If you need more flags to reflect the status of inputs and other stuff, it becomes more complicated and the example code does not cater for it; but it can be done.

The below example shows how to access the bit fields (it will not be used later in the code).

// flags structure
struct Flags
{
  unsigned int TSIState: 1; // tablesaw
  unsigned int BIState: 1;  // Oliver bandsaw
  unsigned int CBIState: 1; // Crescent bandsaw
  unsigned int JLIState: 1; // jointer
  unsigned int PLIState: 1; // planer
  unsigned int DPIState: 1; // drill press
  unsigned int SHIState: 1; // shaper
  //unsigned int VFDTimerState: 1;
};

Flags flags = {0, 0, 0, 0, 0, 0, 0};
void setup()
{
  // set one of the flags high
  flags.TSIState = HIGH;

  // print the status of two of the fields
  Serial.begin(9600);
  Serial.println(flags.TSIState, DEC);
  Serial.println(flags.BIState, DEC);
}

It's a bit of a mission to set all flags in one go; you will also not gain anything (compared to your current code with ifs) if you have to compare every single bitfield to check what needs to be done. Hence we add the below union that allows to access the flags in two different ways (either by bitfield as shown above or by char / int / long).

union Status
{
  Flags binary;
  unsigned int decimal;
};

The below code demonstrates both methods of access

// flags structure definition
struct Flags
{
  unsigned int TSIState: 1; // tablesaw
  unsigned int BIState: 1;  // Oliver bandsaw
  unsigned int CBIState: 1; // Crescent bandsaw
  unsigned int JLIState: 1; // jointer
  unsigned int PLIState: 1; // planer
  unsigned int DPIState: 1; // drill press
  unsigned int SHIState: 1; // shaper
  //unsigned int VFDTimerState: 1;
};

// status definition
union Status
{
  Flags binary;
  int decimal;
};


Status statusregister;
void setup()
{

  // clear the status reister and set TSIState
  statusregister.decimal = 0x0001;
  // also set CBIState high
  statusregister.binary.CBIState = 1;


  Serial.begin(9600);
  Serial.print("Status register: ");
  Serial.println(statusregister.decimal, DEC);
  Serial.print("TSIState: ");
  Serial.println(statusregister.binary.TSIState, DEC);
  Serial.print("BIState: ");
  Serial.println(statusregister.binary.BIState, DEC);
  Serial.print("CBIState: ");
  Serial.println(statusregister.binary.CBIState, DEC);
}

To populate the input bitfields, you can use the function below as an example; this does not debounce !

// read input pins and update status register
void updateStatusregister_Inputs()
{
  statusregister.binary.TSIState = digitalRead(TSISTATE);
  statusregister.binary.BIState = digitalRead(BISTATE);
  statusregister.binary.CBIState = digitalRead(CBISTATE);
  statusregister.binary.JLIState = digitalRead(JLISTATE);
  statusregister.binary.PLIState = digitalRead(PLISTATE);
  statusregister.binary.DPIState = digitalRead(DPISTATE);
  statusregister.binary.SHIState = digitalRead(SHISTATE);
}

You can create a similar function to set other flags (e.g. a timer interrupt can set the VFDTimerState).

To be continued (I might have to wait 5 minutes before posting again :()

Next the fun part begins. We're defining a table that contains conditions and functions that will be executed if the condition is satisfied.

// definition of the action table
struct ActionTable
{
  // condition under which we will execute function
  unsigned int condition;
  // function to execute
  void (*myfunc)();
};

The 'complicated' part is the myfunc; this field in the struct will contain the name of a function that can be called as shown below

// flags structure
struct Flags
{
  unsigned int TSIState: 1; // tablesaw
  unsigned int BIState: 1;  // Oliver bandsaw
  unsigned int CBIState: 1; // Crescent bandsaw
  unsigned int JLIState: 1; // jointer
  unsigned int PLIState: 1; // planer
  unsigned int DPIState: 1; // drill press
  unsigned int SHIState: 1; // shaper
  //unsigned int VFDTimerState: 1;
};

union Status
{
  Flags binary;
  int decimal;
};


struct ActionTable
{
  // condition under which we will execute function
  unsigned int condition;
  // function to execute
  void (*myfunc)();
};

Status statusregister;

// tow action table variables
ActionTable action1;
ActionTable action2;

// function 1
void func1()
{
  Serial.println("function 1 called");
}
// function 2
void func2()
{
  Serial.println("function 2 called");
}

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

  // declare an action
  action1.condition = 3;  // if status flags equal 3
  action1.myfunc = func1; //   execute func1
  // execute the function
  action1.myfunc();

  // declare another action
  action2.condition = 0;
  action2.myfunc = func2;
  action2.myfunc();
}

We now have basically all our 'components' in place. We will not use individual actions as in above example but an ActionTable array when implementing the logic.

Your tablesaw function has two different actions; I assume that the one starts the table saw and the other one the VFD (did not analyze that part; it might even do more than just that). First thing to do is to take those out of the tablesaw function.

// start tablesaw
void tsStartTablesaw()
{
  Serial.println("Tablesaw started");
  /*
    unsigned long currentTSMillis = millis();
    digitalWrite(DC, LOW);
    digitalWrite(TS, LOW);
    if (currentTSMillis - TimerTSON >= 1000) {
    digitalWrite(VFD, LOW);
    TimerPLOFF = millis();
    TimerJLOFF = millis();
    TimerTSOFF = millis();
    TimerCBOFF = millis();
    TimerDPOFF = millis();
    TimerBOFF = millis();
    TimerSHOFF = millis();
    }
  */
}

// start VFD (for tablesaw)
void tsStartVFD()
{
  Serial.println("VFD started");
  /*
    digitalWrite(VFD, HIGH);
    unsigned long currentTSMillis = millis();
    if (currentTSMillis - TimerTSOFF >= 5000) {
    digitalWrite(DC, HIGH);
    }
    if (currentTSMillis - TimerTSOFF >= 30000) {
    digitalWrite(TS, HIGH);
    TimerTSON = millis();
    }
  */
}

You also have 4 conditions. If my analysis is correct

S D P J C B T
1 1 1 1 1 1 0   0x7E    // start table saw
0 0 0 0 0 0 x   
{
0 0 0 0 0 0 1   0x01    // do nothing
0 0 0 0 0 0 0   0x00    // do nothing
}
any other condition     // start VFD and DC

We can now set up actions for the tablesaw function and execute them depending on the condition.

void tablesaw() {
  ActionTable actions[3];

  // conditions and functions to call
  actions[0].condition = 0x007E;
  actions[0].myfunc = tsStartTablesaw;  // start table saw
  actions[1].condition = 0x0001;
  actions[1].myfunc = NULL;             // do nothing (table saw already started)
  actions[2].condition = 0x0000;
  actions[2].myfunc = NULL;             // do nothing (table saw already started)

  // the last condition (anything not matching above) will start the VFD and DC

  // assume we no matching condtions
  bool fDoDefault = true;

  // loop though actions
  for (int conditioncnt = 0; conditioncnt < 3; conditioncnt++)
  {
    // if match
    if (statusregister.decimal == actions[conditioncnt].condition)
    {
      // if not 'do nothing'
      if (actions[conditioncnt].myfunc != NULL)
      {
        // call function
        actions[conditioncnt].myfunc();
        // indicate that we did something so no need for default action
        fDoDefault = false;
      }
    }
  }

  // if no match
  if (fDoDefault == true)
  {
    // start VFD and DC
    tsStartVFD();
  }
}

To be continued (will have to wait another five minutes).

The complete code

// http://forum.arduino.cc/index.php?topic=365174.0

// define input pins
#define TSISTATE 14
#define BISTATE 15
#define CBISTATE 16
#define JLISTATE 17
#define PLISTATE 18
#define DPISTATE 19
#define SHISTATE 2
#define VFDSTATE 3

// function prototypes
void updateStatusregister_Inputs();
void updateStatusregister_Timers();

// flags structure
struct Flags
{
  unsigned int TSIState: 1; // tablesaw
  unsigned int BIState: 1;  // Oliver bandsaw
  unsigned int CBIState: 1; // Crescent bandsaw
  unsigned int JLIState: 1; // jointer
  unsigned int PLIState: 1; // planer
  unsigned int DPIState: 1; // drill press
  unsigned int SHIState: 1; // shaper
  //unsigned int VFDTimerState: 1;
};

union Status
{
  Flags binary;
  int decimal;
};

struct ActionTable
{
  // condition under which we will execute function
  unsigned int condition;
  // function to execute
  void (*myfunc)();
};

Status statusregister;

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

  // pin modes
  pinMode(TSISTATE, INPUT_PULLUP);
  pinMode(BISTATE, INPUT_PULLUP);
  pinMode(CBISTATE, INPUT_PULLUP);
  pinMode(JLISTATE, INPUT_PULLUP);
  pinMode(PLISTATE, INPUT_PULLUP);
  pinMode(DPISTATE, INPUT_PULLUP);
  pinMode(SHISTATE, INPUT_PULLUP);

}

void loop()
{
  updateStatusregister_Inputs();
  tablesaw();
  delay(1000);
}

// read input pins and update status register
void updateStatusregister_Inputs()
{
  statusregister.binary.TSIState = digitalRead(TSISTATE);
  statusregister.binary.BIState = digitalRead(BISTATE);
  statusregister.binary.CBIState = digitalRead(CBISTATE);
  statusregister.binary.JLIState = digitalRead(JLISTATE);
  statusregister.binary.PLIState = digitalRead(PLISTATE);
  statusregister.binary.DPIState = digitalRead(DPISTATE);
  statusregister.binary.SHIState = digitalRead(SHISTATE);
}

// check timers and update status register
void updateStatusregister_Timers()
{
  // check all timers
}


// start table saw
void tsStartTablesaw()
{
  Serial.println("Table saw started");
  /*
    unsigned long currentTSMillis = millis();
    digitalWrite(DC, LOW);
    digitalWrite(TS, LOW);
    if (currentTSMillis - TimerTSON >= 1000) {
    digitalWrite(VFD, LOW);
    TimerPLOFF = millis();
    TimerJLOFF = millis();
    TimerTSOFF = millis();
    TimerCBOFF = millis();
    TimerDPOFF = millis();
    TimerBOFF = millis();
    TimerSHOFF = millis();
    }
  */
}

// start VFD (for table saw)
void tsStartVFD()
{
  Serial.println("VFD started");
  /*
    digitalWrite(VFD, HIGH);
    unsigned long currentTSMillis = millis();
    if (currentTSMillis - TimerTSOFF >= 5000) {
    digitalWrite(DC, HIGH);
    }
    if (currentTSMillis - TimerTSOFF >= 30000) {
    digitalWrite(TS, HIGH);
    TimerTSON = millis();
    }
  */
}


void tablesaw() {
  ActionTable actions[3];

  // conditions and functions to call
  actions[0].condition = 0x007E;
  actions[0].myfunc = tsStartTablesaw;  // start table saw
  actions[1].condition = 0x0001;
  actions[1].myfunc = NULL;             // do nothing (table saw already started
  actions[2].condition = 0x0000;
  actions[2].myfunc = NULL;             // do nothing (table saw already started

  // the last condition (anything not matching above) will start the VFD and DC

  // assume we no matching condtions
  bool fDoDefault = true;

  // loop though actions
  for (int conditioncnt = 0; conditioncnt < 3; conditioncnt++)
  {
    // if match
    if (statusregister.decimal == actions[conditioncnt].condition)
    {
      // if not 'do nothing'
      if (actions[conditioncnt].myfunc != NULL)
      {
        // call function
        actions[conditioncnt].myfunc();
        fDoDefault = false;
      }
    }
  }

  // if no match
  if (fDoDefault == true)
  {
    // start VFD and DC
    tsStartVFD();
  }

}

You can implement the functions for other equipment yourself :wink:

Note:
All your functions contain a part to (as far as I understand it) start the VFD and DC; they are slightly different but the basics are the same. Try to create a generic function for that and call that one everywhere where default needs to be executed (tablesaw, planer, ...); but as I stated, I'm not quite sure if I fully comprehend what your trying to do in that part of your code.

Other note:
the input pins are chosen by me and do not necessarily reflect your setup!
// Edit:
This complete code compiles but I have not tested on an Arduino.

Hutkikz:
How about using just one variable, call it vfdAvailable .

That, I like.

I frequently (always?) find when I work on some code problem that the effective solution is simpler.

Then there could be a small function for each machine that would only trigger the relay for that machine if appropriate.

void tableSaw() {
   if (tableSawSelected == true) {   // operator has pressed button to start saw 
                       //   best if it is a momentary switch, not a latching switch
                       //   or maybe there could be a buzzer to warn of two switches on at the same time
      if (vfdAvailable == true) {
         vfdAvailable = false;
         // turn on machine
      }
   }
}

and there could be a simple function to check if all the machines are off. It would need all the IF statements.

void checkMachineStatus() {
    if (tableSaw == OFF) {
      if (planer == OFF) {
         //etc
         vfdAvailable = true;
      }
    }
}

...R