Programming Guidance DIY Camera trap

Hi all,

Would there be a kind soul out there who could maybe help with some guidance and assistance with a DIY camera trap I am in the process of putting together? :slight_smile: . To give some background to the assembly.

My aim is to have a Sony Handycam activated and set to record/stop when one of the two PIR sensors are triggered. Sounds easy enough eh!

The camera can be controlled through LANC protocol apparently with Arduino and that is my ultimate aim, however at present I cant get them to communicate despite plenty info on the web, anyway I will persevere with this side of things later.

At present I have two servos mounted in the enclosure. One activating the “Nightshot Mode” (which apparently can’t be controlled with LINC protocol so will have to remain permanently) this side of the assembly was fine. My program reads an LDR and sets the switch to on if the light levels fall below preset value).

The other servo being mounted close to the RECORD button. (The camera functions on a single press and release of the REC button activates and again a single press and release stops recording).

I am hoping for some assistance with the record function. In loose terms I am looking for the following to happen, ( my PIR outputs 3.3 v upon being triggered)

Read PIR sensor 1 state on digital pin 7
Read PIR sensor 2 state on digital pin 8

while PIR1 or PIR 2 > LOW

move record servo forward to position 127 for half a second
then return to position 115. ( a press of the RECORD button)

monitor PIR 1 and PIR 2 and continue in this state until no movement on the
PIR is detected for 30 seconds

then move record servo forward to position 127 for half a second
and then return to position 11 (a press of the Record button to stop recording).

I would be very grateful for some help with the above!

Many Thanks

Hec

my code at present is as follows

#include <Servo.h>
Servo nightservo;
Servo recordservo;
int pos = (105); // variable to set the default posision on record servo
int ldrpin = A0; //analog pin to which LDR is connected
int ldr_value =0; //variable to store LDR values
int pirvalue; //variable to store Pirvalue
int pirvalue2; //variable to store pir 2 value

void setup()
{
nightservo.attach(2); // Night button servo attached to Digital pin 2
recordservo.attach(9); // Record Servo attached to Digital Pin 9

}

void loop()
{
ldr_value = analogRead(ldrpin); //read LDR value

if (ldr_value >300) {
nightservo.write(27); // IE dark , tell servo to go to position 27
} else {
nightservo.write(5); // daylight and stay at 10 position
}

pirvalue = digitalRead(8); //read pirvalue
pirvalue2 = digitalRead(7); //read pirvalue2

}

You should really try to get that LANC working, http://playground.arduino.cc/Main/InterfacingWithHardware#Camera Perhaps starting a new topic for the LANC part of the project.

Your sketch is a good start. But a number is a number:

int pos = 105;        // not : (105);

You don't want to switch the night-mode 100 times a second. Perhaps once per 10 minutes. Could you study the BlinkWithoutDelay example, http://arduino.cc/en/Tutorial/BlinkWithoutDelay It uses the millis() function.

To develop your sketch, use the Serial library to send messages to the serial monitor. See the example at the bottom of this page, http://arduino.cc/en/Serial/Println

If you have the serial working, test the pir sensors (use println to show the pir sensors status). If they are working and the servos are working, try to use millis to do something every 10 minutes or so.

Erdin: You should really try to get that LANC working, http://playground.arduino.cc/Main/InterfacingWithHardware#Camera Perhaps starting a new topic for the LANC part of the project.

Your sketch is a good start. But a number is a number:

int pos = 105;        // not : (105);

You don't want to switch the night-mode 100 times a second. Perhaps once per 10 minutes. Could you study the BlinkWithoutDelay example, http://arduino.cc/en/Tutorial/BlinkWithoutDelay It uses the millis() function.

To develop your sketch, use the Serial library to send messages to the serial monitor. See the example at the bottom of this page, http://arduino.cc/en/Serial/Println

If you have the serial working, test the pir sensors (use println to show the pir sensors status). If they are working and the servos are working, try to use millis to do something every 10 minutes or so.

Hi Erdin, and thanks for taking the time to reply. In terms of the PIR sensors, I have them working fine. I can interface with Arduino and trigger a buzzer, led etc. I can get Arduino to read the state of the digital pin and change a variable state etc from both PIR and Serial print the results to the screen. Also, the LDR/Nightshot mode works. It only moves the switch when the lDR is dark/covered etc. Am I right in understanding that your suggesting in fact the program should only "look" once every ten minutes or so rather than constantly referencing the LDR. I would imagine that actually might save tiny bit of processing/battery power.

Yeah a good shout about the LANC protocol. It would in fact simplify the process. I will get a topic up and running and hopefully somebody will be kind enough to point me in the right direction.

I guess I could have been clearer in my first post. What I am really looking for is some guidance on the loop structure for the

While PIR sensors are triggered press the record button and do this until the PIR state has returned to low for a period of 30 seconds. I have had a go but just cant seem to get me head round it!

Cheers

Hec

The press/release to start recording and press/release to stop recording, I see as a big problem. It would be very easy for your Arduino to get out of step with the camera and turn it off when there is motion and on when the motion stops. Since you're aware of the risk there are probably things you could do to minimise it but I don't think you will ever eliminate it unless you have some way to find out whether it is recording, or some other independent method to explicitly start or stop recording. Since you have a LANC interface, this is by far the better way to solve the problem.

Regarding the daylight sensor, I suggest you smooth the input reading over a good long period (ten minutes might be enough) and also include some hysteresis in your threshold comparison so that it doesn't flap when the light lever is fluctuating close to the threshold.

You have to store the (previous) state of the pir sensors, to be able to detect when it is activated. I assume the input is HIGH if the pir sensor has activated.

int pir1Old;
int pir2Old;

void setup()
{
  pir1Old = LOW;
  pir2Old = LOW;
}

void loop()
{
  pirvalue1 = digitalRead( pinPir1);  //read pirvalue
  pirvalue2 = digitalRead( pinPir2);

  if( pir1Old == LOW && pirvalue1 == HIGH)
  {
    // pir 1 just became active.
  }

  if( pir2Old == LOW && pirvalue2 == HIGH)
  {
    // pir 2 just became active.
  }

  // Remember the current state.
  pir1Old = pirvalue1;
  pri2Old = pirvalue2;
}

I think you can extend this example. But I would like to have the timing in the Arduino. So I would not detect the pir becoming not active. I would use millis() for the timing. Did you take a look at the millis() yet ? I think you will be using it in the end.

THanks for your help guys, I am working for a few days so Arduino and the camera will have to take a back step. Once I am days off I will have a look at the suggestions and spend some time reading and understanding the different functions.

Updates to follow

Cheers

Hec

Great Guy thanks.

Ok progress update. I now have LANC working. Good in itself as I now can do away with the record servo. However as far as I can see (in this program anyway) there is no Stop function after record, rather just the record function again which ends the recording (in the example code below a grounding of pin 6 triggers record and same again triggers stop). I have been thinking about this and have an idea. Assuming upon activation of the device, if Record state is set to OFF or 0 for taking sake, and upon each activation/instruction of the record function, 1 is added to the variable, it should be safe to assume if the number is odd then the unit is recording and even then stopped? Does this make sense or am I missing something?? Can arduino look at weather a number is odd or even? I am sure there will be some maths magic to look at that problem if not.

The code for the record function has been taken from the internet and is included below. I am now going to have a go at seeing if I can get some revised better code for the PIR function based upon Erdins example below. I like the idea, for a safety buffer almost, off once activated, checking the sensor three times, five seconds or so apart and only once all three are 0 or LOW do I stop recording. The PIR sensor outputs 2.5vs upon being triggered.( Would this be enough for Arduino to see HIGH, I am guessing so as it fires up LED or buzzers no prob) Therefor giving me 15 seconds or so footage once the cause of the trigger is out of shot.

An alternative method could be to record for a preset time upon trigger and then basically reset the timer upon re-trigger of the sensor?

/*
SIMPLE LANC REMOTE
Version 1.0
Sends LANC commands to the LANC port of a video camera.
Tested with a Canon XF300 camcorder
For the interface circuit interface see

Feel free to use this code in any way you want.
2011, Martin Koch

“LANC” is a registered trademark of SONY.
CANON calls their LANC compatible port “REMOTE”.
*/

#define cmdPin 7
#define lancPin 11
#define recButton 6
#define zoomOutButton 5
#define zoomInButton 4
#define focusNearButton 3
#define focusFarButton 2
int cmdRepeatCount;
int bitDuration = 104; //Duration of one LANC bit in microseconds.

//LANC commands byte 0 + byte 1
//Tested with Canon XF300

//Start-stop video recording
boolean REC = {LOW,LOW,LOW,HIGH,HIGH,LOW,LOW,LOW, LOW,LOW,HIGH,HIGH,LOW,LOW,HIGH,HIGH}; //18 33

//Zoom in from slowest to fastest speed
boolean ZOOM_IN_0 = {LOW,LOW,HIGH,LOW,HIGH,LOW,LOW,LOW, LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW}; //28 00
boolean ZOOM_IN_1 = {LOW,LOW,HIGH,LOW,HIGH,LOW,LOW,LOW, LOW,LOW,LOW,LOW,LOW,LOW,HIGH,LOW}; //28 02
boolean ZOOM_IN_2 = {LOW,LOW,HIGH,LOW,HIGH,LOW,LOW,LOW, LOW,LOW,LOW,LOW,LOW,HIGH,LOW,LOW}; //28 04
boolean ZOOM_IN_3 = {LOW,LOW,HIGH,LOW,HIGH,LOW,LOW,LOW, LOW,LOW,LOW,LOW,LOW,HIGH,HIGH,LOW}; //28 06
boolean ZOOM_IN_4 = {LOW,LOW,HIGH,LOW,HIGH,LOW,LOW,LOW, LOW,LOW,LOW,LOW,HIGH,LOW,LOW,LOW}; //28 08
boolean ZOOM_IN_5 = {LOW,LOW,HIGH,LOW,HIGH,LOW,LOW,LOW, LOW,LOW,LOW,LOW,HIGH,LOW,HIGH,LOW}; //28 0A
boolean ZOOM_IN_6 = {LOW,LOW,HIGH,LOW,HIGH,LOW,LOW,LOW, LOW,LOW,LOW,LOW,HIGH,HIGH,LOW,LOW}; //28 0C
boolean ZOOM_IN_7 = {LOW,LOW,HIGH,LOW,HIGH,LOW,LOW,LOW, LOW,LOW,LOW,LOW,HIGH,HIGH,HIGH,LOW}; //28 0E

//Zoom out from slowest to fastest speed
boolean ZOOM_OUT_0 = {LOW,LOW,HIGH,LOW,HIGH,LOW,LOW,LOW, LOW,LOW,LOW,HIGH,LOW,LOW,LOW,LOW}; //28 10
boolean ZOOM_OUT_1 = {LOW,LOW,HIGH,LOW,HIGH,LOW,LOW,LOW, LOW,LOW,LOW,HIGH,LOW,LOW,HIGH,LOW}; //28 12
boolean ZOOM_OUT_2 = {LOW,LOW,HIGH,LOW,HIGH,LOW,LOW,LOW, LOW,LOW,LOW,HIGH,LOW,HIGH,LOW,LOW}; //28 14
boolean ZOOM_OUT_3 = {LOW,LOW,HIGH,LOW,HIGH,LOW,LOW,LOW, LOW,LOW,LOW,HIGH,LOW,HIGH,HIGH,LOW}; //28 16
boolean ZOOM_OUT_4 = {LOW,LOW,HIGH,LOW,HIGH,LOW,LOW,LOW, LOW,LOW,LOW,HIGH,HIGH,LOW,LOW,LOW}; //28 18
boolean ZOOM_OUT_5 = {LOW,LOW,HIGH,LOW,HIGH,LOW,LOW,LOW, LOW,LOW,LOW,HIGH,HIGH,LOW,HIGH,LOW}; //28 1A
boolean ZOOM_OUT_6 = {LOW,LOW,HIGH,LOW,HIGH,LOW,LOW,LOW, LOW,LOW,LOW,HIGH,HIGH,HIGH,LOW,LOW}; //28 1C
boolean ZOOM_OUT_7 = {LOW,LOW,HIGH,LOW,HIGH,LOW,LOW,LOW, LOW,LOW,LOW,HIGH,HIGH,HIGH,HIGH,LOW}; //28 1E

//Focus control. Camera must be switched to manual focus
boolean FOCUS_NEAR = {LOW,LOW,HIGH,LOW,HIGH,LOW,LOW,LOW, LOW,HIGH,LOW,LOW,LOW,HIGH,HIGH,HIGH}; //28 47
boolean FOCUS_FAR = {LOW,LOW,HIGH,LOW,HIGH,LOW,LOW,LOW, LOW,HIGH,LOW,LOW,LOW,HIGH,LOW,HIGH}; //28 45

boolean FOCUS_AUTO = {LOW,LOW,HIGH,LOW,HIGH,LOW,LOW,LOW, LOW,HIGH,LOW,LOW,LOW,LOW,LOW,HIGH}; //28 41

//boolean POWER_OFF = {LOW,LOW,LOW,HIGH,HIGH,LOW,LOW,LOW, LOW,HIGH,LOW,HIGH,HIGH,HIGH,HIGH,LOW}; //18 5E
//boolean POWER_ON = {LOW,LOW,LOW,HIGH,HIGH,LOW,LOW,LOW, LOW,HIGH,LOW,HIGH,HIGH,HIGH,LOW,LOW}; //18 5C Doesn’t work because there’s no power supply from the LANC port when the camera is off
//boolean POWER_OFF2 = {LOW,LOW,LOW,HIGH,HIGH,LOW,LOW,LOW, LOW,LOW,HIGH,LOW,HIGH,LOW,HIGH,LOW}; //18 2A Turns the XF300 off and then on again
//boolean POWER_SAVE = {LOW,LOW,LOW,HIGH,HIGH,LOW,LOW,LOW, LOW,HIGH,HIGH,LOW,HIGH,HIGH,LOW,LOW}; //18 6C Didn’t work

void setup() {

pinMode(lancPin, INPUT); //listens to the LANC line
pinMode(cmdPin, OUTPUT); //writes to the LANC line

pinMode(recButton, INPUT); //start-stop recording button
digitalWrite(recButton, HIGH); //turn on an internal pull up resistor
pinMode(zoomOutButton, INPUT);
digitalWrite(zoomOutButton, HIGH);
pinMode(zoomInButton, INPUT);
digitalWrite(zoomInButton, HIGH);
pinMode(focusNearButton, INPUT);
digitalWrite(focusNearButton, HIGH);
pinMode(focusFarButton, INPUT);
digitalWrite(focusFarButton, HIGH);

digitalWrite(cmdPin, LOW); //set LANC line to +5V
delay(5000); //Wait for camera to power up completly
bitDuration = bitDuration - 8; //Writing to the digital port takes about 8 microseconds so only 96 microseconds are left for each bit
}

void loop() {

if (!digitalRead(recButton)) {
lancCommand(REC);
}

if (!digitalRead(zoomOutButton)) {
lancCommand(ZOOM_OUT_4);
}

if (!digitalRead(zoomInButton)) {
lancCommand(ZOOM_IN_4);
}

if (!digitalRead(focusNearButton)) {
lancCommand(FOCUS_NEAR);
}

if (!digitalRead(focusFarButton)) {
lancCommand(FOCUS_FAR);
}
}

void lancCommand(boolean lancBit) {

cmdRepeatCount = 0;

while (cmdRepeatCount < 5) { //repeat 5 times to make sure the camera accepts the command

while (pulseIn(lancPin, HIGH) < 5000) {
//“pulseIn, HIGH” catches any 0V TO +5V TRANSITION and waits until the LANC line goes back to 0V
//“pulseIn” also returns the pulse duration so we can check if the previous +5V duration was long enough (>5ms) to be the pause before a new 8 byte data packet
//Loop till pulse duration is >5ms
}

//LOW after long pause means the START bit of Byte 0 is here
delayMicroseconds(bitDuration); //wait START bit duration

//Write the 8 bits of byte 0
//Note that the command bits have to be put out in reverse order with the least significant, right-most bit (bit 0) first
for (int i=7; i>-1; i–) {
digitalWrite(cmdPin, lancBit*); //Write bits.*

  • delayMicroseconds(bitDuration);*

  • }*

  • //Byte 0 is written now put LANC line back to +5V*

  • digitalWrite(cmdPin, LOW);*

  • delayMicroseconds(10); //make sure to be in the stop bit before byte 1*

  • while (digitalRead(lancPin)) {*

  • //Loop as long as the LANC line is +5V during the stop bit*

  • }*

  • //0V after the previous stop bit means the START bit of Byte 1 is here*

  • delayMicroseconds(bitDuration); //wait START bit duration*

  • //Write the 8 bits of Byte 1*

  • //Note that the command bits have to be put out in reverse order with the least significant, right-most bit (bit 0) first*

  • for (int i=15; i>7; i–) {*
    _ digitalWrite(cmdPin,lancBit*); //Write bits*_
    * delayMicroseconds(bitDuration);*
    * }*

* //Byte 1 is written now put LANC line back to +5V*
* digitalWrite(cmdPin, LOW);*
* cmdRepeatCount++; //increase repeat count by 1*

_ /Control bytes 0 and 1 are written, now don’t care what happens in Bytes 2 to 7_
_ and just wait for the next start bit after a long pause to send the first two command bytes again./_

USE CODE TAGS PLEASE

mmcp42: USE CODE TAGS PLEASE

Hi, What is a code tag?

Thanks

Hec

[ code] your code here [ /code]

makes the code more readable

but leave out the spaces I just put there so you could see what to do

your code

mmcp42: [ code] your code here [ /code]

makes the code more readable

but leave out the spaces I just put there so you could see what to do

your code

brilliant thank you :-)

you can go back and edit your posts to add the code tags :)