This is the solution for the step number one for this final project with the Raspberry Pi.
Make sure you have downloaded the PDF from the last lesson, or you can make sure you have read the
PDF so you know what's the challenge.
And in this first step, what we want to do is to detect a movement with the Pi sensor.
And when a movement has been detected for five seconds, we want to take a photo.
So we're just going to do the Pir sensor part and the logic.
And the photo is going to be in the next step.
So let's get started.
I'm going to start with a blank page.
And let's import from Gpio zero import motion sensor okay let's start with this.
Then we are going to initialize our Pir with this motion sensor.
And that's Gpio number four.
After we initialize it we can add the callbacks.
So I'm going to use the callbacks here with Pir dot when Motion and then per dot.
When?
No motion.
Okay.
So I need to create a function for both callbacks here.
I'm going to create the function right here.
For example def motion detected.
And let's create another one def motion.
Let's call it motion finished okay.
Because the no motion trigger here is well after motion has been detected.
And then not this is going to be called.
So we can call it motion finished.
Let's add a column here and then let's register.
So motion detected.
And once again important not to put parentheses here.
And motion finished okay.
And just to finish this global structure I'm going to do from signal inputs pose.
And then let's just do pose.
Okay.
So this is what we've done before in the motion sensor section we just created.
Then we had two callbacks to know when the motion has been detected and when it's finished.
And then we can write the logic of the code in this.
And then we make sure that we pose the problem.
Otherwise it's going to exit right away.
Now before I write the logic here, which is going to be the main challenge, let's just add an LED
and we're just going to turn on the LED when the motion is detected and turn off the LED when the motion
is not detected.
Okay.
So it's going to be easier for us when we test the program.
We can see the LED turned on or turned off.
And it's going to be much easier for us to visualize what's happening.
Okay.
So let's just add this.
And that's going to be very quick.
So I add the LED here.
Then I initialize my LED I just use one.
Okay.
You could use multiple ones if you want.
But one is enough.
And I'm going to use the first one for example, which is on Gpio 17.
Maybe after that I can add a print here.
Let's say Gpio was setup.
Okay.
All right.
So for everything I initialize the Gpio, the camera etc. I'm going to add a print here to say that
it's okay.
So when we start the program if we have an error somewhere we can have a better idea of what happened.
And let's just do setup Gpio.
So I add a comment here okay.
It's not going to be executed.
It's just a comment to say this is the setup Gpio part.
Great.
So now when the motion is detected I can do LED dot on.
And when the motion is finished I can do LED dot off.
All right that's it.
Now if you want you can well you can save the program already.
And let's name it.
So project step one dot pi.
Great.
Now you can go on the terminal.
We're going to try to run everything from the terminal.
You go to documents Python programs and you can do Python three projects.
Step 1CI use the auto completion here and Gpio setup okay.
And if you put your hand in front of the Pir sensor you should be able to see also the LED turned on
or turned off.
Okay.
So you can do a quick test already.
And now that we have this code structure okay.
So that's already a good start.
Let's add the logic to say that we want to take a photo after a motion has been detected for a minimum
of five seconds.
So how to do that?
Well, given this callback here, this callback structure, what I can do is to start monitoring the
time.
So I could create kind of a timer and start the timer.
When we get to the motion detected.
Then I could stop the timer when we get the motion finished.
And I could just compare this value of the time right now, minus the time that we registered here.
Is this value greater than five seconds?
If yes, we take a photo.
Okay.
So here with those two callbacks it's not so hard task to do as an alternative.
And that's also something I'm going to talk in the conclusion of this project.
You could instead of writing callbacks like that, you could use a while loop.
So an infinite while loop.
And the way to detect that the Pir sensor has been triggered for five seconds is going to be a tiny
bit different, maybe a bit more complicated, but I'm going to leave that up to you at the end of the
project.
Okay?
If you want to progress more and to get another challenge for this course, I'm just going to focus
on that solution with the callbacks.
So how to actually get the time and register the time?
Well, if I'm going to run on the shell here a quick test.
You can do import time first.
And then if you do time dot time.
So there is a time function inside the time module with the parentheses.
You see we have.
That's the current time.
That's called the time stamp.
That's the current time with some seconds and then a decimal point.
If I run the time again, you can see.
So it was eight something with eight seconds and now 18 seconds.
So basically it was 10s duration between those two.
If I do this one minus that one I will see about 10s duration.
So that's what we're going to use here.
I'm going to import time and then I'm going to start.
So I'm going to record the time here and check the difference with this starting time in the motion
finished.
So to start the time here and to be able to use it there we need to create a global variable.
So I'm going to create a variable here.
For example I can do global variables.
And we're going to put the global variables here.
And let's name this one time motion started.
We're gonna initialize it to the current time.
Actually, time dot time.
So we give it a first value.
That's going to be the current time when we start the program.
Then when the motion is detected, what we will do is we will do time.
Motion started is equal to time dot time.
Okay.
So we store the current time inside this variable.
And because this is a global variable you can use the global variable in a more nested scope if you're
going to read this variable or just use it.
But if you're going to modify it then you need to use the global keyword.
Okay.
So I'm going to use global time.
Motion started.
So this way when I do this I'm actually modifying that variable here.
And then that's great.
So we have the first step when the motion is detected.
So that's the beginning.
We start this kind of this timer.
Then when the motion is finished what I will do is I will calculate the duration.
So let's call that motion duration.
All right.
So here we talk about time.
So time is the specific moment in time.
So that's what time is it now.
But the duration is a difference between two times.
So the duration is going to be the current time at this moment.
What is the current time.
The current time is time.
The time minus the time motion started.
So this callback is going to be triggered when the motion is detected.
When it's finished, this one is going to be called.
We calculate the duration between the two and then we simply do.
If motion duration is greater we can just use strictly greater than five.
I'm going to use a decimal point here because we are comparing float numbers.
So if it's greater than five seconds then I'm just going to use a print here.
Taking a photo.
and sending it by email.
Okay, so we just have a print and then this is what we're going to do in the next few steps.
But for now we just focus on the logic.
And also I'm just going to put this just to make it a bit cleaner, maybe at the beginning of the program
here it doesn't really matter.
Great.
So we can already test that.
And actually to test it you can add intermediate logs to know what's happening.
Because here you will see this log.
But maybe it would be nice to see when we start the timer.
So print here starting timer.
And maybe let's print the motion duration so we can make some tests and see when we start the timer.
We are also going to see the LED on at this time.
And then when the LED goes off we can see also what was the duration.
So let's run that and let's first save it okay with Ctrl s.
So if you run from the terminal once again, make sure you save the file, because if you don't save
it when you run it here, it's not going to save it automatically and you're going to run the previous
version.
So let's do this and I'm going to make some.
So should be started okay I'm going to make some movement starting timer and make some movement.
And you see I stop and it's five seconds.
It says taking a photo.
I make some movements for less than five seconds.
Okay.
So actually this one was more than five.
Make a quick movement okay.
And you see two seconds.
We don't take a photo.
What you might notice you see here I have for example one second.
What you might notice is sometimes.
So here I made a movement.
But sometimes you might have false positives.
So the Pir sensor is going to just detect a movement but there is no real movement.
Or maybe you are on the side because here I'm a bit on the side.
So the Pir still detects the movement, so make sure that there is nothing in front of the pillar.
When you make the test.
Now stop this and I'm just going to make a quick parenthesis on this pillar sensor once again to talk
about the stability of the reading.
Okay.
It's not necessarily the most stable sensor, especially because, well, you could see a lot of noise.
And this noise can happen with a lot of different things.
For example, with the Wi-Fi signal that goes from, for example, your phone to the Raspberry Pi.
As it's very close, it could create some noise on the Pi sensor.
So the quality of the cable.
So maybe if you have longer cables, good quality cables, and you put the Pir sensor quite far from
the Raspberry Pi, maybe 50cm or 1m, then maybe it's going to be better then if you have too much light
in your room that goes directly into the Pir could also make it less stable.
Okay, if you have too many hardware components on the side and then depending on what surface you put
it.
So if you want to improve this part after this project, you can check for example, how to isolate
better the Pir sensor with some foil, for example, and then how to add a capacitor between the sensor
and the power supply.
Well, there are all sorts of things you can do on the hardware side to make it more stable.
Okay, I'm going to leave it like this for now.
That's going to be good enough for this project.
And also, anyway, you might not even use this specific sensor later.
So the goal is really to do the project and not to worry too much about external things.
So if you have some noise with the readings, if you have some false positives, don't worry too much
about this, okay?
This is just a hardware issue with this sensor and the way it's connected and the noise around this
is something you can fix in the future.
But for now, we're going to say that this is good enough for our project.
All right.
And now what I'm going to add one more thing to this step.
Because here well if the motion has been detected for more than five seconds we take a photo.
But I also want to limit this, to say that we only take a photo every 30s minimum.
So you can only take a photo if the last time you took a photo was at least 30s ago.
So we take maximum two photos per minute, okay?
Otherwise, this could take a lot of photos.
And you don't want to take too many because, well, it's going to take a lot of space on your Raspberry
Pi.
It's going to send a lot of emails, etc..
So we want to be sure to control that.
And here, well, quite arbitrarily, I have decided that we're going to wait at least 30s between two
photos.
So how can I do that?
Well, I'm going to create a new variable here.
I'm going to call it last time photo taken, and I'm going to initialize it to.
So this one I'm going to initialize it to zero.
Why.
Because for the first time when we run the program, I don't want to wait 30s before taking a photo,
I want to take a photo as soon as it's ready and then wait 30s after that.
So I have my variable last time photo taken.
And here, if we have detected that the duration of the motion was more than five seconds inside this,
if I'm going to do another.
If I'm going to do time dot time.
So that's the current time minus last time photo taken.
If this is greater than 30s then I will take a photo.
So I just add the tab here.
And also I need to say last time photo taken is the current time.
Okay, so this is a quite common behavior here.
When you want to limit an action with a minimum duration between two actions.
So when you want to do the action, you check that you have spent at least x amount of time between
the last time and now.
And if yes, then you store the current time as the last time and then you do the action.
All right.
So let's save that and let's test I'm going to run it again okay.
So let's start.
You see starting timer I'm going to do it for at least five seconds.
I stop.
Okay.
And you see, for example, here I have an error.
So let's go back to the program.
You see with Python is that the program can start correctly and then you might have an error because
of some code that is run later.
And I probably made a typo here last time.
Photo taken.
Yes.
Actually, it's not even a typo.
It's just that, you see, I'm using that global variable and I didn't write global, so I'm going to
write global with last time photo taken.
Then I can use the global variable.
So let's save.
Let's run.
And you can see here cannot access variable okay.
Because it was a global one.
So control C let's run again okay.
And let's do a movement for five seconds.
All right.
So you see taking a photo and sending it by email.
But now I'm doing another movement for at least five seconds.
Okay.
And you see, it's 6.5 seconds, but we don't take a photo.
Okay.
So I'm going to wait a few more seconds.
Okay.
And now I'm going to try again for more than five seconds.
And it has been at least 30s.
And.
Okay.
You can see 6.4 seconds.
We take a photo and sending by email.
So here we have two mechanisms.
We make sure that the motion duration is at least five seconds.
And we make sure that the last time we took a photo was at least 30s ago.
Great.
So this part of the program, this first step, this logic, was maybe the more complicated stuff we
do in this project in terms of Python logic.
But as you will see later, it's important that we do this first, because if we start to take photos
and send them by email and we don't have that ready and correctly working, then let's say the program
is taking 1000 photos in a few seconds and sending that by email.
Well, you don't really want that.
Okay.
So we want to make sure that this is working.
And then we can add the functionality to take the photo to send emails, etc..
And to quickly recap here.
So we initialize some global variables.
We initialize the Gpio.
And then we have the two callbacks for the Pir sensor when the motion is detected.
So with the one motion we start the timer.
And then when the motion is not detected anymore we stop the.
We don't restart the timer, but we compute the duration between the current time and the last time
when we started the timer.
If this is more than five seconds, we check that we haven't taken a photo in the last 30s if that's
okay, then we store the current time as the last time we took a photo and we take a photo.
One last thing to improve.
That is, instead of hardcoding the values here, I'm going to create some variables here.
And I'm going to name for example movement.
Detected threshold.
And note here that I am using all uppercase.
So why is that.
Because.
So I'm going to put five because well we want to consider this as kind of a constant variable that we
want to modify later on okay.
So in Python you don't really have constant variables.
So usually what I do is I put it all uppercase meaning that when I see this I try not to modify it later
in the program.
And the only way to modify is to just modify when you initialize it.
Okay.
So movement detected threshold and mean duration between photos 30s.
All right.
So let's take that and let's replace it here.
And then let's take that one and replace there.
Okay.
And with this you can see it's even more clear okay what's happening in the code.
And then you can modify the variables directly here at the beginning of the program.
All right.
And that's going to be it for the first step.