Else if not working

In my code, the else if simply doesn't work. It is supposed to detect when the user types a letter into the serial monitor and turn a stepper motor based on what letter is typed, but it can only detect d (100) even though there is an else if that should detect for D (68) also. Here is the code:

#include <Stepper.h>

Stepper yellow = Stepper(2038, 22, 23, 24, 25);
Stepper orange = Stepper(2038, 28, 29, 30, 31);

 void setup() {
  yellow.setSpeed(10);
  orange.setSpeed(10);
  Serial.begin(9600);
}

void loop() {
  if (Serial.available() > 0) {
    if (Serial.read() == 100) {
      yellow.step(509);
    }
    else if (Serial.read() == 68) {
      yellow.step(-509);
    }
  }
}

Your else is likely working

you have two challenges =

  • Serial.read() returns a byte, which would be the ASCII code of the first character you typed into the serial monitor ➜ if you type 100↵ then the first byte coming in is the character 1 and the ASCII code you'll see is 49(decimal) or 0x31(hex). (or are you really expecting d or D)?

  • the other challenge is that you read twice, so the first compare is for the first byte in the buffer and the second compare is for the next byte (or will be -1 if there is nothing to read)

for example you could test against one letter codes

void loop() {
  if (Serial.available() > 0) {
    char r = Serial.read();
    if (r == 'F') { // forward
      yellow.step(509);
    }
    else if (r == 'B') { // backward
      yellow.step(-509);
    }
  }
}

The first Serial.read() takes the character out of the buffer. The second Serial.read() is waiting for another character. Try storing the character, then comparing the stored character to the values (100, 68).

it's not waiting :slight_smile: it will just return -1 if there is nothing to read

Yes. (the second read needs a second character or "else" that -1 happens)

[edit] similar code to post #2

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

void loop() {
  if (Serial.available() > 0) {
    char a = Serial.read();     // Store the single character
    if (a == 'a') {
      Serial.print(".a.");
    }
    else if (a == 'b') {
      Serial.print(".b.");
    }
  }
}

First idea:
I am typing "d" into the serial monitor, and I know that d means 100 according to the arduino, so that can't be the problem.
Second idea:
I didn't consider that, I thought that Serial.read would be the same every time I checked it until Serial.available was back to 0.
I tried your example here, but now nothing works. What did I miss?

void loop() {
  if (Serial.available() > 0) {
    char input = Serial.read();
    if (input == "d") {
      yellow.step(509);
    }
    else if (input == "D") {
      yellow.step(-509);
    }
  }
}

It is a single character you are comparing so you should use single quotes:

void loop() {
  if (Serial.available() > 0) {
    char input = Serial.read();
    if (input == 'd') {
      yellow.step(509);
    }
    else if (input == 'D') {
      yellow.step(-509);
    }
  }
}

I can't test the new code because my stepper controller is not getting power, and that's why nothing works. I didn't change any wiring.
My current wiring (using arduino mega and 28byj-48 stepper):
Pin 22 to IN1
Pin 23 to IN3
Pin 24 to IN2
Pin 25 to IN4
Power supply negative to arduino GND and controller negative
Power supply positive to controller positive

This has worked until now...

You're not. Chars are single quotes. 'd', not "d". So this:

should be this

Also, check out switch/case/break instead of if/else if/else and see if you prefer anything about it. IMO, it's the cleaner way to go.

  if (Serial.available() > 0) {
    char input = Serial.read();
    switch (input){
      case 'd':
        yellow.step(509);
        break;
      case 'D':
        yellow.step(-509);
        break;
    }
  }
}

My motor controller got power again, so I uploaded the new code with and without single quotes (I tried both) and it still can only detect for d and not D.

void loop() {
  if (Serial.available() > 0) {
    char input = Serial.read();
    if (input == 'd') {
      yellow.step(509);
      Serial.println("D'");
    }
    else if (Serial.read() == 'D') {
      yellow.step(-509);
      Serial.println("D");
    }
  }
}

This is going to be a Rubik's Cube solver and I am just making the moves right now, so that's why I am printing D' and not d.

You did another Serial.read() in your else/if! You should do this:

void loop() {
  if (Serial.available() > 0) {
    char input = Serial.read();
    if (input == 'd') {
      yellow.step(509);
      Serial.println("D'");
    }
    else if (input == 'D') {
      yellow.step(-509);
      Serial.println("D");
    }
  }
}

And print the value read right before the if() statement.

ToddL1962 Oh I didn't see that, but I am switching to hallowed31's switch/case/break idea. I can easily add more inputs.

if you use the switch/case/break rather than if-else you can drop the intermediary variable and the test to see if something is available as read() will return -1 if there is nothing to read so it won't be one of the cases.

switch (Serial.read()) {
  case 'd': yellow.step(509);  break;
  case 'D': yellow.step(-509); break;
}

IMO, as a best practice, the switch() statement should include a default: case, even if it contains nothing but a break;.

it is indeed a best practice (improves code readability and shows you did make that list on purpose and is well thought through) - so you are right

switch (Serial.read()) {
  case 'd': yellow.step(509);  break;
  case 'D': yellow.step(-509); break;
  default: break;
}

Tip: you know if you click immediately to the right of a bracket or curly brace, the IDE will automagically draw a little rectangle around its mate, right?
It really helps make sure code blocks are bounded in conditional statements correctly, as the conditions become nested, like they do in your code.

Pretty slick!