Nested if or some other conditional mechanism

I am using my Arduino to control a two post auto lift in my home garage. Because of the close quarters I need to make sure the garage door is down (via a prox sensor) and the limit switch for the overhead is not tripped (via a prox sensor). But in certain cases I would like to bypass the garage door prox sensor using a bypass button. There are also a series of lights to indicate when the pro xes are good (defined as door prox true and the overheight prox false) and when the bypass is pressed and a buzzer that only will buzz when the up button is pressed and the overheight prox is reading true. Here is a list of inputs and outputs:

//Inputs

Input 1 - Digital: Up Button
Input 2 - Digital: Bypass Button)
Input 3 - Digital: Overhead Door Prox Sensor (Reads true when door is down)
Input 4 - Digital: Overheight Prox Sensor (Reads False when vehicle is too high)

//Outputs

Output 1 - Digital: Lift relay to send power to the lift to raise it
Output 2 - Digital: All Systems Good led
Output 3 - Digital: Fault Light
Output 4 - Digital: Bypass Active Light
Output 5 - Digital: Fault Buzzer

I am wondering what is the best convention to use for accomplishing my task. Nested if statements, Case, etc.... and what is the best way to organize these statements. There are 16 possible scenarios (combinations of buttons and sensors).

For your safety and probably safety of others, I hope you don't use the "delay" command in your code.
if you have a limit switch already on the lift, interface with it. for a bypass you can always wire a relay to cut the sensor signal using a button near the MCU.

Here is one way you might accomplish what you want.

if ( Input1 && Input2 && !Input3 && Input4 ) 
  {
    //do stuff
  }
else if ( !Input1 && Input2 && Input3 && Input4 )
  {
    //do other stuff
  }

and so on

Thanks TF68, I suppose thats the way I was leaning but didnt know if there was a better way. It will end up being an if statement, followed by 14 else if statements and then an else statement. Will this reevaluate constantly for changes in the states?

cspearsall:
Will this reevaluate constantly for changes in the states?

Yes, if it's in the 'loop()' function and there's no 'blocking' code like 'delay()' to slow it down.

cspearsall:
Thanks TF68, I suppose thats the way I was leaning but didnt know if there was a better way. It will end up being an if statement, followed by 14 else if statements and then an else statement. Will this reevaluate constantly for changes in the states?

Don't use the else statement here, it will only complicate the code and there is no need. Each if is triggered on a unique set of conditions so just use a straight if.

The other way to do it is to build up a four bit number from the four logic states and then use a switch statement, but I am not sure there is much advantage to doing this.

There is no down button?

@Grumpy_Mike - I am not sure what exactly you mean by only use if statements. I am including code here. If you can elaborate and maybe show me an example as to how to simplify then I'd be glad to try it.

@aarg - Hydraulic vehicle lifts have no down button. Down is controlled manually by a bleed valve that uses gravity to lower the vehicle back to the ground.

#include "Ultrasonic.h"
#include <LiquidCrystal.h>
int clearance;            //remaning distance from top of vehicle to top of lift

//Inputs

int upButton = 1;          //Input 1 - Digital:Up Button
int bypassButton = 6;      //Input 2 - Digital: Bypass Button)
int doorSensor = 9;        //Input 3 - Digital: Overhead Door Prox Sensor
int heightLimitSensor = 10;  //Input 4 - Digital: Overheight Prox Sensor
Ultrasonic ultrasonic(7,8);  //Input 5 - Analog: Lift height Measurement via Ultrasonic Distance Measurement Sensor

//Outputs

int upRelay = 13;            //Output 1 - Digital: Lift relay to send power to the lift to raise it
int goodLed = 14;            //Output 2 - Digital: All Systems Good led
int faultLed = 15;           //Output 3 - Digital: Fault Light
int bypassLed = 16;          //Output 4 - Digital: Bypass Active Light
int faultBuzzer = 17;        //Output 5 - Digital: Fault Buzzer
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);   //Output 6 - Digital: Dot Matrix Screen


void setup() {
	//Inputs
	pinMode(upButton, INPUT);
	pinMode(bypassButton, INPUT);
	pinMode(doorSensor, INPUT);
	pinMode(heightLimitSensor, INPUT);
	pinMode(heightMeasurementSensor, INPUT);

	//Outputs

	pinMode(upRelay, OUTPUT);
	pinMode(goodLed, OUTPUT);
	pinMode(faultLed, OUTPUT);
	pinMode(bypassLed, OUTPUT);
	pinMode(faultBuzzer, OUTPUT);
  	pinMode(clearanceDisplay, OUTPUT);
 
	//Initialize LCD
	lcd.begin(16, 2);
	lcd.print("Starting...");
	}

void loop() 
{	
	//Lcd Range Write
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Pearsall Lift");
    lcd.setCursor(0, 1);
    lcd.print("Distance: ");
    lcd.print(ultrasonic.Ranging(CM));
    lcd.print("cm");
	
	//16 Cases for combinations of sensors and buttons
	if ( upButton && bypassButton && doorSensor && heightLimitSensor ) //Case 1
   	{
       digitalWrite(upRelay, HIGH);
       digitalWrite(goodLed, HIGH);
       digitalWrite(faultLed, LOW);
       digitalWrite(bypassLed, HIGH);
       noTone(faultBuzzer);
  	}
   	else if ( upButton && bypassButton && doorSensor && !heightLimitSensor ) //Case 2
    {
       digitalWrite(upRelay, LOW);
       digitalWrite(goodLed, LOW);
       digitalWrite(faultLed, HIGH);
       digitalWrite(bypassLed, HIGH);
       tone(faultBuzzer, 30000);
  	}
   	else if ( upButton && bypassButton && !doorSensor && heightLimitSensor ) //Case 3
    {
       digitalWrite(upRelay, HIGH);
       digitalWrite(goodLed, LOW);
       digitalWrite(faultLed, HIGH);
       digitalWrite(bypassLed, HIGH);
       tone(faultBuzzer, 30000);
  	}
   	else if ( upButton && bypassButton && !doorSensor && !heightLimitSensor ) //Case 4
    {
       digitalWrite(upRelay, LOW);
       digitalWrite(goodLed, LOW);
       digitalWrite(faultLed, HIGH);
       digitalWrite(bypassLed, HIGH);
       tone(faultBuzzer, 30000);
  	}
   	else if ( upButton && !bypassButton && doorSensor && heightLimitSensor ) //Case 5
    {
       digitalWrite(upRelay, HIGH);
       digitalWrite(goodLed, HIGH);
       digitalWrite(faultLed, LOW);
       digitalWrite(bypassLed, LOW);
       noTone(faultBuzzer);
  	}
   	else if ( upButton && !bypassButton && doorSensor && !heightLimitSensor ) //Case 6
    {
       digitalWrite(upRelay, LOW);
       digitalWrite(goodLed, LOW);
       digitalWrite(faultLed, HIGH);
       digitalWrite(bypassLed, LOW);
       tone(faultBuzzer, 30000);
  	}
   	else if ( upButton && !bypassButton && !doorSensor && heightLimitSensor ) //Case 7
    {
       digitalWrite(upRelay, LOW);
       digitalWrite(goodLed, LOW);
       digitalWrite(faultLed, HIGH);
       digitalWrite(bypassLed, LOW);
       tone(faultBuzzer, 30000);
  	}
   	else if ( upButton && !bypassButton && !doorSensor && !heightLimitSensor ) //Case 8
    {
       digitalWrite(upRelay, LOW);
       digitalWrite(goodLed, LOW);
       digitalWrite(faultLed, HIGH);
       digitalWrite(bypassLed, LOW);
       tone(faultBuzzer, 30000);
  	}
   	else if ( !upButton && bypassButton && doorSensor && heightLimitSensor ) //Case 9
    {
       digitalWrite(upRelay, LOW);
       digitalWrite(goodLed, HIGH);
       digitalWrite(faultLed, LOW);
       digitalWrite(bypassLed, HIGH);
       noTone(faultBuzzer);
  	}
   	else if ( !upButton && bypassButton && doorSensor && !heightLimitSensor ) //Case 10
    {
       digitalWrite(upRelay, LOW);
       digitalWrite(goodLed, LOW);
       digitalWrite(faultLed, HIGH);
       digitalWrite(bypassLed, HIGH);
       noTone(faultBuzzer);
  	}
   	else if ( !upButton && bypassButton && !doorSensor && heightLimitSensor ) //Case 11
    {
       digitalWrite(upRelay, LOW);
       digitalWrite(goodLed, LOW);
       digitalWrite(faultLed, HIGH);
       digitalWrite(bypassLed, HIGH);
       noTone(faultBuzzer);
  	}
   	else if ( !upButton && bypassButton && !doorSensor && !heightLimitSensor ) //Case 12
    {
       digitalWrite(upRelay, LOW);
       digitalWrite(goodLed, LOW);
       digitalWrite(faultLed, HIGH);
       digitalWrite(bypassLed, HIGH);
       noTone(faultBuzzer);
  	}
   	else if ( !upButton && !bypassButton && doorSensor && heightLimitSensor ) //Case 13
    {
       digitalWrite(upRelay, LOW);
       digitalWrite(goodLed, HIGH);
       digitalWrite(faultLed, LOW);
       digitalWrite(bypassLed, LOW);
       noTone(faultBuzzer);
  	}
   	else if ( !upButton && !bypassButton && doorSensor && !heightLimitSensor ) //Case 14
    {
       digitalWrite(upRelay, LOW);
       digitalWrite(goodLed, LOW);
       digitalWrite(faultLed, HIGH);
       digitalWrite(bypassLed, LOW);
       noTone(faultBuzzer);
  	}
   	else if ( !upButton && !bypassButton && !doorSensor && heightLimitSensor ) //Case 15
    {
       digitalWrite(upRelay, LOW);
       digitalWrite(goodLed, LOW);
       digitalWrite(faultLed, HIGH);
       digitalWrite(bypassLed, LOW);
       noTone(faultBuzzer);
  	}
   	else //Case 16
    {
       digitalWrite(upRelay, LOW);
       digitalWrite(goodLed, LOW);
       digitalWrite(faultLed, HIGH);
       digitalWrite(bypassLed, LOW);
       noTone(faultBuzzer);
  	}
}
if ( upButton && bypassButton && doorSensor && heightLimitSensor )

All those variables are never going to change because they are the pin numbers NOT the value on the pin numbers.
So first you have to read the values on them:-

int upValue = digitalRead(upButton);
// and so on for the others

I am not sure what exactly you mean by only use if statements.

just relplace:-

else if ( upValue && bypassValue && doorValue && !heightLimitValue ) //Case 2

with simply

if ( upValue && bypassValue && doorValue && !heightLimitValue ) //Case 2

On the other hand using:-

int state = (upValue<<3) | (bypassValue<<2) | (doorValue << 1) | heightLimitValue;
switch(state){
 case 0:
// do case 0 stuff
break;
case 1:
// do case 1 stuff
break;
.......

// and so on
}

@Grumpy_Mike - I feel like an idiot :o I should know better. Revised code coming

@Grumpy_Mike - sorry for all the questions but can I set the pins and variables all in one statement. It doesn't make sense to me to set a name for the pin then another name for the value it will return. Could I just do this:

int upButton = digitalRead(1);

It doesn't make sense to me to set a name for the pin then another name for the value it will return

Why ever not?

@AWOL - Obviously I am missing something judging by your question. Should I set them both or can I just set the variable for the pins output. What am I missing?

cspearsall:
@Grumpy_Mike - sorry for all the questions but can I set the pins and variables all in one statement. It doesn't make sense to me to set a name for the pin then another name for the value it will return. Could I just do this:

int upButton = digitalRead(1);

You could apart from three points:-

  1. Using pins 0 & 1 is not a good idea as those pins are used for serial communication.
  2. The whole point about using a name is that it gives a meaning to what you are reading. So what do you prefer 6 or upButton.
  3. By defining a name you only have to change the one line that defines that name if you want to change the pin instead of trying to find everywhere you have used it.
  4. (no one expects the Spanish inquisition) You have to remember what pin reads what switch and in three months you will have forgotten the association.

@Grumpy_Mike - Great points...changing the code again..

  1. Do the digital reads need to happen in the Loop so they can be reread each time through to check for any changes in state?
  2. I changed the pin for #1 to a different pin, but have left pin #2 as part of the LCD until I get the LCD backpack and then wil only need to use two pins. At that point all the pins will change as I will be down to few enough to use an UNO instead of a Mega.

@aarg - thanks for the prompting...I def didn't think about all the impacts like setting the pinMode etc....or the impact of changing pins and having to redo a LOT of code

BTW: All of you guys are great, I really appreciate all of the help

  1. Do the digital reads need to happen in the Loop so they can be reread each time through to check for any changes in state?

Yes.

  1. I changed the pin for #1 to a different pin, but have left pin #2 as part of the LCD until I get the LCD backpack and then wil only need to use two pins. At that point all the pins will change as I will be down to few enough to use an UNO instead of a Mega.

Do you know you can use the analogue pins as digital pins?

@Grumpy_Mike - I did not!!! That is awesome...Inputs and Outputs? That changes things quite a bit for me

Edit: I found the info...you can use them just like the digital I/O pins!! That is great