This is a fantastic video camera! However, to make this webcam work required way too much research time and effort so I thought I would take a few moments to provide my lessons learned with the hope it will help make the lives of other novices, like myself, a little better. This is the easiest way to enjoy excellent live HD video from anywhere in the world from your laptop, Android or iDevice without any service fees.
The goal of the project was to view live weather conditions from hundreds of miles away. Click this link for a video on how the project turned out: https://vimeo.com/157247877
Short Falls Of Most Old Tutorials
Many of the old Raspberry web cam tutorials found on the web were created with older configurations and fell apart as new revisions hit the market that left out key software components, rendering the tutorial useless for today’s projects. Many others explain how to create live video with Local Area Networks (LAN which is restricted inside your home) which is of no use to me. Still others would let you access your web cam over the Wide Area Network (WAN provides access from anywhere in the world) but would disconnect the camera from the web cam when you logged off the computer you were making changes from; this option put your web cam on the same network as your computer somewhere else in the world and shut down the cam when you closed your computer down since it lost the internet connection. Other solutions required Linux be loaded on my laptop but my computer is old and very memory challenged so that was not an option for me.
Still, others solutions required knowledge that I simply don’t have at the moment but may be “standard operating procedure” for many of you more advanced readers. For example, “simply download and cross compile the software form this link”. I don’t know how to do that and could not find a tutorial to explain it (but I have a hunch it requires Linux on my laptop).
Now, Create A Live Web Cam Accessible From Anywhere In the World
The following 3 step solution works great! However, I cannot take credit for any of the technical content of what I am about to provide; that credit goes to the people who spent the time creating the websites referenced. A suggestion would be to open the following links in your Raspberry Pi browser so you can copy and paste most of the commands.
Step 1. Basic Raspberry Pi 2 Startup
If you have not done it yet, here is a good video to get the latest upgrades, updates, enable your camera, enable SSH, and more.
https://www.youtube.com/watch?v=qLo-0Tmmlrc by Peter Oakes
Step 2. YouTube Live Account
Create your own YouTube Live account since we will need information from that account later. From your YouTube Live Stream page, get the encoder information provided at the bottom left of the YouTube Live page to enter into your Raspberry launch command later, and later you will see it go live using the Share link also provided at the bottom of the YouTube Live page. This should get you started: https://support.google.com/youtube/answer/2474026?hl=en
Step 3. Install FFMPEG
Many tutors on the internet complain that FFMPEG takes 9 hours to download but it only took me a little over an hour and a half (very reasonable to me, just go do something else for 1.5 hours). My Verizon FiOS internet speed is about 50 to 75 Mbps upload and download as a reference. Mr. Mueller’s link worked flawlessly for me and provided good explanations along the way, including much needed definitions of segments of the syntax. Except Mr. Mueller’s actual syntax used to stream to my YouTube Channel was close, but didn’t quite work (perhaps too much for YouTube to handle). Between Mr. Mueller and Schlatter I was able to make it work…These links are provided by Val Mueller and Wolfgang Schlatter.
Load FFMPEG from Mr. Mueller’s site:
http://www.valmueller.net/stream-video- … o-youtube/
But use the syntax command from Mr. Schlatter’s site to launch the video to YouTube Live:
https://plus.google.com/+wolfgangschlat … L5fRou17AX
EXCEPT on Mr. Schlatter’s command line, remove the “http://” and the “./” infront of ffmpeg from the command so it looks like this:
raspivid -o - -t 0 -w 1280 -h 720 -fps 25 -b 4000000 -g 50 | ffmpeg -re -ar 44100 -ac 2 -acodec pcm_s16le -f s16le -ac 2 -i /dev/zero -f h264 -i - -vcodec copy -acodec aac -ab 128k -g 50 -strict experimental -f flv rtmp://a.rtmp.youtube.com/live2/
Don’t put the brackets around the words: Your_YouTube_Live_Stream_Name_Key, just cut and paste the long alpha numeric Stream Name Key from your YouTube account and place it right after… live2/.
Remember to launch this syntax from this directory: cd /usr/src/ffmpeg and you don’t need “sudo” in front of the syntax command to launch the video.
Once you enter the syntax you should now see live streaming on your YouTube Live account and then be able to view it from anywhere in the world from your YouTube Live “Share” link (from lower right of the Stream Now page)! Note there is about a 17 second delay from what goes on in front of the camera until it goes live, but otherwise you get a clean, crisp picture without a lot of buffering. You don’t need to worry about creating a New Live Event or using any of YouTube’s suggested software. Just launch and enjoy your live view.
Other Useful Key Items
You might find it desirable to: 1) Work with your Raspberry Pi desktop with a wireless internet connection, 2) View the Rpi2 desktop on your own laptop rather than another monitor, 3) Create a Static IP so the camera doesn’t stop working when the Dynamic IP changes, 4) Have the ability to turn of the camera light so it doesn’t reflect into the camera in low light conditions, and 5) Make the router changes that allow you to work on the camera from miles away using your Windows Remote Desktop Connection. Here is how to accomplish those items…
Remote Desktop with Raspberry Pi
Using the xrdp with Windows Remote Desktop Connection is the best solution. It allows you to view your Raspberry Pi desktop and make changes to your camera from anywhere in the world and not have camera shut down when you close you remote laptop (as happens using other tutorials and free services).
https://www.jeremymorgan.com/tutorials/ … pberry-pi/
How To Use Remote Desktop Connection anywhere in the world through the internet!
Here is how to make changes to your router to accomplish this. Working inside the router sounded complex but the tutorial explained it so well that I could even understand it.
http://www.circuitbasics.com/access-ras … onnection/
Create a static IP address for your Raspberry Pi
Note: Your internet cord plugged in during this process
https://thepihut.com/blogs/raspberry-pi … spberry-pi
How to turn off the raspberry pi cam red led light
At first I would recommend using this tutorial http://thepihut.com/blogs/raspberry-pi- … camera-led
However, it appears that the latest software version again has disabled this simple command. So my solution is to just resort to a hardware change: simply put a drop of silicone on top of the led
Wireless Internet Connection
From the Raspberry Pi Desktop, just click on the icon of two computers in the upper right hand corner, find your internet from the drop down and enter the password for your internet connection. Then you should see the familiar radial internet signal at which time you can unplug the internet cord.
Read more of my helpful lessons learned on my Wordpress site (click this link and scroll down to “Additional Lessons Learned” to bypass the redundant information just read above in this RPi forum): http://wp.me/pEL3n-3y.
Below is the code used to control two stepper motors, two photo resistors and two LED’s to perform the pan/tilt function for the camera. The photo resistors and LED’s are used to optically find home after each reboot (figured this is better on the motors than a hard stop the motors run into and stall). I fashioned a crude pan/tilt assembly that spins one stepper motor on top of another stepper motor with their spin axis 90 degrees apart. I tried to keep the centre of gravity over the lower motor axle as best as practical. A solid thin black plastic shade (with a slit cut in it to allow light to pass) rotates with each axle which separates each photo resistor and LED pair. When the LED light is sensed, home position is established and the pan/tilt routine can start. I used double backed mounting tape to secure the camera to the arm attached to the top
I would recommend against buying the pan/tilt brackets sold online for $6 since they are rather poor quality and designed for an older motor configuration; making your own is pretty easy and less frustrating than trying to force the purchased unit to work. I am using the 28BYJ-48 5VDC stepper and the supplied circuit board. I found a package of 5 motors for about $14 on Amazon.
Code: Select all
import RPi.GPIO as gpio # import library RPi.GPIO gpio=use general purpose input output pin names
import time # import time library
PINSh = [27,10,18,23] # variable 'PINS' holds a list of gpio pin numbers
SEQAh = [(27,),(10,),(18,),(23,)]
PINSv = [4,17,22,24] # variable 'PINS' holds a list of gpio pin numbers
SEQAv = [(4,),(17,),(22,),(24,)]
LED_Pinh = 12
LED_Pinv = 26
#gpio.setwarnings(False) # Disable screen print warnings
DELAY = 0.01 # time between motor steps (too small of a number then the motor stalls)
alpha = 140 # horizontal full scale viewing angle in motor counts 128 counts = 360 degrees
beta = 25 # was 15 vertical full scale viewing angle in motor counts 128 counts = 360 degrees
beta2 = 35 # was 26 beta2 must be greater than beta.
adjusth = 10 # compensates horizontal home for packaging errors using motor counts
adjustv = 10 # compensates vertical home for packaging errors using motor counts
timeh = 100 # RCtimeh (how much light is sensed; lower number = more light)
timev = 100 # RCtimev (how much light is sensed; lower number = more light)
gpio.setmode(gpio.BCM) # tells RPi.GPIO we want to use pin names (BCM is the mfg)
for pin in PINSh: # pin is a variable name assigned a new value each loop; PINS is a list
gpio.setup(pin, gpio.OUT) # this says we want to use 'pin' as an output
for pin in PINSv: # pin is a variable name assigned a new value each loop; PINS is a list
gpio.setup(pin, gpio.OUT)
gpio.setup(LED_Pinv, gpio.OUT)
gpio.setup(LED_Pinh, gpio.OUT)
gpio.output(LED_Pinh, False)
gpio.output(LED_Pinv, False)
def stepper(sequence, pins): # def says 'stepper' is the function name (like a variable), then parameters are inside ()
for step in sequence:
for pin in pins:
if pin in step:
gpio.output(pin, gpio.HIGH)
else:
gpio.output(pin, gpio.LOW)
time.sleep(DELAY)
def RCtimeh (PiPinh):
measurementh = 0
gpio.setup(PiPinh, gpio.OUT)
gpio.output(PiPinh, gpio.LOW)
time.sleep(0.02)
gpio.setup(PiPinh, gpio.IN)
while (gpio.input(PiPinh) == gpio.LOW):
measurementh += 1
return measurementh
def RCtimev (PiPinv):
measurementv = 0
gpio.setup(PiPinv, gpio.OUT)
gpio.output(PiPinv, gpio.LOW)
time.sleep(0.02)
gpio.setup(PiPinv, gpio.IN)
while (gpio.input(PiPinv) == gpio.LOW):
measurementv += 1
return measurementv
#gpio.output(LED_Pinh, True)
#gpio.output(LED_Pinv, True)
#time.sleep(30)
#FIND HOME AT POWER UP:
# But first undo the adjustment from the previous 'power up' so it can't start up past the LED position (see pictures of normal operating area of shade).
counter = 0
while counter < adjusth:
stepper(SEQAh[::-1], PINSh)
counter = counter + 1
print "initializing position; counter horizontal = ", counter, "RCtimeh = ", RCtimeh(6)
counter = 0
while counter < adjustv: # Proives adjustment to correct home packaging error glueing photoresistor
stepper(SEQAv, PINSv) # stepper(SEQAv, PINSv) lowers home vertical angle with a positive adjustv factor
counter = counter + 1
print "initializing position; counter vertical = ", counter, "RCtimeh = ", RCtimev(5)
# Now find home:
counter = 0
counterh = 0
gpio.output(LED_Pinh, True) # Key Point: Size photosensor shade to keep left side always in dark
while RCtimeh(6) > timeh: # but position the shade so it will expose the sensor to light when sweeping right.
stepper(SEQAh, PINSh) # otherwise it will get out of sink and wrap the wires up and make a mess of things.
counterh = counterh + 1 # LED provides adequate light for photo resistors to work in low ambient light conditions
print "Finding Horz. Home ", counterh, "RCtimeh = ", RCtimeh(6) # Measure RC timing of photoresistor using only GPIO06 with 3.3VDC and gnd circuit inputs
if RCtimeh(6) < timeh:
print "Horizontal Home found,", " counter", counter, "RCtimeh = ", RCtimeh(6) # Found home horizontally
time.sleep(0.1)
if counterh > alpha * 1.5: # Protects unit from damage hunting past home position; blinking light = needs attention.
#print "Horizonal home out of range"
for _ in range(9999999):
gpio.output(LED_Pinh, True)
time.sleep(0.5)
gpio.output(LED_Pinh, False)
time.sleep(0.5)
gpio.output(LED_Pinh, True)
time.sleep(0.5)
gpio.output(LED_Pinh, False)
time.sleep(5)
while counter < adjusth: # Provides adjustment to correct home packaging error glueing photoresistor
stepper(SEQAh, PINSh)
counter = counter + 1
print "Adjust Horz. Home = ", counter, "RCtimeh = ", RCtimeh(6)
time.sleep(0.1) # Discharge capacitor in photoresistor circuit
gpio.output(LED_Pinh, False) # Turn off LED used by photoresistor
counter = 0
counterv = 0
gpio.output(LED_Pinv, True) # LED provides adequate light for photo resistors to work in low ambient light conditions
while RCtimev(5) > timev: # Key Point: Size photosensor shade to keep left side always in dark
stepper(SEQAv, PINSv) # but position the shade so it will expose the sensor to light when sweeping right.
counterv = counterv + 1 # otherwise it will get out of sink and wrap the wires up and make a mess of things.
print "Finding Vert. Home ", counterv, "RCtimev = ", RCtimev(5) # Measure RC timing of photoresistor using only GPIO06 with 3.3VDC and gnd circuit inputs
if RCtimev(5) < timev:
print "Vert. Home found", " counter", counter, "RCtimev = ", RCtimev(5) # Found home vertically
time.sleep(0.1) # Discharge Capacitor for 0.1 seconds but the 3.9 seconds is viewing time from home position
if counterv > beta * 1.5: # Protects unit from damage hunting past home position; blinking light = needs attention.
for _ in range(9999999):
gpio.output(LED_Pinv, True)
time.sleep(0.5)
gpio.output(LED_Pinv, False)
time.sleep(0.5)
gpio.output(LED_Pinv, True)
time.sleep(0.5)
gpio.output(LED_Pinv, False)
time.sleep(5)
gpio.output(LED_Pinv, False) # Turn off LED used by photoresistor
while counter < adjustv: # Provides vertical adjustment to home position for correction of packaging error glueing photoresistor
stepper(SEQAv[::-1], PINSv)
counter = counter + 1
print "Adjust vertical home = ", counter, "RCtimev = ", RCtimev(5)
time.sleep(0.1) # Discharge capacitor in photoresistor circuit
# CONTINUAL PAN AND TILT OPERATION (box pattern):
try:
while True:
counterh = 0
counterv = 0
for _ in range(beta): # From home position move down full beta
stepper(SEQAv[::-1], PINSv)
counterv = counterv + 1
if counterv == beta:
# print "view"
time.sleep(12)
for _ in range(alpha): # Move to the lower left in 2 horz viewing steps
stepper(SEQAh[::-1], PINSh)
counterh = counterh + 1
# print "Horz R", counterh, "Vert R", counterv
if counterh == alpha / 2:
# print "view"
time.sleep(10)
if counterh == alpha:
# print "view"
time.sleep(10)
for _ in range(beta): # Move up in 1 beta viewing step
stepper(SEQAv, PINSv)
counterv = counterv - 1
# print "Horz R", counterh, "Vert R", counterv
if counterv == 0:
# print "view"
time.sleep(8)
for _ in range(alpha): # Move upper right in 2 horz viewing steps
stepper(SEQAh, PINSh)
counterh = counterh - 1
# print "Horz R", counterh, "Vert R", counterv
if counterh == alpha / 3:
# print "view"
time.sleep(8)
if counterh == alpha * 2 / 3:
# print "view"
time.sleep(8)
if counterh == 0:
# print "view"
time.sleep(8)
# This second pan/tilt circuit looks a little higher in the sky:
for _ in range(beta): # From home position move down full beta
stepper(SEQAv[::-1], PINSv)
counterv = counterv + 1
if counterv == beta:
# print "view"
time.sleep(12)
for _ in range(alpha): # Move to the left in 2 horz viewing steps
stepper(SEQAh[::-1], PINSh)
counterh = counterh + 1
# print "Horz R", counterh, "Vert R", counterv
if counterh == alpha / 2:
# print "view"
time.sleep(10)
if counterh == alpha:
# print "view"
time.sleep(10)
for _ in range(beta2): # Move up in 1 viewing step to the top level one beta2
stepper(SEQAv, PINSv)
counterv = counterv - 1
# print "Vert R", counterv
if counterv == (beta - beta2):
# print "view"
time.sleep(8)
for _ in range(alpha): # Move to top right in 2 horz viewing steps
stepper(SEQAh, PINSh)
counterh = counterh - 1
# print "Horz R", counterh, "Vert R", counterv
if counterh == alpha / 3:
# print "view"
time.sleep(8)
if counterh == alpha * 2 / 3:
# print "view"
time.sleep(8)
if counterh == 0:
# print "view"
time.sleep(8)
for _ in range(beta2-beta): # Move back down to home in one (beta2 - beta) step
stepper(SEQAv[::-1], PINSv)
counterv = counterv + 1
if counterv == 0:
# print "Start again", "Horz R", counterh, "Vert R", counterv
# print "view"
time.sleep(10)
except KeyboardInterrupt:
gpio.cleanup() # Puts GPIO pins to LOW so you don't damage board with shorts