While at the Milwaukee Makerspace for my weekly Maker-time, I continued working on my idea to use a Raspberry Pi 2 Model B to make a device that will take pictures by controlling an SLR camera. This time, I found some software to display an image, made a prototype with hardware, and wrote most of the python code.
Installed Avahi on the pi so I can connect to the Pi over a network. This allows me to do coding on my Linux laptop and FTP the files to the Pi. If something happens to the Pi, I won't lose the code. The instructions to install Avahi are here. Changed the name of the device to photoinator in both the /etc/hostname and /etc/hosts files.
Also, I would like to display a preview of the picture and let the user decide if it is good enough to keep or not. How do I get the Pi to display a jpg file without using xwindows?
First, I tried an application called feh to display images. This web page has the instructions for installing feh: http://feh.finalrewind.org/
After messing around with feh, I realized that it only works from within xwindows. That does not help -- especially since gphoto2 only runs from the command line and will not work in a terminal session running in xwindows.
The application that I needed is called fbi. I installed the app using sudo apt-get install fbi. After that, it just worked. I ran the program in the directory that has the photos in it. The way to run fbi is fbi image.jpg -a -t 10 -1. The -a will auto re-size the image to fit the screen. -t 10 tells fbi to display the image for 10 seconds. -1 means that fbi should exit after the timeout.
Next, I wrote a quick shell program to take a picture with gphoto2 then display it with fbi. I pass the filename to save the picture to as a parameter. The shell file looks like this:
gphoto2 --capture-image-and-download --filename=$1.jpgfbi $1.jpg -a -t 10 -1
The $1 lets me pass in a file name on the command line.
Next, I used a python program that I found on this Instructable and modified it a bit to control a button and an LED on the Adafruit T-cobbler Plus proto board. It worked. I was able to press a button to start the process. The program flashed an LED, took a picture, and displayed it on the screen for 10 seconds. Nice.
I spent a good part of the day on Sunday (after church of course) writing a much more robust Python program with subroutines and global variables and all of that nerdy goodness.
Finally, I spent Memorial Day back at the Makerspace to build the prototype and debug the code. The prototype has three buttons and four LEDs. One button is to start the picture-taking process. Another will let the human choose to Keep the picture they just saw. The third button will tell the Pi to reset everything and start over. One of the LEDs will light when the picture-inator is ready to take a picture. The second LED will blink increasingly fast to warn the user that the picture is about to be taken. The final two LEDs blink alternately next to the Keep and Reset buttons to encourate the human to push one. This all works fine. For the final version, I would like to use small light bulbs instead of LEDs to increase the brightness. I probably need a stronger power source than the PI to light them. I will also need a more complicated circuit that includes a transistor. I'll design and build that in the next session.
Another idea I had was to add a toggle switch to designate the mode that the picture-inator is in -- one shot or continuous. That should be pretty easy to do but I did not get to it this time.
One of the things I struggled with on the coding side was the GPIO.add_event_detect function. I originally wanted the program to call a subroutine when a button was pressed. However, I could not get that to work. The subroutine might get called the first time the button was pressed but not after that. Sometimes, pressing the button never did anything. I ended up punting and doing several things to make this work.
First, the main loop uses GPIO.event_detected to see if any of the buttons were pressed. Anytime a button is pressed or a state changes, the program turns off event detection for all buttons. Then, it does whatever the function is meant to do, and turns on even detection for any buttons that need to have it. Doing all of this should allow the program to always catch button presses and never have false-positives or multiple button presses.
One other problem is that I don't know how to interrupt the picture being displayed. So, if the person pushes the Keep button while the picture is being displayed, nothing will happen. I don't think I can fix that. I spent a lot of time researching a way to call an external program in a separate thread but I'm not sure it is possible.
The bug I am currently working on has to do with debug mode. When the program is running in debug mode everything works. However, when I run the program with debug mode turned off, it turns on the ready LED but will not do anything when any button is pressed. I have not been able to figure out why.
Another bug is if the camera is off, gphoto2 returns an error. The program cannot handle the error. Need to figure that out.
Here is a picture of the prototype at this point.