Alright, welcome to our next microcontroller video, we are still working with the PIC10F200.
And if you may have wondered why in the world we had it set up with two LEDs and two switches
this entire time and haven't used them yet, this tutorial is why we have it set up.
So, in this tutorial, we are going to learn how to use buttons, we're going to learn exactly
how you scan for them.
We're going to learn a little about polling, and the debounce delay and how to do that
in software.
And then we are going to do some fun things.
So we're going to basically do two things, we're going to make one of the buttons cause
it so when you push it, the light blinks the entire time you're pushing it, and the other
one that when you push the button and release it changes the state.
So if it's off, you push the button, it turns on.
I just did my hands backwards there but you know what I mean.
You push the button and it changes on to off, off to on, just one time per bush.
Push.
One time per push.
There we go.
This is going to be a little bit more complicated than the things we've been doing which makes
sense because each one of these tutorials, we should be learning something new and learning
something a little bit more complicated.
So let's get right into it.
One of the first things I want to know, as you're looking at the code that Sergey has
put together is, if you haven't seen it before, a pipe.
Basically, that vertical line, in this case is treated as an "OR".
So as you're looking at the initialisation, for that move literal, and on lines, 8 and
10, where it has T0CS "PIPE", and then "1" less than, less than NOT GPPU.
That is just a way of making it so you are toggling both of those bits without having
to do much more complicated or just more painful things.
So that pipe in that middle of that vertical line is just an "OR".
And you'll see that in C, C++, all of the bitwise operations that you see in other programming
languages.
So I just wanted to point that out.
So with that, you look in here and you see the first 11 lines are our typical initialisation
we move something to the working register on line 8 and then on line 9, we move what's
in the working register into the option register, then 10 move some new values in the working
register and then line 11, we move that into the TRIS register.
So the actual program itself, the entirety of the main program is literally lines 12
through 15, where you have loop, call check switch one, call checkswitch two, and then
GOTO loop.
And you're just going through that.
And that's literally it.
Everything else has been run as a sub routine.
So what we're doing here is called polling.
Now on a very simple microcontroller, like this, you don't have interrupts you don't
have something that as you're going along, something will flag it and say, oh, something
happened over here, I need to stop what I'm doing right now, go run a specific sub routine,
and then come back.
This doesn't do that.
So that's just one of the side effects of having such an inexpensive microcontroller.
But because we don't have those interrupts to make it so you detect a change on a pin
or something like that.
We have to poll and actively look, what is the value on that pen right now.
And this is an incredibly inefficient way of doing it.
But it's also, for something this simple, extremely effective, and there's no reason
that we need to worry about, "Ah man, it just has to check all the time..." because what
else is it going to be doing?
So polling, if you were building a nice, big, complicated project, you would not do this
because it unnecessarily uses its processing power.
But since again, we don't have anything else going on.
It's not a big deal.
So lines 13-14, all we're doing is polling, switch 1 checking, "hey, switch one has a
changed state?
If it hasn't been it goes to check switch 2.
So, as we look under check switch one, the subroutine, you will see the first and the
only new command we are going to learn in this particular program and that is BTFSC
and that is bit test in the file register, skip if clear.
So what we're doing is we're looking at register GPIO and the bit GP3, and we test it.
And what that means is since it's set up as an input, if the switch has made it a high
or low then it says, "It's a high, or it's a low."
Great!
And then it returns that and it says, All right, if it's a one, if it is set, then (DO
NOT) skip the next line.
So we've seen that sort of command in assembly a lot.
So what it's basically saying is, hey if bit GP3 of the GPIO register is set.
If it's one, if it's high, then (DO NOT) skip the next line.
And that next line is that RETLW where it takes the value from the stack, and it puts
it back into the program counter to jump you back into the main program.
So what that's saying is, if this is high, then that means it's doing what it's supposed
to be doing.
Because right now, the way we have this setup, if you need to go back and check the diagram
again, that's great, but it's set up so it is a pull-up register.
So it should be high, except for when we push the button and basically attach that GPIO
to ground and pull it low.
So this checks and sees, hey, it's high.
That means we haven't pushed the button so I'm not going to skip it.
So jump back up into the main loop.
However, if you do push the button and it drops low, they'll say, hey, it's low, skip
that command, that RETLW.
So I don't go back into the main loop.
And then I go to the debounce delay.
So one of the interesting things about debounce, you can do this in hardware or software, but
what it's doing is it's making it so that you're making up for the physical imperfections
of a button.
When you push a button, you you'd think it's nice that it's going to be for gone from high
to low, it's high and then low.
And that would be ideal.
However, even the best buttons will go high and then kind of bounce a little bit and then
low.
And the other way, if, when you release it, it goes low, bounces a little bit and goes
high.
And it's that bouncing from high to low that you're trying to get rid of, ergo, a debounce.
And you can do this in hardware with a capacitor so that when you push it, instead of it bouncing,
it just kind of goes like that.
And there's pros and cons to doing in hardware and in software, but the whole point of this
debounce delay in this debounce routine is making it so that when you push it, it's not
just some stray signal, some change, but you actually pushed it and held it long enough
for it to be certain that, yes, this button is being pushed.
Now, even though it's called debounce delay, if you go down and you check that lines 42
through 51, you'll notice that's just a typical delay loop.
And so literally, all it's doing is it's saying, hey, it looks like it's been pushed, let's
wait a little bit of time and check to make sure that it is still pushed.
So when you call that debounce delay, you come back in line 21, and you run the exact
same thing that you did in line 18.
And if it is still low, if it's still pushed, then it skips line 22.
We're now at 23, where we're doing the exact opposite command as 18 and 21.
Instead of skipping the line, when it is clear, you're skipping the line when it is set.
And so now what it's basically waiting for is it says you've definitely pressed it, but
I'm not going to do anything until you've released it.
So now we're doing kind of the same thing that we were before waiting for the release
before we toggle the LED.
So that GOTO $-1, as you remember that dollar sign is the current program counter the current
PC.
So every time you hit line 24, it just bumps you back up to 23.
And it's waiting until 23 is released.
And then if it is it checks that debounce delay because again, that bounce happens in
both directions.
And then once everything's good, and you've had the debounce delay, and you've checked
and made sure you've actually released, that's where in 26 and 27, you toggle the GP1 pin,
which is basically the LED.
So again, as you're going through this, it's checking Have you push the button, if so,
double check to make sure it's actually been pushed.
Once you've double checked and assured that it has actually been pushed, then you sit
and wait for it to be released as soon as you release it and make sure that you actually
have released it and once you have it does that toggle of the LED and then bumps you
back up into the loop of the checking switch one and it's checking switch to back into
that polling section.
So that is it for switch one and that's a little bit simpler because you're not, that's
the one where you push it and it toggles every time.
Whereas with switch two as you push it, it then has to toggle while it's holding.
So that's going to be a little bit more complicated, but still not too bad.
So let's jump back into the code with "check switch two" and you'll see that this is very,
very similar and the first thing it's doing is when it's polling it's saying hey, is GPIO
is it zero?
Has switched to been pressed?
If not, then jump back out.
Go back to the polling, if so, call that debounce delay.
Now because this will be toggling the entire time it calls the debounce delay and then
it goes into this switch two loop.
And this loop is where it basically checks make sure that it is still pressed, if it's
not still pressed, it bumps you out of the subroutine.
But if it is still pressed then it toggles the LED calls the toggle delay which is a
different length of time then the debounce s delay and then goes back up to the switch
two loop line 35 checks - Is it still pressed?
If not jump out of the subroutine.
If it is 37 and 38 toggle the GPIO, wait, you know, again about an eighth of a second
before jumping up, double checking, making sure it's still pressed and doing that forever
and ever until you release it and then it jumps back up.
And so that is really it.
And this is something where is interesting with the PWM is a little bit harder conceptually
to figure out but for me, this one is easier to understand, but it's more complicated.
There's more moving parts here, and more things to go wrong.
But if you do all this, it should work out just fine.
And to prove that let's load this thing up and get it working.
Okay, let's see, this thing should be programming.
Okay, this is exactly what happened the first time I did it.
You notice it's blinking right now and it's not supposed to be blinking.
And that is because of the PICKit4, and he uses a PICKit3 and it happened with him.
So as far as I can tell, it's the same problem with all of the PICKits.
But because our programming lines are... actually I'm not 100% sure what lines those are...
but because two of the lines from the programmer connected to our switch pins, you have to
pull those pins for it to work properly.
So now you see the LED has stopped blinking.
And as I push this one, you can see the light.
It waits and I'm pressing.
And like I mentioned, it waits until you release, and then it switches, press, waits, releases.
And then the other one is you press it and hold it, it blinks.
So I know the green one is a little bit harder to see.
So hopefully you can see that.
Now also notice that as I'm pressing one, the other one doesn't work.
And that's one of the drawbacks of a polling type routine is that since it's just in that
loop, it doesn't care what I'm doing with the other one and I can do the same thing
here.
It's whichever one is being pressed first.
Now another challenge here is this is setup fairly well.
Let's see if I can do this without causing any problems.
But it... uh oh...
I just... man, I bumped it with my arm now it's all confused.
So if you just do it too fast, it thinks that it's some sort of bounce.
So you do have to do it at least at a semi reasonable speed.
And then you have to be really, really fast to not do that.
But that's something where you can say, Oh, I need to be able to push it super duper fast.
So you decrease that debounce delay.
And if that's the case, then you're going to be more open to extraneous signals coming
in and causing problems.
So there's always a trade off.
For me, this is perfect, because there's no reason you should be going like that.
And it still works most of the time anyway.
One of the beautiful things about this setup, though, in the program, is that you can use
this module and basically copy and paste this into any of your projects.
So don't think that's cheating.
Don't think that Oh, man, I gotta recreate it from scratch every time.
That's ridiculous.
Once you create it and you get it working, you get it refined and you make it portable
on purpose.
Use it as much as possible.
Why, why reinvent the wheel?
It's just crazy.
So that's basically it.
That is how you read a button in the PIC10F200 using assembly.
As always, if you want to learn more, we highly recommend doing Sergey's recommended homework.
Now in this case, what he's thinking is making it so every time you push the button, you
show the number of presses as a binary number here.
So basically treat this as the first digit and this is the second digit, and then have
that go one and then turn off two and then have them both turn on three and then have
them both turn off.
The solution that Sergey came up with, actually, you learn two new commands and it's ANDWF
and RLF.
Now he doesn't actually give that to you in the written portion of the tutorial.
So that's one of the benefits of watching the video and learning something else.
So that's a little bit of a hint.
I hope that was interesting.
I hope you learned a lot about debounce.
I hope you learned a lot about assembly again as always.
And if you liked this video, give it a like, subscribe to our channel and we'll catch you
on the next one.