Who hasn't wanted to monitor what goes on when they aren't there. When I was little, I was always curious about whether or not anyone was going into my room and would have loved a camera monitoring system. It may even be a good idea to have a simple security setup for an apartment.
This tutorial shows how to set up a PIR sensor along with a small TTL camera and an SD card to capture images whenever there is movement in the monitored area.
The necessary libraries are: SoftwareSerial (for the camera) and SDFat (for the SD card).

Below is the code:
/***************************
PIR Motion Detection - Camera Capture
by Jennifer Case
5/21/2013
Parts:
-PIR Sensor
-SD Card Breakout Board
-TTL Camera
Pin 2,3 - Camera
Pin 8 - PIR Sensor
Pin 10 - CS/D3
Pin 11 - CMD
Pin 12 - D0
Pin 13 - CLK
****************************/
#include <SoftwareSerial.h>
#include <SdFat.h>
//SD Card
SdFat sd;
SdFile myFile;
int picCnt = 0;
//Camera
byte incomingbyte;
SoftwareSerial cameraSerial = SoftwareSerial(2, 3); //Configure pin 2 and 3 as soft serial port
int a=0x0000,j=0,k=0,count=0; //Read Starting address
uint8_t MH,ML;
boolean EndFlag=0;
//Declare pins
const int chipSelect = 10;
int pirPin = 8;
void setup() {
Serial.begin(19200); //start serial
cameraSerial.begin(38400); //start serial with camera
// Initialize SdFat or print a detailed error message and halt
// Use half speed like the native library.
// change to SPI_FULL_SPEED for more performance.
if (!sd.begin(chipSelect, SPI_HALF_SPEED)) sd.initErrorHalt();
SendResetCmd(); //allows camera to take pictures
delay(3000); //delay necessary for camera reset
}
void loop() {
int val = digitalRead(pirPin); //read from PIR sensor
//when val is HIGH, there is motion -> take pictures
if (val == HIGH) {
//create title for images
char photoTitle[25] = {};
sprintf(photoTitle, "pic%d.txt", picCnt);
//Serial.println(photoTitle);
//make sure file can be created, otherwise print error
if (!myFile.open(photoTitle, O_RDWR | O_CREAT | O_AT_END)) {
sd.errorHalt("opening photoTitle.txt for write failed");
}
//Serial.print("Writing to file...");
SendTakePhotoCmd(); //take photo
delay(200); //delay to make sure there is no drop in the data
//Serial.println("Start pic");
while(cameraSerial.available()>0) {
incomingbyte=cameraSerial.read(); //clear unneccessary serial from camera
}
byte b[32];
while(!EndFlag) {
j=0;
k=0;
count=0;
SendReadDataCmd(); //command to get picture from camera
delay(75); //delay necessary for data not to be lost
while(cameraSerial.available()>0) {
incomingbyte=cameraSerial.read(); //read serial from camera
k++;
if((k>5)&&(j<32)&&(!EndFlag)) {
b[j]=incomingbyte;
if((b[j-1]==0xFF)&&(b[j]==0xD9))
EndFlag=1; //when end of picture appears, stop reading data
j++;
count++;
}
}
for(j=0;j<count;j++) { //store picture into file
if(b[j]<0x10)
myFile.print("0");
myFile.print(b[j], HEX);
}
myFile.println();
}
StopTakePhotoCmd(); //stop this picture so another one can be taken
EndFlag = 0; // reset flag to allow another picture to be read
//Serial.println("End of pic");
myFile.close(); //close file
//Serial.println("done.");
//Serial.println();
picCnt++; //increment value for next picture
}
}
//Send Reset command
void SendResetCmd() {
cameraSerial.write((byte)0x56);
cameraSerial.write((byte)0x00);
cameraSerial.write((byte)0x26);
cameraSerial.write((byte)0x00);
}
//Send take picture command
void SendTakePhotoCmd() {
cameraSerial.write((byte)0x56);
cameraSerial.write((byte)0x00);
cameraSerial.write((byte)0x36);
cameraSerial.write((byte)0x01);
cameraSerial.write((byte)0x00);
a = 0x0000; //reset so that another picture can taken
}
void FrameSize() {
cameraSerial.write((byte)0x56);
cameraSerial.write((byte)0x00);
cameraSerial.write((byte)0x34);
cameraSerial.write((byte)0x01);
cameraSerial.write((byte)0x00);
}
//Read data
void SendReadDataCmd() {
MH=a/0x100;
ML=a%0x100;
cameraSerial.write((byte)0x56);
cameraSerial.write((byte)0x00);
cameraSerial.write((byte)0x32);
cameraSerial.write((byte)0x0c);
cameraSerial.write((byte)0x00);
cameraSerial.write((byte)0x0a);
cameraSerial.write((byte)0x00);
cameraSerial.write((byte)0x00);
cameraSerial.write((byte)MH);
cameraSerial.write((byte)ML);
cameraSerial.write((byte)0x00);
cameraSerial.write((byte)0x00);
cameraSerial.write((byte)0x00);
cameraSerial.write((byte)0x20);
cameraSerial.write((byte)0x00);
cameraSerial.write((byte)0x0a);
a+=0x20;
}
void StopTakePhotoCmd() {
cameraSerial.write((byte)0x56);
cameraSerial.write((byte)0x00);
cameraSerial.write((byte)0x36);
cameraSerial.write((byte)0x01);
cameraSerial.write((byte)0x03);
}This code sets up the SD card, reads from the PIR sensor and then takes pictures while there is motion. Everytime a picture is taken, the name of the file is incremented up.
The Python code from the camera tutorial has been revamped to allow for multiple photos to be processed at a time. This is set up to work with the naming given in the above code. The user may still have to adjust the range depending on the number of photos.
#!/usr/bin/python
# open file
import binascii
count = 0
for count in range (0,4):
f = open ("PIC%d.txt" % (count),"r")
nf = open("IMAGE%d.jpg" % (count),"wb")
#Read whole file into data
while 1:
c = f.readline()
d = c.strip()
#print (c)
#print (d)
if not c:
break
nf.write(binascii.a2b_hex(bytes(d, "ascii")))
# Close the file
f.close()
nf.close()Here are a couple proof of concept images showing that the camera and motion detection works.
