Using Serial.parseInt() with Arduino

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
- [Instructor] Are you trying to send numerical values over the serial port using parseInt with Arduino, like you're trying to send integers or something like that? Maybe you're struggling to understand the difference between serial.read and serial.parseInt and how they can work for you. Do you just need to convert multiple digit characters to one integer? Well, in this lesson, you will learn exactly how to use parseInt from the Arduino serial library to convert characters into an integer. Get ready (lighthearted music) Subscribe to our YouTube channel to get more videos like this. Are you learning Arduino programming? Check out our membership program to learn the software and hardware skills you'll need to build your own projects. You will get an all-access pass to our high-quality video training that covers everything from the basics of programming like variables and control structures up to using interrupts, arrays, and more. Follow the link in the description to sign up today. All right, let's talk about what we're gonna cover. First, we'll do a quick overview of serial communication. We'll compare serial.read with serial.parseInt. We'll play around with some code for converting characters to integers with parse.Int. And then we're gonna talk about the several parseInt details, like setTimeout, lookahead mode, and ignore. If you've already watched our lesson on using serial.read, then you already know one method of taking serial input and converting the characters into an integer by putting all the incoming bytes into a character array. If you wanna learn that method, make sure to check out the lesson on serial.read. Now, that code worked great, but it was somewhat lengthy. In this lesson, we're gonna talk about a different way to do it and we'll be using the function from the serial library called parseInt. So let's do a quick review of how serial communication works with Arduino. Your Arduino has some hardware on it that will allow you to receive data serially over USB. It will store that data in a buffer called the serial receive buffer. Now, if the word buffer throws you off, don't sweat it. You can think of a buffer like a bunch of horse stalls in a stable. Some stables are big and have a bunch of stalls. You can put a bunch of horses in there. Other stables are quite small and you only have room for so many horses. You can't take in more horses than you have stalls. A buffer is like a stable, but instead of having horse stalls, it has spaces and memory where the data can be stored. Generally speaking, a buffer is a transient place for data storage in a program. Usually you're gonna be receiving data into a buffer and then reading it out pretty quickly because more data is gonna be coming in and you need to make space for it. This isn't some hard and fast rule though. The serial receive buffer has room for 64 bytes. So when data comes to your Arduino over serial, each byte will end up in this serial receive buffer. It's your job as the programmer to read the data out of the serial receive buffer and actually do something with it. Say your Arduino is attached to your Raspberry PI and the Raspberry PI has a program sending serial data to your Arduino. You've got to do something with that serial data that's ending up in the serial receive buffer. But how do you do that? Well, it turns out there's quite a few ways. If you wanna take out each byte at a time, then you can use the serial.read function. When you use serial.read, it takes out the first byte in the serial buffer. And that's what it returns. The rest of the bytes then shift over. If your serial received buffer was filled with the characters, SeaBiscuit, and you call serial.read once, then the capital S would be read out and eaBiscuit would be left, every character having shifted over so that now the lower cased E is the next in line. Serial.read is great if you wanna read in each character at a time and then maybe do some things based on different characters that come in. But what if you wanna get a whole number like 1776? If you use serial.read, you'd get a one and then you'd get a seven and then you'd get another seven and finally you'd get a six. Plus, they'd all be stored as characters, not as integers. And you don't want one digit integers all the time. You might want the whole number 1776 saved as an integer. Now, as I mentioned before, we talked about how to accomplish this in the last lesson using a character array and the atoi function. But there's a somewhat simpler method if all you wanna do is convert the character input into an integer. That's where the parseInt or parseInteger function from the serial library comes in. What the parseInt function will do is scan down the serial receive buffer one byte at a time in search of the first valid numerical digit. So if you have the characters, 314, in the serial receive buffer, you'd get 314 returned the first time you call serial.parseInt. If you had "I ate 314 tacos" in the serial receive buffer, you'd only get 314 returned the first time you call serial.parseInt. So parseInt is looking at the first item in the serial receive buffer and it's checking, "Hey, is this character a numerical character like zero through nine or a negative sign? If it is, I'm gonna go ahead and start reading in until I get to a non-numerical character." This scanning that parseInt does allows you to grab an entire integer out of the serial receive buffer. What does serial.parseInteger do with non-numeric values in the serial receive buffer? If the non-numeric values are only before a valid numerical digit, what it does is it tosses them out. It grabs those numerical digits. Then it leaves the rest in the serial receive buffer. So if in our serial receive buffer we had "I ate 314 tacos," when we call serial.parseIn the first time, it's gonna skip over I ate. It's gonna grab the 314 and combine them into one integer. And then it's going to leave the space tacos in the serial receive buffer. It's not gonna touch that. What does parseInteger do if there's only non-numeric values in the serial receive buffer. If all parseInteger can see in the serial receive buffer are non-numeric values, it's gonna return a zero and it's gonna leave all those values sitting in the serial receive buffer. It's probably like, "Hey, why are you calling me? There's no numbers in the serial receive buffer. That's what I'm for, getting the integers, not this stuff." Now, if you start getting a bunch of zeros returned from parseInt and you're not sure why, remember that newlines and carriage returns maybe added when using the serial monitor window in the Arduino IDE, even though you're not actually gonna see them in the send section where you enter the text. If you don't want these terminating characters, make sure to select No line ending from the dropdown. Now, a common method of using parseInteger is to pair it with a while loop and serial available. So that the only time you check for a new integer is when data has actually arrived at the serial port. Now, if this code structure looks odd to you, then check out the lesson that we did on serial.read because it explains it in depth. So this code construct here is how you can convert data coming in over serial in the form of characters into a whole integer. But there's a couple really important things you need to know about the parseInteger function. As they say, the devil is in the details, and parseInt has a couple of really neat details. The first of these interesting details is that parseInteger actually returns a long data type. It's not an integer data type. So if you've got a big number coming in, you can save it into a long data type variable. Second is the fact that parseInteger will time out after a given programmable set point. The default set point is one second or a thousand millisecond. Let's say, for example, it takes awhile for your data to arrive at the serial port. Like maybe every 300 milliseconds, you get a new character, maybe you get the three digit, 300 milliseconds later you get the one digit, 300 milliseconds later you get the four digit, 300 milliseconds later you get the five. So the total time to receive the value 3145 is 900 milliseconds. Instead of just reading out each of those values as it arrives, parseInteger is gonna wait that set amount of time before it returns the integer that it's found. To adjust the timeout period, you use the function serial.setTimeout, and you parse in the amount of time that you want parseInteger to wait. So in the example above, parseInteger would read out the three as soon as it came. It's still in that timeout period. And then when the one came up, it would read the one out and add that to the end of the three. So now we'd have 31. It'd still be waiting. The timeout period's still going. It grabbed that four when it came in, added to the end. So we'd have 314. And then finally, the five came in just in the nick of time and then it put the five at the end. And it would return the integer 3145 or 3,145 as one integer. But what if the delay was even longer for incoming characters, say 400 milliseconds? So we'd be able to get the 314 but then that last digit five would still be sitting in the serial receive buffer because it didn't make it in in time. So the first time parseInteger is called, we get 314. The next time we call parseInteger, then we get the five. Again, the devil's in the details. This set timeout function is something you'll definitely want to explore. It's kind of interesting to play around with that timeout period and see what results you get. Another interesting detail of the parseInteger function is that you can call it with optional parameters. The first optional parameter is called lookahead mode. And there are three predetermined lookahead mode values that you can send, skip, skip_all, and skip_whitespace. Skip_all is the default mode which is used when you call serial.parseInt and you don't parse anything. So you could use it explicitly like serial.parseInt skip_all. That would be the same thing as just calling serial.parseInt. So it's the default mode. With the skip_all mode, all characters other than numerical digits in a minus sign are ignored as parseInteger scans down the serial receive buffer in look of its first numerical digit. This is the behavior that we've already explored. If you use the skip_none mode, what this does is tell parseInteger, as it scans down the serial buffer, not to skip any of the items. So basically what it's saying is, "Hey, when you look at that first value, if it is not a numerical digit or a negative sign, then we're not gonna mess with anything in the serial receive buffer, and it would return a zero." So let's say your serial buffer you had "You ate 314 tacos." If you call parseInt, it's gonna return a zero. It's going to say, "Hey, you told me to skip none. The letter capital Y is not a numerical digit, so I'm not even gonna mess with this." Finally, with lookahead mode set to skip_whitespace, then only tabs, spaces, line feeds, and carriage returns are skipped. Now, tabs, spaces, line feeds, carriage returns, they are all represented in ASCII. So they all have ASCII values. And those ASCII values are what is going to be skipped when we use skip_whitespace. So let's say your serial receive buffer you had a bunch of spaces. So again, there's an ASCII code for a space. So you have a bunch of spaces. Then you have the numerical numbers, 314, another space and then tacos, exclamation. If you call parseInt with skip_whitespace's lookahead mode, it's gonna skip all that white space and then grab the 314 for you. This lookahead feature is pretty cool, especially if the data you're receiving has a bunch of mixed things, like maybe you're sending character commands like turn on and turn off, but you're also sending numerical values like 314 or whatever. These options give you one way to differentiate between that incoming serial data. But is there a way to ignore specific characters coming into the serial port and just grab the numerical values? Well, in fact, there is because parseInteger has another optional parameter that you can parse. So first, we have the lookahead mode that we can parse. And after that, we can send a character that we want to ignore. For example, maybe you've got commas on the incoming data stream or any character for that matter. You can parse that character as the ignore value. So if in the serial buffer you had 3,142 and you had a comma in there, parseInt would ignore the comma and grab out the 3,142 for you. That's pretty cool. This can come in handy if there are characters you don't want to act as delimiters in your number. Also, when you're putting in the value, make sure to use single quotes around your ignore value so that parseInteger knows that it's a single character. All right, we covered a ton. Let's do a recap here. So we talked about how serial data, when it arrives at the serial port, it goes to the serial receive buffer. We said that, hey, serial.read is great, but it only reads in one byte at a time. We talked about how parseInteger can be used to convert characters in the serial receive buffer into integers. We talked about three lookahead modes, skip_all, skip_none, and skip_whitespace. We know that the default lookahead mode is skip_all. We also talked about how you can ignore a specific character in the serial receive buffer with parseInteger. Thanks a ton for watching, and I hope you learned something useful. Make sure to check back soon for other great lessons. Hey, take it easy. And I look forward to seeing you next time. Bye. (gentle music)
Info
Channel: Programming Electronics Academy
Views: 45,234
Rating: undefined out of 5
Keywords: Arduino, Arduino(Brand), Arduino Tutorial, Arduino Lesson, Open Source Hardware Group, Learning Arduino, Microcontrollers, Electronics, Arduino IDE, Arduino Sketch, Computer programming, C++, Programming Electronics Academy
Id: lcjLUdDB1Us
Channel Id: undefined
Length: 15min 38sec (938 seconds)
Published: Fri Jul 02 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.