If OR condition tracking

Hi, Thanks for taking a look at my post.

I have some complex conditions in my if statements and I was wondering if there is a way to output what condition passed when using OR in if statements?

at a basic level, this is what I am trying to achieve.

if (condition_1 || condition_2 || condition_3){

  Serial.println(   the condition that passed the if statement   );

}

At the moment I am just printing out all the variables belonging to the if statement and tracing back from there to see what condition passed but this is time-consuming and as my code gets bigger and more complex if or statements get added it will become very difficult to keep track.

Any advice is welcome.

Thank you.

Hi
How about using switch() instead of if?
RV - mineirin

bool c_1 = condition_1;
bool c_2 = condition_2;
bool c_3 = condition_3;
if (c_1 || c_2 || c_3){

  if (c_1) Serial.println("1st condition that passed the if statement");
  if (c_2) Serial.println("2nd condition that passed the if statement");
  if (c_3) Serial.println("3rd condition that passed the if statement");

}
1 Like

@PaulRB not quite, as C/C++ has short circuit evaluation.

If c_1 triggers the execution of the body, c_2 may well be true but did not pass the if statement.


bool c_1 = condition_1;
bool c_2 = condition_2;
bool c_3 = condition_3;
if (c_1 || c_2 || c_3){

  if (c_1) Serial.println("1st condition passed the if statement");
  else if (c_2) Serial.println("2nd condition passed the if statement");
  else if (c_3) Serial.println("3rd condition passed the if statement");
}

a7

@alto777 quite true, but even your refinement does not make the code behave exactly as the original in all circumstances. In the original, if condition_1 is true, condition_2 and _3 are not evaluated. In both our versions, all 3 are always evaluated, and any side-effects of those evaluations will always occur, unlike in the original. For example the conditions might compare one variable to another and apply ++ or -- to one variable.

But judging by the question, I think short circuit evaluation and side-effecting are a little beyond @staroflaw 's experience at this point. They need to build up their basic coding skills at the moment, and the effects we are discussing will make more sense when they encounter them for the first time in their own code.

I missed that or you are wrong. Something to test. If/else shouldn't run on after an if is true... no caffeine yet, but that's my claim.

Besides in this exact case the conditions are byte various that do not, but I tots was not thinkinking about side effect of evaluations.

a7

What I meant was: both our codes evaluate all 3 "conditions" in advance, and assign the results to 3 bool variables. I agree that the if() should not check the second or third bool variables if the first bool variable is true. But at that point, all 3 "conditions" have been previously evaluated.

Oh that's what you meant. 'K.

a7

Thank you for taking the time to look at my question and give some examples, much appreciated.

I may have given a too basic example of my if statement.
This is one of the smaller if statements I am currently using.

if ( (micros() - start_t >= timeout_t) || (trip_count >= trip_threshold) || (low_count, >= low_threshold) || (high_count >= high_threshold) ){
}

    // Debug - Print out all variables to check what passed the if statement.
    Serial.printf("Adc: %d, %d uSec, Low: %d, High: %d, Loop: %d, Trip: %d \n", adc_val, end_t, low_count, high_count, loop_count +1, trip_count);

    // Do other things......

}

I did consider doing something like @alto777 suggested but was worried it was wasting clock cycles? and am sure it could be done more elegantly.

int pass_code = 0;

if (micros() - start_t >= timeout_t) {
    pass_code = 1;
}else if (trip_count >= trip_threshold) {
    pass_code = 2;
} else if (low_count >= low_threshold) {
    pass_code = 3;
} else if (high_count >= high_threshold) {
    pass_code = 4;
}

if (pass_code >> 0){
    
    // Debug - Print out pass_code
    Serial.println(pass_code);

    // Do other things......

}

So if I understand what your both saying correctly, using else if will still check the other conditions even if the first one is true?

No. I think we agree that the if/else will not go further in evaluating the conditions than it has to.

As for time/efficiency, there is nothing to worry about, either way of expressing a short circuit in the sequential evaluations will take about the same time.

Writing it out if/else might be more clear explicit. But most ppl do know about short circuit logic.

a7

Shift 'pass_code' right by zero bits?

...but you didn't say what should happen if more than one condition is true...

Haha, that's OK here, but good eye.

a7

C/C++ IDE really needs a "did you mean [this instead]?" feature. :slight_smile:

 || (low_count, >= low_threshold) ||

Was that comma supposed to be there?

if (pass_code >> 0){

Was that >> supposed to be > ? (>> means bit-shift-right!)

Correct, in theory. The code I and @alto777 posted might waste cycles that could have been avoided. From your original question, it did not sound like you were experienced enough to be aware of such things! The solution you are now proposing could prevent those wasted cycles.

In practice, in your example above, the second and third criteria are so trivial to evaluate that it will probably make no difference. But in an example where the second and third criteria are more complex, your method could definitely save some cycles.

(>> means bit-shift-right!) - Never even thought of that. The IDE was happy so I just accepted it but thanks for pointing that out as I need to be more aware.

@PaulRB No the comma wasn't supposed to be there it was a typo. Well spotted tho, you all have keen eyes :slight_smile:

Still a huge amount to learn and I didn't want to come across as more experienced than I was so I tried to keep it simple, just didn't really give enough information for the help I needed. But I got there in the end.....

My objective is to test various gauges of nichrome/other wire to see how long and what current it takes to blow. This is a stripped-down function I have so far. The ADC takes about 65uS to complete each cycle and for now that's fine as I can play with that once my code runs as expected. Once the wire has blown (detected by trip_threshold) it should go into (if (pass_code > 0){) and output various information and depending on the pass_code eventually pass to other functions for more testing.

void runTest(){

    // Setup
    unsigned long timeout_t = 10000;  // 10,000uS - 10mS
    int a_pin = ADC_1, f_pin = debug_pin;
    int loop_count, low_count, high_count, trip_count = 0;
    int low_threshold = 250, high_threshold = 251, trip_threshold = 3;
    int buffer[160];  // buffer to store ADC readings
    int pass_code = 0;

    // Enable FET pin
    digitalWrite(f_pin, HIGH);

    // set start time
    unsigned long start_t = micros();

    // Start loop
    int x=0; while (x==0){

        // read ADC
        int adc_val = analogRead(a_pin);

        if (adc_val >= high_threshold) {high_count++; trip_count = 0;}
        if (adc_val <= low_threshold) {low_count++; trip_count++;}

        // save to buffer
        buffer[loop_count] = adc_val;

        if (micros() - start_t >= timeout_t) {
            pass_code = 1;
        } else if (trip_count >= trip_threshold) {
            pass_code = 2;
        } else if (high_count >= 15){
            pass_code = 3;
        } else if (low_count >= 15){
            pass_code = 4;
        }

        if (pass_code > 0){

            // Disable FET pin
            digitalWrite(f_pin, LOW);

            // Debug - Print out pass_code
            Serial.println(pass_code);

            // print buffer content
            for (int i=0; i<=loop_count; i++){
                Serial.printf("%d, ", buffer[i]);
                if (i==loop_count) {Serial.println("\n");}
            }

            // end while loop
            x=1;

        }        

        // increase loop count
        loop_count++;

    }
}

I will test what I have so far when I get home and see how it behaves. As always I really appreciate all the help and time you have all taken to help me.

    // Start loop
    int x=0; while (x==0){
            ... your code...
            // end while loop
            x=1;
        }        

Well that is a bit of do nothing. It always runs once. Why any loop at all then?

The while loop keeps polling the ADC and checking the results against the if statements until one of the conditions is met or a timeout is reached. Then x=1 stops the while loop and allows the function to end. The while loop runs approx 150 times before timeout is reached or less if one of the other conditions is met.

If/when the time comes that you need non-blocking code, runTest can (easily?) be changed into a routine that is meant to be called very frequently.

To do its job (or nothing) one step at a time and perhaps return a value that indicates whether pass_code did in fact end up letting something else happen and maybe even why.

a7

Why not just make it a 'while( pass_code == 0 ) {' ?

... since that is the actual logic that you are testing...