1

My intention is to write a code that asks a user to enter the name and then the age. The code should then simply display the persons name and age. To do that, I have written a simple code. I find it difficult to get it to work.

char temp = 0;
char ArrayName [50]; 
int positionArray = 0;
int age =0;

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

void loop() {

    positionArray = 0;
    Serial.println ("What is your name?");

    do {

        while (Serial.available()==0);
        temp = Serial.read ();
        ArrayName [positionArray++] = temp; 
    } while (temp != '\r');

    ArrayName [--positionArray] = '\0';

    Serial.print ("Your Name is: ");
    Serial.println (ArrayName);


    // clear the UART Buffer
    while (Serial.available()==1){    
        temp = Serial.read();
    }

    Serial.println ("What is your age?");
    while (Serial.available()==0);
    temp = Serial.read ();
    age = temp;

    Serial.print ("You are ");
    Serial.print (age);
    Serial.println (" Years old.");

    while (Serial.available()==1){    
        temp = Serial.read();
        delay (10);
    }

} 

The error I receive is that the program already outputs age without me even typing it. Would it be possible to know the error? I use both NL and CR to send in characters to Arduino and the Arduino IDEs default UART terminal.

EDIT:

Listening to advice gotton from answers I got the code to work but in a very weird way. My new code works! but it proves the clearing of buffer cannot be done by just reading it. This is in contrast to Arduino documents. My new code is as follows.

char temp = 0;
char ArrayName [50]; 
int positionArray = 0;
int age =0;

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

void loop() {

    positionArray = 0;
    Serial.println ("What is your name?");

    do {

        while (Serial.available()==0);
        temp = Serial.read ();
        ArrayName [positionArray++] = temp; 
    } while (temp != '\r');

    ArrayName [--positionArray] = '\0';

    Serial.print ("Your Name is: ");
    Serial.println (ArrayName);


    // clear the UART Buffer **WHY IS THIS CODE NOT EFFECTIVE?**
    while (Serial.available() >= 1){    
        temp = Serial.read(); // performing dummy reads untill buffer empty.
    }

    temp = Serial.read();
    delay (1000);
    temp = Serial.read();
    temp = Serial.read();
    temp = Serial.read();

    Serial.println ("What is your age?");
    while (Serial.available()==0);
    temp = Serial.read ();
    temp = temp - 48;
    age = temp*10;
    delay (1000); // providing the user a day to enter next digit of age

    if (Serial.available()){  
        temp =  Serial.read ();
        temp = temp - 48;
        age = (int) temp + age; //whatever that is added have to be of same type. Else they need to be cased to same type.
    }


    Serial.print ("You are ");
    Serial.print (age);
    Serial.println (" Years old.");

    while (Serial.available() >=1 ){    
        temp = Serial.read();
        delay (10);
    }

} 
  • In what way does it "not work"? – Majenko May 28 '16 at 15:00
3

As we don't know what you are using as a terminal program we can't comment specifically on your choice of EOL characters.

It is likely you are receiving everything in ASCII code. That is, when you type the number 1 you are actually getting the ASCII equivalent (0x31) from your terminal.

This is fine when you are working with character strings. But when you want to work with numbers that are to be used in equations you need to 1) make sure that the user is only entering a number (check to make sure the values are from 0x30 to 0x39) and 2) subtract the ASCII value for '0' from the value you received from the terminal. That is, subtract 0x30.

It should now be obvious that you can only enter 1 digit at a time when using a terminal. That you will have to reconstruct the number as the user types each digit. For example the number 13 is a 1 and a 3 and you will have to multiply the 1 by 10 then add it to the 3.

Since this is such a common conversion, there are Arduino libraries that do this for you. Consider using ParseInt for this purpose.

Added later...

In the modified code, consider the possibility the terminal program is sending both a Carriage Return (aka: CR, 0x0D, \r) and Line Feed (aka: LF, 0x0A, \n) each time the Enter key is pressed. And that the code is only waiting for the CR.

The delays are necessary as UART communication, as most communications, takes a finite amount of time. And additional characters, if any, and even if autonomously sent, will take a finite amount of time to arrive.

Consider "looking" for the LF character after finding for the CR character and removing the added delays.

| improve this answer | |
  • Great answer. Thank you. Could you also please tell me why my code automatically moves to accepting age without me even typing it? I'm clearing the UART buffer by reading it untill it becomes empty prior to asking the user for age. Still, the code goes on and spits out the age of the user without me even typing it. Thank you for teaching me my error and telling me that I need to handle user inputs for integers as single ASCII charactors. – Denis May 28 '16 at 15:19
  • 1
    You did not repeat your code design when entering a string of characters when you coded up the part of your program to enter the age. You basically said: "If there is something from the terminal read it. Otherwise skip reading anything." As you can't type that fast (time between pressing the enter key and typing the 1st digit of the age), the program continued on to the end. – st2000 May 28 '16 at 15:27
  • 1
    If you are a beginning programmer, I would recommend you do all your own parsing and ASCII to integer conversion. It is good experience. As your programs become more complex, you can benefit from using libraries to keep you programs "clean" and their purpose obvious. – st2000 May 28 '16 at 15:31
  • 1
    After this line: "// clear the UART Buffer", try changing " while (Serial.available()==1){ " to " while (Serial.available() >= 1){ " – st2000 May 28 '16 at 15:37
  • 1
    Stack Exchange isn't a good place to debug code. But, going on, my next suggestion is to print out the character read after each and every read. I would use "Serial.print(temp, HEX)" so everything (including control characters) are printed as hex number. Then look them up in the ASCII table to find their exact meaning. You might have some other bugs but once you get this working you can spot and fix them. – st2000 May 28 '16 at 15:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.