In this video, we are going to learn all about functions in MicropPython. Functions are just a way of storing a piece of code away, giving it a name, and then running that code when we call its name. This is a great tool to use when we have sections of code that need to be repeated. We will also be covering some tricky caveats when dealing with functions, namely; parameters, arguments, and local and global variables.

Transcript

Functions are typically a bit of a harder concept for beginners to grasp, but an easy analogy would be like teaching a robot to do the Macarena dance. Let's imagine that you had to program the movements of a robot to do the Macarena. You might tell the robot to do that, and then that, and then that, and that, and so on until you tell it to rotate around. And with how that dance works, you repeat that exact same set of moves over and over. But imagine if you had to program all of that again, every time you wanted the robot to repeat those same set of dance moves. It would be really long and tedious. Well, that's where functions come in. What if instead we write the instructions of how to do one loop of the Macarena, store it in a place in our code, give that place a name, and then whenever we want our robot to do one loop of the Macarena, we just call that name and it will follow the instructions that we wrote, as if it's like following a recipe that we've pre-written. And that's what a function is. It's a chunk of code that we store somewhere that we can call the name of and execute that code that we have stored inside of that function.

For example, here is some code I've written to flash SOS on an LED when we press the button. And I've done so by using a function. So here that is. And as you can see, creating functions is super easy. We start with def, which defines the function here, followed by the name of the function, which shares the same naming rules as variables. Then we have brackets and a colon after it. And then whatever code we indent into this function is the code that will be executed when we call it. So here I've just got a long list of sleep and LED dot value to flash it three times short for S, three times long for O, and then three more short times for another S. But this code that you put inside of your function could be anything you want. It could do and achieve whatever you want it to do. And here where the indentation ends is where our function ends. And this function is defined in the beginning setup phase of our code before our while true loop, kind of in the same place that I would define variables in.

Now, although it is placed before our main while true loop and our code runs from top to bottom in sequential order, it won't run this function or the code that's inside of it until we call it by its name. By placing and defining it here, we're just letting our Pico know that this function exists and this is what's inside of it. So our Pico would do the imports, it would set up our pins, it would go, okay, there is a function, it exists, it'd come to our while true loop, and then it would go, okay, if the button is pressed, now it calls the function and the things that are inside of it. So our Pico goes from where we call the function up to the start of that function, and then it executes all the code inside of that function. Once it's finished that function, it's going to go back and then it's going to execute the sleep command and then keep doing that over and over. And this is what functions are great for, when we have a set of code or instructions that we want to repeat multiple times in our code. And by doing so, we've stored this really long list of instructions up here in our function away from our main while true loop, and so we don't have any of that cluttering up our code. It's really nice and streamlined. It's a lot cleaner and it makes it easier to read.

When you call functions, you can also pass information and variables into that function. And the best way to demonstrate this is by making a function that just adds two numbers together. We're going to need some focus for the next 30 seconds because this is the part of functions that trips people up. So we start here by defining our function, sweet. But if we create a function with variables in the brackets, like we're doing so here, we are saying that this function needs to take in information. If we put two variables in here, like so, we're saying that this thing needs two things to input into it. If we put four things here, we need to put four things into it when we call it, and so on. Now, when we call the function down here in our while true loop, we are sending whatever information we put in the brackets here to the function. Now, here's the tricky bit. When they arrive in our function up here, they are no longer called what we put down here. So these are no longer called x and y. Instead, their names are now kind of temporarily changed to whatever we put up here in the brackets. So the first number we put here becomes the first number in here, and the second number in here becomes the second number in here. So in this function, we feed in x and y, but when we are inside of the function doing whatever we want to do up here, we would now need to use the names num1 and num2. This is only when we are inside of the function though, and you can pick any name you want for these variables in the function. They don't have to be num1 and num2. So now that we are inside the function, just for this example, we are going to add num1 and num2 together and store it in a variable called total. You don't have to store it in a variable or anything like this. This is just what we are doing inside of our code, and you can write anything in here or do whatever you want with these variables. And then this return here is very special. It's how we get data out of a function. So here I say return total, and what this does is that it immediately ends the function and sends total back to where we called the function initially. And whatever you put in this return line here is what is returned back. So result will be equal to total in this case. If we run it, you can see that, as you expect, it prints 19, a really simple function, and yet we still have a lot of information flying around everywhere inside of our code. So let's just quickly go over how that information flows one more time, just to ensure that we understand it.

Okay, so we set x and y equal to 9 and 10, then we pass that data into the function called add. When it arrives, their name changes to num1 and num2, but this is only when we're working inside of the function. It's kind of like it's its own little isolated world in the code. Then we add num1 and num2 together and call it total. So we're just adding 9 and 10. Then we return total, and because we set result equal to this function, result is equal to whatever is returned, which is total. So this is just a really elaborate way of adding 9 and 10. To show you that name change only happens inside of that function, if I go here now and type print x and y, not 7, and we run that, we can see that we get 9 and 10. Those variables are still there and they're still called that, but let's say instead I tried to print num1 and num2, it is going to throw us an error because it doesn't exist outside of that function.

All right, for formality sakes, let's from now on use the proper terms for all of these. These variables up here in the function are called parameters, and when we call the function, the variables that we put into that or the information we put into that, we call them arguments. So function parameters and arguments of the function.

One more concept for this video, is local and global variables. I got some code here, and here I set x equal to 5. Then I call a function up here, which just sets x equal to 1. Then once that function is done, I just simply print the value of x. And if I run this code, it should print out 1, right? Well, it prints out 5. So what's going on here? Global and local variables. When we create or change a variable in a function like we're doing so here with x equals to 1, it's called a local variable. Whenever that function is finished or it ends, the entire function and all of the local variables that we made inside of it cease to exist. And if we called that function again, all the variables would restart from scratch again. So what actually happens in this code is we set x equal to 5. Then we call the function test, which creates a local variable called x. The function gets the end, the x equals 1 disappears, and we're left with x equals 5. And just to prove that, if I delete this x equals 5 and try to run it, it gives me an error because it doesn't know what x is. We haven't declared it outside of the scope of that function. Now when we set x equal to 5 here, it's called a global variable. And what's special about a global variable is that they work even inside of functions, even if we don't put them as an argument within the brackets, like we were doing so with x and y. For example, I can delete that x equals 1 and just put a print here, and it prints 5 because global variables work everywhere, even inside any function. And something else important about the interaction between these two is that a local variable will always overrule a global variable. So if I put that print inside of our function and I run that, it's going to print 1 because the local variable overrules the global variable. So when we declare a variable inside of a function, it's a local variable and it only works in that function, but global variables work everywhere. But there is an exception to this. We can use the global keyword inside of a function to make a global variable instead of a local variable. For example, this is the same original code. If I run it, it prints 5. But if I go here and I say global x, this now means that whenever I deal with x inside of this function, I'm telling it that I want you to now deal with the global variable instead of making a local variable called x. And so we set x equal to 1 and when the function ends, that information survives. And because we've told it that it's a global variable now and it prints 1. This whole dealing with global and local variables can trip you up sometimes, so just keep an eye out for it.

Let's use functions to build something incredibly practical. We're going to write some code to filter out something called sensor noise. Really quick rundown, when we're dealing with any sort of analog readings, it isn't always going to perfectly read the exact true value every time. For example, here I am analog reading my potentiometer and even though I'm not touching it, you can see that it's a bit rough and jittery. And this kind of bouncing around all over the place is called noise. If we were reading the temperature of a room, it would bounce around like this as well. If we were reading the speed of a car, it would bounce around like this as well. Basically, any analog reading is going to have noise like this. And this isn't because the temperature of the room fluctuates that quickly, it's to do with how the ADC works, it's to do with electrical interference, how the sensor works. Now, most of the time this noise doesn't matter and it's not going to be a huge issue, but other times it is very important. Chances are you might not have to worry about noise and filtering for a while, but it's just an important thing to learn about. And so this code uses something called a moving average filter to smooth out noise. And it's one of the simplest filters that we can use. So the blue line that you're seeing is us printing the raw reading and the orange line is the filtered reading. And as you can see, it is a lot smoother. And all our code is going to do is that it's going to remember the last four analog readings and takes the average of them. That's what the orange line is. It's just an average of the last four measurements.

Alright, you're going to need a potentiometer plugged into pin 26 and you're going to need the demo code, which can be found on our course page on our website, link in the description for our YouTube audience. So we start by importing our relevant libraries and then we set up a potentiometer on pin 26. Then we're going to define two functions here, update the window and calculate the average. We'll just come back to them in a minute. Then we're going to set up variables here and we're just using these to store the last few readings in. And these are going to be global variables because we didn't create them inside of a function. And look at our while true loop. Look how clean and easy to read it is because we're using functions and we have all that big nasty code in a function at the very beginning. So to start, we call update window, which if we go up to it, we can see it starts by declaring all of these variables as global. These are just the ones that were created here. Now it looks a bit complicated, but all we do is we read the potentiometer, we assign it as the current reading. The current reading becomes the last reading, the last reading, the second last, second last, third last, third last, fourth last. We're just kind of shuffling along the readings one step. Then the function ends. And then because we said we're using global variables here, all of the changes we made inside of this function carry on into what we can use in the while true loop. They don't disappear. After that, we call the calculate average function and we're going to feed in all of those variables as arguments into that function. So those arguments come into our function where they become our val1, val2, val3 parameters. And then in the function, we simply add them together, assign it to total, then divide it by five. And this is going to just calculate the average of five numbers. And then we just simply return average, which means if we go back down to here, moving average is now just going to be set to the average of the five arguments that we put into calculate average. Then we just simply print the raw reading followed by our new moving average, and then just put it to sleep for 0.1 seconds. And as you can see, the orange line is our moving average, and it is a lot smoother and actually a lot closer to the real reading of our potentiometer. Again, you don't need to use a filter like this in every project. And 95% of the time, the noise that you see is not actually going to really do much in your project. So don't stress about mastering it. We're kind of just killing two birds with one stone here, demonstrating functions and showing you a handy tool while we're at it. If you do ever need to use one of these, you can easily Google it and find a million other examples to use online. The important thing is knowing how to use functions and to just be aware that noise exists and that there are ways to filter it.

So when should you use functions? Well, there are no hard and fast rules for when to use them, and the answer is whenever you feel it's appropriate. And technically, you don't even need to ever use them. You could just put everything in that main while true loop, but by using functions, we can not only make our code cleaner and easier to read, but it also kind of breaks it up into manageable chunks and it makes it easier for us to update. Back to our filtering example, let's say we wanted to tweak how our filter calculates the average. To do so, we would just go up to the function, change what we need to change, and we can rejig our average calculation without touching any of the other code because it's nice and compartmentalized up there. Functions are just a really powerful tool in helping to organize our code and just making life easier for us.

Comments


Loading...
Feedback

Please continue if you would like to leave feedback for any of these topics:

  • Website features/issues
  • Content errors/improvements
  • Missing products/categories
  • Product assignments to categories
  • Search results relevance

For all other inquiries (orders status, stock levels, etc), please contact our support team for quick assistance.

Note: click continue and a draft email will be opened to edit. If you don't have an email client on your device, then send a message via the chat icon on the bottom left of our website.

Makers love reviews as much as you do, please follow this link to review the products you have purchased.