void setup() {
Serial.begin(9600);
}
void loop() {
char buffer[] = {' ',' ',' ',' ',' ',' ',' '}; // Receive up to 7 bytes
while (!Serial.available()); // Wait for characters
Serial.readBytesUntil('\n', buffer, 7);
int incomingValue = atoi(buffer);
Serial.println(incomingValue);
}
There are some limitations to using that method. For example, what if you want to keep your program active while waiting for Serial input to finish? Or if you want to ignore certain characters (like a comma or decimal). The following code gives you much more control over receiving multiple digit integers like 99 or 100 or 1000. There is also an explanation of how this code works, so you can modify it for your sketch.
Code Example
void setup() {
Serial.begin(9600);
}
unsigned int integerValue=0; // Max value is 65535
char incomingByte;
void loop() {
if (Serial.available() > 0) { // something came across serial
integerValue = 0; // throw away previous integerValue
while(1) { // force into a loop until 'n' is received
incomingByte = Serial.read();
if (incomingByte == '\n') break; // exit the while(1), we're done receiving
if (incomingByte == -1) continue; // if no characters are in the buffer read() returns -1
integerValue *= 10; // shift left 1 decimal place
// convert ASCII to integer, add, and shift left 1 decimal place
integerValue = ((incomingByte - 48) + integerValue);
}
Serial.println(integerValue); // Do something with the value
}
}
Caution

- You absolutely must enable “Newline” (only) termination in the Serial Monitor (or your favorite serial terminal program). Otherwise, the while(1) loop will never exit. See below for a screen shot on how to do this in the Arduino IDE.
- The maximum value you can send is 65535. There is no checking to verify if this will overflow.
Why does this work?
There are 4 lines of code that make this work. The first block are:
while(1) {
//...
if (incomingByte == '\n') break;
if (incomingByte == -1) continue;
The while(1) will cause the Arduino to wait until the character ‘n’ is received. This is “Newline”, set by the Serial Monitor. The second is an important fact that Serial.read() will return -1 if no characters are available. This keeps the program from having to constantly check Serial.available(). Math can be fun and may make the next couple of lines look like magic, but let’s break them down.
[cpp]integerValue *= 10;
integerValue = ((incomingByte – 48) + integerValue)[/cpp]
When a decimal number (base 10) is multiplied by 10, all of the digits shift left once. So each time a digit is entered, the value of integerValue is shifted to the left and the new digit is added. Cool, eh? Why do the subtraction? Because… the variable ‘incomingByte’ has an ASCII value in it. The character “0” has an ASCII value of 48. (See this ASCII Chart for more information.) So by subtracting 48 from the incomingByte, we get the integer value of that ASCII character. [Note: This is why you are limited to “65535”. This is the maximum value that can be held by an unsigned int.]
Conclusion
Either the Serial.readUntil() method or the code above can be used to receive big integers. They both have advantages and potential disadvantages. It just depends on what you need to do in your code. Keep in mind, both methods require having the IDE set the line termination to ‘n’ (newline).How else do you want to capture serial data?
48 Comments
Excellent communication tutorial with the ARDUINO. It has helped me with my project, thanks for all this great effort 🙂
Can we recieve negative integers with this code
i use this method on the stm32f4 i send 3 different values height and angles but after second and third values board is stacking.
HI. I am reading 24 bytes from a xbees serial port, but only need the last four of the 24 bytes. The first of the four last bytes refers as a device (or xbee) number and the last three as an analog value. Can you help?
couldn’t get this to work until i exchanged break and continue and then this worked fine but i when i assign intergerValue to an int it allways gives me 30053 for a number when i serialprint, any sugestions?
Exchanging break and continue will cause the code to stop working. The intent is to break out of the while(1) loop once the new line character is received. The continue allows for skipping processing when no character comes in, since Serial.read() returns -1 when the receive buffer is empty.
Since the variable integerValue is defined as an unsigned int, in your version of the code -1 is getting processed when it should not have been.
That said, if you see problems with the original code, change incomingByte to an int or byte on line 6.
I tried to send the data from C#. But it seem like not working. Could you please help me for this case.
serialPort1.Write(“100”); // Send 100 to the arduino
My code is looking for ASCII characters. Is C# sending ASCII or the binary numbers 0x01, 0x00, and 0x00?
I want to use this with visaul basic but it’s does work
Thank you! You’ve very helpful and I appreciate it.
Randomly stumbled on your website after doing a bit of Google searching for some Arduino-related information. This was pretty helpful. Thanks for this! I’ll definitely check out some of the website.
hello dears,
i have a small bugg with getting a value from serial, it s an ascii code ( ex: 0x05 0x00 0x00 0x00), all i need is the value 5 and the i want to get rid of the other three bytes, so i wrote an arduino code as following :
[arduino firstline=””]
void setup() {
Serial.begin(9600);
pinMode(53,OUTPUT);
}
void loop() {
while (Serial.available() == 0);
byte n0 = Serial.read();
String mystring = String (n0, DEC);
if (n0 == 5 )
digitalWrite(53,HIGH);
else
digitalWrite(53,LOW);
{
Serial.println(n0);
}
}
[/arduino]
but the n0 returned is :
Serial.print(n0); => 5000
or
Serial.println(n0); =>
5
0
0
0
my question: what can we do to Keep only the value ( 5) and get rid of the other bytes,
i.e : what what should we do to get a new variabl with the val 5 ??
thank you very much.
(Now reformatted) lines 14-16 execute every time loop does, which is everytime there is a byte in the serial buffer. So it is going to print exactly what you receive. If the sequence is always 4 bytes, then just ignore the other three.
There is no reason to use “String” in this code. The if-statement on line 9 could just be if (n0 == 0x05).
dear James,
thanks for the claification, but the “0x05” i mentioned is just an exemple, it can be any other value, but the last three zeros are ruining the aplication, in another way is there a possibility to split the code and get a variable containing only the first byte/digit ??
Just drop the last three.
[arduino firstline=””]
if (Serial.available() > 3) {
byte n0 = Serial.read();
for (int x; x< 3; x++)
Serial.read();
}
[/arduino]
Got it now 🙂 tks
Saved my day ty 🙂
I mean can I read a log file using arduino
The Arduino communicates with the PC over serial. If you can write a program on the PC to interact with the serial port, sure, you can read a log file.
Can I read a log file from my pc using ariyumo
I say thank you more than one trillion time.
i want the work some think like that but due to weak programmer i am unable to do so.
i am trying to call function from single push button and if i press button twice(suppose ) i want to be in configuartion setting where i can add some value manually from serial monitor like apn,username,password and url extra so please if can help in this
Thank you!
I have used your code to read csv values from an SD card, it worked perfectly after I figured out that I was getting a Carriage Return (\r) at the end of the line and adjusted the code by adding the following lines:
if (incomingByte == ‘,’) break;
if (incomingByte == ‘\r’) break;
Regards,
Peter
I have project to revice data sensors in serial data from an other arduino as data logger, the data logger is sent packet data with start byte (*) and end byte (#)
The data example like this:
*4/10/2015,1:58:01,2,30,60,3000,1.2,360.0#
*4/10/2015,1:58:02,4,40,160,3010,1.3,0.10#
*4/10/2015,1:58:03,6,50,300,3520,1.4,1.00#
How do i receive packet correctly?
Thank You James
Lots of answers. I would suggest posting a question on the Arduino Forum and sending me a link. That way others can help you.
Hey James
This was really useful. I have an another question
suppose I enter N-bit number in serial monitor then how can i spilt it into digits and use it??
Thank you
What do you mean by “N-bit”? Can you give an example.
Basically, I want to enter a 4 digit no then my system will check whether it is a 4 digit number it is. then it will assign each digit to a variable.
if (Serial.available() >= 4)
need_message = false;
type = Serial.read();
parameter = Serial.read()
n = Serial.read();
l = Serial.read();
I tried this way, but I m getting some ASCII and some random values.
please ignore Need_message = false
How are you sending the characters? The Serial Monitor sends LF and CR by default. (it’s selectable in the dropdown.) Probably a good idea to ignore anything that’s not in the range of ‘0’ and ‘9’.
Hello James
This article was very helpful for me. Thank you much !
Claude
It is a helpful tutorial, appreciated it.
May I have another question about the serial message sending.
I wanna use an analog input to measure DC voltage(not only 5V) and send the value to serial immediately.
if it is a continue voltage, the value sending is correct.
Currently, there is a chopping voltage like square wave, the frequency is around 500 Hz and duty cycle 50%, I want to measure it by analog input.
I tried to print the value to serial in few seconds and drawing the value against time,
it seems the sending rate(sample rate) is not fast enough, so the wave is not correct and not a period wave.
Is there something wrong about the sending??
The amount of time it takes to transmit serial may be slowing down the sampling rate. Make sure you are using 115200 baud. If not fast enough, cut down the number of characters you are transmitting.
Do you know a way to get this to handle negative numbers that are sent?
Working a little bit more, here’s the code. Bascailly, set a flag when the negative character is received. Then when the operation is done (newline or \n is received), invert the value.
Don’t forget to change the type of variable to “int” for integerValue.
[arduino]
void setup() {
Serial.begin(9600);
}
int integerValue=0;
bool negativeNumber=false; // track if number is negative
char incomingByte;
void loop() {
if (Serial.available() > 0) { // something came across serial
integerValue = 0; // throw away previous integerValue
negativeNumber = false; // reset for negative
while(1) { // force into a loop until ‘n’ is received
incomingByte = Serial.read();
if (incomingByte == ‘\n’) break; // exit the while(1), we’re done receiving
if (incomingByte == -1) continue; // if no characters are in the buffer read() returns -1
if (incomingByte == ‘-‘) {
negativeNumber=true;
continue;
}
integerValue *= 10; // shift left 1 decimal place
// convert ASCII to integer, add, and shift left 1 decimal place
integerValue = ((incomingByte – 48) + integerValue);
}
if (negativeNumber)
integerValue = -integerValue;
Serial.println(integerValue); // Do something with the value
}
}
[/arduino]
This was an awesome tutorial! Thank you so much. Really helped.
Thank you for this great article. I have a litlle issue: I tried to do specific actions when a specific string are typed in serial monitor. For exemple, I want a led to become HIGH if I type the word “on” in the serial monitor. The problem is that it turns HIGH whatever I type in serial monitor. I tried several codes but without sucess at all. For example, using your code I modified this line to:
if (incomingByte == ‘on’ && incomingByte == ‘\n’) break;
digitalWrite(led, HIGH);
The led turns HIGH If I Type any string in serial monitor, not a specific string.
Can you help me in this issue?
Thank you in advance.
Best regards
If you read your code outloud, you might understand your problem.
if (incomingByte == ‘on’
“on” is two characters, which means it is two bytes. You only receive one byte at a time. The easiest thing to do is make your “Commands” single characters.
Hey
I’m glad to run into your code. It’s much better to read a byte instead of trying to piece an integer number together from ascii digits like this guy does it here:
http://combustory.com/wiki/index.php/Arduino_Communications
Very strange that yesterday his code worked, today with the same settings it does not. I reseted, unplugged ardu all the settings are the same…
One little correction for your article is that
if (incomingByte == ‘n’) break;
Should be
if (incomingByte == ‘\n’) break; // exit the while(1), we’re done receiving
I guess the engine of your blog removes the \ (ASCII 0134) character.
Thanks. I fixed the newline references. There’s some background process that runs which mangles code. I copy/paste/compile after posting, but at some point it gets mangled.
some thing wrong in code still print byte byte ??!!
I’m sorry, but I don’t understand your comment.
Thanks a bunch for this article, it really helped me out. I didn’t know Serial.readBytesUntil() even existed.
Hi there,
I want to use something like Serial.readBytesUntil() for just 7 chars. but if the user inputs something larger than 7 chars I get something weird:
first line: 1234567
second line: 8934567
How can I limit the function from re-writing the extra chars?
Either flush the input buffer before calling readBytesUntil() or don’t use it. I’m not a fan of the function because of its limited use such as cases like this. It is also probably a bad idea to rely on a human entering the correct number of characters. You are better off waiting for a delimiter like end of line.
Mihalis, good point. I’ve updated the code and explanation.
If you multiply integerValue by ten, after line 14 and before you add (incomingByte – 48) to it:
……
13 if (incomingByte == ‘n’) break;
14 if (incomingByte == -1) continue;
15 integerValue *= 10;
16 integerValue = ((incomingByte – 48) + integerValue);
17 }
18 Serial.println(integerValue);
19 }
20 }
you don’t have to divide by 10 and you can use
integers to 65535.This happens because every time you have a new digit you first shift the old integerValue, by multiplying by 10, and then you add the new integer which you may not need to shift because your could find ‘n’ and break the loop.
Your code helped me a lot!Thank you!
Good stuff!