Alright, welcome to the 10th tutorial on the microcontroller PIC10F200 microcontroller
assembly language one...
whatever we're calling this series.
And this one's really interesting.
It's very complicated.
There's actually a lot of moving parts.
So I'm going to try and keep this short and concise.
But I want to make sure we hit the big things.
But the goal for today is to create a code lock.
So basically, we've been learning how to deal with buttons, how to get inputs and all that
sort of stuff.
Now we're going to make it so we get an input from those buttons.
And depending on how you put the buttons in order, it compares it with a code that you've
programmed in it.
And depending on whether it's right or it's wrong, you can drive a servo motor to open
or close the lock.
That's the theory.
Anyway, we are going to be talking about that code comparison, which is actually going to
be using some indirect addressing, which, if you're familiar with the higher level languages,
is basically like pointers.
We're going to talk about the servo.
And then we're also going to talk about two new commands and then we're going to go through
the structure.
I'm going to show you all the... it's going to be a crazy day, but it's going to be fun.
Let's get into it.
The first thing I want to talk about is servos.
So if you haven't dealt with a servo, a servo?
It looks exactly like this.
This is an SG90.
They're extremely common.
Serge basically said, Hey, I have some SG90s lying around, I'll use some.
And then I looked around, and I just happen to have a couple line around too.
So it's entirely possible that you have a couple lying around.
But the way a servo works is with a typical one, without the continuous rotation, the
ability to go all the way around, you have the capability of saying exactly where you
want the servo motor to be.
And the way you do that is by changing the duty cycle of a 20 millisecond pulse to it,
and... it's a little bit hand wavy... but you send it a 20 millisecond pulse, and between
18 or 19 milliseconds of that is low voltage.
And then one to two milliseconds is a high voltage and depending on how long that is,
whether it's one or two seconds, gives you where you were So one millisecond of those
20 milliseconds will put it here, two milliseconds of those 20 milliseconds, we'll put it there.
Now the reason I say it's a bit hand wavy is because it doesn't have to be exactly a
20 millisecond cycle.
So the way we are actually doing it in this program is we're just saying that the low
is 20 milliseconds no matter what.
And then we are changing how high the pulses to change exactly where we want to put this.
So this is a very, very high level overview.
If you don't know anything about servos, that should get you enough to kind of understand
this, but I highly recommend you go look some more somewhere else and find out more about
servos.
So we'll get into that more in the code.
The second thing I wanted to talk about was the two new items, the two new commands that
we are going to learn today the two commands that we need to learn about are RRF, which
is rotate right through carry.
So we did the rotate left in an earlier command when basically you have your eight bits and
you can rotate it.
For me, this is left and this is right.
In a previous program, we took everything and we rotated it left.
And now we want to take the same thing, take those eight bits and just move them over one
set.
So instead of being 012345678, now this one is 012345678 on the end, and then it grows
through the carry bit.
So that's what the RRF stands for.
It's pretty straightforward.
And the second thing is we are doing the ANDLW, so that second command is ANDing the literal
and what's in the working register, and then outputting, whatever the result is from those
ANDs, and that is yet another one of those bitwise operators.
So incredibly important.
If you do understand bitwise, super easy.
If you don't, you need to learn more.
We don't have the time to deal with it now.
But those are the two commands that we have learning and using in this particular program.
So the final thing that I want to get into before we go through the structure and how
this actually setup is indirect addressing.
Addressing?
Something like that everything that we've been doing so far has been direct addressing.
We basically say I want to put a value in "that" register and we say that register the
the GP1 bit of the GPIO register.
And so that is the direct addressing.
However, indirect addressing is where you are actually dealing with the address.
So you pulling the address of the GPIO... is it address or address?
But you're getting the address.
Yeah, that sounds better.
You're getting the address of the place that you want to go to.
And so instead of saying, let's put something in the GP1 bit of the GPIO register, you're
saying, let's put something in bit 1 of the register that happens to be at this address.
You may think, Okay, so what is the point of that?
That seems like you're putting in an extra step, and you're making it even more confusing
because now you're dealing with the addresses instead of just going to it straight.
So I spent a good two to three seconds working on this idea that will hopefully make it more
clear.
So, imagine you are in a basketball stadium and there are people sitting in the seats,
and you want to get peanuts to those people.
And so with direct addressing, you say, give this bag of peanuts to Jane.
And you go and you give that bag of peanuts to Jane.
And then you say, give this bag of peanuts to Bob.
So you go and give it to Bob.
And you say, give, give this bag of peanuts to Mary, okay go give it to Mary.
Well, that can be a bit tedious when you can say, well, they're all sitting right next
to each other.
So give a bag of peanuts to Bob and everybody to his right, the six people to his right,
and then somebody knows, okay, at that address where Bob is located, that plus one plus one
plus one plus one plus one.
And that is kind of the benefit of indirect addressing is that way instead of having to
individually address each one of those spots, you can do a whole series of things that are
right next to each other or separated in a certain pattern very, very easily.
So that's one of the huge benefits of indirect addressing or pointers and there's probably
a huge amount of other ways, but that is the way we are going to be using it.
And that's actually one of the ways that Microchip uses it as an example in their code as well.
So it does take a little bit more to wrap your mind around it.
But in cases like this, where you are trying to point at things that are in a consecutive
line, it makes things easier, makes the code faster, and all around is better.
Once you get past that initial "mind wrapping" issue.
So now that we've talked about some of the concepts that we are going to be dealing with,
let's jump into the code itself.
It's pretty long, and it looks kind of crazy at first, but really, it's just a bunch of
different things.
And once you get the overall structure, it'll be fine.
Okay, so looking at the code, we have our normal, everything's initialized and we're
putting values with the EQU's from lines 8 to 14.
One of the things I do want to point out is on line 4, we are putting in the code that
is going to be used as a comparison.
So for us to use this we are going to need to type in the code 2311.
So in this case I haven't set up and if you follow the schematic that we may have flashed
up on the screen or may not have, but definitely have on circuitbread.com, you have 2311 just
to have that be the code that open and close it.
So that is where you putting in the code that will be referenced.
The other huge thing that we need to talk about is line 14 that NUM1, and that's the
first number register.
And that is the first one of the numbers that we will be using to compare with the code.
We don't have to have numbers 123 and 4, because we're doing the indirect dressing.
And because all we need to know like going back to that first example, you just need
to know that Jane was in one, and that there are three more people right next to her.
So let's keep on going.
We initialize things in lines 18 through 25.
We want this to start up and initialize to the lock being closed.
So that's why we have that in 23-24 is just basically making sure that whenever it starts
up, the lock is closed and we're moving on.
And then we start going to where, it looks a little bit crazy, but really all we're doing
is reading buttons and doing the debounce like we've done in prior projects, so it won't
be too terrible.
And number 29, we check the buttons.
And now once we get the buttons that is not only checking to see that a button was pressed,
but it is also checking to see which button was pressed.
And so it comes back in the check button sub routine, down lower, can look at that really
quick.
And notice that it's checking to see if switch one, switch two, switch three was pressed.
And then depending on which one was actually pressed, it returns the proper value or if
nothing was pressed, returns a zero and then it takes that and it goes back up.
And then you have lines 34-35 to do the debounce in that ANDLW, what that's doing is it's returning
eight bits, but you want to make sure that the top six basically just bits two through
seven are ignored.
They're complete garbage, you're only going to be returning a 0,1,2, or 3 which you can
do with the bottom two bits.
And so that's all that ANDLW is for with the three is to make sure that you're getting
rid of anything in there that's not supposed to be there.
So keep on going, I will point out one thing, the way this is set up is that if the lock
is open, and you just push any button, it'll immediately close.
And so that's why in lines 46 and 47, you're checking, oh, the locks already open, a button
has been pushed, close it, and then jump back and start the whole thing over again.
Otherwise, if it is already closed, and you're getting the button reads, you keep on going
fill up your buffer with the input before finally jumping into line 53, where you now
compare the codes between what is input and what you have that we established back up
at the top of the file.
So I'm going to get into a little bit more detail between lines 53 and 63.
Because this is where we're checking the code and this is where we're using the indirect
addressing.
So in 54, we are putting the code that we've gotten and putting it into the working register
so that we can actually deal with it.
And also because we're going to manipulating it.
And we don't want to mess up the original value that we got.
So we take that code, we put it into the into the working register.
And then again, we clear out everything but the bottom two bits of what's in the working
register.
In that way, we can check the first number.
So we subtract what is in the indirectly addressed register, which is basically that number one
that we established up at the top.
And if the result is not zero, that means that they are not the same that what is in
the bottom two bits of the code that was entered and the bottom two bits of the code that you're
expecting.
They should be the same.
And if they subtract and you get zero, then they're the same.
Otherwise they're not.
If they're not the same, then you do not skip the next line and you go to the top of the
loop.
So you basically start the whole thing over again, if it is the same, then you go down
two lines, 59 and 60, where you do that shift right register twice to move everything over.
So then later, you can compare that so 59-60 you shift everything to the right twice.
61, you increment the indirect address.
So now you're changing from Jane to Bob or from the first number and that you want to
compare with the second number that you want to compare.
And then you decrement the count to check to see, hey, have we checked all of them,
and we haven't at this point.
So we go back up to check the code, where we do the exact same thing, we take everything
we put in the working register, we get rid of everything that we don't want to look at,
we subtract it, we check to see if it's zero.
If it's still zero, great.
That means it's the same shift everything to the right increment the indirect address
decrement, the count, if the count is still not zero, go up and do that.
So should be doing that four times.
And then if you go through and it is correct every single time, then you're going to finally
skip that GOTO Check Code and you're going to go straight into line 65, where you open
the lock, and everything is great.
Then once you've manipulated the servo, you've opened it up, then you jump up and you start
the whole thing over again.
So while there were a lot of moving parts to this code, it actually wasn't too bad.
Each one individually, so it could seem a little bit overwhelming at first.
But all of these things individually should be pretty straightforward.
And as always, if you do still have questions, and you've watched this two or three times,
we have each one of these lines, basically described in detail on circuitbread.com with
the written tutorial that Sergey did.
So all of this stuff is based on those written tutorials that Sergey wrote and they're on
circuitbread.com that again, that's down in description, the link straight to this tutorial
should be there.
And so if you have any more questions, or you want further detail, please go check that
out.
As it is, I'm going to program this thing up, and I'm going to show it to you in action,
and then we'll be done for the day.
So let me get that done.
All right, it's programmed.
Let's see if I did this successfully.
One of the things that I found when we... when I was testing this, and Sergey has had
the same problem, is that for some reason, all these programming lines are affecting
the switch reads, so I'm going to unplug everything from the PICKit that is on the same line as
one of the buttons and then I'm going start... going through this...
Which one is that?
There we go.
So now, again, the code is 2311.
So the way I have the setup is 123.
So it's 2311.
The interesting thing is the way this is set up is if you're off, and it's, it's expecting
for button inputs.
And so if you put in the code and it's off by one, then you need to put in the code,
and then hit another extra random button to shift everything put in the code.
Still doesn't work, shift, put another random button to shift everything.
And keep on doing that until you get it.
So... so 2311.
Nope.
Let's try that again 2311.
I hope I'm not just making a fool of myself here.
There we go.
Now we're alive.
So that was it.
That was the movement.
Now the interesting thing is for a servo, the way it works, is if you stop giving it
any pulses, it just stays where it is, but then it's pretty easy to move.
And that's the way we have it set up whereas if you want to stay in place no matter whether
or not you're trying to move it, then you need to constantly give it that pulse.
But that's not necessary for what we're doing.
So that's why I can move it like this.
Now, like I mentioned, should be able to just hit any button and it should go back.
And then I should be able to put the code in again to move it.
See, there we go.
Two, three, one, one.
Yeah, I can just sit here all day.
I don't have anything better to do.
So now it's locked again!
Everything is good to go.
And that is the whole thing working.
Hope you found this interesting.
Hope you found it fascinating.
Again, there's a whole lot more detail and a lot more information on circuitbread.com
and again, that description to the, excuse me, the link to this actual tutorial is in
the description.
So go check it out.
If you have not subscribed to our channel, we appreciate the support you would be showing
us with a subscription.
And that way you can find out more and learn more about not only microcontrollers, and
things along these lines, but everything about electronics and electrical engineering.
If you liked it, give it a like, all that jazz but we will see you in the next one.
Take care!