Hello Clinton here from Core Electronics! Welcome to chapter 6 on our MicroPython for Micro:bit workshop.
In this video, what we're going to have a look at is using sensors to make a virtual cup that fills when I hold it up and empties when I tip it. So, let's start first up by having a look at what sensors are and how we interact with them. So sensors are electronic devices that are built onto a lot of boards and you can add yourself, in this case they're down here, these chips allow the board to interact with the real world so on the Micro:bit we have a couple different sensors so there's the built-in accelerometer, the built-in magnetometer which allows us to detect magnetic fields including Earth's magnetic field which we can use as a compass.
There's also a temperature sensor built into the Micro:bit which can be used to detect the ambient temperature, you can also hack together a solution but by using the LEDs on the front as a light sensor but that's not a supported feature it's just something that you can do which is quite cool. There's a few things that are worth talking about with sensors and one of those being how we interact with them, in a lot of cases when you're dealing with just code you will use “equal to” you can't get away with this with sensors because the values are never that exact because they're a device that's reading a real-world continuous system into digital fashion, so they tend to be a little bit off but in such a small way but it's enough for your program to be messed up by it, so we use “greater than” and “less than” or “greater than” and “equal to” and that way we avoid kind of getting unusual behaviour.
The other thing that we need to be aware of when using sensors is noise, depending on what you're doing noise can be different things. So, if you were say for example measuring the acceleration of a bus pulling out of a station then what you're interested in is the force of acceleration as the bus moves away, so your noise would be vibration, people walking around the bus and those kinds of things. Whereas if you were more interested in those vibrations then the force of acceleration would be the noise. Noise can be also caused by other things so because these chips are electronic and digital, they tend to be sensitive to heat so you will find there's more noise or more temperature around.
Now that we've kind of had a look at what they are let's get into programming. So as with all the other ones, the codes already written there, and we'll just go through it and you can have a look you can code along if you would like. So, the first thing we're going to do is we're going to import the library and declare a level variable, this level variable will keep track of how full our virtual cup is. We’re then going to create a new list and this list will contain images that we can display on the Micro:bit screen, so the Micro:bit library has an image function and inside here you see this string and each one of these numbers represents an LED on the front of the Micro:bit, the semi-colon represents the end of the line, you can actually make these images larger than the display and then navigate around them with some other commands that you can find in the microfiber library.
Then the numbers represent 0 to 9 which 0 being off, 9 being full brightness we're going to create a series of images, one being the screen entirely full and then slowly down to the screen being entirely empty. Once we have this structure we're going to use this to make an animation later, but first let's have a look at functions, so a function is a block of code that lets us perform an action again and again by calling it. A function returns a value and receives values, we define our inputs by putting them inside brackets so in this case we take a direction and a level, this is the name of our function and we'll look at how to call it a bit later so with our sensor in this case we're using the accelerometer which is a three axis device, it can detect where the acceleration is happening either in the up and down, the left and right or the forward and back and because gravity is equivalent to an acceleration there's always gravity acting on the Micro:bit, so even when it's on the table it's accelerating towards the ground and we can use this to find out which direction it's facing so we take in a direction and if the direction is greater than 40% which is what this is because a measure is from 0g to 2g plus and negative, for this sensor. So, if we get 1g we know that it's facing perfectly in that direction, if we get 400 milli G, we know that it's at least 40% in that direction we can then also check the level and because we want to check these both at the same time we're using this end and that just means this one has to be true and this one has to be true. If either of these is false, this whole statement will evaluate as false.
We're then going to work out how much we're going to take off our level, based on the angle so we're going to take our current level and from that we're going to remove, we're rounding up to the nearest integer we're also going to take the absolute value of the direction because we don't care if it's forward or backwards we still want to reduce our value and then we're going to divide by 20 just to make it smaller. So what this will do then is return and this is what the function will hand back to the program, so when I call this we’ll see that we set a variable to be equal to the results of this function and this is what that equals will be set to. We then have an “elif” statement for level greater than 0, so if the cups not empty we're going to return the level being what it currently is without modifying it and finally we're going to return 0 if the level is not above 0, so this is to take care of the case if we accidentally go negative because a negative value in a cup doesn't make sense, so we return 0.
So, we're going to create our wild true loop again and then the first thing we're going to do is we're going to grab the values from the sensor. To do this we create a variable and then we're going to go “microbit.accelerometer.get_values” and this will return a list of our X, Y and Z axis we're going to call them “roll”, “pitch” and “yaw” what we're then going to do is we're going to measure, we're going to index those with 0, 1 and 2 so we're taking the first one, the second one and the third one. We're then going to take pitch and we're going to see if it's greater than a 1000 so 1000 milli g would be equivalent to 1 gravity so what this is saying is, in my Y-direction I want to make sure that all of gravity is acting in that direction which means that I have to have it upright.
If I make this equal to, sometimes the sensors have been off or the noise will make the error slightly larger and so using equal to here would be one of the instances where you could run into problems where it doesn't work. We're also going to check to make sure that the level is less than a 1000 because 1000 is a full cup and again it doesn't make sense for a cup to be over a 1000 it can't possibly go over a full. Once it's full we're going to add 40 to our level so whenever it's up right it'll keep filling up. We're then going to call our function, so the first time we call our function we're going to put roll in, and it will return the level and make it equal to the value that we set in the function before. Whatever value our function returned, then we're going to do “yaw” so that each time it checks both and so if we're tipped forward it'll empty, if we're tipped sideways it'll empty and if we tipped a combination of both with empty faster.
So now we're going to create our animation and to do this we're going to use an else--if structure. The nature of this structure is quite important because it's easy to make a mistake that will give you unusual results, for example if I were to create use greater than here and say with levels greater than 0, I want to display an empty cup, if it's greater than 200, I want to display a middle cup and so forth if I'd done that, what would happen is it would get to the first one and no matter what level it was it would always evaluate as true and so none of the others would be evaluated because it skips everything after the first one, if this one returns true. So, we need to make sure that if we're using less than, our values are increasing as we go down so this one evaluates as false if the water level is above 10 and so on and so forth.
Now that we have that our code should be complete, except for one last line we're going to put in which is print level. So, print level will output our level but we're not going to see it on the Micro:bit it's going to display it on the REPL, so if we open up REPL, we get this message about what version of it is. We hit “ctrl D” to reset and then we start getting values coming so at the moment our tanks empty, so it's at 0 when I put it upright we jump up and if you were quick you may have seen a negative value in there, we call it that with our thing and it returned to 0.
So thanks for watching this video that should now give you a pretty good understanding of how sensors work, if you have any questions about anything in this workshop or any of the videos in this workshop please post them in the comments and thank you again for watching!
Makers love reviews as much as you do, please follow this link to review the products you have purchased.