Problems with Serial.print() and Serial.read

Then would you please guide me through it? I don't know how to convert the user-entered number into an ascii value... also if you could help me with getting the program to accept the full multidigit answer...

arjmon: Then would you please guide me through it? I don't know how to convert the user-entered number into an ascii value... also if you could help me with getting the program to accept the full multidigit answer...

Maybe start here

Almost done with it! Thank you for the help... Though there is something that's still bugging me... Its that due to the delay function that even after the answer it types by the user, it waits for that stipulated amount of time? I want it to display the next question as soon as the user has entered the answer...

Then don't delay.

The simplest answer is this:

while(Serial.available() == 0);

That will do nothing until available returns that there are characters to read. You might want a quick few millisecond delay right after that to make sure all of the digits have arrived though and not just the first one.

You may find some useful stuff in serial input basics and in planning and implementing a program

…R

Here you go, fellow. I've added plenty comments, so that I hope you'll be able to get the dynamics of things. Let me know should you have further difficulties. I have NOT added the "blinking lights" code. That's pretty simple and you'll be able to handle it by yourself. Just remove the messages I wrote with your code and see if you can do it.

P.S.: As an exercise for you to better comprehend the workflow of the program, try splitting the code into functions.

String inData = ""; // String to hold input data.
int rand1 = 0, rand2 = 0, ansArduino = 0, ansUser = 0;

void setup () // This code runs only once.
{
    pinMode (0, INPUT); // Sets pin 0 as input.

    Serial.begin (9600); // Begins serial communication at 9600 bauds.
    while (!Serial) // While serial is not ready.
    {
    ; // Waiting for serial to be ready.
    }

    randomSeed (analogRead (0)); // Generates a random seed out of an analog reading of pin 0.
}

void loop () // This code keeps being executed infinitely.
{
    inData = ""; // Resets the input data string for each interaction.

    rand1 = random (0, 1000); // Generates a random number between 0 and 1000.
    rand2 = random (0, 1000); // Generates another random number between 0 and 1000.

    ansArduino = rand1 + rand2; // Assigns the sum of both random numbers.

    Serial.print (rand1); // Output the first random number to the Serial port.
    Serial.print (" + "); // Outputs " + " to the Serial port.
    Serial.print (rand2); // Outputs the second random number to the Serial port.
    Serial.println (": "); // Outputs ": " to the Serial port, followed by a new line.

    Serial.println ("Inform your answer and press ENTER."); // Outputs Inform your answer and press ENTER." to the Serial port.

    while (Serial.available () == 0) // While there is NO data comming from the Serial port.
    {
    ; // Waits for user input...
    }

    while (Serial.available () > 0) // While there's data comming from the Serial port...
    {
    int inChar = Serial.read (); // Reads each char...
    inData += (char) inChar; // Concatenates the char read into the string inData, with a typecast (char), for type conversion of the assignment.
    delay (10); // Give the Serial port some time to flush the last char and make the following one ready for reading...
    }
    ansUser = inData.toInt (); // Assigns the input data from inData, converted to Integer, to ansUser.
    Serial.print ("You entered "); // Outputs "You entered " to the Serial port.
    Serial.println (ansUser); // Outputs the contents of ansUser to the Serial port.
    if (ansArduino == ansUser) // Checks if value calculated by Arduino equals to the answer provided by the user.
    {
    // If the value calculated by Arduino MATCHES the user response...
    Serial.println ("Yay!"); // Outputs "Yay!" to the Serial port.
    }
    else
    {
    // If the value calculated by Arduino DOES NOT match the user response...
    Serial.print ("Dud torpedo, sir! Correct answer is "); // Outputs "Dud torpedo, sir! Correct answer is " to the Serial port.
    Serial.println (ansArduino); // Outputs the contents of ansArduino (the sum calculated by Arduino) to the Serial port, followed by a new line.
    }
    delay (5000); // Waits for 5 seconds before starting the next interaction...

    // Code inside loop ended... Starting it all over again...
}

Thanks fabianoantunes…

I am a newbie and though I understood most of the code, here is some thing i did not…

while (Serial.available () > 0) // While there’s data comming from the Serial port…
{
int inChar = Serial.read (); // Reads each char…
inData += (char) inChar; // Concatenates the char read into the string inData, with a typecast (char), for type conversion of the assignment.
delay (10); // Give the Serial port some time to flush the last char and make the following one ready for reading…
}
ansUser = inData.toInt (); // Assigns the input data from inData, converted to Integer, to ansUser.

What is happening and why are we doing this?
I tried using Serial.parseInt() and it worked wonderfully except that the program would wait for the delay() to pass. I want the the arduino to ask the next question immediately after the user enters the answer…

arjmon: delay (10); // Give the Serial port some time to flush the last char and make the following one ready for reading... } ansUser = inData.toInt (); // Assigns the input data from inData, converted to Integer, to ansUser.

What is happening and why are we doing this? I tried using Serial.parseInt() and it worked wonderfully except that the program would wait for the delay() to pass. I want the the arduino to ask the next question immediately after the user enters the answer...

There is no need to use delay()s while receiving serial data. It just wastes time that the Arduino could use for something useful.

I think you need to think clearly how to organize your program. The business of reading data and the business of when data is read should be separate. Look at the Thread planning and implementing a program. Separating your code into short functions makes the overall logic easier to see.

...R

Robin2: There is no need to use delay()s while receiving serial data. It just wastes time that the Arduino could use for something useful.

I'm sorry, but I must disagree, Robin2. That will depend on the control structure and instruction you use to read from the serial. For me, with Arduino Mega 2560 R3, with the following snippet...

...
int inputByte = 0;
...
while(Serial.available() > 0)
{
    inputByte = Serial.parseInt();
}
Serial.println(inputByte). // This prints 0
...

... the while loop restarts so fast that the last character read (carriage return) still counts as available in the serial port, thus the delay instruction. If you're performing a single read, the following snippet works fine.

...
int inputByte = 0;
...
if(Serial.available() > 0)
{
   inputByte = Serial.parseInt();
}
Serial.println(inputByte); // This prints correctly

Yes, I'm aware there are much cleaner and sophisticated ways of performing this task, but I don't think throwing those on a novice programmer's face would be convenient, from the didactic perspective.

[]'s

arjmon:
Thanks fabianoantunes…

I am a newbie and though I understood most of the code, here is some thing i did not…

while (Serial.available () > 0) // While there’s data comming from the Serial port…
{
int inChar = Serial.read (); // Reads each char…
inData += (char) inChar; // Concatenates the char read into the string inData, with a typecast (char), for type conversion of the assignment.
delay (10); // Give the Serial port some time to flush the last char and make the following one ready for reading…
}
ansUser = inData.toInt (); // Assigns the input data from inData, converted to Integer, to ansUser.

What is happening and why are we doing this?
I tried using Serial.parseInt() and it worked wonderfully except that the program would wait for the delay() to pass. I want the the arduino to ask the next question immediately after the user enters the answer…

arjmon, for you to use the same code with Serial.parseInt(), replace that while loop with this:

    if (Serial.available () > 0) // If there's data comming from the Serial port...
    {
	inChar = Serial.parseInt (); // Reads and Integer...
    }

You may want to refer to my previous message for further explanation on why I replaced the while for an if here.
For you to remove the delay in the end, just drop that last line which reads

    delay (5000); // Waits for 5 seconds before starting the next interaction...

BTW, this last one you could have solved on your own if you took the time to read the ALL the comments I spared you the time to write.

fabianoantunes: Yes, I'm aware there are much cleaner and sophisticated ways of performing this task, but I don't think throwing those on a novice programmer's face would be convenient, from the didactic perspective.

Allow me to disagree. I wrote the examples in serial input basics to be simple and reliable for novices. They do not use delay().

...R

Robin2: Allow me to disagree. I wrote the examples in serial input basics to be simple and reliable for novices. They do not use delay().

...R

Again, Robin2, allow me to disagree. I understand your perspective. I trully do. But from a real novice, such as in this case, with difficulties to understand and follow a procedural program, step by step, probably due to the repetition and conditional structures of the language, which is simply put like a "cake recipe", adding the complexity of following functions and understanding these functions return to the calling point in the stack is, yet, not simple. That's a great tutorial, and yes, that works very well, but for people with a little bit of previous knowledge on programming. As I've been seeing many people which are mostly technology enthusiasts, with no prior contact with development, thus my point of view, at least for this forum specifically. Of course, that's a case-by-case situation. []s

fabianoantunes: difficulties to understand and follow a procedural program, step by step, probably due to the repetition and conditional structures of the language,

If those sort of difficulties exist in my examples in serial input basics I would genuinely appreciate it if you would point them out so that I can improve my text.

I am not at all concerned whether those sorts of problem exist in other code that might be found elsewhere.

I do not like the idea of encouraging newbies to depend on delay(). Using delay(10) for receiving 20 characters potentially wastes 200 millisecs of valuable Arduino time. Also, delay(10) limits the repeat rate for loop() to 100 per second which is very slow if the code is also trying to detect other events.

...R

Robin2,

Robin2:
If those sort of difficulties exist in my examples in serial input basics I would genuinely appreciate it if you would point them out so that I can improve my text.

I never said that difficulties where created by your examples. I’m sorry if anyhow you felt like I implied or suggested that. I meant that the student/person learning the basics, such as in the case of the author/creator of this topic, which clearly - by receiving his replies - can and gets confused with the simulated multi-tasking program structure that Arduino programming offers. Which is why I have no real problem recommending a real novice using delay(), at least for first steps of learning, if that will make his comprehension easier in the beginning, and then have some knowledge base to advance in further logic understanding on how to control multiple events and tasks simultaneously. For instance, in this case, all the OP intended for was a single, procedural, sequential task. He does not have the needs of controlling multiple events/statuses, have an ultimately optimized for speed and memory code, or anything else like this. He’s just learning the basics, which is not even Arduino or C/C++ specific only. But that’s just my point of view.

Robin2:
I am not at all concerned whether those sorts of problem exist in other code that might be found elsewhere.

I’m not quite sure, but I’m guessing this refers to the “enthusiasts” and “people with no prior development contact” portion of my previous message. If so, that’s not happening elsewhere. It’s happening here. This very topic is an example.

Robin2:
I do not like the idea of encouraging newbies to depend on delay(). Using delay(10) for receiving 20 characters potentially wastes 200 millisecs of valuable Arduino time. Also, delay(10) limits the repeat rate for loop() to 100 per second which is very slow if the code is also trying to detect other events.

Well, I do not like this idea too. But seen the difficulty of the OP in understanding the basics of the programming logic and lack of any further needs regarding loop speed or detection of multiple events, I see no harm in there. He can/could use that for learning his baby steps and then advance to a more intelligent, clean, concise, controlled programming without delay1

*1 - With triple meaning:

  1. Do it immediately after learning those baby steps;
  2. With no harm to the milliseconds wasted by delay();
  3. And, of course, without delay().

But then, if that doesn’t make any sense to you; though - like I said before - I understand your perspective, and I think that for real novice students/programmers there is no harm in that from a didactical point of view; I agree to disagree.

s, Fabiano.

fabianoantunes: I never said that difficulties where created by your examples. I'm sorry if anyhow you felt like I implied or suggested that. I meant that the student/person learning the basics, such as in the case of the author/creator of this topic, which clearly - by receiving his replies - can and gets confused with the simulated multi-tasking program structure that Arduino programming offers.

I am not taking any of your comments as personal criticism.

However my examples are specifically directed at the sort of person you describe and, consequently, your comments can only mean that you believe my approach is more complex than is desirable for a newcomer.

That is where I want your help so that I can make any necessary updates to my examples.

My reference to "code that might be found elsewhere" was only intended to distinguish my examples from any others.

...R

Right, then. I'll read your examples throughly and see if I can be of any help in this matter, because the real fundamental issue here, for programming newbies, IMHO, is that they don't/won't take the time to learn programming basics prior to trying and writing code for Arduino, which doesn't follow a standard cake recipe structure programming. It's intended for much more than that and people starting with the basics, mostly, don't realize that. I'll let you know and send you my notes once I'm finished reading your examples carefully. Should I send them to you via PM or do we continue this matter in here?

[]s, Fabiano.

Please continue the discussion here, in public.

...R

@Robin2,

I haven’t been able to examine entire post, but here’s something for a start: “Comments”.
I know, you code has comments. But for either professional or educational purposes, IMHO, they’re not quite enough. Let me explain:

  • For professional reasons:

  • Good quality code is not only about the code itself, but the quality and quantity of comments too, mainly if identifiers don’t have easy-to-identify-at-first-look meaning or if performing a very complex instruction.

  • It makes it easier for you and anyone else reading your code to understand what you’re doing and even check it the expected results are those in described in the comment.

  • It helps you remember what/why you did something at your code after a couple of years, or a bunch of code/projects. People (mainly starters) may think they don’t need this. Well, let me know in a couple of years.

  • For educational reasons:

  • It’s a good practice.

  • If you can’t explain it, you don’t really know what you’re doing. Plain and simple. You should have full understanding of what you’re doing or you should study harder.

  • If it’s too complex to explain, it’s bad code. This helps in separating code into functions. If your function is too complex and you can’t provide a short, clean, simple explanation of what it does, then you should keep “splitting” it into other functions. Do one thing and do it very well.

  • If it is the instructor/teacher who’s writing the program, the more comments you provide, the easier it will be for the student to understand each step of what you wrote. I usually think that there’s no such thing as over commented when it comes to code for educational purposes.

  • If the student doesn’t like those much comments, then a) he’s not truly interested in learning, but in copy-‘n’-paste. I tend not to waste my time with those. b) In a decent IDE, you can always collapse comments.

I hope you don’t understand it as bad criticism, as my sole intentions are helping people seeking for knowledge to achieve it.

Here’s a copy of the first program you wrote in that post, with ‘a little bit more’ of comments.

/*
 * newData
 * It's a boolean variable.
 * Boolean variables can hold either true or false.
 *
 * For our program, true will be assigned to newData if data has been received by the serial
 * port and has been collected (i.e., it's on serial port buffer).
 *
 * For our program, false will be assigned to newData in either cases:
 * 1) No data has been received by the serial port.
 * 2) Data has been received by serial port, but not collected yet.
 */
boolean newData = false; // We start with false, as the program has just started we don't have data to be collected by the serial port or to be handled yet.

char receivedChar; // Variable which will hold a single character, received by the serial port.

/*
 * setup()
 *
 * Arduino basic program structure function.
 * setup() is fully executed, only once, at Arduino boot.
 */
void setup ()
{
    Serial.begin (9600); // Opens serial port for communication, at 9600 BAUD.
    Serial.println ("<Arduino is ready>"); // Outputs message to the serial port.
}

/*
 * loop()
 * Arduino basic program structure function.
 *
 * loop() runs continuously, indefinitely, until Arduino is powered off.
 * It starts right after the setup() function finishes.
 */
void loop ()
{
    recvOneChar (); // Call/jump to function recvOneChar() ...
    // recvOneChar() lands here when it finishes.
    showNewData (); // Call/jump to function showNewData() ...
    // showNewData() lands here when it finishes.
    // Back to the beginning of loop()...
}

/*
 * Receives one char from the serial port, if available.
 */
void recvOneChar ()
{
    if (Serial.available () > 0) // Checks if data has been received by serial port and is available for read.
    {
	// If there is data available at serial port, collect it...
	receivedChar = Serial.read (); // Serial.read() reads one byte (char) from the serial port and assigns it to receivedChar.
	newData = true; // Sets newData to true, since we have collected data from the serial port.
	// Finished collecting data from serial port.
    } // Finished checking if data is available at serial port.

    // recvOneChar() finished, then, returning back to the calling point in the loop() function.
} // End of recvOneChar()

/*
 * Outputs one char to the serial port.
 */
void showNewData ()
{
    if (newData == true) // If newData is true, then, data has been collected from the serial port and we need to handle it.
    {
	// Start handling collected data...
	Serial.print ("This just in ... "); // Prints a message, without a line break.
	Serial.println (receivedChar); // Prints the contents of receivedChar variable, followed by a line break.
	newData = false; // Sets new data to false, since we have already handled data received from the serial port.
	// Finished handling new data.
    } // Finished checking if we had new data to handle.
    // showNewData() finished, then, returning back to the calling point in the loop() function.
} // End of showNewData ()

s, Fabiano.

Thank you. I have had a careful look at your example.

I can see where you are coming from. It was not, and is not my aim to present my code examples as an introduction to programming for beginners which is how your comments appear to me. I can easily see how a tutorial of that nature would be very useful and you are very welcome to write it. I can't see myself doing so. A big problem is how to decide the scope of a piece of work like that. It would be easy to fill a 200 page book, but then few would bother to read it.

For myself, when I am learning some code concept I prefer to have the instructions separate from the code. When there are large amounts of comments I find that they make it hard to see the code as a continuum. I try to use meaningful variable names and short functions so that the general concept of the code is obvious even with no comments.

A lot of this is, of course, a matter of preference - just like indentation.

...R