Raspberry Pi Pico W LESSON 71: Allow Thread to Complete Task Before Termination

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello guys this is Paul mcarter with toptechboy dcom and we're here today with episode number 71 in our incredible new tutorial Series where you are unleashing the power of your Raspberry p Pico W what I will need you to do is pour yourself a nice tall glass of ice cold coffee that would be straight up black coffee poured over ice no suar sugar no sweeteners none needed and as you're pouring your coffee as always I want to give a shout out to our friends over at sunfounder sunfounder is actually sponsoring this most excellent series of video lessons and in this class we will be using the Kepler kit for Raspberry Pi Pico W now hopefully most of you guys already have your gear but if you don't look down in the description there is a link over to Amazon and you can hop on over there and pick your kid up and believe me your life and my life are going to be a whole lot simpler if we are working on identical Hardware but enough of this Shameless self-promotion let's jump in and talk about what I am going to teach you today and what I'm going to do is I'm going to show you my solution to the homework assignment that I gave you in lesson number 70 now what was that homework assignment we're learning how to gracefully operate when we're running dual cores on the Raspberry Pi Pico W when we're running that thread on the second core and the main program on the first core we have to make sure that those two processes are working well together and usually where when the problem comes up is when we try to kill the program and we have to make sure that we kill it in such a way that we terminate the thread first of all we kind of got to let the thread finish the work that it doing it then terminate the thread and then terminate the main program and if we just come in and hit that stop button on TH or do a control C it just slams stops Slams on the brake the main program and then the thread is left on that other core in a sort of ambiguous state it might keep running or it might crash ugly because its variables all of the sudden disappeared so we really got to think through terminating the program so we don't have to end up going in and disconnecting the Raspberry Pi Pico from power to get it to work again okay now let's go in and what I'm going to show you is let me show you the circuit that we're working on we're picking up from where we left off last week only this time we're going to make the program terminate better where it doesn't crash if you terminate the program in the midst of the servo moving so so let's go ahead and look at what our circuit is that we ended up with last week and just ignore these two LEDs I'm not using them in this example but I've got the servo the orange pin or the uh the orange pin or the control pin of the servo is connected to GPI pin 17 on the Raspberry Pi Pico W red is connected to physical pin 40 and the brown is ground and that is connected to physical pin 30 38 then we also have this button we have got the button and let me do a little Windows management here and the button is this red button is connected to GPO pin 16 and then the other leg of the button is connected to ground this is a ground Rail and then uh everything else is uh just like you just like you see it here so that's a quick way to get it hooked up and then also we're going to get the code that we ended up with in lesson number 70 and so you can come over here to the most excellent www.top techboy do.com and let's get that code that we ended up with last week and if you search using this happy little this happy little search icon here search on something like cleanly exiting dual core program and should come up to this you'll come down here this was the code that we ended up with last week and so I can click here to copy it and then I'll come over here and paste it into to my th and just a reme just a reminder that this code is using this custom library that we developed a few weeks ago called Servo if you haven't installed our Servo Library you need to do that again come to www.top techboy do.com search on Servo Servo library for the Raspberry Pi Pico and you should come to this code and this is the little snippet of code that is the servo Library you'll need to copy that and then you will need to put it in your lib folder you'll need to put it in your lib folder on th and we'll come uh come back over here to th come back over here to th like this and if we view our files you can see you can see there is the lib folder if you don't have one you need to uh you need to create it and that little Servo snippet of code you need to save it as uppercase Servo dopy lowercase in your lib folder and then when you do this import Servo it will work okay I apologize to you guys that are taking the class and actually already have this stuff done it's just I never know if we end up with driveby Shooters on this lesson that just hop into lesson 71 without having watched the earlier 70 lesson so I try to catch them up to speed in four or five minutes and I apologize to you guys that are in the class that already know this stu okay now what is the problem with this code okay let's run it and so I'm going to come over here and I'm going to run it you can keep your eyes on the servo and then if I run this thing ah something's not happy okay something is not happy let's see ah when I copied that I ended up with a strange little space there was that on the website pardon me I digress let's come back over here do I have a little inadvertent space there no I don't so I'm not sure what how I up with that space maybe it's the way I did the paste but anyway it should work now okay and so the thing is booted up and remember what this program does is if I toggle the switch this will go from 0 to 180 if I toggle again it'll go from 180 to zero okay so it was in the wrong position so it goes back to zero now it's going to 180 and that all looks like what we would expect it gets to 180 and then it comes back the other way and that looks good and now over here on the code what I want you to remember that we did we put in a keyboard interrupt and so our main program we have a trial try inside the try we have a while true so that's our main Loop and then we have an accept so we jump down to the accept when there is a false when there is a keyboard interrupt and what do we do well we first of all print out to let the user know that we've gotten down to this interrupt except and then what we do we set running equal to false and then what is that do up here in the thread that if running goes to false we will no longer be looping here we will drop out of the while loop and then the uh other core uh the thread will stop because there's no more code it gets the little last line of code which is print of chord terminal ated and then it will stop and then after it does that we give it about a tenth of a second to do that and so we print out keyboard interrupt then when this becomes false and we wait a little bit then we will get that the thread is stopped and then we will get that the program is done and so if I come over here to the keyboard and put contrl c as expected we get the keyboard interrupted from here and then the other core is terminated because running became false and then we print program is done beautiful beautiful so what is the problem well if I run it and I come up here and I click the toggle switch and now while I'm in the middle of toggling if I hit control C to stop if I hit control C to stop okay well actually that one worked okay maybe I didn't do it quick enough let me come here do it again and then I will toggle and then I will hit contrl C okay and this time what happened the thread crashed and the program ended ugly now why is that well I came here and I printed keyboard I hit contrl C while it was in the midst of moving and then I printed keyboard interrupt then I made running false but what is the problem if I come up here I'm inside of this while running that's good but I am in the midst of this slow for Loop so it is sitting going through that for Loop and it's not looking at whether running is true or false because it has to go all the way through and then it will come back up here and see whether running is true or false but if I'm in this loop it's not looking and it's a slow Loop so what happens it is true that running went to false but while I'm in that for Loop this next line of code executes it waits a tenth of a second I'm still in the for Loop up there and then I print the program is done and then I have enter I have reached the last line of the program the main core program terminates and now all of the sudden that for Loop is still going but we have no idea what's going to happen like if it's using variables from the main program it's going to crash or it might just keep running and get confused all types of bad things happen okay so what do we want we have to make sure that we don't terminate the program while we are inside that for Loop we've got to make sure that we don't terminate the program while we are still inside of that for Loop now I am actually not sure if this is going to run or not I'm going to just kind of see where we are on the program okay so yeah it's uh it's confused and so what we're going to have to do is we're going to have to come over here and unplug it and plug it back in okay now there's actually several different ways that we could do this and I'll show you one and one way is what do we need to do down here yes we need to set running equal false but then what do we need to do after we set running equal false well I guess one way we could do it is we could tell the user do not stop the program while the servo is in motion but that would be kind of a lame way to do it another way we could do it is is that after we set running equal to false we could have the program wait 30 seconds here before it went on in its termination routine that's also kind of lame so what do we want to do we don't want to time do sleep of 0.1 we want to wait here what as long as it takes for the for Loop to finish well let's look up here how could we do that well as long as we are looping as long as we are looping we want to pause well what is true while we are looping Servo toggle is true as long as we are in the this for Loop okay and after we finish the for Loop then Servo toggle becomes false okay so how long do we want to wait I'm going to put just a I'm going to put a while loop here and I'm going to inside that while loop I'll put the condition here in a minute but inside that while loop what do I want to do absolutely nothing I just want to keep looping in this while loop as long as what as long as Servo toggle is true I want to just Loop and that might be a tenth of a second or that might be five minutes but as long as Servo toggle is true I am going to pause so we're going to come here and say while we could say while Servo toggle equal equal true or since Servo toggle is a logical you know true false we could just say while Servo toggle if it's true it'll Loop if it's false it'll drop out and so let's look at what's going to happen we are running now let's say we're in the middle of running we are in the middle of moving that Servo and I hit contrl C what's going to happen it's going to come down here and it is going to print keyboard inter uh interrupt it's going to give running is equal to false and now it's going to wait and then up here all a sudden in the middle of this for Loop running has become false but what does this do it finishes the for Loop it sets Servo toggle to false and then what can happen Servo toggle becomes false I then drop out of this and then I print program is done and what happens up here well Servo toggle becomes false we come back up here is running true no running was set to false so then this will come down here and it will terminate this core so we will enter the accept keyboard say that we're in except keyboard we will wait for we will wait for that for Loop to finish then we will drop out and stop the other core and then we'll come down here and then we will say print program is done and then the whole thing will be finished so let's run this and see if that works okay I'm going to toggle and that looks good and now what I'm going to do is I'm going to do a contrl c and what does it say keyboard interrupt and then it gets to the end the other core is terminated and the program is done now let's watch that again okay let's run it okay now this time I'm going to try to do the contrl C quicker and so I toggle and then contrl C look keyboard interrupt but that for Loop is finishing here nothing is crashing ugly when the for Loop is finished then the other core is terminated and then we come back and the program is done do you see how clean that is and look we can just run it over and over control contrl C run it over and over do this in the middle of it do a controll c and it always finishes nicely doesn't crash doesn't require us to unplug our Raspberry Pi picco W okay now there's another way we can do that and the way that works is and there's no one way that works for everybody but I'm showing you ways of thinking about it and I'm showing you tools that you can use and then when you get to your particular problem you can figure out what the best tool is but what I'm going to do is I'm going to take out this while business okay I'm going to take out this while business and I'm even going to take out the sleep okay and what I'm going to do is I'm going to create a baton okay and only one part of the program can have the Baton at a time now other parts of the program can do whatever they want okay but if I've got a certain snippet of code and he goes out and gets the Baton as long as he's holding the Baton a different Runner cannot get the Baton so only one snippet of code can have the Baton at a time so if that for Loop has the Baton who cannot have the Baton who cannot have the Baton would be who could not have the Baton would be the except down here okay does that make sense so let's let's do this and let's see if that makes sense so up here before we Define the other core we're going to create our baton okay and the way I'm going to do it is I'm going to say the Baton is equal to underscore thread our library okay do allocate lock open close so if somebody gets the Bon baton if they acquire the Baton it locks anybody else from having the Baton now the main program will keep running somewhere else but if this part of the code has the Baton and another part of the code tries to acquire the Baton it will have to wait its turn so let's see how that works here we're going to come here and where do we really want to make sure that I lock up that other part of the code well it's in the for Loop so immediately before the for loop I could baton do acquire like that okay and then as soon as the for Loop is done as soon as the for Loop Loop is done I can baton do release like that and we would need to do it for the other for loop as well and so right before the for Loop but baton Bon do acquire okay and then immediately after the for Loop we would baton do release like that okay now when we come down here we set running equal to false that's good now we're going to try to get the Baton baton do acquire like that a c q i r e I hope I spelled it up right in those earlier places baton do acquire all right now it's not going to let me get the Baton until the other one is finished so at Baton do acquire it is going to just sit there and wait and wait and wait until that thread releases the Baton and then once it releases the Baton then this one can acquire the Baton and what and finish the program and then it will for good measure release it now the only thing I'm not sure of what might happen here is this might release the Baton this might release the Baton and then it might execute these lines of code slower like the other one might get the Baton and then it might stop before these were able to finish so we might end up with a little bit of a race to the end of the program here but let's just see what happens okay so there we go we're running and then I'm going to uh acire I knew I was going to misspell that there is a c and a choir and I have no idea why I have no idea why okay let's try to run it again hopefully we didn't okay hopefully the thing is still running okay so we go there and that's looking good I come down with the contrl c I get the keyboard interrupt that's good it's coming over to finish it's locked up with that baton and then boom we got the keyboard interrupt we got the program is done and then the court terminated well what's the problem the program was done and then the core terminated so they were kind of racing there a little bit and so what we're going to do is once this thing gets the Baton once this thing gets the Baton I think what we will do is we will time do sleep about 0.1 just to make sure that the thread has the chance to finish before the uh this SE of code finishes because it stopped everything stopped okay but you want the thread to stop first because if there had been something in there that was using one of our other variables it could still crash and so we want to deliberately stop the thread and then stop the main program so we will get the acquire uh we'll acquire the Baton then we'll slow up a little bit we'll print the program is done and then we'll release the Baton and this time I think it'll work right okay so we're gonna click this that's looking good we come up and I am going to do a contrl c keyboard interrupt we're waiting for this thing to come on over and then other core is terminated and the program is done okay now do you see how robustly this works so you guys if you're going to use threads you've got to be very deliberate in the way that you terminate the program now I've shown you how to do keyboard interrupt and I've shown you how to use the Baton uh in order to kind of control your timing and synchronize your timing a little bit now why is this important because as we start working with more components like we might start working with the little infrared remote or we might start working with the RF tag ID and working with things like that a lot of times you really need that second core because you need that second core to be sitting and looking at your input device and interacting with your input device while the main program down here is doing the main business of the program and so a lot of things our life is going to be a whole lot easier because we know how to do object-oriented programming we know how to do methods and classes and functions and we know how to do dual core threading so we've really Advanced our software capabilities quite a bit and so now we're going to go in and start using some of the more advanced Hardware in the kit okay guys I hope you are having as much fun taking this class as I am having making it uh as always I want to give a shout out to you guys who are standing with me on patreon it is your support and encouragement that keeps this great content coming you guys can also help me by uh giving me a thumbs up and leaving a comment down below if you haven't already subscribed to the channel ring the bell when you subscribe so you'll get notifications When Future lessons drop and most importantly share this video with other people because the world needs more people doing engineering and fewer people sitting around watching silly cat videos Paul mcarter with toptechboy tocom I will talk to you guys later
Info
Channel: Paul McWhorter
Views: 1,781
Rating: undefined out of 5
Keywords: STEM, LiveStream, TopTechBoy
Id: Xm3chr1-hkY
Channel Id: undefined
Length: 24min 43sec (1483 seconds)
Published: Tue May 28 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.