trying to do a tripwire with some logic - I think

I'm trying to tweak some code that I found but I'm not having much luck. I'm trying to get something up and running to protect my koi pond. There is a blue heron that keeps showing up trying to eat my koi. It already got one of them. I've been getting up at 5am and watch over the pond waiting for the bird to show up and scare it. As much as I would love to do some harm, it's illegal and only looking to activate a water sprinkler and a radio.

The tripwire will be activating a water valve and a radio. I would like to use the code below but add a few features that if the sensor gets blocked the water wouldn't be running all day and when tripped it only outputs water for few seconds.

  1. When in the armed state-- When the laser beam gets interrupted output for 15 seconds and then rearm itself, while keeping the arm and disarm button
    (I didn't have much luck with delay or timer.h)

  2. When in the armed state-- if laser beam gets interrupted say 3 times within 45 seconds - 1 minute- disable alert led and buzzer and play a different tone or flash an led of problem. (if something falls out of alignment- water,radio,etc isn't running all day.)

Any tips on what function I should search for and try to implement? Thanks

/*
 * Laser trip wire
 * v 1.3
 * by: Keith Kay
 * 1/31/2013
 * CC by-sa v3.0 - http://creativecommons.org/licenses/by-sa/3.0/
 * http://keithkay.com
 *
 * Laser trip-wire sketch which implements the following functionality:
 * - Calibration to current light environment
 * - Visual feedback on alignment
 * - Arming and disarming mechanism
 *
 * attribution: siren code modified from
 * Annoying siren
 * CC by-sa v3.0
 * http://tronixstuff.wordpress.com
 *
 */
 
// first define the constants used for sensor / emitter pins
const int triggeredLED = 7; // pin for the warning light LED
const int RedLED = 3; // pin for the 'armed' state indicator
const int GreenLED = 4; // pin for the 'un-armed' state indicator
const int inputPin = A0; // pin for analog input
const int speakerPin = 12; // pin for the speaker output
const int armButton = 6; // pin for the arming button

// define variables used for readings and programatic control
boolean isArmed = true; // variable for the armed state
boolean isTriggered = false; // has the wire been tripped
int buttonVal = 0; // variable to store button state and compare with previous
int prev_buttonVal = 0; // variable to 'debounce' button
int reading = 0; // variable to store the analog value coming from the sensor
int threshold = 0; // variable set by the calibration process

// constants used for the siren
const int lowrange = 2000; // the lowest frequency value to use
const int highrange = 4000; // the highest...

void setup(){
  
  // configure LEDs for output
  pinMode(triggeredLED, OUTPUT);
  pinMode(RedLED, OUTPUT);
  pinMode(GreenLED, OUTPUT);
  
  //configure the button for input
  pinMode(armButton, INPUT);
  
  // for debugging and calibration review
  Serial.begin(9600);
  Serial.println("");
  Serial.println("Initializing...");

  // intial 'test' to be sure all LEDs and the speaker are working
  digitalWrite(triggeredLED, HIGH);
  delay(500);
  digitalWrite(triggeredLED, LOW);
  
  Serial.println("Unarmed");
  setArmedState();
  delay(500);
  
  Serial.println("Armed");
  setArmedState();
  delay(500);
  
  // calibrate the laser light level in the current environment
  // this was moved to a function for future integration of a reset function
  calibrate();
  
  // start unarmed
  setArmedState();
  
}

void loop(){
  
  // read the LDR sensor
  reading = analogRead(inputPin);
  
  // check to see if the button is pressed
  int buttonVal = digitalRead(armButton);
  if ((buttonVal == HIGH) && (prev_buttonVal == LOW)){
    setArmedState();
    delay(500);
    Serial.print("button val= ");
    Serial.println(buttonVal);
  }
  
  // print the value to serial
  Serial.print("Reading = ");
  Serial.println(reading);
  
  // check to see if the laser beam is interrupted based on the threshold
  if ((isArmed) && (reading < threshold)){
    isTriggered = true;}
    
  if (isTriggered){
    
    // siren code
    // increasing tone
    for (int i = lowrange; i <= highrange; i++)
    {
      tone (speakerPin, i, 250);
    }
    // decreasing tone
    for (int i = highrange; i >= lowrange; i--)
    {
      tone (speakerPin, i, 250);
    }
    
    // flash LED
    digitalWrite(triggeredLED, HIGH);
    delay(10);
    digitalWrite(triggeredLED, LOW);
    
  }
 
  // short delay - if you are debugging a modification you may want to increase this to slow down the serial readout
  delay(20);

}

// function to flip the armed state of the trip wire
void setArmedState(){
  
  if (isArmed){
    digitalWrite(GreenLED, HIGH);
    digitalWrite(RedLED, LOW);
    isTriggered = false;
    isArmed = false;
  } else {
    digitalWrite(GreenLED, LOW);
    digitalWrite(RedLED, HIGH);
    tone(speakerPin, 220, 125);
    delay(200);
    tone(speakerPin, 196, 250);
    isArmed = true;
  }
}

void calibrate(){
  
  int sample = 0; // array to hold the initial sample
  int baseline = 0; // variable to set the baseline reading
  const int min_diff = 200; // minimum difference needed between current light level and laser calibration
  const int sensitivity = 50;
  int success_count = 0;
  
  // ensure both LEDs are off
  digitalWrite(RedLED, LOW);
  digitalWrite(GreenLED, LOW);
  
  // start by taking a 10 reading sample, then take the average for our baseline
  for (int i=0; i<10; i++){
    sample += analogRead(inputPin); // take reading and add it to the sample
    digitalWrite(GreenLED, HIGH);
    delay (50); // delay to blink the LED and space readings
    digitalWrite(GreenLED, LOW);
    delay (50); // delay to blink the LED and space readings
  }
  
  // calculate and print the baseline
  baseline = sample / 10;
  Serial.print("baseline = ");
  Serial.println(baseline);
  
  // now keep taking a reading until we've gotten 3 successful reads in a row
  do
  {
    sample = analogRead(inputPin); // this time we work with one reading at a time
    
    if (sample > baseline + min_diff){
      success_count++;
      threshold += sample;
      
      digitalWrite(GreenLED, HIGH);
      delay (100); // delay to blink the LED and space readings
      digitalWrite(GreenLED, LOW);
      delay (100); // delay to blink the LED and space readings
    } else {
      success_count = 0; // this give us the 'in a row' result
      threshold = 0;
    }
    
  } while (success_count < 3);
  
  //lastly we need to correctly set the threshold as it now hold the sum of 3 samples
  threshold = (threshold/3) - sensitivity;
  
  // play the arming tone and in reverse and print the threshold to condfrim threshold set
  tone(speakerPin, 196, 250);
  delay(200);
  tone(speakerPin, 220, 125);
  Serial.print("baseline = ");
  Serial.println(baseline);
  
}

^ pulled from here arduino/Arduino Laser Tripwire at master · keithkay/arduino · GitHub

A video from the creator in operation if it helps anyone understand it all.

setArmedState() doesn't. At a minimum that function needs a new name. One that actually reflects what it really does.

The siren code should go in a function that you call to sound the siren.

Think about how YOU would do what you want, equipped with just a watch, a pad of paper and a pencil.

The variables in the sketch take the place of the paper and pencil. The millis() function takes the place of the watch.

Thanks PaulS for heading me in the right direction. I'll be burning the midnight oil tonight :slight_smile:

Ive got a similar problem with deer and my flower gardens, I am built a little device that uses a motion detector to trigger a noisemaker. Could be pretty much the same thing. I used a light resistor to activate it since deer are nocturnal. You may need a real time clock since your nuisance is more time specific but who knows.

Here is the code

int pirPin = 4;
int motorPin = 1;
int lightPin = A1;

int light = 0;

int threshold = 950;
boolean motion = false;

void setup()
{
  //Serial.begin(9600);
  pinMode(lightPin, INPUT);
  pinMode(pirPin, INPUT);
  pinMode(motorPin, OUTPUT);
}
void loop()
{
  light = analogRead(lightPin);
  digitalWrite(motorPin, LOW); 
  
  while(light < threshold)    // 0 - bright   1023 - dark   
  {
    motion = digitalRead(pirPin);
    digitalWrite(motorPin, LOW);  //pull up resistor, inverted command
    //Serial.println(light);
    
    if(motion == 1)
    { 
      digitalWrite(motorPin, HIGH);    //motor on
      delay(1500);
      digitalWrite(motorPin, LOW);
      //Serial.println("motion!");  
      delay(10000);  
    }
  } 
}

PaulS:
setArmedState() doesn't. At a minimum that function needs a new name. One that actually reflects what it really does.

The siren code should go in a function that you call to sound the siren.

Think about how YOU would do what you want, equipped with just a watch, a pad of paper and a pencil.

The variables in the sketch take the place of the paper and pencil. The millis() function takes the place of the watch.

I renamed everything with setArmedState with either setArmedState and setUnarmedState. That got confusing so I just went with setArmingState for everything. I call it twice in the loop to disarm and rearm.
I moved the siren code to a function and called it in the loop as alarm()
I played with millis() but couldn't figure it out. In the end I pulled the alarm() and used delay on the led output pin.

Still trying to figure out how to add if the laser beam gets broken as soon as it rearms 3 times in a row - disarm and remain disarmed and turn on an indicator. (failure alert of alignment)

rclymer:
Ive got a similar problem with deer and my flower gardens, I am built a little device that uses a motion detector to trigger a noisemaker. Could be pretty much the same thing. I used a light resistor to activate it since deer are nocturnal. You may need a real time clock since your nuisance is more time specific but who knows.

Here is the code

int pirPin = 4;

int motorPin = 1;
int lightPin = A1;

int light = 0;

int threshold = 950;
boolean motion = false;

void setup()
{
  //Serial.begin(9600);
  pinMode(lightPin, INPUT);
  pinMode(pirPin, INPUT);
  pinMode(motorPin, OUTPUT);
}
void loop()
{
  light = analogRead(lightPin);
  digitalWrite(motorPin, LOW);
 
  while(light < threshold)    // 0 - bright   1023 - dark   
  {
    motion = digitalRead(pirPin);
    digitalWrite(motorPin, LOW);  //pull up resistor, inverted command
    //Serial.println(light);
   
    if(motion == 1)
    {
      digitalWrite(motorPin, HIGH);    //motor on
      delay(1500);
      digitalWrite(motorPin, LOW);
      //Serial.println("motion!"); 
      delay(10000); 
    }
  }
}

Thanks for your code - I'm finally understanding most of it:) I do have a DS3231 module but with my luck the bird will change his schedule and clean me out :frowning:

rclymer,
What kind of motion sensor did you use? I was looking at the fairly cheap units online - I couldn't think of a way to waterproof the unit. So I just hit the homedepot and picked up a cheap, no frills Heath/Zenith motion sensor for flood lights. I had a higher end one at the house that I took apart but that one uses a Triac for the 'dualbrite', the only output pin that would somewhat work would be the + LED pin that goes on as an indicator. I wasn't certain of how to protect current to the arduino - maybe a 2n2222? So I went with the no frills motion sensor that has a relay. I scraped off a trace, and soldered a wire to the common. I wouldn't recommend it, due to safety issues - do so at your own risk.

I scraped the trace pretty far back to prevent arcing

This is the unit with dualbrite, no relay, but it does have a 2.5v output to the led to indicate when it was tripped, not sure how to hack it.
It also has a large range due to two sensors

Triac is a BTA10 400C

That is getting to be pretty intense project. I used a PIR motion sensor off of ebay, its very cheap, easy to use and still very effective. Here is the linkhttp://www.ebay.com/itm/360606642522?var=630093650065&ssPageName=STRK:MEWNX:IT&_trksid=p3984.m1439.l2649

A new way to waterproof things has finally come to the market, a product that I have been following for a while but they never had distribution figured out until they partnered with Rustoleum. Its called NeverWet, a two part spray coating that causes surfaces to become "superhyrdrophobic" which basically means it repels water in a serious way. Ive seen some youtube videos of people using it on an iPhone and actually using it underwater. There are some other crazy videos of this stuff. Heres the link http://www.homedepot.com/p/Rust-Oleum-Stops-Rust-18-oz-NeverWet-Multi-Purpose-Spray-Kit-274232/204216476#.UcTpVz6gmHc

You could coat basically anything with this an not only make with weather resistant but damn near waterproof.

I renamed everything with setArmedState with either setArmedState and setUnarmedState. That got confusing so I just went with setArmingState for everything.

The function does what? toggleArdmedState. So, why not call the function that?

rclymer, thanks for the tip on Neverwet. That is the first I ever heard of it, amazing stuff!! > http://www.huffingtonpost.co.uk/2013/06/21/neverwet-spray_n_3477178.html

PaulS, I don't know why the author named it that. I do appreciate the assistance / hints on how to do what I want it to do. I spent 7 hours tweaking stuff and then went to bed. I decided to start over and try my luck with RPi and picked up Python much quicker than I did with arduino, never used either platforms nor programmed. I'll be using the Uno for something but not sure yet. Thanks anyways...

happy to help. good luck with rpi, Ive never used one or python, but I have put in an order for a UDOO quad, so it wont be long until I get acquainted with one. Ive always heard that the rpi doesnt do quite as well with sensors but Im sure it can get the job done.