delay() Arduino Function: Tight Loops and Blocking Code
Let’s say you’re making a project with Arduino. And you want some event to happen at a timed interval. Maybe every three seconds you want a servo to move, or maybe every minute you wanna send a status update to a web server.
Whatever it may be, you want something to occur at a timed interval. How do you do that?
If your answer is using the delay function, well, you’re kind of right. But there is another way. And that’s using the Arduino millis function. And the more familiar you are with using the millis function, to help you time events in your Arduino code, the easier it will be to incorporate other parts into your program later on.
Plus, you’ll be happier, more cheerful, and gosh darn it, people will like you. Now, this is the second part in a series about using the millis function. In the first part, we described what the millis function is. By the end of this lesson, you’ll get a better sense of why the delay function can start to cause issues in your code.
Specifically, in this lesson, we’ll talk about tight loops, blocking code, and an ancient recipe for inspiring music. Alright, we’ll I’m gonna take you on a little journey. And this is the first part of that journey. Where I ultimately wanna end up, is I want you to be able to use the Arduino millis function in your code so that you can create timed repetitive events.
So, let’s go ahead and start this journey. And what I wanna do, is talk about a couple concepts that I will think help us understand the why and the how of doing what we wanna do. So, we’re gonna start with the concept of a tight loop. And when I say a tight loop, what does that mean?
So let’s take a look at an Arduino sketch to kind of demonstrate what I mean by a tight loop. So, here we are in an Arduino sketch, and we’ve only got two functions. Void setup, and void loop. And as you may know, void setup only runs once, and then it hands the show over to void loop.
And what void loop does, is it goes through every line of code that might be inside the loop, inside these curly brackets. And it executes the first line, then it executes the second, and then the third, and so on and so forth, until it gets to the bottom. And then it goes back to the top.
And it does that as fast as it can. Now how fast can it actually do that? Well, it depends on which Arduino board you’re using. But an Arduino Uno has a clock speed of 16 megahertz. So that means that 16 million instructions are happening every second on the Arduino.
Now, each line of code isn’t necessarily one instruction. In fact, it’s most likely that it’s multiple instructions. But still, that’s pretty fast. So let me get rid of these comments real quick, and I have a question for you. Is this sketch right here, the one where I have no code in this loop, is this a tight loop? That is, is the time from the start of the loop to the end of the loop, is that fast? So the answer here is, yes. This is about as tight of a loop we can get.
And that is because there’s literally nothing inside the loop that gets executed. So the time between the start of the loop at the top, and it getting to the bottom it’s like practically zilch. So this is a very tight loop. Now let’s add a couple lines of code.
What I’m gonna do is start serial communication, and then I’m gonna print something to the serial monitor window. So let’s do that. Okay, so now, in the loop function, I have one line of code. And I’m printing something to the serial monitor window. And I’m gonna ask you a question again. Is this a tight loop? That is, from the start of the loop to the end of the loop, does that take a lot of time? So, we still have a pretty tight loop, here. We’ve got one line of code.
Now, it’s worth noting, that this loop is not as tight as the previous example. In the previous example, we had no code. So it was just racing through this loop. Now, we’ve got a function here, a serial print. And so we are gonna be taking time to print something to serial monitor.
But for all intents and purposes, this is still a pretty quick loop. So now what I’m gonna do, is I’m gonna add a little bit more code. What I’m gonna do is, I’ll have the program check to see if a button is pressed, and if it is, I’ll have it write something to the serial monitor. So let me do that now. Okay, so I’ve added some code. I’ve declared a button. And then I’ve got an if statement, and we check to see if the button has been pressed.
That is, is the voltage at pin five high? And if it is, then we print something else to the serial monitor window. So if I press the button, then it prints something different out to the serial monitor. So, I’m gonna ask you again. Is this a tight loop? So, from the start of the loop, to the end of the loop, is that pretty quick?
So, I would still say, yes. This is a pretty tight loop. We’ve got one, two, three, four, four lines of code. We’re printing to the serial monitor, and then we’re just doing a quick check to see if a button’s being pressed. And if it is, we print something out. So, I would say, yes.
This is still a pretty tight loop. Now, it’s not as tight as the last two examples. But all of this code is still happening pretty darn quick. So let’s look at one final example. What I’m gonna do, is add a delay to this program, using the Arduino delay function. So that I don’t have this printing to the serial monitor so frequently. So, let me do that. Okay. So, now I’ve added a delay to the loop. And it’s a thousand millisecond delays. So that’s one second.
Now, I wanna know. Is this still a tight loop? Is the time from the start of the loop to the end of the loop, is that a lot of time? Okay, so you’ve probably guessed that, no, this is definitely not a tight loop. The code starts fast. We do the serial print.
But then we get halted right there at the delay function. It’s like the whole program comes to a standstill, and we need to wait for this delay code to finish. When the Arduino gets to this line of code, it’s kind of like going to the grocery store. You get into the 12 items or less line, but then the guy in front of you pulls out his checkbook, and starts writing a check. You know you’re gonna be there for a minute. It’s the same deal here.
So this is not a tight loop. The time from the start of the loop to the end of the loop is pretty significant. Especially compared to the last couple programs. The order of magnitude of time is huge. Now, one thing you might have started picking up on.
And I was trying to demonstrate it here, is that this whole thing about tight loops is relative. It all depends on your application. If you need to check the status of a sensor every 10 millionth of a second, then a program that has three lines of code may not be tight enough at all.
It just depends. And another point to make is that not all lines of code take the same amount of time to execute. If you’re calling a function that does a bunch of stuff, like serial print, for example, then that one line of code may take a whole lot longer than 10 other lines of code.
So, the tightness of a loop is a relative idea. Okay. So, when a program stops at some point. When it takes some time to execute some code. That code can be called blocking code. And this is kind of like, just a general term. So here, we’ve got the delay function, and the delay function is acting as blocking code. Because none of the other code after delay can run. So it’s getting blocked. But, it doesn’t just have to be the delay function.
Let’s take this code and let’s get rid of delay, but we’ll add a for loop. So, I’ll do that now. Okay, so I’ve added a loop to this program. And it prints out numbers to the serial port, and some other text. So, how long does this loop run for?
Well, it’s gonna run for a while. It’s gotta go through 100 iterations before it stops. Now, this is gonna take some time to finish. And what does that mean for the code after this for loop? Is it able to go? Well, it’s gotta wait because it’s being blocked by the for loop.
So here, we could say that this for loop is blocking other code. It’s acting as a block. Now, here’s a quick side note, that I think is worth talking about. This loop, this for loop, well it’s also a loop. It’s nested inside the main loop.
And I’m gonna break my promise here, and I’m gonna ask you again. Is this for loop, is this a tight loop? Now, before you answer, let me re-emphasize how I want you to think about this. For one time through this for loop, from the top to the bottom.
Does it take a lot of time? Well, not really. It’s only got two lines of code. So this is a pretty tight loop. But it’s a tight loop that goes through a lot of iterations. So, even a tight loop, if taking long enough, can block our code. Okay, that was a little bit of a deviation, but anyway.
Okay, so we’ve talked about tight loops, and we’ve talked about code that blocks, or blocking code. Now I wanna take a moment and just talk a little bit more about this delay function. What’ve we established so far? Okay, first we’ve said that the delay function decreases the tightness of a loop. So if you’ve got a tight loop, and you add the delay function, well, it’s gonna make it less of a tight loop. That is, the amount of time it takes to get from the start of the loop to the bottom.
That time is gonna increase with the delay function. So we also know that the delay function blocks code. Kind of goes hand in hand with what we just said. So, when the delay function is running, it is gonna block other code from running while it’s going.
So we could be like, man, this delay function is a total slacker, and it’s never gonna amount to anything in our projects. But you know, for a lot of simple programs that we write, delay function works fantastic. It’s simple to use, it’s really easy to spell, and it does just what it says.
So, we shouldn’t necessarily ostracize delay from our programming toolbox. We should just recognize that it’s a simple programming function that can work in a lot of instances. But there is a time when you start to run into issues. And that has to do with the blocking effect that the delay function has in our program.
Now, in the next lesson in the series, we’re gonna identify where this really becomes an issue. You’ll learn when it makes sense to use the delay function in a program, and when it’s time to switch to using the millis function. So let’s do a quick review. First, we talked about the tightness of a loop.
And we said that the tightness of a loop is relative. It depends on what your application is. Then we talked about blocking code, or code that blocks. And essentially, it’s a generic term we can give to code that’s gonna take some time to execute, that’s gonna stop other parts of our program from running while it executes.
Well, I hope you enjoyed this lesson. In the next part of this series, we’re gonna continue our journey of learning how to use the millis function to create timed, repetitive events in our Arduino code. I’ll see you there. Bye.