Late night switch case confusion

We are not trying to annoy you, we are trying to figure out what you want and why your sketch works even if you do not set LEDstate...

One of the things is: you keep shouting that it works perfectly fine with // break;
And indeed: it does what you want.
But only because you do not really use the switch case...

Our conclusion:
You do not understand the idea behind switch case...
And in this case you may be better off with your if else....
You could do the if else before the switch to set LEDstates. But that makes only sense if you have code to be handled for the different cases.

Try adding a print statement for LEDstates so you can see it change (if it does) during operation.

Yes. The first line creates a type named LEDStates. You then need to declare variables of that type to use the enum, shown here with an initial value also provided:

LEDStates myLEDState = OFF;

I did not read the rest of your problem description.

When presenting code, it will draw more eyes if it is in any of several common formats, one easy way to do this is to apply the IDE Auto Format tool.

If you wanna roll with your own style, format a copy of the sketch every time you post it anew. But these adherences to common style are for reasons, it would be best if you adopted one.

After some time, the formatting will live in your elbows. I can't type a '+' without automatically typing next a space, for example.

a7

The reason it works with the break commented out is because without the break the code just runs through all the cases as if the switch statement wasn't there. It's called "falling through".

When you put the break in, then it will only run whichever case matches what is in the LEDStates variable that you are switching on. Since nothing ever sets that to anything other than 0, only case 0 will run.

Without the break statement it runs case 0 and then falls through to case 1 and case 2. If that's what you want to happen then the switch is redundant as you are running all of the code all of the time.

A switch case is for when you want to run different pieces of code depending on the value of a variable. Since your variable never changes value, it only ever runs the one case.

Here is a "switch/case" to lend a hand.

void setup() {
  randomSeed(analogRead(A0)); // create a more-random sequence
  Serial.begin(300); // relive 1985
}

void loop() {
  byte mosquitoes = random(3);  // random value 0 to 2
  switch (mosquitoes) {
    case (0): Serial.print(0); break; // value was 0
    case (1): Serial.print(1); break; // value was 1
    default: Serial.print(2); break; // default action (including "2")
  }
  delay(250);
}
1 Like

I remember using a cassette tape to save/load programmes at 300 Baud.

.....and 8 kiloBytes of RAM.

That was my "new" MODEM... I had to disable the speaker because it picked up the local AM radio station.

Hi Delta. Yeah that became apparent to me after a while. I realized the switch basically wasn't doing anything but adding extra words to the program I wrote and the if's within the cases were just doing their things. I'm having a hard time working out in my mind why people say switch/case is better then if/else when it looks (at least from my perspective now) that they do the exact same thing. I was kind of hung up on trying to learn how to use the switch/case to make better code, but it seems like it makes no difference over if/else.

There is no "better" (if/then // switch/case). It all depends on the program. For example, your program, no if/then/switch/case...

#define ledpinRed 13
#define ledpinGrn 12
#define ledpinBlu 14

#define buttonRed 2
#define buttonGrn 4
#define buttonBlu 5

int pin[3][2] = { // array of "int"s called "pin" with three (color) rows and two (pins) columns
  {ledpinRed, buttonRed}, // pin[0][0], pin [0][1]
  {ledpinGrn, buttonGrn}, // pin[1][0], pin [1][1]
  {ledpinBlu, buttonBlu}  // pin[2][0], pin [2][1]
};

void setup() {
  for (int i = 0; i < 3; i++) { // three colors
    pinMode(pin[i][0], OUTPUT); // LED pins
    pinMode(pin[i][1], INPUT_PULLUP); // button pins
  }
}

void loop() {
  for (int i = 0; i < 3; i++) {
    digitalWrite(pin[i][0], !digitalRead(pin[i][1])); // read a pin, light an LED
  }
}
diagram.json tab for wokwi.com
{
  "version": 1,
  "author": "Anonymous maker",
  "editor": "wokwi",
  "parts": [
    { "type": "wokwi-arduino-nano", "id": "nano", "top": 4.8, "left": -19.7, "attrs": {} },
    {
      "type": "wokwi-led",
      "id": "led1",
      "top": -51.6,
      "left": -92.2,
      "attrs": { "color": "red" }
    },
    {
      "type": "wokwi-led",
      "id": "led2",
      "top": -51.6,
      "left": -73,
      "attrs": { "color": "green" }
    },
    {
      "type": "wokwi-led",
      "id": "led3",
      "top": -51.6,
      "left": -53.8,
      "attrs": { "color": "blue" }
    },
    {
      "type": "wokwi-pushbutton",
      "id": "btn1",
      "top": -41.8,
      "left": 115.2,
      "attrs": { "color": "red" }
    },
    {
      "type": "wokwi-pushbutton",
      "id": "btn2",
      "top": -89.8,
      "left": 115.2,
      "attrs": { "color": "green" }
    },
    {
      "type": "wokwi-pushbutton",
      "id": "btn3",
      "top": -137.8,
      "left": 115.2,
      "attrs": { "color": "blue" }
    }
  ],
  "connections": [
    [ "nano:GND.2", "led3:C", "black", [ "v-9.6", "h-163.6" ] ],
    [ "led3:C", "led2:C", "black", [ "v9.6", "h-9.2" ] ],
    [ "led2:C", "led1:C", "black", [ "v9.6", "h-18.8" ] ],
    [ "led1:A", "nano:13", "green", [ "v86.4", "h96" ] ],
    [ "led2:A", "nano:12", "green", [ "v28.8", "h76.8" ] ],
    [ "led3:A", "nano:A0", "green", [ "v96", "h86.4" ] ],
    [ "nano:GND.2", "btn1:2.l", "black", [ "v0" ] ],
    [ "nano:GND.2", "btn2:2.l", "black", [ "v0" ] ],
    [ "nano:GND.2", "btn3:2.l", "black", [ "v0" ] ],
    [ "nano:2", "btn1:1.l", "green", [ "v0" ] ],
    [ "nano:4", "btn2:1.l", "green", [ "v0" ] ],
    [ "nano:5", "btn3:1.l", "green", [ "v0" ] ]
  ],
  "dependencies": {}
}

Keep an open mind when solving problems. Sometimes a different approach is all you need.

Good advice there indeed.

By the way that's a cool little array trick you posted there. I'm going to try that out for sure.

Can't hurt to try. What could go wrong?

You can make any control structure out of just testing for equality to zero and goto label.

Everything else is gravy, or to use the term of art "syntactic sugar".

Using for, while, do/while and switch/case appropriately leads to code that is easier to write, maintain, fix and perhaps most importantly read.

Keep an open mind, you will see (and one day use) the switch/case statement where not doing would be quite not so pretty.

a7

It doesn't work for your case because all of your if statements are checking different variables. A switch-case setup is to replace a bunch of if statements about the same variable.

It replaces something like this with more readable code.

if (x == 0) { ... }
else if (x == 1) { ...}
else if (x == 2 { ... }
...
1 Like

OK I changed it up and now have this which does also works. It just doesn't feel right for some reason though. I decided to use separate functions for each of the LED states because I was repeating so much in the loop with digitalWrite stuff. I don't know if this is the best approach or not. I don't know if I'm using too many functions or too many global variables. Also for everyone's viewing pleasure I put it in the Arduino IDE and applied auto formatting.

I also rigged up a Wowki sim of this project if you guys are interested in seeing it and giving some feedback.

#include <Arduino.h>
#include <ezButton.h>

#define redLEDPin 13
#define greenLEDPin 12
#define blueLEDPin 14

ezButton buttonRed(2);
ezButton buttonGreen(4);
ezButton buttonBlue(5);

bool redLEDOn = false;
bool greenLEDOn = false;
bool blueLEDOn = false;

void displayRed();
void displayGreen();
void displayBlue();
void displayOff();

void setup() {
  pinMode(redLEDPin, OUTPUT);
  pinMode(greenLEDPin, OUTPUT);
  pinMode(blueLEDPin, OUTPUT);
  buttonRed.setDebounceTime(25);
  buttonGreen.setDebounceTime(25);
  buttonBlue.setDebounceTime(25);
}

void loop() {
  buttonRed.loop();
  buttonGreen.loop();
  buttonBlue.loop();

  if (buttonRed.isPressed()) {
    if (redLEDOn == false) {
      redLEDOn = true;
      greenLEDOn = false;
      blueLEDOn = false;
      displayRed();
    } else {
      redLEDOn = false;
      displayOff();
    }
  }
  if (buttonGreen.isPressed()) {
    if (greenLEDOn == false) {
      redLEDOn = false;
      greenLEDOn = true;
      blueLEDOn = false;
      displayGreen();
    } else {
      greenLEDOn = false;
      displayOff();
    }
  }
  if (buttonBlue.isPressed()) {
    if (blueLEDOn == false) {
      redLEDOn = false;
      greenLEDOn = false;
      blueLEDOn = true;
      displayBlue();
    } else {
      blueLEDOn = false;
      displayOff();
    }
  }
}

void displayRed() {
  digitalWrite(redLEDPin, HIGH);
  digitalWrite(greenLEDPin, LOW);
  digitalWrite(blueLEDPin, LOW);
}

void displayGreen() {
  digitalWrite(redLEDPin, LOW);
  digitalWrite(greenLEDPin, HIGH);
  digitalWrite(blueLEDPin, LOW);
}

void displayBlue() {
  digitalWrite(redLEDPin, LOW);
  digitalWrite(greenLEDPin, LOW);
  digitalWrite(blueLEDPin, HIGH);
}

void displayOff() {
  digitalWrite(redLEDPin, LOW);
  digitalWrite(greenLEDPin, LOW);
  digitalWrite(blueLEDPin, LOW);
}

For where you are at on the learning path, it looks good. It is a literal straightforward expression of what you want to do, is something you understand and possibly most important works and works the way you think it is working.

Thanks for Auto Formatting you code, it looks pretty.

Also, thanks for building it in the wokwi! In my empty life playing with it there is kinda fun. I forget that you can select the button colour.

To wet your appetite but not jump you too far ahead, look forward to functions like

void setLEDs(ledState theState)
{
  bool red = false;
  bool green = false;
  bool blue = false;   // all LEDs off until determined otherwise

  switch (theState) {
  case OFF :
    // nothing to change, nothing to do
    break;

  case RED :
    red = true;  // red now

    break;

  case GREEN :
    green = true;

    break;

  case BLUE :
    blue = true;

    break;
  }

// now write to the LEDs

  digitalWrite(redLEDPin, red ? HIGH : LOW);
  digitalWrite(greenLEDPin, green ? HIGH : LOW);
  digitalWrite(blueLEDPin, blue ? HIGH : LOW);

  return;
}  

I think you didn't use the ternary operator ?/: before, it's just shorthand (syntactic sugar maybe even) for what would otherwise here be an if/else statement controlling assignments.

Which I see is referred to here as the conditional operator, I've always called it by the other name, and it is the only ternary operator in C/C++, so.

The function above assumes the existence of an enum type like you were aiming for at the start of this; some small changes to how you handle the isPressed() indications that buttons have gone down would allow you to use it as one function to rule all LEDs.

Sry I can't test it from where I am just now, and jamming it into your code would deprive you of the fun that might be.

Imma guess you can figure that out, just from what I've seen on this thread sofa.

HTH

a7

Just for you my friend :smiley:

Thanks a ton for the great little code snippet of a switch. I can see a faint light bulb going off in my mind now.

The whole enum thing seems a bit out of reach at this point. I was thinking that would be useful for the wrong reasons. I'll tackle it one day soon though.

Also thanks for the link about Conditional Operator ?: Some juicy stuff to soak up indeed.

1 Like

A friend who will not be named took the last few minutes to test my function, she was able to put it into your program.

The surprising thing is that lotsa stuff went away when she did - the four functions, as well as the global bool variables - it's all in the one myLEDState instance of the ledState type variable.

This was what replaced the control logic of the red LED

  if (buttonRed.isPressed()) {
    myLEDState = myLEDState == RED ? OFF : RED;
  }

If the red lamp is on, turn it off. Otherwise (all lamps are off, or a lamp of a different colour is on) turn on the red lamp.

Don't worry about it too much. I just remember learning this stuff, I enjoyed it and every minute of learning pays off many fold in the future.

All of this is hard until it is easy.

a7

That's some next level stuff there. I was messing around trying to use that but I'm not quite sure how I'd go about declaring the variables myLEDState, ledState, and RED. I'm not sure what they would need to be to make that little magic you posted work.

I'm also quite confused with your function up there with the switch/case statement in it. I've never made a function with anything inside the ( ) so that's got me all kinds of confused. Also I'm not sure how or where to declare the variables and or what type they should be when I do to make it work.

Today we amused ourselves between other things, and ended up with this implementation of "radio buttons", which I present here shamefully. This is the kind of code that should get ppl fired. We all retired, so. No one wanted to be named or take credit for any of it.

Try it here:

Wokwi_badge UA Radio Buttons


// https://wokwi.com/projects/403520059001187329
// https://forum.arduino.cc/t/late-night-switch-case-confusion/1281147

# include <ezButton.h>

const byte ledPin[] = {13, 12, 14};
ezButton button[] = {2, 4, 5};
const byte nLEDs = sizeof ledPin / sizeof *ledPin;

void setup() {
  for (byte ii = 0; ii < nLEDs; ii++) {
    button[ii].setDebounceTime(25);
    pinMode(ledPin[ii], OUTPUT);
  }
}

void loop() {
  static byte ledState = nLEDs;

  for (byte ii = 0; ii < nLEDs; ii++)
    if (button[ii].loop(), button[ii].isPressed())
      ledState = ledState == ii ? nLEDs : ii;

  for (byte ii = 0; ii < nLEDs; ii++)
    digitalWrite(ledPin[ii], ledState == nLEDs ? LOW : (ledState == ii ? HIGH : LOW));
}

Don't learn anything from this code! And if anyone can find a way to make it even worse, we are all ears.

Oh, I see we could have removed the return statement.

edit: removed the entire function.

a7

1 Like

I have a question.

First why bother using arrays for the button and led pins? Seems like it'd just be easier defining them at the top and being done with it. What's gained by using an array and for loops in the setup? You sure did make some short work of the mess I came up with though lol.

The reason I started doing this little led project was because I was having such a hard time with what I really want to do. I have a series of 5 different animation arrays. What I want to do is have 2 buttons. Button 1 will start the first animation playing on an 8x32 max7219. If pressed again it will start the second and so on. If button 2 is pressed it will halt the current animation and wipe out the screen. The purpose of the LED project was so I could learn how to handle multiple buttons. Small steps for man :smiley: Who knows maybe one day I'll even be able to cook with gas haha.