Serial.read returns byte, looking for char works intermittently , why?

Simple goal: turning on and off the built-in LED in response to keyboard press

I realize the correct code would be something like this:

char keypressed;

void setup(){

Serial.begin(9600);
pinMode(13, OUTPUT);

}

void loop(){
  
  if(Serial.available() >0){
    
keypressed =    Serial.read();
    
    if(keypressed == '1'){
      analogWrite(13,0);
      Serial.println("light off");
    }
    
    if(keypressed == '2'){
      analogWrite(13,255);
      Serial.println("light on");

   }
  }

}

But I tried this:

void setup(){

Serial.begin(9600);
pinMode(13, OUTPUT);

}

void loop(){
  
  if(Serial.available() >0){
    
    if(Serial.read() == '1'){
      analogWrite(13,0);
      Serial.println("light off");
    }
    
    if(Serial.read() == '2'){
      analogWrite(13,255);
      Serial.println("light on");

   }
  }

}

And (surprisingly) it worked (i.e. the LED turned on in response to a '2' sent in the serial monitor) about a quarter of the time, even though Serial.read returns a byte (rather than a char, which is what I check for). Why does it still work, but only sporadically?

The character '1' or '2' is also a number. We see it as an ascii character, but the compiler doesn't care how we see it. They are binary number 49 and 50.

You do Wire.read() twice. That means that if a '2' was pressed, and Wire.read() was checked against '1', the '2' was missed.

I'm afraid I don't understand.

The compiler sees them as binary 49 and 50... so how are they read as the characters '1' and '2'?

By Wire.read I assume you you're referring to Serial.read in the second section of code...

Are you suggesting that both if statements are not considered? Even if if(Serial.read() == '1') is true, the other if statement (if(Serial.read() == '2')) would still be tested. Can you expand on your previous answer?

Jnnfr: I'm afraid I don't understand.

The compiler sees them as binary 49 and 50... so how are they read as the characters '1' and '2'?

http://en.wikipedia.org/wiki/ASCII

... also, 49 and 50 are not binary numbers!

void loop(){
  
  if(Serial.available() >0){
    
    if(Serial.read() == '1'){
      analogWrite(13,0);
      Serial.println("light off");
    }
    
    if(Serial.read() == '2'){
      analogWrite(13,255);
      Serial.println("light on");

   }
  }

}

In this section you read from Serial twice. So if you enter a '2' in the Serial monitor, then the first read gets the '2' and compares to '1' and it isn't '1' so it moves on. When it gets to the next test against '2', there is a new call to Serial.read() so it reads a new character. The '2' is gone and either a carriage return, line feed or possibly an 0xFF is read in and that is what gets compared to '2'.

Instead what you want to do is read once from the Serial and store that in a char variable. Then run all your if tests against that same variable.

what you want is:

  byte charIn = Serial.read();

  if(charIn == '1'){
      analogWrite(13,0);
      Serial.println("light off");
  } else if(charIn == '2'){
      analogWrite(13,255);
      Serial.println("light on");
  }

or possibly even add a switch on charIn statement here

Jnnfr:
even though Serial.read returns a byte (rather than a char, which is what I check for).

In truth, Serial.read returns an int. Only the bottom 8 bits mean anything unless there was nothing to be read. If the buffer is empty when you call Serial.read it will return 0xFF (-1). Since only the bottom 8 bits contain anything useful, we usually just stick it in either a char or byte variable depending on what we want to do. But you could use int instead and your code would still work. Writing characters in single quotes just tells the compiler to stick in ascii code. All the processor sees is a number.

what you want is:

Code: [Select]

byte charIn = Serial.read(); [/code]

You certainly do NOT. That's about as stupid as

float myInt;

aarg: http://en.wikipedia.org/wiki/ASCII

... also, 49 and 50 are not binary numbers!

I realize this. I was referring to and seeking clarification of Peter_n's comment "binary number 49 and 50".