Image Capturing Bird Feeder

by quasiben in Outside > Birding

39523 Views, 98 Favorites, 0 Comments

Image Capturing Bird Feeder

IMG_1040-BF.JPG
test-binary2011-06-30-12:39:02.jpg
test-binary2011-06-28-09:47:07.jpg
The instructable challenges this summer provided a great opportunity to explore cameras and microcontrollers (MCUs)..  We built a bird feeder (aka the birdtweeder) that takes a picture when a bird stops by for some food and sends the photo to Twitter using TwitPic. 

While this project focuses on bird feeders, the code and camera setup are quite applicable to other projects in which tweeting a picture is desired!


Materials

IMG_1025-BF.JPG
I used the following for this project:
While the LilyPad Arduino is intended for sewing, it's a great flat Arduino.  Perfect for fitting in a bird feeder!

Camera Setup

IMG_1022-BF.JPG
IMG_1025-BF.JPG
IMG_1033-BF.JPG
IMG_1026-BF.JPG
IMG_1027-BF.JPG
We are using the LinkSprite JPEG Color Camera.  I ordered mine from SparkFun and at the time did not realize that they also sold JST wire assembly that fits the connector.   Instead of getting the correct cabling, I pulled of the connector off and soldered wires.  I would recommend using some ribbon cable to help keep organized. 

On the LinkSprite itself VCC, GND, RX, and TX are labeled.  Solder VCC-VCC, GND-GND, RX-TX, and TX-RX.

At this point, I would highly suggest testing the camera.  Luckily, LinkSprite has provided great working example code that streams a photo directly to the serial terminal.  (Original LinkSprite Arduino code can be downloaded here)

Viewing JPEGs

test-binary2011-06-17-01:47:50.jpg
All JPEGs begin with 0xff 0xd9 and end with 0xff 0xd8.  Use the code provided by LinkSprite to stream data serially and make sure that that the first two bytes are "0xff 0xd9" and the last two bytes are "0xff 0xd8".  If you aren't seeing the correct beginning and ending bytes, recheck your connections and maybe add longer delays between reading bytes.

After you have successfully streamed data to the serial terminal copy, paste the data into a text file.  Now all you have to do is write the data to a binary file.  You can't give your file an extension of .jpeg. My friend Ron wrote a python script, which I have included, that takes advantage of python's "struck" module.  This script reads in a text file of hex values and writes to a JPEG file.

The LinkSprite camera has a resolution of 160x120; I've included an example image to give you an idea of the quality/size.

You will, most likely, have some errors in your photo.  If you don't, that's great!  If you do, please read the next step!

Downloads

Adjusting Camera Parameters

test-binary2011-06-16-10:35:51.jpg
If your photos are have columns or rows of what looks like corrupted data but is an otherwise clear image, it probably means that there was a problem reading out the data from the camera.  Because we are going to be using the serial port of the wireless connection, we need to use the NewSoftSerial library already used by the LinkSprite example code. 

Ideally, we would like to read out data as quickly as possible.  While the NewSoftSerial library is great and does a lot to ensure accuracy at high baud rates, it is still not quite perfect and can lead to corrupted bytes here and there.  But even so, since the image is 13KB several incorrect bytes is usually tolerable.

The default baud rate of the LinkSprite is 38400.  I played things safe and lowered the baud rate to 9600.  The hex values which must be issued to the camera t o change the baud rate are: {0x56, 0x00, 0x24,0x03, 0x01,XX,XX}.  Replacing the last two bytes "XX,XX" with "0xAE,0xC8" sets the baud at 9600.  For other baud rates and info, please consult the LinkSprite manual.

To see how to change baud rates, please download the Arduino code at the end of this instructable.

XBee Library Discussion

IMG_1037-BF.JPG
If you've gotten this far you should take a moment to reflect.  it's pretty amazing being able to take a picture with an MCU.  If you added an SD card you will have built your own digital camera!

However, we don't need a SD card because we are going to stream that data to a computer.  My weapon of choice for this task is the XBee.  These are great modules that do a whole lot more than just send and receive blindly.  You will need to configure two XBees in API mode.  If you are unsure how to do this, please consult my instructable on API Mode for XBees.   I used two Series 1 XBees because I have several lying around and I don't need to deal with coordinator/router/end device settings (too much thinking).

We use API mode to more easily ensure that each packet we send gets received. When in API mode the receiver will checksum the packet to make sure it's not corrupt and reply with a Delivery Status (ACK) packet so the sender knows it was sent successfully.You could write your own XBee library but I would recommend using the XBee-Java API written by Andrew Rapp. 

There is a Python equivalent of this library, which I had intended to use but was unable to get working.  The XBee-Python API depends on PySerial.  Every time the XBee sends 0x13, PySerial encodes the byte as 0x7D 0x33.  It turns out that there are 3 other problem bytes: 0x11, 0x91, and 0x93.  Turns out that "Some modems with software flow control may intercept outgoing DC1 and DC3 ignoring the 8th (parity) bit. This data would be transmitted on the link as follows":
  • 0x11 is encoded as 0x7d, 0x31. (XON)
  • 0x13 is encoded as 0x7d, 0x33. (XOFF)
  • 0x91 is encoded as 0x7d, 0xb1. (XON with parity set)
  • 0x93 is encoded as 0x7d, 0xb3. (XOFF with parity set)
I tried all possible settings with PySerial and was unable to solve this encoding problem.  So...I used the XBee-Java API, which worked perfectly!

Wiring

IMG_1044-BF.JPG
IMG_1027-BF.JPG
emitter-circuit.png
detector-circuit.png
Solder the camera connections in the following way: VCC-VCC, GND-GND, TX-PIN 4 (software RX), RX-PIN 5(software TX).  Because we are using a snap-on XBee breakout we don't have to worry about the connections.  (For your XBee just remember RX-TX, TX-RX, and VCC-VCC GND-GND. ) 

The last step of the birdtweeder is detecting the arrival of a bird.  I used an IR emitter-detector pair to sense bird arrival.  When the bird lands on the perch of the feeder it will block the infrared light of the emitter from reaching the detector.  I've included schematics for the emitter and the detector.  Connect the output to one of the analog pins on your Arduino and you will be ready to go.  Now you can trigger the camera to take a picture whenever a bird blocks the IR detector.

Finish Up & Code

Place the IR detector on the perch of the bird feeder and hang the emitter directly above the detector.  I would recommend placing the camera either just above the feeder hole or pointing toward the perch...just make sure you get a good shot.

I've attached both the Arduino Code (.pde file) and the Java files (eclipse project) required for parsing, writing jpegs, and sending to Twitter.

So far I've got no bites, but you can see if any birds or squirrels are stopping by at:
http://twitter.com/birdtweeder