Raspberry Pi Pico Stepper Motors via PIO

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello folks my name is tim and welcome back to my channel so today we're going to be looking at some stepper motors and we're going to be using the raspberry pi pico to control them via a pio routine so that should be pretty interesting specifically we're going to be looking at this little stepper motor here so this is a 28byj48 stepper motor it runs on 5 volts and it's just about the smallest and cheapest stepper motor you can buy and for that reason it's very popular now these little steppers are usually paired with one of these driver boards so this is a uln 2003 uh driver to power this little stepper and it's very very easy to use you can get these things usually in arduino kits and things like that you know those big project bundle packs that you can buy with loads of sensors and things in they usually have one of these motors and one of these drivers so to use it very very simple you just plug your stepper motor in like so and you need to power this thing as i said it's a 5 volt stepper motor apparently this board will also accept 12 volts but i think five is plenty given the motors rated at that so we'll put a supply let's make sure i get the polarity the right way around there we go so those are our power supply pins there we go and then we need four inputs for controlling it for sending the control signals so i've got four cables here and we'll just put those onto this little header there there we go and then these guys will connect on the other end into our raspberry pi pico so here we go we're just gonna put them into our breadboard if i get them in the right order right there we are so i've just set those up so that they align with gpio pins two three four and five so that's how we're going to control it there's really nothing to wiring up one of these things as you can see it's very straightforward so we'll put some power into this guy i've just got my bench top supply set up here to deliver 5 volts there we go all right so now that we've wired this thing up how do we actually make it move well that's relatively straightforward actually this is a stepper motor and as with all stepper motors it works by dividing the 360 degree rotation up into a number of discrete slices called a step so in the case of this motor it divides that 360 degrees up into 64 discrete steps it also has a gearbox in here though there's some gears in here which have a 1 to 64 gear reduction so taking that 64 steps per rotation into account and calculating for the gears it actually gives us 4096 discrete steps per uh rotation so that is a lot of individual positions that this motor can effectively be set to and that's using uh full stepping you can actually make stepper motors do something called micro stepping where you can subdivide the individual steps up into fractions of a step and that can go all the way down to 32 times micro stepping meaning instead of having doing a single step you do one 30 second of a step and you can imagine then you can get some very very precise positioning out of stepper motors there are pros and cons for doing micro stepping but on a little motor like this especially one that's already running through a gearbox we won't bother we'll just do full full stepping for this and that should be absolutely fine so how do we actually make the thing advance by a step well that's where the controller chip comes in so within this motor there are a number of magnetic coils arranged such that the coils are next to each other all the way around the circumference they are wired up in such a way that they're grouped into four discrete magnetic phases and each phase can be turned on or off by triggering one of these control pins so when you want to turn the motor what you first do is you enable the first magnetic phase then you will disable that magnetic phase and enable an adjacent phase which should energize an adjacent coil within the motor and cause the shaft to turn by one step so what you do is you enable the first pin then you disable it and enable the second pin then you disable that pin and enable the third pin and so on once you've enabled the fourth pin you then swing back around to the first pin again very very simple there's actually four little leds on the control board here which illuminate when each of the phases are enabled so that's quite useful for debugging this thing you can actually see visually what's going on as those phases cycle around so i've already written a little bit of software that's running on the raspberry pi pico to do that so let's give it a whirl and see what it looks like all right and there we go so we can see the phases being activated in sequence as shown by the leds and the stepper motor is actually turning it might not be too clear because i'm running this very slowly the frequency at which you activate these phases is significant to how well the motor will perform running it at such a slow speed uh the motor isn't going to do very well but i'm doing this so that you can see a nice illustration of what i was talking about um for activating these things so what i'm going to do now is i'll turn the frequency right up and we'll see the motor turn around nice and comfortably but these leds will be flickering so fast that they'll they'll basically look like they're permanently switched on and that's a little bit more like it so there we are the motor is now running at a very happy comfortable frequency obviously the leds aren't really helpful at this point but we can see the motors moving and everything's working the way it should do so all right that's enough for that let's take a look at the software that we're actually using to control this and how you can do it with the raspberry pi pico and micro python okay so here we are at my raspberry pi 400 desktop and i've loaded up the source code for the control program that we were running on the pi code so it's a very basic simple bit of software but it does demonstrate one really nice feature of the raspberry pi pico and that is its ability to do pio or programmable io what that actually means is you can create a i o routine using a very simple instruction set that runs on a dedicated hardware within the raspberry pi's chip and it runs independently of the main cpu and that's really useful because if you have a very tight loop that you need to run maybe you're generating a pwm signal or you're using some sort of real-time communications protocol or something then rather than tying up your cpu running that all the time you can offload it to a pio routine and let it get on with it and then the the cpu is free to do more interesting things so this is a really lovely feature so what i've set out to do here is to build a pio control routine for driving this stepper motor so this was the first attempt uh so let's take a look at what we're actually doing so to make a pio routine the first thing you need to do is to create something called a state machine and that's how you do it this command here builds a state machine um to run the program just called prog it runs it at a particular frequency that you can specify here and this final parameter this set base equals pin 2 that instructs the state machine to use an offset into the gpio pins that begins at pin two so when i say set the first pin high that's understood to mean set gpio pin to high and you can set adjacent gpio pins high from within the routine you can use all the pins but you have this kind of offset into them so once you've created your state machine you can activate it by setting active flag true and because we're not running on the cpu we've actually got nothing to do at this point so all we do is go to sleep so here we just sleep the cpu for a little bit uh whilst the pio routine runs and does its job then later on once we wake back up again we deactivate the routine and this command here this just cleans things up by setting all of the pins back to zero so there you are very little to it so let's take a look at the routine itself we'll start here and this set pins and then eight is actually um using a binary value to set a number of gpio pins to either high or low and that's controlled by a bit in the binary value that you provide so here this 8 is actually a binary value zero zero zero one so that's going to set the first gpio pin which is pin two you remember we set the the set base here so pin two is going to be set low pin three low pin four low and pin five will be set high this final little bit here means uh delay so each of these instructions features the optional choice of adding a delay for a number of cycles before the next instruction is executed i've put a lot of delays in here and this was to deliberately slow down the program for the purposes of demonstrating it otherwise it just runs too fast and you can't really tell what's going on so we set the first pin high which is pin number four sorry gpio pin five but we can ignore the actual gpio pin specifics now and think of it as the fourth pin that'll be set high these no ops don't really do anything at all they are literally just here to slow the program down then we have another set pins command here and this is a different binary value this is zero zero one zero so that sets pin four that was previously high low sets pin three high and leaves pins one and two low and then we have two and then we have one and those are the binary values that you would expect so that we energize the the fourth phase then the third phase then the second phase then the first phase and we loop around again so when a pio routine like this finishes runs out of instructions by default it will jump back to the top of the procedure and it will start all over again so this will just keep on cycling the phases four three two one four three two one four three two one round and round and round and round and that causes our motor to move and that's really all there is to it it's very very simple with the added benefit that we're not using up our cpu i really love this pio stuff so once that was working and we'd actually got it to do something interesting it was time to make the program a little bit more advanced so the second stab at this program and i'll be uploading all of this source code to my github page so if anybody is interested in taking this stuff building upon it or just using it as an example i'll put a link in the description where you can go and get it anyway so the second more advanced version of this program slightly different but effectively it's doing the same thing and what this does it uses the pull command that is how you communicate between a running state machine and the cpu there is a mechanism a transmission fifo that's a first in first out cue that you can push values onto from the cpu side and pull those values off of in the pio routine and that's exactly what we're doing here we are pulling a value from the fifo and we are then using a move instruction to move that value so the osr here that stands for the output shift register that is where the value ends up when you use pull and we're going to take that value and use a move command to move it into the y scratch register so you don't really get a lot of instructions and you don't really get a lot of flexibility in these pio routines so you have to be a little bit clever in how you design stuff you actually only get two scratch registers one called x and one called y so those are effectively variables you can think of them that way so you really only get two variables to play with and a few other specialized registers for doing different things it's not a lot but it's enough so once we've taken the value from osr and we put it into y we do exactly the same thing here only in this case we're putting it into the x temporary scratch registry and let's have a look here on the cpu side you can see these are the values that we're pushing in so the first thing we put in is this weird looking number but it's actually a binary mask for controlling the four individual phases of the motor you can see there how it breaks out into these individual nibbles that's a four bits we're actually going to put that in twice because this is a 32 bit value and we only need 16 bits to act to express our pattern so we'll just fill up the rest by putting the pattern in twice because we're going to loop through this thing anyway so it doesn't hurt the second value here sm.put 1000 that instructs the program how many steps it should run normally when you control the stepper motor you don't turn the motor on and let it run then turn it off you normally instruct it to run for a specific number of steps that is to say turn to a very specific and precise position and stay there so for this control program you can do that by setting the number of steps that the motor should turn using this second push so that comes out in x within the procedure immediately then we have this jump command here this is an if this is how you do conditionals inside of these pio programs and this is saying not x what that means is the jump will jump to a named label if the condition that it's been told to check for is true so not x means a jump if x is zero so if the user of this routine said move the stepper motor by zero steps we need to check for that explicitly and jump to the end of the program otherwise we'd accidentally move at least one step which is not what the user wanted all right so the next thing we come down to here is this loop so we declare a label for the top of the loop here and then we have immediately this additional jump statement on this strange looking thing called not osre what on earth is that well the output shift register allows us to put a value into it and then to shift bits out of it that is to say if we have a 32-bit value in there we can shift up to 32 bits of data out of that register bit at a time or a number of bits at a time which is quite useful but you can only hold so much in the osr so this check here simply says is the osr empty if it is not empty it jumps over this next instruction here if it is empty this move instruction simply puts the value of y back into the osr so if we deplete the osr we refill it with the original value so that we can keep looping around and around and around so within the main body here we have this little bit of code and this should look a little bit familiar to the previous program rather than the set command we use out so out takes a number of bits from the osr and puts them somewhere else in this case we're putting them into the pins here and we're using four bits so this is going to take the the next four bits from the osr and write them out to the pins that will effectively set the gpio pins high and low based on the pattern that we have provided so it's exactly the same as in this program although rather than explicitly saying set it set it set it set it we're just reading the values out of the osr four bits at a time and doing the same thing inside of a loop now the loop is going to run for x cycles stored in the x scratch registry there to do that we use this final little jump here that says jump x deck what that means is test the x value and if it is not zero jump to the label at the same time decrement the value of x so if that if x is five when we come here it will go yep okay that's not zero so i will jump back up to the top of the loop but i will make x now have the value four and so on so eventually you loop around until you've completed the number of iterations you've been asked to do in this case the number of steps that the motor needs to move by and the program can end so here i've just got a little final command that just sets a pin hi and that's just to tell me that the program main loop has finished and everything's fine so there we are that's a slightly more complicated version of the first program but the goal is to allow us to specify the exact number of steps that we would like the stepper motor to move by with the added advantage that we can control the movement pattern if we wanted to enable any micro stepping or anything like that at a future date pretty good but we're not quite done yet so the final version of this program and i will put all versions up because the simpler ones are nice as an illustration for people learning this stuff but the final version the completed version of this program looks like this so the main body of the pio routine is essentially the same we're doing that loop we're doing the osr bit shifting stuff and we reload the osr with the movement pattern should it become exhausted but at the end of the program we now have this little thing what's that well that's an irq so we already know how to push data into pio procedure but how do we communicate back to let the cpu know we've finished with what it wanted us to do well you use an interrupt there we are raise your interrupt and in micropython that's implemented like this you just set the irq to a python method and then when the irq is raised in the pio routine the method is called and that's on the cpu side so we can be in fact asleep you see we're just sleeping here but we'll still get the irq called and we'll still execute this routine even though we're sleeping so there we are that's nice and simple there's a bunch of interesting bit shifting and stuff going on here and that's because when you move the stepper motor by a number of steps what you want to do when you send another instruction to move the stepper motor again by some more steps you want to resume the movement pattern where you left off so if you move the stepper motor let's say five steps you will basically go through a movement pattern uh one movement pattern two movement pattern three movement pattern four then you loop back to movement pattern one so the next time you ask the stepper to move it should begin moving at movement pattern two then go to three then go to four then go to one so all we're doing here is we're adjusting the stepper movement pattern that we want based on where we got to last time there are four discrete phases we have four possible permutations just to say starting at one we're starting at two we're starting three or we're starting at four and that's just stored in this little list here so whenever the irq is called i simply update the bit mask by shifting these values down and packing them into a 32-bit integer and then using put to pass that into the pio routine along with the number of steps we'd like the motor to move by so here we are just moving the motor 500 steps uh then once that finishes we have a little sleep then we move the motor by another 500 steps we have a little sleep and so on and so on and so on until our 50 second sleep down here expires and the program exits so there we are that is the basis of a pretty reasonable stepper motor control routine the only thing it's missing is ramping now ramping refers to the ability to speed up or slow down your stepper motor at the beginning or end of a movement that means if you've got a large mass connected to the motor and you try to move it instantly at full speed or you try to come to a dead stop you will probably find it won't work and that's because the torque of the stepper motor is not sufficient to defeat the inertia of the mass that you're moving the net result of that is usually lost steps and as anyone who's seen those lovely photographs of 3d printers producing plastic spaghetti instead of a nicely formed part nose lost steps are a bad thing anyway ramping is a task for another time i'm going to upload all of this code so anybody who fancies hacking on it or using it as a starting point for their own projects is very welcome but that's plenty for now so i hope this has been useful and thanks for watching
Info
Channel: Tinker Tech Trove
Views: 28,007
Rating: undefined out of 5
Keywords:
Id: UJ4JjeCLuaI
Channel Id: undefined
Length: 25min 17sec (1517 seconds)
Published: Sun Feb 21 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.