This works and it shouldn't! I 'd really like to know why (switch/ case)

Hello,

I’d really appreciate it if somebody would be kind enough to help me with this. It all works great, but as far as I can see it shouldn’t…

I have four “analog ins” being read on an UNO (being used as digital inputs) and that works well.
Depending on those four inputs, a “Switch/Case” command runs the relevant bit of code - and that seems to work okay too- at the moment just turning LEDs on and off to test the code (it will do other stuff later).

What I want to happen is the “case” to “break” as soon as the case variable (cntrl) changes - instead of carrying on with the “for” loop.

I can get it to do this brilliantly but with wrong sign???
Shouldn’t it “break” with the != (not equals) and not the == sign?
It only breaks out with the == sign.

Can somebody kindly explain what I am completely missing here.

…and I apologise for the formatting in advance…
…and I apologise for not doing this in the proper/most logical/sensible/easy way etc.

Thanks.

Here’s the code…

switch (cntrl) {

case 1: // Red Sequence when case variable ‘cntrl’ == to decimal number ‘1’.

Serial.print(“case is Red”); Serial.println(cntrl);

for (int i=0; i<20; i++)
{digitalWrite(3, HIGH);
delay(50);
digitalWrite(3, LOW);
delay (50);

if (cntrl == 1){break;} // check for change in ‘cntrl’. THIS SHOULD BE “NOT EQUAL TO” but it don’t work that way???
}
break;

case 2: // Green Sequence

Serial.print(“case is Grn”); Serial.println(cntrl);

for (int i=0; i<20; i++)
{digitalWrite(5, HIGH);
delay(50);
digitalWrite(5, LOW);
delay (50);

if (cntrl == 2){break;}// check for change in ‘cntrl’
}

break;

case 3: // Blue Sequence

Serial.print(“case is Blue”); Serial.println(cntrl);

for (int i=0; i<20; i++)
{digitalWrite(6, HIGH);
delay(50);
digitalWrite(6, LOW);
delay (50);

if (cntrl == 3){break;}// check for change in ‘cntrl’}
}

break;

case 4: // White Sequence

Serial.print(“case is Red”); Serial.println(cntrl);

for (int i=0; i<20; i++)
{digitalWrite(9, HIGH);
delay(50);
digitalWrite(9, LOW);
delay (50);
if (cntrl = 4){break;}// check for change in ‘cntrl’
}

break;

}

Codes tags? Full code?

What's the point inside a case testing the variable that you already know is the same as the current case?

Because the variable 'cntrl' can (and will) change when the relevant case is running through its loop or whatever. This was the easiest way I could think to "trap" a change in the case variable and go back to the switch in order to get straight to the new "correct" case.

..or don't it work like that??

Because the variable 'cntrl' can (and will) change when the relevant case is running through its loop or whatever.

I'm not sure what you mean, but then, I can't see your code.

The variable called "cntrl’ after the word “switch” directs the sketch to the relevant “case”.

The code in the relevant “case” runs . In there , there is a loop and eventually a lot of other stuff.

If the variable “cntrl” changes while that case is running, I want the to break out of the loop immediately- and not when the loop (or whatever other stuff is in the “case”) has done it’s thing and “breaks” at the end.

I need to “break” as soon as the variable “cntrl” has changed, and not necessarily at the end of the case.

here is the code with just the first case…

switch (cntrl) {

case 1: // Red Sequence when case variable ‘cntrl’ == to decimal number ‘1’.
Serial.print(“case is Red”); Serial.println(cntrl);

for (int i=0; i<20; i++)
{digitalWrite(3, HIGH);
delay(50);
digitalWrite(3, LOW);
delay (50);

if (cntrl == 1){break;}// check for change in ‘cntrl’. THIS SHOULD BE “NOT EQUAL TO” but it don’t work that way???
}
break;

switch (cntrl) {

  case 1: 
...  some other stuff 
 if (cntrl == 1){break;}// How could cntrl have any value other than 1 here? So why test it?

(did you see how I used code tags there? You could do that too. You could also post all your code)

I’m sorry about all this but it just looks like just another font??
I literally cut and pasted from the IDE?? I will attach the whole sketch as it stands but I know it’s badly written.

It’s called case “1” (then 2,3,4,5…) because the variable called “cntrl” is literally returning a number 1 or 2 or 3 etc…

It all works beautifully.

The thing is though, surely the == should be !=. Meaning that it “breaks” out of the for loop if the variable “cntrl” that WAS equal to 1 is NOW not equal to 1 but say 4…

If I replace the == with !=, it runs to the end of the case… but why?

Thanks for your help.

Board1M5w.ino (2.11 KB)

I truly do not comprehend how such a simple thing as “post your code, use code tags” is so hard to understand.

/*
 Control Board 1 Master for Arduino UNO
PWM on  pins 3 5 6 9 10 and 11

4 bit Control Input pins uing analog input A0, A1, A2, A3 (14 - 17)

 */



int ledPin[] = {2,3,4,5,6,7,8,9,10,11,12,13,};//14,15,16,17}; // initialise pins

//------------------------------
 void setup() 
{
   
   DDRC= B00000000; //set analog pins to input using a 'port' command

    for (int i =0;i<13;i++)
   {pinMode(ledPin[i], OUTPUT);  // set pins as outputs 
  digitalWrite(ledPin[i], LOW);} // sets pins low 
 
 Serial.begin(9600);
}
//---------------------------------------------------------------

void loop()         
{
  int cntrl=(PINC); //cntrl = the 'PINC" read value of the analog inputs 1-4
 
  //Serial.println(PINC,BIN); // serial monitor control lines in BIN if reqd
 // Serial.println(cntrl); // serial monitor control lines in Decimal if reqd
  //delay(50);
 


switch (cntrl) {
 
  
  
  case 1: // Red Sequence when case variable 'cntrl' == to decimal number '1'.
   Serial.print("case is Red"); Serial.println(cntrl);

for (int i=0; i<20; i++)
 {digitalWrite(3, HIGH);
 delay(50);
 digitalWrite(3, LOW);
 delay (50);
 
 if (cntrl == 1){break;}// check for change in 'cntrl'. THIS SHOULD BE "NOT EQUAL TO" but it don't work that way?????
 }
 break;
 
 
  case 2: // Green Sequence 
   Serial.print("case is Grn"); Serial.println(cntrl);

for (int i=0; i<20; i++)
 {digitalWrite(5, HIGH);
 delay(50);
 digitalWrite(5, LOW);
 delay (50);

 if (cntrl == 2){break;}// check for change in 'cntrl'
 }
 
 break;
 
 
  case 3: // Blue Sequence
 Serial.print("case is Blue"); Serial.println(cntrl);

for (int i=0; i<20; i++)
 {digitalWrite(6, HIGH);
 delay(50);
 digitalWrite(6, LOW);
 delay (50);
 
 if (cntrl == 3){break;}// check for change in 'cntrl'}
 }
 
 break;
 
 
 
  case 4: // White Sequence
  Serial.print("case is Red"); Serial.println(cntrl);

for (int i=0; i<20; i++)
 {digitalWrite(9, HIGH);
 delay(50);
 digitalWrite(9, LOW);
 delay (50);  
 if (cntrl = 4){break;}// check for change in 'cntrl'
 }
 
 
 break;
 
}
 
/* case 3:
 case 4:
 case 5:
 case 6:
 case 7:
 case 8:
 case 9:
 case 10:
 case 12:
 case 13:
 case 14:
 case 15:*/





}

Looks like I pissed him right off then... :(

How is cntrl supposed to change?

If the unused pins on port C are not tied LOW or HIGH and left FLOATING, there's no telling what you will read on PINC.

Hey Jimmy that's a bloody good point!

AWOL made it it too but I didn't get it at the time.

Thing is though it does somehow. The way it's written works! If the input lines change, the case immediately changes to the new case after the loop... but not if the != is used.

I really don't know whats going on here...and what you have just pointed out makes it even worse!

jcallen: If the unused pins on port C are not tied LOW or HIGH and left FLOATING, there's no telling what you will read on PINC.

Thanks. No, I can serial read the "cntrl" value and its all good.

Is cntrl a digital 1 or ascii '1' (49)? How is the cntrl variable changed?

Serial.println(cntrl,DEC);

Laserbee: Looks like ...

Yet another user who refuses to read the forum manual (click !). It tells you how to do things, and in this case even gives a very brief reason why (meaning there's more to it). Just read all of that page. You will find a link to it on top in every section of this forum, if you need it to look up things in the future.

Line 94 has an error, the result of that test will always be true. The most obvious problem is already mentioned multiple times.

Hi Tim,

'cntrl' variable is assigned here..

int cntrl=(PINC); //cntrl = the 'PINC" read value of the analog inputs 1-4

PINC is a simultaneous port read of all the analogue inputs and can be read as a binary or decimal number. ie //Serial.println(PINC,BIN); // serial monitor control lines in BIN if reqd // Serial.println(cntrl); // serial monitor control lines in Decimal if reqd

I am using the four lines from another arduino to give me a binary 0 -15 number for controlling and synchronising this and other Arduinos.

Assuming you're inputting 4 bit binary, try:

cntrl = PINC & 0x7; // without the "()"

And fix line 94

MAS3: The most obvious problem is already mentioned multiple times.

..but it doesn't explain what I am seeing.

cntrl = PINC & 0x7; // without the “()”

That only lets 3 bits thru - 0b00000111.
Four bits, use 0x0F

I also don't see how cntl can change during the switch:case if PINC is not read again after the switch starts.