If statements are the backbone of decision making for microcontrollers and systems. They allow you to enter or bypass a section of code based on a condition or set of conditions. This could be as simple as checking to see if a variable is a 1 or a 0, or a more sophisticated condition such as determining whether an array is sequenced correctly. If statements follow the "if this, then that" mentality. So we'll take a look at how to use them in the Arduino IDE. We're going to be turning a simple momentary button that we've used previously into a toggle switch using code. Toggle switching allows for more complex tasks and doesn't require a huge amount of code. It's a good way to get started with using if statements as it highlights some of the decision-making elements to consider when using if statements. Not to mention that having a method for creating an efficient toggle switch is a great addition to any programmer's toolkit.
Along with if statements, we'll be introducing a couple of new elements such as variable modifiers and the very useful `millis` function. So let's take a look. Alright, so let's take a look at the code behind it. It's fairly straightforward and it follows some of the styling from previous code examples. We have our pin definitions up the top where we're using LED pin as the onboard LED pin 13 and button pin for pin 2. You can change these to whatever you like, of course, if you want to use an external LED that's fine too. Some global variables here are we're using the variable `toggleState` which will help keep track of whether our switch or our toggled state is a 1 or a 0, on or off. The last button state is so we can help remember whether the button was last pressed or released. Long unsigned int, now this is an unfamiliar one. You can see int is quite familiar but this bit here, long unsigned, what's that all about? Well, that's called a variable modifier. Long essentially doubles the length of the int, doubles the size of the container. Instead of only being able to store 2 bytes, it can store 4 bytes of data in there which is really handy.
Unsigned removes the possibility for negative values within the integer. You see within an int or any variable for that matter that is a signed variable, let's say it's capable of storing 10 values for simplicity's sake. It can store 8 bits worth of data or 16 bits worth of data. Let's take 10. If it can store 10 bits of data all up then half of those are going to be positive and half are going to be negative which means you can only count to 4 or perhaps 5 depending on how the system works worth of data. You can only count up to that far and then the rest is a negative variable. But we're going to be working here with time and we're never going to have negative time. But it could be the possibility that we don't press the button for such a long time. It goes into that extra length of time that we've got. So it's the equivalent of doubling again the length of the variable that we can store. So that's long unsigned int. Very useful if you know you're only ever going to be dealing with numbers greater than or equal to 0. And then again a standard integer variable is debounce time which we're going to be using for debouncing our switch. And we'll get to that a little bit later on.
So we've got void setup here. Pretty familiar. Pin modes to set our LED pin and button pin as outputs and input pull-ups as per the previous chapter. And then in the loop, this is where we get to the business end of the code. And it's not as complicated as it first looks. There's some comments here to help you sort through what's going on. So the first thing we're doing in our loop is we're going to read the value of the button and store it as a variable. Pretty standard. We've done it in the previous chapter heaps. So now that we know every iteration what our button is equal to. Now we've got two sets of if statements that we can separate a little here. We've got this one and this one. And you'll see they're actually nested in yet another if statement. So we'll separate those a little bit more. So this if statement here is the state or the sequence of events that will happen if the button is pressed. If the condition is true that it's a press. And the conditions here for if the button is released. And then above this we have another if statement here which is using this function called `millis` which we're not familiar with yet.
So what is `millis`? Well `millis` is a software timer that is specific to Arduino. It's an Arduino function. And what it does is it records the amount of time that has transpired since boot or since the program was initiated. So you can use `millis` to keep track of timing-specific things and use that to update other variables as a software timer. It's very useful. So what we're doing here is dealing with a property in switches called debounce or a phenomenon called debouncing. Or we're solving the bouncing issue using some debouncing if you will. So with a button, it's covered more in the all about switches tutorial on our website. So take a look at that. But simply put a button like any mechanical object has inertia. Which means when you press it whilst the contacts make contact with the other side. There's a little bit of bounce in there because it travels, hits, bounces, and finally settles. The bigger the switch, the heavier the switch, the more debounce there is going to be in that as well. So it's something to keep in mind.
Now ordinarily if you were to use this with an LED it would be happening so quickly you wouldn't even notice. But a microcontroller does. It's running fast enough. And because we're using it as a toggle switch. It will actually register all those individual little bounces that might be happening less than 5 milliseconds apart in total. It will register those as individual toggle presses which is not good. We only want it to trigger when we truly press and activate the button. So we're using a method that is similar to a low pass filter if you're familiar with that. And all it means is we're getting rid of the noise, the high-frequency noise that's happening. And we only want the events. We only want to do something on the events that are happening at a lower frequency. We're passing the lower elements of the signal. So what's happening here? Well, we've got an if statement. Now the if statement has two different or a few different things in here actually. We've got a set of brackets which are used for separating different elements. So we can see here that we're grouping together `millis` which is the time since boot. And then we're subtracting the value last press from it.
If this is a little bit complicated, don't worry. Just re-read it and it will eventually get there because it's a really powerful use of if statements. So `millis` minus last press. Now last press initializes at 0 because we haven't defined it. So it's going to be 0. So `millis`, let's say that we run our program for 10 seconds before we press the button. That means that `millis` is equal to 10,000 milliseconds because 1,000 milliseconds to a second. So 10,000, let's use this hypothetically. 10,000, we can put that in there. Minus 0 is greater than the debounce time. So what this is saying is if this number is greater than this number, then we're going to go into the code that follows the if statement. Now if it's not, we're simply going to bypass that whole section of code and keep going. And what this allows us to do is we can use this to track how frequently our button is being pressed. And if we press it, we don't want to do anything with it until an amount of milliseconds has transpired so we can ignore all of that debouncing noise. Or bouncing noise, I should say.
So we've got `millis` minus last press. And you can understand a bit or make a bit more sense once you dive into it. But we'll take that, you know, we're frequently checking to see if a condition is true. Then if it is, if the time, if `millis` minus the last pressed is greater than the debounce time, so enough time has transpired for the event to occur again, then what are we doing here? Well, last press is equal to `millis`. And what this is doing is it's just recording the time that the button was pressed. And it's recording that time in `millis`. `Millis` is constantly updating. So now the last press is equal to `millis`. So let's say this were to all happen again, almost instantaneously. `Millis` minus `millis`, which are almost the same thing, or sorry, last press minus that is equal to `millis`. So it's almost the same thing, is greater than the debounce time. Oh, it's not greater. And debounce time is equal to 20. So it needs 20 milliseconds to occur between presses in order for it to do something. So that's the debouncing there. It's quite simple, but really, really efficient as far as Arduino goes because we don't have any inline delays which chew up our processing.
Then in here, as I said, we've got these two levels of if statements, which are the really important parts. They're the heavy lifting which control the toggle action. So what do we have here? If button state is equal to zero, what's that using? The double equal signs there means is equal to. So we're using some operators here. And we cover operators more thoroughly in the next chapter. But these relational operators are used to check if one value is equal to or if it is greater than or if it is greater than or equal to different conditions like that. So if button state is equal to, because a single equal sign defines a variable, makes it equal to something, whereas double equal sign checks. So if button state is equal to zero, if it is currently being pushed down because that's active low logic, and the double ampersand here means and, so both of these conditions have to be true in order for something to occur. We could use an or relational logical operator, sorry, which would be if one of them is true, that's okay, but if both of them have to be true.
Because the reason for this is, so if button is being pressed low and the last button state is one, so that's checking if it is being pressed and the last time an action was recorded was it being released, because otherwise we would just hold it down and that event would continually repeat and repeat and repeat. So we need a way of saying only when it's a push, only when it has been released, and then we're pressing it again. And what do we do here? We have a variable called toggle state, which initially is equal to zero. So toggle state is equal to zero. Now we've got this funny-looking statement here. Toggle state is equal to question mark, sorry, exclamation mark, toggle state. What's the go with that? Well, what we're using here is another logical operator. The exclamation mark is called not. So what we're saying is that toggle state is equal to not toggle state. Now we can put that exclamation mark there. That'll work exactly the same way. But what that's doing is toggle state is either going to be one or a zero because it's just an on-off binary toggle switch, which is saying if toggle state is zero, well, toggle state now is equal to not zero, which is a one.
And if toggle state is one, it is equal to not one. So it's a zero. It just flips or inverts, toggles that value. Fantastic. So we toggle that and then we're writing that directly to our LED pin, which means every time a press is registered, it will turn the LED on equal to toggle state. Every time we press it, it flips toggle state. So one press, it'll be on. The other press, it'll be off. You could put a different event or function in here, but we're just toggling an LED for now. You could use it to count button presses, for example. And then we're recording the last button state, which is important. We're telling our program, yep, a press has been recorded. The next event has to be a release in order for another press to be valid. And then it will exit that loop there. Sorry, that statement, the if statement there. When it gets to the end of the curly bracket, all of your code goes inside the curly brackets. And once it's finished that, unless it's been told otherwise, it will keep flowing through the program. And it gets to here. If button state is equal to one, well, it's not equal to one because we've just said it's equal to zero because it's been pressed.
And that's happening so quickly, there's not enough time to press it and then release it in order for those to both become true. And the last button state is equal to zero, which means if it has not been pressed, if it is open, which is right now. So we need another condition to make sure it's only open after a press. So if it is equal to one, if it is high, if it is not being pressed, and the last button state equals zero, which means it has just been pressed and is now being released, then all we need to do is put last button state is equal to one. Set last button state to one so that we can reset our condition to register the press. So as you can see, if statements are really useful, really powerful logic statements that we can use to control the flow of events. So let's wire up our circuit and test out our toggle switch code and see how it goes. So first of all, we're going to need a push button. That's all we're going to need because we'll be using the onboard LED. You can, of course, wire up an external LED as per our previous examples, if you like, but I'm just going to be using a button.
Alright, so we'll put that in there, and that one in D2. So we just need two wires for this particular example. It's just using circuit examples that we've used before, so check out the previous chapters for how these circuits work and some wiring diagrams. And let's connect our Arduino up to our computer so we can upload this program. Taking your USB cable. Plug our Arduino in. Alright, now let's go ahead and upload this, making sure you have your board type and COM port selected. Upload. Oh, what have we got? So we've got an error, and that's because we left in the if-else, so we didn't include the correct brackets. So we'll delete that, and it's going to work exactly as intended now. There we go. Beautiful. Done uploading. So when we push our button, our LED onboard turns on. I don't know if you can see that very well. In fact, I might just wire up an external LED really quickly so that you can see that a bit better. So I'm just taking the LED, wiring it up here with a resistor, and I'm going to connect the negative leg of the LED to ground as per our previous example. So I'll just use the onboard ground pins here to complicate things.
Take the jumper lead to connect that to pin 13. I'll just hook it straight into pin 13 so I don't have to modify any of the code. And there we go. You can see that LED a bit more clearly. So when we push our button, it turns off and it's running, toggling, press on, press off, press on, press off. Very useful, very cool bit of code. So that's a little bit about how if statements work. And if they seem a little bit complicated, don't worry. It can take a little while to wrap your head around. But I consider this such a fantastic example of if statements because being able to create a toggle switch out of a simple momentary push button is so invaluable. Everything from creating user interfaces to all sorts of projects which require tactile input are really important, and they're going to rely on being able to just register the press of a button and perform an event such as a toggle switch. So that's a bit about if statements. You can see that we've got if a condition is true, run the section of code. If the condition is false, bypass the section of code in the curly brackets and continue on with whatever else the program was doing.
Now, there's one more thing to if statements which we haven't quite covered here, and this is if else. So else is a really handy statement. As we've seen, if allows us to say if a condition is true, then run this code. And we've got another if statement here saying, oh, if this is true, run this section of code. But there could be a situation where both of these are true, and we don't want them both to run in the same loop, which is where else comes in. So we use else, exactly the same as an if statement, except there's nothing inside the brackets. So if we were to go down here and create another else statement. Now, else, and this says if all of it has to be preceded by an if statement, and it says if the if statement's before it, if none of those, or if there's only one, if that one's not true, but say if both of those are false, then let's perform something else. So it's sort of like a default, a backup option, where if none of the other conditions for any of the if statements before it in the current level are true, else, let's do something completely different. And you can use else with if as well.
So you can use if else. And what this does is it says, well, if these conditions are true, but else, so we can't run both of these, else that has to not be true. So if that if statement is true, it will automatically cancel out that one. So only one of them can run. Really, really handy. I've put a quick reference guide along with the source code of this on the text file for the workshop. It's up on the webpage there. You can go take a look and re-read it and get a good understanding of how if statements work because they're incredibly powerful, and we're going to keep looking at some different logic statements in the next couple of sections.
Makers love reviews as much as you do, please follow this link to review the products you have purchased.