The full Raspberry Pi Workshop in step-by-step format can be found here http://coreelec.io/piworkshop We'll be reusing the LED-button setup from Section 2.2 for this section.
In this section we’ll be writing a much more interesting function than before which will allow us to pulse this LED nice and smoothly. Almost to create this breathing LED effect on a Raspberry Pi. Now when we hold the button down it will pulse alot faster. So let’s get started with that.
I’ll just stop my demo, and lets create a new file. So this is where we can reuse a lot of the work we’ve already done. A lot of the boring stuff, like setting up GPIO we can pull from old code to set that up. So i’m going to pull the code from section 2.2 and I’ll grab the imports and the PIN definitions and I’ll copy them over. Definitely want to grab the SETUP, the GPIO SETUP, we can pull that. We can even just grab the skeleton of this loop. So hey, we’ve essentially copied the entirety of that script so I guess there was an if condition so I’m going to leave that button as the if condition and I’m going to erase some of this stuff just for us to fill in. So we’ve got the imports, the PIN definitions, the setup and the try/except which allows us to quit cleanly along with some loop. So that’s a pretty painless way to get all the boring stuff out of the way. So what was happening there, we were kind of using a similar thing to the last section where we had this function that was going up and down nice and smoothly but instead of printing it to the terminal we’re now somehow driving the LED with it. This is going to take us on a bit of a journey to creating a function that is going to be quite useful probably down the track for other projects and for also doing a bit of Math. So lets get started with that.
I guess the first thing we need to do is - well, to drive the LED nice and smoothly with PWM - we’re obviously using PWM and we’re changing that value smoothly. So the function that we’re going to write is going to allow us to go from Sin of something - which is -1 to 1 and its going to give us a duty cycle of 0 - 100 so we need to write some function that allows us to do that scaling. It’s not just going to be from -1 to 1, we’re going to write a very general function that we can use down the track for any kind of mapping from one scale of numbers to another. So, lets create that function now.
I’m going to call it mapFun and I know that I need to pass something into it - that is the number that I want to scale and I want the lowest number that I expect it to be, the highest number that I expect it to be, and then the same for the output - this will be clear in a moment. So, I’ve just defined a function, it’s currently empty. What I need to do is represent - I know that the input has to exist between 2 numbers, so what I want to do is represent whatever number comes in as a percentage of that scale. So I need to know what scale I’m working with. So we’ll say - in range and the range is equal to in high minus inlo - that’s the range of numbers we can expect expressed as the difference. We can do the same with out - OK so we now have our two ranges that we can possibly be within and now we need to express the input as a percentage of the input range. So we can say - I’ll call that scale, inscale equals x minus inlow divided by inRange. What this is doing is normalising x into inscale. If x were say, zero, which is half way between negative one and one, then inscale is saying that is 50% of that possible range. It’s come up by 50% from negative one to zero. So that’s the process called normalising. Then, once we’ve normalised that and turned it into a number between 0 and 1 we can just apply it to the output. So we can say we want to return and we want to return outlo plus that scale. So we’re going to say inScale times outRange. If you didn’t follow along with that, that’s not really to worry - the essence of what we’re doing here is just to really understand that we can create functions and think of them as these useful blocks that we can put things into and pull things out of and if we’ve written them and we’ve debugged them and we know that they work so we can trust that they will work forever and do exactly what they say they will do on the tin. In this case its a mapping function. So we’ve just written, certainly a more complex function than last time that is going to map our Sine function into something we can use to drive the LED. We haven’t defined any constants either - everything is able to be parsed in so we can use this for any other application where we need to rescale a number into another range.
OK, so over in the main loop - well first before try we’re going to set x equal to zero as always and this is where we’re going to decide how fast the LED breathes, whether the button is pressed or not. So we can say if the button is not pressed (we covered that in the last video) if the button is not pressed we want it to go kind of slowly. So I’m going to say step equal 0.03 - it doesn’t really matter what step is at the moment but we just know that that is a small number, and else step equals 0.1. We can close out the old script, we don’t need that any more. That is going to be the end of that if statement - all that is doing is changing a variable based on that button press. So we can continue on and say that this is where we want to set out duty cycle. So we are going to set the duty cycle to something and we’re going to use our map function to set it, that’s what’s going to be returned. So we’re going to use mapFun (mapfunction) and this is where all the magic is going to happen. So x is the thing being incremented so x is the thing we want going into Sine to create that nice smooth effect. So, we’re going to parse into that sine x and this is ok, we can parse functions into other functions because sine x returns a number that is compatible with what we’ve decided we want as an input which is just another number. Now we know that sine x returns values between negative 1 and 1 and we want to rescale that into a duty cycle between zero and one hundred. So, with one call to our special mapping function we’ve been able to go from a sine wave in one domain to a duty cycle compatible with a driver LED. After we set our duty cycle we can say x plus equals (and this is where our step comes in) so this code is always running and the code for this ‘if/else’ statement - all it’s doing is choosing how big to make the step and that is going to directly effect how fast the LED is breathing in and out or growing brighter or dimmer. From there we can pwm.change duty cycle to duty. Now we’ve got the bare bones and maybe we can give that a run. Unless I’ve made any errors then we might be able to run that. I haven’t saved it yet so I’ll save it in the chapter 2 directory and I’ll call it 2.4 breathe LED - and I have an error. Well this is classic, I’ve written a lot of code and there’s an error now so we can go through a bit of debugging in line 18 - pwm start duty - ah OK so when I was copying the code over I neglected to initialise duty with some value so I’m just going to declare duty and set it equal to zero. Give it a save, give it a run, and some more red text! Ah, of course, so again, last time I’m using sin but I haven’t yet defined what sine is so I could put in here - rather that write that sine function again - I can just say math.sin cos we only use it once and math is not defined, oops! So this is just a quick look inside the workflow, getting rid of the red text and let’s have a look now…. ok so, these are just warnings and these are ok. They’re just telling us that the channels are already in use.
We’ve got our LED, its definitely doing something but it’s behaving kind of crazy. If if press the button it kind of changes its behaviour but what I think is happening is that everything is running way too quickly so lets try slow everything down. I’m going to decrease everything by that factor - ah - we don’t have a pause so we can’t actually see the LED breathing so let’s include a pause that is time. sleep and let’s be quite generous with .05 seconds and give that a run now. Over at our LED we can see that it is slowly dimming and then slowly brightening again and if I hold down the button it appears to do it much faster. That is still quite a bit too slow for my liking so I’m going to make the very slowest point 1 and the fastest - let’s say .3 and give that another go. Here we have our LED pulsing nice and smoothly and we can speed it up much faster too.
Ok, well that was a bit of a bumpy ride and we definitely got some red text on the screen - all that’s left now are the warnings and that’s because I haven’t cleanly quit so I can press Control-C and run the script again and we don’t get those warnings - that’s ok. But we definitely saw that we came across a few errors and that was from that copy paste programming that I started off with. So if you rush and you copy paste programming you are almost certainly going to make an error so get ready for some red text!