Simple problem - Serial read DEC that is 1-32

Hi, I have an arduino mega and I want to read serial messages coming in that are from 1-32 DEC. Can I do that? i.e. the information that is coming into the ardunio serial is between 1 to 32 DEC and I want the arduino to activate certain pins depending on the information that is coming in. I think this sketch will work, but I need to change the 'a', 'b', 'c' etc to 1 DEC, 2 DEC etc.

void setup() {
// initialize serial communication:
Serial.begin(9600);
// initialize the LED pins:
}

void loop() {
// read the sensor:
if (Serial.available() > 0) {
int inByte = Serial.read();
// do something different depending on the character received.
// The switch statement expects single number values for each case;
// in this exmaple, though, you're using single quotes to tell
// the controller to get the ASCII value for the character. For
// example 'a' = 97, 'b' = 98, and so forth:

switch (inByte) {
case 'a':
digitalWrite(2, HIGH);
break;
case 'b':
digitalWrite(3, HIGH);
break;
case 'c':
digitalWrite(4, HIGH);
break;
case 'd':
digitalWrite(5, HIGH);
break;
case 'e':
digitalWrite(6, HIGH);
break;
default:
// turn all the LEDs off:
for (int thisPin = 2; thisPin < 7; thisPin++) {
digitalWrite(thisPin, LOW);
}
}
}
}

How do I do this?

Thanks.

If the data is being sent as a string ('1", "5", "14", "32", etc.), you really need to consider some sort of end of packet marker. Without that, how do yo know when the end of the serial data stream has arrived?

When you are reading a post, or a reply, you know when the end of a sentence has arrived because there is some sort of punctuation that marks the end of a sentence - either a period, a question mark, or an exclamation point.

When reading the serial data, the same idea applies. You just keep reading until something indicates that it is time to stop reading and do something with what you have read.

Storing the characters read in an array, and converting them to an integer is a topic that is asked about at least once a week on the forum.

Thanks Paul.

Basically, if I do a simple reading of the information coming in from the serial monitor, it is 1,1,1,1,1,1,1 or 2,2,2,2,2, (scrolling downwards). I have tried to read this information (and make it turn a corresponding pin on), but it seems that the arduino cannot read anything below 33 DEC. Should I search back through the forum?

Basically, if I do a simple reading of the information coming in from the serial monitor, it is 1,1,1,1,1,1,1 or 2,2,2,2,2, (scrolling downwards). I have tried to read this information (and make it turn a corresponding pin on), but it seems that the arduino cannot read anything below 33 DEC. Should I search back through the forum?

The data sent by the serial monitor is a string. If you are not reading that string correctly, then you won't be turning on the right light.

The Arduino can read any string sent. It is up to you to write the right code to do this. Post your code that does not seem to be able to read a string that represents a value less than 33, and we can point out what is wrong.

Hi Paul,

Thanks heaps. Sorry, I'm pretty much a complete beginner at this (just got my arduino a couple of weeks ago and have no programming exp).

The code above is the basis of what I am using and I was just trying to change the 'a', 'b' etc to 1 or 2 etc. So, I want to make it such that if the info that is coming in to the arduino says '1', then I want pin 2 to go high, if it says 2, then pin 3 to go high and if it goes back to 0, then to do nothing.

Maybe you can point me to a tutorial that will help?

Thanks

Some simple serial code for handling strings sent.

// zoomkat 8-6-10 serial I/O string test
// type a string in serial monitor. then send or enter
// for IDE 0019 and later

String readString;

void setup() {
	Serial.begin(9600);
        Serial.println("serial test 0021"); // so I can keep track of what is loaded
        }

void loop() {

        while (Serial.available()) {
        delay(10);  
    	if (Serial.available() >0) {
        char c = Serial.read();
        readString += c;}
        }
        
      if (readString.length() >0) {
      Serial.println(readString);
      
      readString="";
      } 
   }

Hi zomkat and PaulS,

Thanks heaps for your help, much appreciated. However, I'm still pretty lost - spent days on this with no avail. From what I understand, now that I am reading the string, I need to convert it into an integer so the arduino can use it to turn an outputs on and off (is that right)? So when it receives '0' into the serial, nothing happens, and when it receives 1, then digital pin 2 goes HI etc. Anyways, so here is my butchered code...

String readString;

void setup() {
Serial.begin(9600);
Serial.println("I'm Online"); // so I can keep track of what is loaded
for (int thisPin = 2; thisPin < 7; thisPin++) {
pinMode(thisPin, OUTPUT);
}
}
void loop() {

while (Serial.available()) {
if (Serial.available() >0) {
char c = Serial.read();
readString += c;}
}

if (readString.length() >0) {
switch (inByte) {
case '1':
digitalWrite(2, HIGH);
break;
case '2':
digitalWrite(3, HIGH);
break;
case '4':
digitalWrite(4, HIGH);
break;
case '8':
digitalWrite(5, HIGH);
break;
case '32':
digitalWrite(6, HIGH);
break;
default:
// turn all the LEDs off:
for (int thisPin = 2; thisPin < 7; thisPin++) {
digitalWrite(thisPin, LOW);
}
}
}
}

inbyte is not declared and it is obviously not finished and does not work. Can you guys give me a hand?

Thanks

It has been suggested that you put each { and } on a separate line, and indent the code properly, so you can see what is going on.

        while (Serial.available()) {
       if (Serial.available() >0) {
        char c = Serial.read();
        readString += c;}
        }

should be:

   while (Serial.available())
   {
      if (Serial.available() >0)
      {
         char c = Serial.read();
         readString += c;
      }
   }

Some things you need to ask yourself. Serial.available() returns a number - the number of bytes available to read. You have an implicit test in the while statement, and an explicit test in the if statement. Why?

Make it an explicit test in the while statement, too.

Next, the body of the while statement will not be executed unless there is serial data available to read. In the body, the first thing you do is test whether there is serial data available to read. The only thing that can change whether there is data available to read is a call to Serial.read(), which is not happening between the while test and the if test. What useful purpose does the if test serve?

Serial data is sent slowly. As written, whatever is available to be read when the while test is first evaluated is all that will be read, since reading serial data is orders of magnitude faster than receiving serial data. If, in the Serial Monitor, you type "12345678" and hit send, the data will arrive at the serial port one character at a time, and will be processed during hundreds, thousands, or even millions of passes through loop. On any given pass, there being nothing that takes very long to do, you will read and deal with one character at a time. Is that really what you want to do? Or, are you trying to receive a number of characters that make up a packet, and process them all as a packet?

If it is the latter, you have two choices. You can use zoomkat's method of adding a delay in the while loop, so you waste a bunch of time waiting around, hoping that all the data that makes up a packet arrives before you assume that you have received a complete packet.

Or, you can send an explicit end-of-packet marker. With a marker (; as in "12345678;" for example), you read whatever data is available, append it to readString, and end the while loop with no delay. If the character that was read was the end of packet marker, you set a flag and break out of the while loop.

You do nothing with the data in readString unless that flag is set.

Some minimal time with the search field, and "end of packet marker" or zoomkat's name will get you code to implement either method.

Once you have a packet, in readString, you need to extract the character array from the string (using toCharArray), convert that array to an integer (using atoi), and perform your switching based on that integer, not some character values.

    case '32':

'32' is a multibyte character. While this is legal syntax in C, there is no support for multibyte characters on the Arduino. If you want to compare the value in a character array to a constant collection of characters, double quotes are required. The switch/case construct can not be used to do this. The strcmp() function in a series of if tests could.

Thanks PaulS for your help and support... this thread is really interesting...No intention to hijack this thread but as my question is relevant here and can't start another thread with all this context, so please pardon me..

1- Can you help us make a small/short sketch "12345678;" for this you described above.
2- Lets i have "10010010;" and i extract 10010010 from it.. can i convert this into a binay number(1 byte)?...or can i convert this into DEC?...

I am not quite sure if I grasp what you're asking, but the problem may be a confusion with character constants and int. From your initial post, it appears that you're trying to process data for ascii characters in the 1 to 32 range. If that's the case then your problem is that your case statements are testing the wrong values.

for example,

case '1':
digitalWrite(2, HIGH);
break;

here you're testing for character '1', which is ascii character 49. If your data really is in the low range, what you need is this:

case 1:
digitalWrite(2, HIGH);
break;

note that the quotes are gone.

Back to the origional question, do you have control over what is being sent to the arduino and the format? Also, give an example of what is being sent to the arduino. If you can use an end of packet delimiter (the "," below), then you might use code like below.

//zoomkat 9-9-10 simple delimited ',' string parce 
//from serial port input (via serial monitor)
//and print result out serial port
// CR/LF could also be a delimiter

String readString;

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

void loop() {

        //expect a string like wer,qwe rty,123 456,hyre kjhg,
        //or like hello world,who are you?,bye!,
        while (Serial.available()) {
        delay(1);  //small delay to allow input buffer to fill
    	if (Serial.available() >0) {
        char c = Serial.read();  //gets one byte from serial buffer
        if (c == ',') {break;}  //breaks out of capture loop to print readstring
        readString += c; } //makes the string readString
        }
      
      if (readString.length() >0) {
      Serial.println(readString); //prints string to serial port out
      
      readString=""; //clears variable for new input
      }
   }

1- Can you help us make a small/short sketch "12345678;" for this you described above.

boolean eopFound = false;
String someStuff = "";

void loop()
{
   while(Serial.available() > 0)
   {
      char aChar = Serial.read();
      if(aChar == ';')
      {
          eopFound = true;
          break;
      }
      else
         someStuff += aChar;
   }

   if(eopFound)
   {
      // Use the data in someStuff

      someStuff = "";
      eopFound = true;
   }
}

2- Lets i have "10010010;" and i extract 10010010 from it.. can i convert this into a binay number(1 byte)?...or can i convert this into DEC?...

You want to perform the conversion as part of the extraction process. If the string is "10010010", and you pass that to strtol(), you will get a decimal value.

Hey guys, thanks so much (I can't quite get over how people are just willing to help others out for nothing over the net!!!). Do you guys work for arduino???!!! Thanks heaps!

I think it best that I start from the beginning and explain exactly what I am making, so you guys can understand better where I am coming from (sorry, should have done this first up). So first of all, here is the project I am trying to make: Wifi Robot - JBProjects.net

Basically, it is a wifi car that you drive through a computer (over wifi) - the router sends information to the arduino that turns certain digital pins on depending on the information received. (BTW, the code that was originally written for the arduino for this project uses PORTD etc and is very confusing, difficult to edit and needs to be changed depending on the arduino model that you have). I thought I would rewrite the code and make it simple, so it can be used by anyone.

So, from the code below, I read what is coming into the arduino from the router.

int incomingByte = 0;	// for incoming serial data

void setup() {
    Serial.begin(9600);	
    Serial1.begin(9600);	// opens serial port, sets data rate to 9600 bps
}

void loop() {

	// send data only when you receive data:
	if (Serial1.available() > 0) {
		// read the incoming byte:
		incomingByte = Serial1.read();

		// say what you got:
		Serial.print("I received: ");
		Serial.println(incomingByte, DEC);
	}
}

So from this code, I could read what the router was sending to the arduino through the serial monitor. When I didn't push any buttons (forward, backwards, left and right), the serial monitor gave back this info:

" I received: 0
I received: 0
I received: 0
I received: 0"

And it keeps scrolling down several lines per second. When I pushed forward, the serial monitor gives back this info:

"I received: 1
I received: 1
I received: 1
I received: 1"

And it gives a different number depending on whether I push forwards, backwards, left or right.

So basically, I want to write some arduino code that interprets this information and sets a digital pin to high when it receives 1, sets a different digital pin to high when it receives 2, and so on. And I want it to turn all pins to low when it receives 0.

So there you have it. Based on that information, am I on the right track with the coding? And PaulS and zoomkat, which of your suggestions should I implement into the code?

Phew. Thanks.

You have it really with your existing code. You are indeed sending low ascii values to the arduino. Here's a slight variant for loop that does what you're asking (I think, can't easily test it):

void loop() 
{
if (Serial.available() >0)
  {
  char c = Serial.read();
  switch (c)
    {
    case 1:    
      digitalWrite(2, HIGH);
      break;
    case 2:    
      digitalWrite(3, HIGH);
      break;
    case 4:    
      digitalWrite(4, HIGH);
      break;
    case 8:    
      digitalWrite(5, HIGH);
      break;
    case 32:    
      digitalWrite(6, HIGH);
      break;
    default:
      // turn all the LEDs off:
      for (int thisPin = 2; thisPin < 7; thisPin++) 
         {
        digitalWrite(thisPin, LOW);
         }
    } 
  }
}

Below is some code you can experiment with using the arduino LED pin. If you send a single character for each action, the delay can be removed. Turn the LED on/off by sending on and off from the serial monitor.

// zoomkat 8-6-10 serial I/O string test
// type a string in serial monitor. then send or enter
// for IDE 0019 and later

String readString;


void setup() {
	Serial.begin(9600);
        pinMode(13, OUTPUT);
        Serial.println("serial test 0021"); // so I can keep track of what is loaded
        }

void loop() {

        while (Serial.available()) {
        delay(1);  
    	char c = Serial.read();
        readString += c; 
        }
        
      if (readString.length() >0) {
      Serial.println(readString);
     
    if (readString == "on") {
	digitalWrite(13, HIGH);
        Serial.println("Led On");
    }
   if (readString == "off") {
	digitalWrite(13, LOW);
        Serial.println("Led Off");
    }
        readString="";
   } 
}

Hi Wildbill,

Your code worked!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! WHOOOOOOHOOOOOOOOOO!!!! Thanks so much everyone! Thanks! Phew. It was a combination of the code and my usb serial port - for some reason, that serial port can't handle it, but the serial port 1 can. Phew. Much appreciated - wow, that took me 2 months to solve.....man..... Thanks everyone!!!