Introduction: Vintage Raspberry Pi Camera
Cameras have been around for centuries. But since the birth of digital, many of the old film cameras have just been tossed aside. Let’s give these amazing pieces of technology a second chance by upcycling an old film camera into a digital camera! We can do this using a small computer module called a Raspberry Pi Zero and it’s corresponding camera module. In part 1 of this 2 part series, we will assemble the hardware and retro-fit it all to fit inside the camera!
Don't wanna read? Watch the video instead!
Step 1: Finding a Vintage Digital Camera
The purpose of this project is to give new life to an old film camera by converting it to digital. So, obviously, to make this project, you’ll need to have a vintage camera to convert. Some of you may have one of these sitting around the house. Otherwise, you can find them at thrift stores or yard sales. However, if you’re like me and would prefer not to rip apart an old camera, you can purchase a cheap DIY camera kit. Basically, the goal is to keep the shell of the camera in tact, but clear out any of the internal components that won’t be needed. This includes, camera obscuras, mirrors, gears, springs, film rollers, etc. The only thing I kept was a switch to trigger the camera and the turn dials on the outside of my camera. The more room you have for our electronic components, the better.
Step 2: The Electronic Components
Now that we have a vintage camera shell, we need to figure out a way to make it digital. In theory, the basic components we’ll need are:
- A camera sensor that will capture images
- Something that can process and save those images
- A screen of some sort to view the images
- A physical button to trigger a photo
- A rechargeable battery to power it all.
You can interpret those components however you see fit, so feel free to work with whatever you have access to. The list of what I ended up using is below, but some of the parts can be substituted:
Step 3: Out With the Old, in With the New!
For you electronics buffs, this step should be fun! If you hate electronics, this step might be miserable! It’s actually not too bad. Basically we just need to figure out how to wire everything together. First, let’s figure out the LCD. The small Adafruit TFT LCD’s have similar pin-outs to the one below. It will need to be wired up to the GPIO pins on the Raspberry Pi. You can use the diagram below to see how to wire it all up.
We’re also going to need to connect the button we’re using to snap pictures to the GPIO pins. This will allow us to read the button state so that we can tell if it’s been pressed or not using Python., I used a simple momentary button with a 10k resistor. and connected it (along withe LCD) as laid out below.
The next thing we need to wire up is the power supply. Since we’re wanting this camera to be portable, it would be ideal to have a rechargeable power supply that can last for at least a few hours. Those emergency cell phone charges you can buy at the store fit the bill perfectly. The one I purchased was slightly larger than a AA battery, so it fit perfectly into the small size of the camera. So that we could turn it on and off easily, I wired the power through an on/off switch before running it to the Pi zero.
An unforeseen problem that I ran into was that the camera didn’t have enough space for plugging any cables into the Pi zero. It just wasn’t wide enough to support the cables. So I had to figure out another way to run power and USB capabilities (for the wifi dongle) to the Pi. One option would have been to run the power through the GPIO pins, but unfortunately our LCD screen and buttons are already occupying the necessary pins. So another method is to solder the power and USB wires to the reverse side of the corresponding ports on the Pi Zero. IMPORTANT: IF YOU POWER YOUR PI LIKE THIS, YOU CAN NO LONGER PLUG ANYTHING INTO THE POWER PORT ON THE PI AT THE SAME TIME. IT COULD OVERLOAD YOUR PI. You can see more details in the images below:
Now that everything is wired up, it’s only a matter of fitting it into the camera shell. I placed my camera sensor behind one of the existing lenses, and placed my momentary button underneath the existing camera switch lever (so that when the lever is pressed, it will take a picture. I fashioned the battery charger so that you can easily plug in a USB cable to charge it. As an added benefit, all of the Pi ports (HDMI, USB, SD Card) were still easily accessible when the camera case was open, so the Pi could still readily be used.
But at this point, our project is nothing more than a glorified Raspberry Pi case. In order to make it function like a camera, we need to start writing some code!
Step 4: Setting Up the Pi
With the hardware side of things done, let’s get started on the software side of things. The first thing we need to do is boot up the Pi. So you need to download the Raspbian OS, burn it to an SD card and put it into the SD card slot on your Pi Zero. Before you power it on, connect an HDMI monitor and a powered USB hub with a keyboard, mouse, and wifi connected. Now power it on and it should boot to the desktop.
The first thing we want to do is give the Pi static IP address on our network so that it will be the same IP address everytime the Pi boots up. To do this, right click on the wireless icon in the upper right and select “wireless configuration”. Then in the first field, type in a static IP address and then click OK. Next we need to click on the menu in the upper left and find the Raspberry Pi Configuration option. Once that window opens up, you want to click on the “interfaces” tab and make sure these items are enabled:
- Camera – to enable the use of our webcam
- SSH – so that we can remotely connect to our Pi
- SPI – to enable the use of our LCD screen.
With those things are enabled, you can reboot your Pi and unplug the HDMI calbe and the USB hub, making sure that the wifi dongle is now the only thing plugged into the Pi’s USB port.
Step 5: Setting Up Dropbox
For this project, I decided to use Dropbox to upload my photos for its easy to use API (Application Programming Interface). However, sites like Facebook, Twitter, Google + and Tumblr also have API’s that you can use for this project. To set up the Dropbox API, just follow these steps:
- Sign into the Dropbox Developer website with your Dropbox account
- Click “Create Your App”
- Select “Dropbox API” from Step 1
- Select “App Folder” from Step 2
- Give your app a unique name in Step 3 and then click “Create App”
- On the application page, click on “Generate Access Token”
- Copy down the token that it gives you.
We will be using this token in our code to connect to dropbox and upload the pictures.
Step 6: Setting Up the Software
With Dropbox setup, we can now start getting the Pi Zero ready for our software. With our Pi powered on (and with no monitor, mouse, or keyboard plugged into it), we need to remotely connect to it from a different computer. We can do this through SSH, and you can follow these steps for how to set that up on your computer. Once you have connected and logged in, the first thing we need to do is enable the camera and LCD modules by typing these commands:
sudo modprobe bcm2835-v4l2 sudo modprobe fbft_device name=adafruit18
Make sure to change the fbtft_device name to match the LCD you’re using. This will enable those modules for this session only. Once the Pi reboots, you’ll have to re-enable these modules each time. To avoid having to do this, we can add them to the module startup script by typing:
sudo nano /etc/modules
And then adding these modules to the bottom of the list:
spi-bcm2835 sudo modprobe bcm2835-v4l2 sudo modprobe fbtft_device
The modules document doesn’t allow us to specify which LCD screen we have, so we need to add that specification to a new document
sudo nano /etc/modprobe.d/fbtft.conf
and add this line (again, making sure the device name matches the LCD you’re using)
options fbtft_device name=adafruit18
Now, everytime you reboot your Pi, the camera and LCD modules should automatically launch. So now let’s turn our focus to software dependencies. Dependencies are programs we need to install that are required for our code to work properly. There are two that we need to install for our program: pygame and dropbox. So after updating our repositories, follow the steps below to install them:
sudo apt-get update<br> sudo apt-get install python-pygame pip install dropbox
That’s it! Now we can start coding!
Step 7: Writing a Dropbox Program
For our camera program, I actually decided to split it up into two programs. The first one is code that will upload our pictures to dropbox, and the second one is code that will actually take the pictures. Create a new file called “python_dropbox.py”. The dropbox program essentially creates a module (called dropbox uploader) that will be passed variables from our primary picture taking program. It then connects to dropbox using our token, then it checks to see if dropbox.com is available, i.e. if an internet connection is available. If not, it returns a false result, if so, it loops through our Picture folder looking for pictures, uploads them to dropbox, deletes the local pictures, and then returns a True result.
#!/usr/bin/python<br> #Import dependencies #Make sure the python libraries are installed (pip install dropbox) import os import sys import urllib2 from dropbox.client import DropboxClient
#Create a function called 'dropbox_upload' #Pass it the variables from our main program def dropbox_upload(access_token, local_directory, remote_directory): #Create a client variable client = DropboxClient(access_token) #See if Dropbox.com is available. #If so, continue. If not, return false. try: urllib2.urlopen("http://www.dropbox.com") except urllib2.URLError, e: return False else: #Create a directory loop that: #1. Loops through all the files in a directory #2. Grabs the file path for each existing file #3. Uploads it to Dropbox #4. Removes the file after it's been uploaded. for root, dirs, files in os.walk(local_directory): for filename in files: local_path = os.path.join(root, filename) relative_path = os.path.relpath(local_path, local_directory) dropbox_path = os.path.join(remote_directory, relative_path) with open(local_path, 'rb') as f: client.put_file(dropbox_path, f) #Remove this code if you don't #want your image deleted after upload os.remove(local_path) return True
Step 8: Writing the Camera Program
No onto our primary camera program. I simply called it “python_camera.py”. This program does several things. First it initializes the GPIO pins to monitor whenever the button is pressed. Then it initializes the LCD interface as well as the camera. It has a function that snaps a picture and calls our Dropbox upload program. Then it cycles through checking for a button press and triggering events whenever the button is pressed.
#!/usr/bin/python<br> #Import dependencies from pygame, time, GPIO, sys and OS import sys, os, pygame import pygame.camera from time import sleep, strftime import RPi.GPIO as GPIO
#Import custom made 'python_dropbox' module import python_dropbox
#Set GPIO pins for camera button GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) GPIO.setup(2, GPIO.IN)
#Change display to tft screen os.environ["SDL_FBDEV"] = "/dev/fb1"
#Initialize pygame pygame.init()
#Initialize camera pygame.camera.init()
#Disable mouse pointer pygame.mouse.set_visible(False)
#Set screen size size = width, height = 128,160 screen = pygame.display.set_mode(size)
#Set the camera to use, the resolution, and start it cam_list = pygame.camera.list_cameras() cam = pygame.camera.Camera(cam_list, (1080, 720)) cam.start()
#Declare variables that will be used in the code dropbox_token = '[place your token here]' local_dst = '/home/pi/Pictures' dropbox_dst = '/' upload_trigger = 0
#Define the 'takePicture' function that will: #1. Capture the image from the camera #2. Create a date variable and save picture using the date #3. Set the screen to black #4. Render text saying 'Picture Captured' #5. Rotate the text to match the screen orientation #6. Put contents on the screen (with screen.blit) #7. Refresh the screen using 'screen.flip' #8. Pause for 2 secs, and then load the saved picture #9. Adjust the size and orientation and display it to the screen using screen.blit def takePicture(): snapshot = cam.get_image() curr_time = strftime("%Y%m%d-%H%M%S") pygame.image.save(snapshot, "/home/pi/Pictures/retrocam%s.jpg" % (curr_time)) screen.fill((0,0,0,0)) font = pygame.font.Font(None, 25) text = font.render("Picture Captured", 0, (0,250,250)) Surf = pygame.transform.rotate(text, -270) screen.blit(Surf,(50,10)) pygame.display.flip() sleep(2) preview = pygame.image.load("/home/pi/Pictures/retrocam%s.jpg" % (curr_time)) preview = pygame.transform.scale(preview,(160, 128)) preview2 = pygame.transform.rotate(preview,90) screen.blit(preview2,(0,0)) pygame.display.flip()
#Start the main loop while True: #Continuously capture images from the camera, #adjust them, and display them image1 = cam.get_image() image1 = pygame.transform.scale(image1,(160, 128)) image2 = pygame.transform.rotate(image1,90) screen.blit(image2,(0,0)) pygame.display.update() #Check to see if the upload variable is 1. #If so, run the upload script and set the variable back to 0. if (upload_trigger == 1): if python_dropbox.dropbox_upload(dropbox_token, local_dst, dropbox_dst): font = pygame.font.Font(None, 20) text = font.render("Uploading...", 0, (0,250,250)) Surf = pygame.transform.rotate(text, -270) screen.blit(Surf,(0,10)) pygame.display.flip() upload_trigger = 0 else: upload_trigger = 1
#Check to see if the GPIO button is triggered. If so, then: #1. Run the 'take picture' function #2. Refresh the screen and set the upload variable to 1. if ( GPIO.input(2) == False): takePicture() upload_trigger = 1 sleep(1)
#For any error, stop the camera, quit pygame, and exit the program for event in pygame.event.get(): if event.type == pygame.QUIT: cam.stop() pygame.quit() sys.exit()
Step 9: Using the Camera
With all of our scripts saved to the home folder, you can run the camera program by typing:
sudo python python_camera.py
This will run the program, and you should see a preview of the camera on the LCD screen. Whenever the picture lever is pressed, it’ll trigger a picture to be taken, and if there is a wi-fi connection, it’ll upload it to dropbox. If there is no wi-fi connection, it’ll keep the photos in the picture folder. Then whenever there is a wifi connection, you can take another picture and it will trigger all of the photos to be uploaded. In order to get this python script to run automatically every time the Pi boots up, you need to edit the profiles file:
sudo nano /etc/profile
And add this line to the bottom of it:
sudo python python_camera.py &
Don’t forget the “&’ symbol at the end. Now whenever you restart your Pi, it should boot up and act as a fully functioning camera!
So a normal use case would be that you charge up the battery, close up the camera and then push the on/off button to turn on the pi. After a minute or so, you should see the camera preview on the LCD screen. To take a picture, just push down the front lever. It should say "Picture Captured" on the LCD screen followed by a 5 second preview of the picture you just took. If the Pi is connected to wi-fi, the pictures will upload to your Dropbox account to the App folder you created. If it's not connected to wi-fi, the pictures will stay on the camera until it is connected to wi-fi, at which point you will need to take another picture to trigger the upload script and it will upload all the photos (just a limitation of the code. feel free to fix it for me).