├── .gitattributes ├── .gitignore ├── ReadMe.txt ├── picamcorder.sh ├── picamcorder2.py ├── picamstills-db.py ├── picamstream-sudo.py └── picamstreamer.py /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac crap 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | -------------------------------------------------------------------------------- /ReadMe.txt: -------------------------------------------------------------------------------- 1 | This Readme contains basic info about the RasPiCamcorder 2 2 | by Alex Eames of RasPi.TV 3 | 4 | ============================= 5 | Released under the Creative Commons Attribution 3.0 Unported (CC BY 3.0) 6 | http://creativecommons.org/licenses/by/3.0/ 7 | 8 | You may do whatever your like with this software. If you release a derivative 9 | it must contain at or near the top of the documentation... 10 | 11 | "Based on RasPiCamcorder scripts by Alex Eames of http://RasPi.TV/ 12 | https://github.com/raspitv/RasPiCamcorder/" 13 | 14 | That is your ONLY obligation. 15 | ============================= 16 | 17 | Basically there are three major parts... 18 | 19 | Video recording [sudo python picamcorder2.py] 20 | Stills capture (plus DropBox upload) [sudo python picamstills-db.py] 21 | Video streaming [python picamstreamer.py] 22 | 23 | These are currently three separate programs. See below for details. 24 | 25 | Photos and further info on the http://RasPi.TV blog or YouTube... 26 | 27 | http://raspi.tv/?p=3424 28 | and 29 | http://youtu.be/dSgj4bUFBCQ 30 | 31 | Buttons 32 | ======= 33 | Basically you need a button connected between GPIO 23 and GND. 34 | This is the "shoot video or photo" button. (Mine is the blue one in this photo 35 | http://raspi.tv/wp-content/uploads/2013/06/DSC_4467.jpg). 36 | 37 | You also need a button between GPIO 24 and 3V3, which is the 38 | "stop shooting" button. It also doubles as the close program and shutdown 39 | button depending on how long you press it for. (Mine is the black one in this 40 | photo http://raspi.tv/wp-content/uploads/2013/06/DSC_4467.jpg). 41 | Pressing this button for >1s stops the program (useful if you are running 42 | automatically on boot). Pressing it for >3s shuts down the Pi. 43 | 44 | 45 | LEDs 46 | ==== 47 | The camera LED is on GPIO 5. 48 | I have an additional LED (I wanted one on the back) on GPIO 22 49 | 50 | Setting up camera led control (script may not work properly without this) 51 | ----------------------------- 52 | 53 | sudo nano /boot/config.txt 54 | 55 | Add this line to your config.txt 56 | 57 | disable_camera_led=1 58 | 59 | 60 | Usage 61 | ===== 62 | 63 | Video 64 | ----- 65 | To run the video recording program manually, you can type 66 | 67 | sudo python picamcorder2.py 68 | 69 | Add a 0 (zero) if you want to disable the front LED 70 | (assuming you have added the necessary tweak to your config file) 71 | 72 | sudo python picamcorder2.py 0 73 | 74 | Stills 75 | ------ 76 | To run the stills program manually, you can type 77 | 78 | sudo python picamstills-db.py 79 | or 80 | sudo python picamstills-db.py 0 (if you want to disable the front LED) 81 | 82 | Video Streaming 83 | --------------- 84 | This uses two scripts to separate the GPIO and non-GPIO parts since 85 | VLC can't run as root, but RPi.GPIO has to run as root. 86 | 87 | To start the video streaming program (it works just as the recording program 88 | except it streams to port 8090 rather than recording) just type... 89 | 90 | python picamstreamer.py 91 | or 92 | python picamstreamer.py 0 (if you want to disable the front LED) 93 | 94 | This program handles the streaming part, but the GPIO part is handled by 95 | picamstream-sudo.py (which is called by picamstreamer.py). 96 | 97 | Then, on your receiving device, you need to have VLC running and looking at 98 | a network stream from... 99 | 100 | http://ip_address_of_your_pi:8090 101 | 102 | Further instructions about VLC streaming here 103 | http://raspi.tv/?p=3099 104 | 105 | I haven't yet managed to get streaming working automatically at boot 106 | because VLC won't run as root. I'm sure there's a way though. 107 | 108 | 109 | Setting up your Pi 110 | ================== 111 | 112 | Setting up for auto start on boot 113 | --------------------------------- 114 | Add this line to your /etc/rc.local 115 | 116 | /home/pi/picamcorder.sh 117 | 118 | Which runs a simple bash script on boot, allowing us a 10s time delay. 119 | 120 | picamcorder.sh will have to be executable for this to work 121 | 122 | chmod +x picamcorder.sh 123 | 124 | 125 | The bash script picamcorder.sh just contains this... 126 | sleep 10 127 | sudo python /home/pi/picamcorder2.py & 128 | 129 | ...which slows things down at startup, just enough to make it work and puts 130 | the process in the background. 131 | 132 | If you prefer to auto-start-up the stills or streaming programs instead of 133 | video, just edit picamcorder.sh to call the program you want to run. 134 | 135 | 136 | Setting up for small screen use 137 | ------------------------------- 138 | 139 | sudo dpkg-reconfigure console-setup 140 | 141 | lets you increase console font size for small screens 142 | 143 | 144 | Setting Up Dropbox Upload for Stills mode 145 | ----------------------------------------- 146 | Blog article here http://raspi.tv/?p=3572 shows full instructions on how to 147 | set up DropBox Uploader on your Pi and basic usage. 148 | 149 | Full documentation at the author's GitHub 150 | https://github.com/andreafabrizi/Dropbox-Uploader 151 | 152 | To set up as a user, should only take an hour or so. A lot less if you already 153 | have a DropBox account. 154 | 155 | 156 | Hardware Component list 157 | ======================= 158 | 1 model A Raspberry Pi 159 | 1 Raspberry Pi camera board 160 | 1 switching regulator board ~$3 ebay LM2596 DC-DC Step-down Adjustable 161 | 1 Bluetooth serial adaptor $8 dx.com SKU: 104299 162 | battery & connectors 163 | female .1" pin headers 164 | wire 165 | 0605 LED 166 | 150R 1206 for led 167 | Cyntech case 168 | White tack 169 | hot glue gun 170 | buttons 171 | bit of stripboard 172 | 4x2 angled header 173 | 174 | 175 | Possible Future Development 176 | =========================== 177 | 178 | LED on the back to show recording --> DONE 179 | camera LED toggle to disable front LED, maybe with an argv argument? --> DONE 180 | leds flashing on program exit and shutdown --> DONE 181 | indication of how much recording time/disk space left --> DONE 182 | micro USB adaptor so Pi can be stood up at SD card end --> DONE 183 | 52mm thread adaptor for adding lenses --> DONE 184 | 185 | Stills button or button combo 186 | need a mount for it 187 | possibly pan and tilt 188 | possibly a rotating base for all-round work - either stepper or highly geared 189 | 190 | it would be nice to have a third button for stills too, but getting errors 191 | after adding port 25 for stills, so all parts referring to GPIO25 are 192 | commented out for now. 193 | 194 | It seems that raspivid and raspistill don't play nicely together in the 195 | same script - (I got MMAL errors which only cleared on reboot), 196 | so had to remove the stills option from the script and implement it separately. 197 | -------------------------------------------------------------------------------- /picamcorder.sh: -------------------------------------------------------------------------------- 1 | sleep 10 2 | sudo python /home/pi/picamcorder2.py & 3 | -------------------------------------------------------------------------------- /picamcorder2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2.7 2 | # script by Alex Eames http://RasPi.tv 3 | # needs RPi.GPIO 0.5.2 or later 4 | # No guarantees. No responsibility accepted. It works for me. 5 | # If you need help with it, sorry I haven't got time. I'll try and add more 6 | # documentation as time goes by. But no promises. 7 | 8 | import RPi.GPIO as GPIO 9 | from subprocess import call 10 | import subprocess 11 | from time import sleep 12 | import time 13 | import sys 14 | import os 15 | 16 | front_led_status = sys.argv[-1] 17 | if front_led_status == "0": 18 | print "front LED off" 19 | front_led_status = 0 20 | 21 | GPIO.setmode(GPIO.BCM) 22 | 23 | # GPIO 23 & 25 set up as input, pulled up to avoid false detection. 24 | # Both ports are wired to connect to GND on button press. 25 | # So we'll be setting up falling edge detection for both 26 | GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP) 27 | #GPIO.setup(25, GPIO.IN, pull_up_down=GPIO.PUD_UP) 28 | 29 | # GPIO 24 set up as an input, pulled down, connected to 3V3 on button press 30 | GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) 31 | 32 | # Set up GPIO 5 for camera LED control and rear LED control 33 | GPIO.setup(5, GPIO.OUT) 34 | GPIO.setup(22, GPIO.OUT) 35 | 36 | recording = 0 37 | vid_rec_num = "vid_rec_num.txt" 38 | vid_rec_num_fp ="/home/pi/vid_rec_num.txt" # need full path if run from rc.local 39 | base_vidfile = "raspivid -t 3600000 -o /home/pi/video" 40 | time_off = time.time() 41 | 42 | def write_rec_num(): 43 | vrnw = open(vid_rec_num_fp, 'w') 44 | vrnw.write(str(rec_num)) 45 | vrnw.close() 46 | 47 | def start_recording(rec_num): 48 | global recording 49 | if recording == 0: 50 | vidfile = base_vidfile + str(rec_num).zfill(5) 51 | vidfile += ".h264 -fps 25 -b 15000000 -vs" #-w 1280 -h 720 -awb tungsten 52 | print "starting recording\n%s" % vidfile 53 | time_now = time.time() 54 | if (time_now - time_off) >= 0.3: 55 | if front_led_status != 0: 56 | GPIO.output(5, 1) 57 | GPIO.output(22, 1) 58 | recording = 1 59 | call ([vidfile], shell=True) 60 | recording = 0 # only kicks in if the video runs the full period 61 | 62 | #### Quality VS length ### 63 | # on long clips at max quality you may get dropouts 64 | # -w 1280 -h 720 -fps 25 -b 3000000 65 | # seems to be low enough to avoid this 66 | 67 | def stop_recording(): 68 | global recording 69 | global time_off 70 | time_off = time.time() 71 | print "stopping recording" 72 | GPIO.output(5, 0) 73 | GPIO.output(22, 0) 74 | call (["pkill raspivid"], shell=True) 75 | recording = 0 76 | space_used() # display space left on recording drive 77 | 78 | def space_used(): # function to display space left on recording device 79 | output_df = subprocess.Popen(["df", "-Ph", "/dev/root"], stdout=subprocess.PIPE).communicate()[0] 80 | it_num = 0 81 | for line in output_df.split("\n"): 82 | line_list = line.split() 83 | if it_num == 1: 84 | storage = line_list 85 | it_num += 1 86 | print "Card size: %s, Used: %s, Available: %s, Percent used: %s" % (storage[1], storage[2], storage[3], storage[4]) 87 | percent_used = int(storage[4][0:-1]) 88 | if percent_used > 95: 89 | print "Watch out, you've got less than 5% space left on your SD card!" 90 | 91 | # threaded callback function runs in another thread when event is detected 92 | # this increments variable rec_num for filename and starts recording 93 | def my_callback2(channel): 94 | global rec_num 95 | time_now = time.time() 96 | if (time_now - time_off) >= 0.3: 97 | print "record button pressed" 98 | rec_num += 1 99 | if recording == 0: 100 | write_rec_num() 101 | start_recording(rec_num) 102 | 103 | def flash(interval,reps): 104 | for i in range(reps): 105 | GPIO.output(5, 1) 106 | GPIO.output(22, 1) 107 | sleep(interval) 108 | GPIO.output(5, 0) 109 | GPIO.output(22, 0) 110 | sleep(interval) 111 | 112 | def shutdown(): 113 | print "shutting down now" 114 | stop_recording() 115 | flash(0.05,50) 116 | GPIO.cleanup() 117 | os.system("sudo halt") 118 | sys.exit() 119 | 120 | print "Make sure you have a button connected so that when pressed" 121 | print "it will connect GPIO port 23 (pin 16) to GND (pin 6)\n" 122 | print "You will also need a second button connected so that when pressed" 123 | print "it will connect GPIO port 24 (pin 18) to 3V3 (pin 1)\n" 124 | #print "You will also need a third button connected so that when pressed" 125 | #print "it will connect GPIO port 25 (pin 22) to GND\n" 126 | 127 | # optional for when you're at the terminal 128 | #raw_input("Press Enter when ready\n>") 129 | 130 | # when a falling edge is detected on port 23 my_callback2() will be run 131 | GPIO.add_event_detect(23, GPIO.FALLING, callback=my_callback2) 132 | 133 | # when a falling edge is detected on port 25, my_callback() will be run 134 | #GPIO.add_event_detect(25, GPIO.FALLING, callback=my_callback, bouncetime=500) 135 | 136 | # check rec_num from file 137 | try: 138 | directory_data = os.listdir("/home/pi") 139 | if vid_rec_num in directory_data: 140 | 141 | # read file vid_rec_num, make into int() set rec_num equal to it 142 | vrn = open(vid_rec_num_fp, 'r') 143 | rec_num = int(vrn.readline()) 144 | print "rec_num is %d" % rec_num 145 | vrn.close() 146 | 147 | # if file doesn't exist, create it to avoid issues later 148 | else: 149 | rec_num = 0 150 | write_rec_num() 151 | 152 | except: 153 | print("Problem listing /home/pi") 154 | flash(0.1,10) 155 | GPIO.cleanup() 156 | sys.exit() 157 | 158 | try: 159 | while True: 160 | # this will run until button attached to 24 is pressed, then 161 | # if pressed long, shut program, if pressed very long shutdown Pi 162 | # stop recording and shutdown gracefully 163 | print "Waiting for button press" # rising edge on port 24" 164 | GPIO.wait_for_edge(24, GPIO.RISING) 165 | print "Stop button pressed" 166 | stop_recording() 167 | 168 | # poll GPIO 24 button at 20 Hz continuously for 3 seconds 169 | # if at the end of that time button is still pressed, shut down 170 | # if it's released at all, break 171 | for i in range(60): 172 | if not GPIO.input(24): 173 | break 174 | sleep(0.05) 175 | 176 | if 25 <= i < 58: # if released between 1.25 & 3s close prog 177 | print "Closing program" 178 | flash(0.02,50) # interval,reps 179 | GPIO.cleanup() 180 | sys.exit() 181 | 182 | if GPIO.input(24): 183 | if i >= 59: 184 | shutdown() 185 | 186 | except KeyboardInterrupt: 187 | stop_recording() 188 | GPIO.cleanup() # clean up GPIO on CTRL+C exit 189 | 190 | -------------------------------------------------------------------------------- /picamstills-db.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2.7 2 | # script by Alex Eames http://RasPi.tv 3 | # RasPiCamcorder stills camera mode with dropbox upload 4 | 5 | # http://raspi.tv/?p=3424 and 6 | 7 | # http://youtu.be/dSgj4bUFBCQ 8 | 9 | import RPi.GPIO as GPIO 10 | from subprocess import call 11 | import subprocess 12 | from time import sleep 13 | import time 14 | import sys 15 | import os 16 | import urllib2 17 | import thread 18 | 19 | front_led_status = sys.argv[-1] 20 | if front_led_status == "0": 21 | print "front LED off" 22 | front_led_status = 0 23 | 24 | GPIO.setmode(GPIO.BCM) 25 | 26 | # GPIO 23 set up as input, pulled up to avoid false detection. 27 | # wired to connect to GND on button press. 28 | # So we'll be setting up falling edge detection 29 | GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP) 30 | 31 | # GPIO 24 set up as an input, pulled down, connected to 3V3 on button press 32 | GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) 33 | 34 | # Set up GPIO 5 for camera LED control and 22 for rear LED control 35 | GPIO.setup(5, GPIO.OUT) 36 | GPIO.setup(22, GPIO.OUT) 37 | 38 | # set initial variables 39 | photo_rec_num = "photo_rec_num.txt" 40 | photo_rec_num_fp ="/home/pi/photo_rec_num.txt" # need full path if run from rc.local 41 | base_vidfile = "raspistill -t 500 -o /home/pi/photo" 42 | time_off = time.time() 43 | 44 | def write_rec_num(): 45 | vrnw = open(photo_rec_num_fp, 'w') 46 | vrnw.write(str(rec_num)) 47 | vrnw.close() 48 | 49 | def take_photo(rec_num): 50 | global time_off 51 | vidfile = base_vidfile + str(rec_num).zfill(5) + ".jpg" 52 | filename = "/home/pi/photo" + str(rec_num).zfill(5) + ".jpg" 53 | print "taking photo\n%s" % vidfile 54 | time_now = time.time() 55 | if (time_now - time_off) >= 0.3: # debounce 56 | time_off = time.time() 57 | if front_led_status != 0: 58 | GPIO.output(5, 1) 59 | GPIO.output(22, 1) 60 | call ([vidfile], shell=True) 61 | sleep(1) 62 | GPIO.output(5, 0) 63 | GPIO.output(22, 0) 64 | space_used() 65 | flash(0.1,3) 66 | 67 | enable_dropbox = internet() 68 | if enable_dropbox: 69 | print "\nsending %s to dropbox" % filename 70 | photofile = "/home/pi/Dropbox-Uploader/dropbox_uploader.sh upload " + filename 71 | 72 | # put the dropbox upload into another thread 73 | # so we can take more pictures without waiting for it 74 | 75 | threadname = "DB-Upload" + str(rec_num).zfill(5) 76 | try: 77 | thread.start_new_thread(db_thread, (threadname, photofile, )) 78 | except: 79 | print "Error: unable to start thread" 80 | flash(0.05,6) 81 | else: 82 | print "Unable to connect to dropbox. No internet?" 83 | flash(0.2,2) 84 | time_off = time.time() # for debounce 85 | 86 | def db_thread(threadName, photofile): 87 | print "%s: %s" % (threadName, photofile) 88 | call ([photofile], shell=True) 89 | 90 | 91 | def stop_recording(): # this may not be needed for stills 92 | global time_off 93 | time_off = time.time() 94 | print "stopping recording" 95 | GPIO.output(5, 0) 96 | GPIO.output(22, 0) 97 | call (["pkill raspistill"], shell=True) 98 | time_off = time.time() # repeat seems to help prevent false double records 99 | space_used() # display space left on recording drive 100 | 101 | def space_used(): # function to display space left on recording device 102 | output_df = subprocess.Popen(["df", "-Ph", "/dev/root"], stdout=subprocess.PIPE).communicate()[0] 103 | it_num = 0 104 | for line in output_df.split("\n"): 105 | line_list = line.split() 106 | if it_num == 1: 107 | storage = line_list 108 | it_num += 1 109 | print "\nCard size: %s, Used: %s, Available: %s, Percent used: %s" % (storage[1], storage[2], storage[3], storage[4]) 110 | percent_used = int(storage[4][0:-1]) 111 | if percent_used > 95: 112 | print "Watch out, you've got less than 5% space left on your SD card!" 113 | 114 | # threaded callback function runs in another thread when event is detected 115 | # this increments variable rec_num for filename and takes a photo 116 | def blue_button(channel): 117 | global rec_num 118 | time_now = time.time() 119 | if (time_now - time_off) >= 0.3: 120 | print "\nphoto button pressed" 121 | rec_num += 1 122 | write_rec_num() 123 | take_photo(rec_num) 124 | 125 | def flash(interval,reps): 126 | for i in range(reps): 127 | GPIO.output(5, 1) 128 | GPIO.output(22, 1) 129 | sleep(interval) 130 | GPIO.output(5, 0) 131 | GPIO.output(22, 0) 132 | sleep(interval) 133 | 134 | def shutdown(): 135 | print "shutting down now" 136 | stop_recording() 137 | flash(0.05,50) 138 | GPIO.cleanup() 139 | os.system("sudo halt") 140 | sys.exit() 141 | 142 | def internet(): 143 | try: 144 | urllib2.urlopen("http://www.dropbox.com") 145 | enable_dropbox = 1 146 | except urllib2.URLError: 147 | enable_dropbox = 0 148 | return enable_dropbox 149 | 150 | print "Make sure you have a button connected so that when pressed" 151 | print "it will connect GPIO port 23 (pin 16) to GND (pin 6)\n" 152 | print "You will also need a second button connected so that when pressed" 153 | print "it will connect GPIO port 24 (pin 18) to 3V3 (pin 1)\n" 154 | 155 | # when a falling edge is detected on port 23 blue_button() will be run 156 | GPIO.add_event_detect(23, GPIO.FALLING, callback=blue_button) 157 | 158 | # check rec_num from file 159 | try: 160 | directory_data = os.listdir("/home/pi") 161 | if photo_rec_num in directory_data: 162 | 163 | # read file photo_rec_num, make into int() set rec_num equal to it 164 | vrn = open(photo_rec_num_fp, 'r') 165 | rec_num = int(vrn.readline()) 166 | print "rec_num is %d" % rec_num 167 | vrn.close() 168 | 169 | # if file doesn't exist, create it to avoid issues later 170 | else: 171 | rec_num = 0 172 | write_rec_num() 173 | 174 | except: 175 | print("Problem listing /home/pi") 176 | flash(0.1,10) 177 | GPIO.cleanup() 178 | sys.exit() 179 | 180 | try: 181 | while True: 182 | # this will run until button attached to 24 is pressed, then 183 | # if pressed long, shut program, if pressed very long shutdown Pi 184 | # stop recording and shutdown gracefully 185 | print "Waiting for button press" # rising edge on port 24" 186 | GPIO.wait_for_edge(24, GPIO.RISING) 187 | print "Stop button pressed" 188 | 189 | # poll GPIO 24 button at 20 Hz continuously for 2 seconds 190 | # if at the end of that time button is still pressed, shut down 191 | # if it's released at all, break 192 | for i in range(60): 193 | if not GPIO.input(24): 194 | break 195 | sleep(0.05) 196 | 197 | if 25 <= i < 58: 198 | print "Closing program" 199 | flash(0.02,50) # interval,reps 200 | GPIO.cleanup() 201 | sys.exit() 202 | 203 | if GPIO.input(24): 204 | if i >= 59: 205 | shutdown() 206 | 207 | except KeyboardInterrupt: 208 | # stop_recording() 209 | GPIO.cleanup() 210 | sys.exit() 211 | 212 | # it would be really nice for headless use if we could have another led 213 | # for upload flash it in another thread while uploading to dropbox 214 | # 215 | # have a demo mode which runs at lower res off mobile hotspot wifi 216 | -------------------------------------------------------------------------------- /picamstream-sudo.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2.7 2 | # script by Alex Eames http://RasPi.tv 3 | import RPi.GPIO as GPIO 4 | import sys 5 | import os 6 | import time 7 | from time import sleep 8 | 9 | front_led_status = sys.argv[-1] 10 | if front_led_status == "0": 11 | print "front LED off" 12 | front_led_status = 0 13 | 14 | streaming_on = 0 15 | streaming_file = "/home/pi/streaming.txt" 16 | time_off = 0 17 | 18 | GPIO.setmode(GPIO.BCM) 19 | 20 | # GPIO 23 set up as input, pulled up to avoid false detection. 21 | # wired to connect to GND on button press. 22 | # So we'll be setting up falling edge detection 23 | GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP) 24 | 25 | # GPIO 24 set up as an input, pulled down, connected to 3V3 on button press 26 | GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) 27 | 28 | # Set up GPIO 5 for camera LED control and rear LED control 29 | GPIO.setup(5, GPIO.OUT) 30 | GPIO.setup(22, GPIO.OUT) 31 | 32 | def write_streaming_status(streaming_on): 33 | vrnw = open(streaming_file, 'w') 34 | vrnw.write(str(streaming_on)) 35 | vrnw.close() 36 | 37 | def check_streaming_status(): 38 | # read file streaming_file, make into int() set streaming_on equal to it 39 | vrn = open(streaming_file, 'r') 40 | streaming_on = int(vrn.readline()) 41 | #print "streaming_on is %d" % streaming_on 42 | vrn.close() 43 | return streaming_on 44 | 45 | # threaded callback function runs in another thread when event is detected 46 | # this increments variable rec_num for filename and starts recording 47 | def stream_button(channel): 48 | global time_off 49 | time_now = time.time() 50 | if (time_now - time_off) >= 0.3: 51 | streaming_status = check_streaming_status() 52 | if streaming_status == 0: 53 | write_streaming_status(1) 54 | print "stream button pressed" 55 | if front_led_status != 0: 56 | GPIO.output(5, 1) 57 | GPIO.output(22, 1) 58 | time_off = time.time() 59 | 60 | def flash(interval,reps): 61 | for i in range(reps): 62 | GPIO.output(5, 1) 63 | GPIO.output(22, 1) 64 | sleep(interval) 65 | GPIO.output(5, 0) 66 | GPIO.output(22, 0) 67 | sleep(interval) 68 | 69 | def shutdown(): 70 | print "shutting down now" 71 | flash(0.05,50) 72 | GPIO.cleanup() 73 | os.system("sudo halt") 74 | sys.exit() 75 | 76 | try: 77 | write_streaming_status(0) 78 | except: 79 | print "couldn't write streaming status" 80 | sys.exit() 81 | 82 | # when a falling edge is detected on blue stream button port 23 stream_button() will be run 83 | GPIO.add_event_detect(23, GPIO.FALLING, callback=stream_button) 84 | 85 | try: 86 | while True: 87 | # this will run until black button attached to 24 is pressed, then 88 | # if pressed long, shut program, if pressed very long shutdown Pi 89 | # stop recording and shutdown gracefully 90 | print "Waiting for button press" # rising edge on port 24" 91 | GPIO.wait_for_edge(24, GPIO.RISING) 92 | #print "Stop button pressed" 93 | 94 | time_now = time.time() 95 | if (time_now - time_off) >= 0.3: 96 | streaming_status = check_streaming_status() 97 | if streaming_status == 1: 98 | write_streaming_status(0) 99 | print "Stop button pressed" 100 | GPIO.output(5, 0) 101 | GPIO.output(22, 0) 102 | time_off = time.time() 103 | 104 | # poll GPIO 24 button at 20 Hz continuously for 2 seconds 105 | # if at the end of that time button is still pressed, shut down 106 | # if it's released at all, break 107 | for i in range(60): 108 | if not GPIO.input(24): 109 | break 110 | sleep(0.05) 111 | 112 | if 25 <= i < 58: 113 | print "Closing program" 114 | flash(0.02,50) # interval,reps 115 | write_streaming_status(2) # 2 will close the host program 116 | GPIO.cleanup() 117 | sys.exit() 118 | 119 | if GPIO.input(24): 120 | if i >= 59: 121 | shutdown() 122 | 123 | finally: 124 | write_streaming_status(2) 125 | GPIO.cleanup() # clean up GPIO on exit 126 | -------------------------------------------------------------------------------- /picamstreamer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2.7 2 | # script by Alex Eames http://RasPi.tv 3 | 4 | from subprocess import call 5 | import sys 6 | import time 7 | 8 | front_led_status = sys.argv[-1] 9 | if front_led_status == "0": 10 | print "front LED off" 11 | front_led_status = 0 12 | 13 | streaming_on = 0 14 | streaming_file = "/home/pi/streaming.txt" 15 | if front_led_status == 0: 16 | sudo_file = "sudo python /home/pi/picamstream-sudo.py 0 &" 17 | else: 18 | sudo_file = "sudo python /home/pi/picamstream-sudo.py &" 19 | 20 | stream = "raspivid -o - -t 9999999 -w 640 -h 360 -fps 25|cvlc stream:///dev/stdin --sout '#standard{access=http,mux=ts,dst=:8090}' :demux=h264 &" 21 | 22 | # you can change -w and -h numbers for whatever suits your network. 23 | # Depending on what I'm streaming to, mine can cope with 720p, 24 | # which is -w 1280 -h 720 25 | 26 | def stream_video(): 27 | print "starting streaming\n%s" % stream 28 | call ([stream], shell=True) 29 | 30 | def stop_stream(): 31 | print "stopping streaming" 32 | call (["pkill raspivid"], shell=True) 33 | call (["pkill vlc"], shell=True) 34 | 35 | def check_streaming_status(): 36 | # read file streaming_file, make into int() set streaming_on equal to it 37 | vrn = open(streaming_file, 'r') 38 | streaming_on = int(vrn.readline()) 39 | #print "streaming_on is %d" % streaming_on 40 | vrn.close() 41 | return streaming_on 42 | 43 | def write_streaming_status(streaming_on): 44 | vrnw = open(streaming_file, 'w') 45 | vrnw.write(str(streaming_on)) 46 | vrnw.close() 47 | 48 | try: 49 | write_streaming_status(0) 50 | except: 51 | print "couldn't write streaming status" 52 | sys.exit() 53 | 54 | call ([sudo_file], shell=True) 55 | 56 | previous_streaming_on = 0 57 | counter = 0 58 | 59 | #have a file containing the streaming_on variable value 60 | while True: 61 | streaming_on = check_streaming_status() 62 | #print "streaming status = %d" % streaming_on 63 | 64 | if streaming_on != previous_streaming_on: 65 | if streaming_on == 1: 66 | stream_video() 67 | elif streaming_on == 0: 68 | stop_stream() 69 | else: 70 | stop_stream() 71 | print "Closing picamstreamer.py" 72 | sys.exit() 73 | if counter % 50 == 0: 74 | print "streaming status = %d" % streaming_on 75 | previous_streaming_on = streaming_on 76 | counter += 1 77 | time.sleep(0.1) 78 | --------------------------------------------------------------------------------