Taking Down the RPi Camera Over My Hummingbird Feeder
As the temperature heats up it’s time to take down my hummingbird feeder. While the winds have cooled down the valley for the last few days, 100+ days are slowly creeping in and I need to take it down before the CPU melts.
When I took it down last year I though, meh, how hard could it be to put back up. And then I put it back up in the Fall last year and had nothing but problems.
This year, I wanted to document the wires and what not so that I can just put it back up once the temps cool down outside.
Anyway, I could describe it or just take some pictures ... so here are some pictures for when I need to set it up again later this year.
Above the feeder:
Wires to the sensor:
Wires to the GPIO pins:
Monitoring the temperature of my Raspberry Pi Camera
In late April of this year I wrote a script that would capture the temperature of the Raspberry Pi that sits above my Hummingbird feeder and log it to a file.
It’s a straight forward enough script that captures the date, time and temperature as given by the internal measure_temp
function. In code it looks like this:
MyDate="`date +'%m/%d/%Y, %H:%M, '`"
MyTemp="`/opt/vc/bin/vcgencmd measure_temp |tr -d "=temp'C"`"
echo "$MyDate$MyTemp" >> /home/pi/Documents/python_projects/temperature/temp.log
I haven’t ever really done anything with the file, but one thing I wanted to do was to get alerted if (when) the temperature exceeded the recommended level of 70 C.
To do this I installed ssmtp
onto my Pi using apt-get
sudo apt-get install ssmtp
With that installed I am able to send an email using the following command:
echo "This is the email body" | mail -s "This is the subject" user@domain.tld
With this tool in place I was able to attempt to send an alert if (when) the Pi’s temperature got above 70 C (the maximum recommended running temp).
At first, I tried adding this code:
if [ "$MyTemp" -gt "70" ]; then
echo "Camera Pi Running Hot" | mail -s "Warning! The Camera Pi is Running Hot!!!" user@domain.tld
fi
Where the $MyTemp
came from the above code that gets logged to the temp.log file.
It didn’t work. The problem is that the temperature I’m capturing for logging purposes is a float, while the item it was being compared to was an integer. No problem, I’ll just make the “70” into a “70.0” and that will fix the ... oh wait. That didn’t work either.
OK. I tried various combinations, trying to see what would work and finally determined that there is a way to get the temperature as an integer, but it meant using a different method to capture it. This is done by adding this line:
ComparisonTemp=$(($(cat /sys/class/thermal/thermal_zone0/temp)/1000))
The code above gets the temperature as an integer. I then use that in my if
statement for checking the temperature:
if [ "$ComparisonTemp" -gt "70" ]; then
echo "Camera Pi Running Hot" | mail -s "Warning! The Camera Pi is Running Hot!!!" user@domain.tld
fi
Giving a final script that looks like this:
MyDate="`date +'%m/%d/%Y, %H:%M, '`"
MyTemp="`/opt/vc/bin/vcgencmd measure_temp |tr -d "=temp'C"`"
echo "$MyDate$MyTemp" >> /home/pi/Documents/python_projects/temperature/temp.log
ComparisonTemp=$(($(cat /sys/class/thermal/thermal_zone0/temp)/1000))
if [ "$ComparisonTemp" -gt "70" ]; then
echo "Camera Pi Running Hot" | mail -s "Warning! The Camera Pi is Running Hot!!!" user@domain.tld
fi
Adding my Raspberry Pi Project code to GitHub
Over the long holiday weekend I had the opportunity to play around a bit with some of my Raspberry Pi scripts and try to do some fine tuning.
I mostly failed in getting anything to run better, but I did discover that not having my code in version control was a bad idea. (Duh)
I spent the better part of an hour trying to find a script that I had accidentally deleted somewhere in my blog. Turns out it was (mostly) there, but it didn’t ‘feel’ right … though I’m not sure why.
I was able to restore the file from my blog archive, but I decided that was a dumb way to live and given that
- I use version control at work (and have for the last 15 years)
- I’ve used it for other personal projects
However, I’ve only ever used a GUI version of either subversion (at work) or GitHub (for personal projects via PyCharm). I’ve never used it from the command line.
And so, with a bit of time on my hands I dove in to see what needed to be done.
Turns out, not much. I used this GitHub resource to get me what I needed. Only a couple of commands and I was in business.
The problem is that I have a terrible memory and this isn’t something I’m going to do very often. So, I decided to write a bash script to encapsulate all of the commands and help me out a bit.
The script looks like this:
echo "Enter your commit message:"
read commit_msg
git commit -m "$commit_msg"
git remote add origin path/to/repository
git remote -v
git push -u origin master
git add $1
echo ”enter your commit message:”
read commit_msg
git commit -m ”$commit_msg”
git push
I just recently learned about user input in bash scripts and was really excited about the opportunity to be able to use it. Turns out it didn’t take long to try it out! (God I love learning things!)
What the script does is commits the files that have been changed (all of them), adds it to the origin on the GitHub repo that has been specified, prints verbose logging to the screen (so I can tell what I’ve messed up if it happens) and then pushes the changes to the master.
This script doesn’t allow you to specify what files to commit, nor does it allow for branching and tagging … but I don’t need those (yet).
I added this script to 3 of my projects, each of which can be found in the following GitHub Repos:
I had to make the commit.sh executable (with chmod +x commit.sh
) but other than that it’s basically plug and play.
Addendum
I made a change to my Kings script tonight (Nov 27) and it wouldn’t get pushed to git. After a bit of Googling and playing around, I determined that the original script would only push changes to an empty repo ... not one with stuff, like I had. Changes made to the post (and the GitHub repo!)
The PIR Sensor Debacle of 2018
Last spring I set up a Raspberry Pi to record humming birds at my hummingbird feeder, compile the recorded h264 files into an mp4 and upload it to YouTube.
I’ve written about that process before here, here, and here.
This post is a bit of documentation to remind myself about how to connect the PIR sensor to the Raspberry Pi so I don’t forget.
When I went to set it up this year, it appeared like the PIR sensor wasn’t working. It would start the video capture, but it wouldn’t end it.
I tried a couple of different things (including the purchase of some new PIR sensors) but none of them seemed to work. I was worried that the heat from the early bit of summer last year had maybe fried my little Pi.
But no, it turns out that the link I was using as the basis for my project had a diagram AND a description about how to connect the PIR.
I had assumed that the diagram was correct and that I didn’t need to read the description, but it turns out I did BECAUSE the diagram had the connections set up in a way that didn’t line up with the PIR sensor(s) I have.
In the Parent Detector PIR sensor the connectors are (1) Power, (2) Ground, (3) Out
In my PIR sensor the connectors are (1) Power, (2) Out, (3) Ground.
This meant that the power was getting to the PIR sensor, but there was no way to send the trip because the signal was being sent to the Ground.
Anyway, the morale of the story is, pictures are nice, but reading may save you some time (and money) in the long run.
Cronjob Redux
After days of trying to figure this out, I finally got the video to upload via a cronjob.
There were 2 issues.
Issue the first
Finally found the issue. Original script from YouTube developers guidehad this:
CLIENT_SECRETS_FILE = "client_secrets.json"
And then a couple of lines later, this:
% os.path.abspath(os.path.join(os.path.dirname(__file__), CLIENT_SECRETS_FILE))
When crontab
would run the script it would run from a path that wasn’t where the CLIENT_SECRETS_FILE
file was and so a message would be displayed:
WARNING: Please configure OAuth 2.0
To make this sample run you will need to populate the client_secrets.json file
found at:
%s
with information from the Developers Console
https://console.developers.google.com/
For more information about the client_secrets.json file format, please visit:
https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
What I needed to do was to update the CLIENT_SECRETS_FILE
to be the whole path so that it could always find the file.
A simple change:
CLIENT_SECRETS_FILE = os.path.abspath(os.path.join(os.path.dirname(__file__), CLIENT_SECRETS_FILE))
Issue the second
When the create_mp4.sh
script would run it was reading all of the h264
files from the directory where they lived BUT they were attempting to output the mp4
file to /
which it didn’t have permission to write to.
This was failing silently (I’m still not sure how I could have caught the error). Since there was no mp4
file to upload that script was failing (though it was true that the location of the CLIENT_SECRETS_FILE
was an issue).
What I needed to do was change the create_mp4.sh
file so that when the MP4Box command output the mp4
file to the proper directory. The script went from this:
(echo '#!/bin/sh'; echo -n "MP4Box"; array=($(ls ~/Documents/python_projects/*.h264)); for index in ${!array[@]}; do if [ "$index" -eq 0 ]; then echo -n " -add ${array[index]}"; else echo -n " -cat ${array[index]}"; fi; done; echo -n " hummingbird.mp4") > create_mp4.sh
To this:
(echo '#!/bin/sh'; echo -n "MP4Box"; array=($(ls ~/Documents/python_projects/*.h264)); for index in ${!array[@]}; do if [ "$index" -eq 0 ]; then echo -n " -add ${array[index]}"; else echo -n " -cat ${array[index]}"; fi; done; echo -n " /home/pi/Documents/python_projects/hummingbird.mp4") > /home/pi/Documents/python_projects/create_mp4.sh
The last bit /home/pi/Documents/python_projects/create_mp4.sh
may not be necessary but I’m not taking any chances.
The video posted tonight is the first one that was completely automatic!
Now … if I could just figure out how to automatically fill up my hummingbird feeder.
Cronjob ... Finally
I’ve mentioned before that I have been working on getting the hummingbird video upload automated.
Each time I thought I had it, and each time I was wrong.
For some reason I could run it from the command line without issue, but when the cronjob would try and run it ... nothing.
Turns out, it was running, it just wasn’t doing anything. And that was my fault.
The file I had setup in cronjob was called run_scrip.sh
At first I was confused because the script was suppose to be writing out to a log file all of it’s activities. But it didn’t appear to.
Then I noticed that the log.txt file it was writing was in the main \`
directory. That should have been my first clue.
I kept trying to get the script to run, but suddenly, in a blaze of glory, realized that it was running, it just wasn’t doing anything.
And it wasn’t doing anything for the same reason that the log file was being written to the \`
directory.
All of the paths were relative instead of absolute, so when the script ran the command ./create_mp4.sh
it looks for that script in the home directory, didn’t find it, and moved on.
The fix was simple enough, just add absolute paths and we’re golden.
That means my run_script.sh
goes from this:
# Create the script that will be run
./create_script.sh
echo "Create Shell Script: $(date)" >> log.txt
# make the script that was just created executable
chmod +x /home/pi/Documents/python_projects/create_mp4.sh
# Create the script to create the mp4 file
/home/pi/Documents/python_projects/create_mp4.sh
echo "Create MP4 Shell Script: $(date)" >> /home/pi/Documents/python_projects/log.txt
# upload video to YouTube.com
/home/pi/Documents/python_projects/upload.sh
echo "Uploaded Video to YouTube.com: $(date)" >> /home/pi/Documents/python_projects/log.txt
# Next we remove the video files locally
rm /home/pi/Documents/python_projects/*.h264
echo "removed h264 files: $(date)" >> /home/pi/Documents/python_projects/log.txt
rm /home/pi/Documents/python_projects/*.mp4
echo "removed mp4 file: $(date)" >> /home/pi/Documents/python_projects/log.txt
To this:
# change to the directory with all of the files
cd /home/pi/Documents/python_projects/
# Create the script that will be run
/home/pi/Documents/python_projects/create_script.sh
echo "Create Shell Script: $(date)" >> /home/pi/Documents/python_projects/log.txt
# make the script that was just created executable
chmod +x /home/pi/Documents/python_projects/create_mp4.sh
# Create the script to create the mp4 file
/home/pi/Documents/python_projects/create_mp4.sh
echo "Create MP4 Shell Script: $(date)" >> /home/pi/Documents/python_projects/log.txt
# upload video to YouTube.com
/home/pi/Documents/python_projects/upload.sh
echo "Uploaded Video to YouTube.com: $(date)" >> /home/pi/Documents/python_projects/log.txt
# Next we remove the video files locally
rm /home/pi/Documents/python_projects/*.h264
echo "removed h264 files: $(date)" >> /home/pi/Documents/python_projects/log.txt
rm /home/pi/Documents/python_projects/*.mp4
echo "removed mp4 file: $(date)" >> /home/pi/Documents/python_projects/log.txt
I made this change and then started getting an error about not being able to access a json
file necessary for the upload to YouTube. Sigh.
Then while searching for what directory the cronjob was running from I found this very simple idea. The response was, why not just change it to the directory you want. 🤦♂️
I added the cd
to the top of the file:
# change to the directory with all of the files
cd /home/pi/Documents/python_projects/
Anyway, now it works. Finally!
Tomorrow will be the first time (unless of course something else goes wrong) that The entire process will be automated. Super pumped!
Hummingbird Video Capture
I previously wrote about how I placed my Raspberry Pi above my hummingbird feeder and added a camera to it to capture video.
Well, the day has finally come where I’ve been able to put my video of it up on YouTube! It’s totally silly, but it was satisfying getting it out there for everyone to watch and see.
Hummingbird Video Capture: Addendum
The code used to generate the the mp4
file haven’t changed (really). I did do a couple of things to make it a little easier though.
I have 2 scripts that generate the file and then copy it from the pi to my MacBook Pro and the clean up:
Script 1 is called create_script.sh
and looks like this:
(echo '#!/bin/sh'; echo -n "MP4Box"; array=($(ls *.h264)); for index in ${!array[@]}; do if [ "$index" -eq 0 ]; then echo -n " -add ${array[index]}"; else echo -n " -cat ${array[index]}"; fi; done; echo -n " hummingbird.mp4") > create_mp4.sh | chmod +x create_mp4.sh
This creates a script called create_mp4.sh
and makes it executable.
This script is called by another script called run_script.sh
and looks like this:
./create_script.sh
./create_mp4.sh
scp hummingbird.mp4 ryan@192.168.1.209:/Users/ryan/Desktop/
# Next we remove the video files locally
rm *.h264
rm *.mp4
It runs the create_script.sh
which creates create_mpr.sh
and then runs it.
Then I use the scp
command to copy the mp4
file that was just created over to my Mac Book Pro.
As a last bit of housekeeping I clean up the video files.
I’ve added this run_script.sh
to a cron job that is scheduled to run every night at midnight.
We’ll see how well it runs tomorrow night!
Using MP4Box to concatenate many .h264 files into one MP4 file: revisited
In my last post I wrote out the steps that I was going to use to turn a ton of .h264
files into one mp4
file with the use of MP4Box
.
Before outlining my steps I said, “The method below works but I’m sure that there is a better way to do it.”
Shortly after posting that I decided to find that better way. Turns out, ~~it wasn’t really that much more work~~ it was much harder than originally thought.
The command below is a single line and it will create a text file (com.txt) and then execute it as a bash script:
~~(echo '#!/bin/sh'; for i in *.h264; do if [ "$i" -eq 1 ]; then echo -n " -add $i"; else echo -n " -cat $i"; fi; done; echo -n " hummingbird.mp4") > /Desktop/com.txt | chmod +x /Desktop/com.txt | ~/Desktop/com.txt
~~
(echo '#!/bin/sh'; echo -n "MP4Box"; array=($(ls *.h264)); for index in ${!array[@]}; do if [ "$index" -eq 1 ]; then echo -n " -add ${array[index]}"; else echo -n " -cat ${array[index]}"; fi; done; echo -n " hummingbird.mp4") > com.txt | chmod +x com.txt
Next you execute the script with
./com.txt
OK, but what is it doing? The parentheses surround a set of echo commands that output to com.txt. I’m using a for loop with an if statement. The reason I can’t do a straight for loop is because the first h264
file used in MP4Box
needs to have the -add
flag while all of the others need the -cat
flag.
Once the file is output to the com.txt
file (on the Desktop) I pipe it to the chmod +x
command to change it’s mode to make it executable.
Finally, I pipe that to a command to run the file ~/Desktop/com.txt
I was pretty stoked when I figured it out and was able to get it to run.
The next step will be to use it for the hundreds of h264 files that will be output from my hummingbird camera that I just installed today.
I’ll have a post on that in the next couple of days.
Using MP4Box to concatenate many .h264 files into one MP4 file
The general form of the concatenate command for MP4Box is:
MP4Box -add <filename>.ext -cat <filename>.ext output.ext
1
When you have more than a couple of output files, you’re going to want to automate that -cat
part as much as possible because let’s face it, writing out that statement even more than a couple of times will get really old really fast.
The method below works but I’m sure that there is a better way to do it.
- echo out the command you want to run. In this case:
(echo -n "MP4Box "; for i in *.h264; do echo -n " -cat $i"; done; echo -n " hummingbird.mp4") >> com.txt
- Edit the file
com.txt
created in (1) so that you can change the first-cat
to-add
vim com.txt
- While still in
vim
editing thecom.txt
file add the#!/bin/sh
to the first line. When finished, exit vim2 - Change the mode of the file so it can run
chmod +x com.txt
- Run the file:
./com.txt
Why am I doing all of this? I have a Raspberry Pi with a Camera attachment and a motion sensor. I’d like to watch the hummingbirds that come to my hummingbird feeder with it for a day or two and get some sweet video. We’ll see how it goes.