Reading more than one bit from serial input?

Hey, another beginner project just to get myself more familiar with the Arduino platform. In this case, I’m just trying to build a binary LED display unit that will take serial input from 0-15 and display it as a series of LEDs. The program works, except when I enter a two-digit number. Then it will only display the last number. I tried to remedy this by adding all the data received at any given point, but that didn’t work. Does anyone have any ideas?

int pins[]= {2,3,4,5}; // Array of output pins
int val[]= {0,0,0,0}; // Intialize value of binary bits
int sel; // The Serial input number
void setup ()
{
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  Serial.begin(38400);
}


void loop()
{
  sel = 0; // Because we use compound addition
 if (Serial.available() > 0)
 {
   delay(10);
   while (Serial.available()>0)
   sel += (Serial.read()); // SHOULD add all bytes together. Doesn't.
   
   digitalWrite(2, LOW); // Similar to a CLR function when drawing
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);
    digitalWrite(5, LOW);
    val[0] = 0;
    val[1] = 0;
    val[2] = 0;
    val[3] = 0;
    for (int ii=0; ii<=3; ii++) // Read 4 least significant bits
    {
      val[ii]=bitRead(byte(sel),ii); 
      if (val[ii]==1)
      {
        digitalWrite(pins[ii], HIGH); // If bit is 1, go high
      }
      else
      {
        digitalWrite(pins[ii], LOW); // Else go low
      }
    }
    Serial.print(val[3]); // For debugging
    Serial.print(val[2]);
    Serial.print(val[1]);
    Serial.println(val[0]);
    delay(500); // To not kill the buffer
 }
}

**EDIT:**Well that was embarassing…Umm, the compound addition works as it should: if I input 11, it puts out 2 (Because 1+1 = …yeah). So, I need a better way to do this.

There are a couple of issues with this program. First, when you send it a 7, you are not really sending it a 7. You are sending it a '7'. The character 7 and the number 7 are not the same thing.

The correct way to do what you are doing would be:

int digit = Serial.read() - '0';

Then, to get the whole multi-digit number, change it to:

int num = 0;

while(Serial.available() > 0)
{
   num *=10 +  Serial.read() - '0';
}

If the string of characters sent was '3', '1', '7', num starts at 0, becomes 3, 31, and 317.

I figured I'd have to use some sort of 10 multiplication. I tried using the code you gave me, but now my debugger is returning 0000, no matter what I input:

 sel = 0;
 if (Serial.available() > 0)
 {
     delay(10);
     while(Serial.available() > 0)
    {
     ((sel *= 10) + Serial.read());
    }

bret,

The way your assignment statement is written, it does not add the value of Serial.read to sel. Try it like this:

sel = 0;
 if (Serial.available() > 0)
 {
     delay(10);
     while(Serial.available() > 0)
    {
     sel = (sel * 10) + Serial.read();
    }

One of the strange characteristics about the C programming language is that it will let you code long, complex statements where the result is thrown away! For example, the following statement is perfectly legal, but has no effect:a + (b * 12) + (c / 33) - (d * d * d);

Regards,

-Mike

You also ignored the first part of my post.

Print out the value read by the Serial.read command:

int stuff = Serial.read();
Serial.print("Read a ");
Serial.print(stuff);
Serial.print(" which has a decimal value of ");
Serial.println(stuff, DEC);

Then, tell us what the value of stuff is, when the program is sent 7, 0, and 1.

The statement I defined:

num *=10 +  Serial.read() - '0';

and the one you entered:

((sel *= 10) + Serial.read());

are not the same, and do not do the same thing. Why did you add all the extra parentheses?

Upon further review, the statement I defined was wrong, too. Too early in the morning to be telling other people how to write code:

The correct statement(s) would be:

num *= 10;
num += Serial.read() - '0';

PaulS: I added the parentheses because I was trying to write the exact same code that Mike just gave me (Thanks! It works!). Somehow, though I thought it was the same, his worked and mine didn't. Of course, I'm the newb here, so that's not terribly surprising.

I could be wrong, but I think by defining my sel variable as an int, the data is automatically stored as an integer, because I did not need to use the - '0'; code, and don't quite understand it.

I could be wrong, but I think by defining my sel variable as an int, the data is automatically stored as an integer, because I did not need to use the - '0'; code, and don't quite understand it.

When you type "7" iinto the serial monitor, what is transmitted is nt the value 7, but the value of the ASCII character representing the numeral 7. This value is 0x37 (decimal 55). The value of the ASCII character representing the numeral zero is 0x30 (decimal 48) and fortunately, the representations of the decimal digits in ASCII are consecutive.

So, by subtracting '0' from an ASCII numeral, you convert it from the value of its representation as an ASCII numeral to its decimal value.

Thus, '7' - '0' is the same as writing 55 - 48 = 7.

Yet, the code that Mike provided me worked. Flawlessly, no - '0'; statement needed. So now I'm more curious as to why the code DOES work as to why it doesn't, since you guys are essentially saying it shouldn't work.

Did you try printing the value read from the serial port, as described in reply #4? If so, what did you see? If not, why not?

Sure enough, Paul, you were right. Though the program still works, I get this in the Serial Monitor:

Read a 49 which has a decimal value of 49
0001
Read a 50 which has a decimal value of 50
0010

Weird.

ASCII '1' is 0x31, 49 decimal, in binary is 0011[u]0001[/u] ASCII '2' is 0x32, 50 decimal, in binary is 0011[u]0010[/u]

Ha. That makes sense. I suppose if I'd debugged and printed the character in binary it would've shown up. Alright, I'll parse the thing. Is there a way to convert ASCII to numeric values? Maybe int(sel-'0');?

You have already declared sel to be an int. Subtracting '0' from it is exactly the same as subtracting 0x30. There is no need to call the int() function with an int as input. Just use "sel - '0'".