Motion Capture Code // This is a modification of a motion-detect camera sketch using the Adafruit VC0706 library. // I updated it to serve as a motion detection camera using IR features for wildlife photos // to date the images at night are not very clear, but so far it looks like I only captured birds in flight. // slow refresh at 640x480 means not that many pictures in close sequence // Updates include adding an LCD screen to show status when not connected to a computer // and using a PIR sensor for nighttime sensing of activity as motion sensor does not work well at night. // On start, the Arduino will find the camera and SD card and turn // on motion detection. If motion is detected, the camera will // snap a photo, saving it to the SD card. // Public domain. #include #include #include #include #include int inPin = 14; // the number of the input pin int outPin = 15; // the number of the output pin int state = HIGH; // the current state of the output pin int reading; // the current reading from the input pin int previous = LOW; // the previous reading from the input pin // the follow variables are long's because the time, measured in miliseconds, // will quickly become a bigger number than can be stored in an int. long time = 0; // the last time the output pin was toggled long debounce = 200; // the debounce time, increase if the output flickers // initialize the library with the numbers of the interface pins LiquidCrystal lcd(4, 5, 6, 7, 8, 9); // this is cutomized for my setup as a number of others are used by the SD Card. // SD card chip select line varies among boards/shields: // Pins for camera connection are configurable. // On Uno: camera TX connected to pin 2, camera RX to pin 3: #define chipSelect 10 SoftwareSerial cameraconnection = SoftwareSerial(2, 3); Adafruit_VC0706 cam = Adafruit_VC0706(&cameraconnection); void setup() { pinMode(inPin, INPUT); pinMode(outPin, OUTPUT); // set up the LCD's number of columns and rows: lcd.begin(16, 2); // When using hardware SPI, the SS pin MUST be set to an // output (even if not connected or used). If left as a // floating input w/SPI on, this can cause lockuppage. #if !defined(SOFTWARE_SPI) #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) if (chipSelect != 53) pinMode(53, OUTPUT); // SS on Mega #else if (chipSelect != 10) pinMode(10, OUTPUT); // SS on Uno, etc. #endif #endif Serial.begin(9600); Serial.println("VC0706 Camera test"); lcd.print("VC0706 Cam tst"); lcd.setCursor(0, 1); // see if the card is present and can be initialized: if (!SD.begin(chipSelect)) { Serial.println("Card failed, or not present"); lcd.print("Card fail"); lcd.setCursor(0, 1); // don't do anything more: return; } // Try to locate the camera if (cam.begin()) { Serial.println("Camera Found:"); lcd.print("Cam Found:"); lcd.setCursor(0, 1); } else { Serial.println("No camera found?"); lcd.print("No Camera"); lcd.setCursor(0, 1); return; } // Print out the camera version information (optional) char *reply = cam.getVersion(); if (reply == 0) { Serial.print("Failed to get version"); lcd.print("Failed to get version"); lcd.setCursor(0, 1); } else { Serial.println("-----------------"); lcd.print("-----------------"); lcd.setCursor(0, 1); Serial.print(reply); Serial.println("-----------------"); } // Set the picture size - you can choose one of 640x480, 320x240 or 160x120 // Remember that bigger pictures take longer to transmit! cam.setImageSize(VC0706_640x480); // biggest // cam.setImageSize(VC0706_320x240); // medium //cam.setImageSize(VC0706_160x120); // small // You can read the size back from the camera (optional, but maybe useful?) uint8_t imgsize = cam.getImageSize(); Serial.print("Image size: "); if (imgsize == VC0706_640x480) Serial.println("640x480"); if (imgsize == VC0706_320x240) Serial.println("320x240"); if (imgsize == VC0706_160x120) Serial.println("160x120"); // Motion detection system can alert you when the camera 'sees' motion! cam.setMotionDetect(true); // turn it on //cam.setMotionDetect(false); // turn it off (default) // You can also verify whether motion detection is active! Serial.print("Motion detection is "); if (cam.getMotionDetect()) Serial.println("ON"); else Serial.println("OFF"); delay (500); } void loop() { reading = digitalRead(inPin); if (reading == HIGH && previous == LOW && millis() - time > debounce) { if (state == HIGH) state = LOW; else state = HIGH; time = millis(); } digitalWrite(outPin, state); previous = reading; if (cam.motionDetected() ) { Serial.println("Motion!"); lcd.print("Motion!"); lcd.setCursor(0, 1); cam.setMotionDetect(false); if (! cam.takePicture()) { Serial.println("Failed to snap!"); lcd.print("Failed to snap!"); lcd.setCursor(0, 1); } else { Serial.println("Picture taken!"); lcd.print("Picture taken!.."); delay (500); lcd.clear(); lcd.setCursor(0, 0); } char filename[13]; for (int i = 0; i < 1000; i++) { sprintf(filename, "IMAGE%03d.JPG", i); // create if does not exist, do not open existing, write, sync after write if (! SD.exists(filename)) { break; } } File imgFile = SD.open(filename, FILE_WRITE); uint16_t jpglen = cam.frameLength(); Serial.print(jpglen, DEC); Serial.println(" byte image"); Serial.print("Writing image to "); Serial.print(filename); lcd.print("writing:"); lcd.print(filename); while (jpglen > 0) { // read 32 bytes at a time; uint8_t *buffer; uint8_t bytesToRead = min(32, jpglen); // change 32 to 64 for a speedup but may not work with all setups! buffer = cam.readPicture(bytesToRead); imgFile.write(buffer, bytesToRead); //Serial.print("Read "); Serial.print(bytesToRead, DEC); Serial.println(" bytes"); jpglen -= bytesToRead; } imgFile.close(); Serial.println("...Done!"); lcd.clear(); lcd.print("Done..."); delay (100); lcd.clear(); lcd.setCursor(0, 0); cam.resumeVideo(); cam.setMotionDetect(true); } }