Problems with an alarm based on arduino

My friend tyler is the one that got this started.

He is attempting to make a burglar alarm of sorts, basically he has a motion detector that when triggers pulls a line low, when it does, a relay is closed and a alarm sounds.

he also has a window pin that is monitored, when it goes low, another relay is closed, and a strobe light goes off.

When either alarm is triggered, a message is printed to the lcd screen, that states how many times the alarm has been set off.

The problem we are having is that the count increases the entire time the alarm is in the tripped state. Another words, if it is only tripped once, and the low condition stays the same, then it increments the count again, thus giving us a totally wrong number of times that the alarm has been tripped.

I know that we are right at figuring it out, but i have given up on it.
Here is the code we are using right now.

#include <LiquidCrystal.h>

// LiquidCrystal display with:
// rs on pin 12
// rw on pin 11
// enable on pin 10
// d4, d5, d6, d7 on pins 5, 4, 3, 2
LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);


int strobePin = 28;
int winPin = 30;
int ledPin = 13;
int inPin = 32;
int val = 0;
int Tripped = 0;


void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(inPin, INPUT);
  pinMode(strobePin, OUTPUT);
  pinMode(winPin, INPUT);
  
  lcd.begin(2, 16);        // This sets the lcd to a two line, 16char display
  lcd.clear();             // clear the display
  
}

void loop() {

  val = digitalRead(inPin);
  if (val ==LOW) {
    
    Trip();                    //  <--- THIS IS THE PROBLEM - it's in the wrong place or not right.
    
    digitalWrite(ledPin, LOW);
  } else {
    digitalWrite(ledPin, HIGH);
 //    delay(25000);
  }
 val=digitalRead(winPin);
 if(val==LOW){
  
   digitalWrite(strobePin,LOW);
}else{
 digitalWrite(strobePin,HIGH);
 //delay(9000);
 }
}

 void Trip(){
   Tripped++;
  lcd.print("alarm tripped ");    //  Printed on default line on lcd
  lcd.setCursor(0,1);            // moves the cursor to the second line
  lcd.print(Tripped);            // prints on the second line.
  lcd.print(" Times!");
  lcd.home();                    // Returns cursor to first line.
 }

If anyone could tell us a way to change how the counter is incremented, or what we are doing wrong, please please do.

Thanks in advance.

This is a classic programatic challenge. And you are not the first to be challenged by it :slight_smile:

You will need to do this:

  • Use two variables, one for the current state, and one for the previous
  • When they are not equal, this indicates a unique change
  • When they are not equal AND the current state is LOW, this implies a Trip();

Example implementation:

[UNTESTED CODE]

const byte tripPin = 12;

//declare a variable to hold the currentState
boolean currentState = false;

//declare a variable to hold the previousState
boolean previousState = false;

void setup(){ pinMode( tripPin, INPUT ); }

void loop(){
  currentState = digitalRead( tripPin );
  if (currentState!=previousState && currentState==LOW){
    Trip(); //the state has changed from 'not' tripped to tripped
    //delay(20); //might need this for debouncing
  }else{
    //not tripped
  }
  previousState = currentState; //prevent multiple triggering of Trip();
}

Thank you for the input!

I will try to implement this in my code and post the results back.

Thanks again.

Ok, i made some changes to my code, implementing the type of fix that you spoke of, and I have the exact same results. As long as the pin is pulled low, the counter steadily increments.

Maybe I am attempting something here that is just impossible.

Here is the code that I have now.

#include <LiquidCrystal.h>

// LiquidCrystal display with:
// rs on pin 12
// rw on pin 11
// enable on pin 10
// d4, d5, d6, d7 on pins 5, 4, 3, 2
LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);


const byte strobePin = 7;
const byte winPin = 8;
const byte ledPin = 13;
const byte inPin = 9;
boolean currentState = HIGH;
boolean previousState = LOW;
int Tripped=0;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(inPin, INPUT);
  pinMode(strobePin, OUTPUT);
  pinMode(winPin, INPUT);
  
  lcd.begin(2, 16);        // This sets the lcd to a two line, 16char display
  lcd.clear();             // clear the display
  
}

void loop() {

  currentState = digitalRead(inPin);
  if (currentState!=previousState && currentState==LOW) {
    
    Trip();                    //  <--- THIS IS THE PROBLEM - it's in the wrong place or not right.
    delay(200);
    digitalWrite(ledPin, LOW);
  } else {
    digitalWrite(ledPin, HIGH);
previousState = currentState;
  }

 currentState=digitalRead(winPin);
 if(currentState!=previousState && currentState==LOW){
   Trip();
   delay(200);
   digitalWrite(strobePin,LOW);
}else{
 digitalWrite(strobePin,HIGH);
previousState = currentState;
 }

}

 void Trip(){
   Tripped++;
  lcd.print("alarm tripped ");    //  Printed on default line on lcd
  lcd.setCursor(0,1);            // moves the cursor to the second line
  lcd.print(Tripped);            // prints on the second line.
  lcd.print(" Times!");
  lcd.home();                    // Returns cursor to first line.
 }

I had thought that we could implement a count just to let us know how many times the alarm was tripped while we were away. I am beginning to think that the way I am going about this, it is just impossible to do.

The alarm actually counts up when nothing is tripped.. so if the alarm is sitting there armed with no breach or anything the LCD will just count up as high as 44,000 and up then it will switch to negative numbers... but once one of the switches is tripped the LCD will stop counting up and stop at what ever number it has managed to count to.

ummm.. no it don't tyler.. :slight_smile: (he's the one i am helping.. )

If you load this code on a "normal" (non-mega) with a pullup resistor on both the input lines, it does not just count up. It does as it should.

But, if and when the sensor is tripped, it steadily increases the count as long as the "low" condition on the line persists. As soon as the line returns to high, the count stops increasing.

The code you have now maybe the older version, check your email, i sent this code, with MY pins on it.. of course on the mega you will have to remap the pins.

Wait.. when the alarm is tripped is the line supposed to be high or low tyler?

If it's supposed to be high, then yes, you are getting a count when you "Think" the alarm is tripped, the way I have it coded, when the line goes low, you are in a "tripped" state.

That's a very easy fix, just need to swap a couple of statements from LOW to HIGH and vice versa.

But that still leaves the issue of it counting constantly while in a tripped state.

The relay on the PIR sensor is normally closed so when it sees motion it opens it. The code is suppose to turn the LED pin HIGH when the PIR relay opens.

Ok, after viewing a video of his setup, Motion activated PIR Arduino controlled lights - YouTube, i see more of what was happening on his end.

I adjusted the code, we were showing a tripped state at the totally wrong time.. and adding a couple of delays in the code to keep the relays on for a longer period, it seems to work pretty well.

Here is our heavily commented code..

#include <LiquidCrystal.h>

// LiquidCrystal display with:
// rs on pin 12
// rw on pin 11
// enable on pin 10
// d4, d5, d6, d7 on pins 5, 4, 3, 2
LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);


const byte strobePin = 7;    // pin for the strobe light
const byte windowPin = 8;       // pin for the window plunger
const byte relayPin = 13;      // pin for the Relay (this was the ledPin, this is just easier for me to understand than ledpin.)
const byte pirPin = 9;        // pin for the pir sensor

boolean currentState = LOW;    // holder for the current state of the alarm
boolean previousState = HIGH;  // holder for the previous state of the pin

int Tripped=0;                  // variable to hold the count of times the alarm was tripped

void setup() {
  pinMode(relayPin, OUTPUT);
  pinMode(pirPin, INPUT);
  pinMode(strobePin, OUTPUT);
  pinMode(windowPin, INPUT);
  
  digitalWrite(pirPin, LOW);    // this sets the initial state of the pin
  digitalWrite(windowPin, LOW);   // this sets the intial state of the pin
  
  lcd.begin(2, 16);        // This sets the lcd to a two line, 16 char display
  lcd.clear();             // clear the display
  
}

void loop() {

  currentState = digitalRead(pirPin);    // read the pirpin and store the state 
  if (currentState!=previousState && currentState==LOW) {    // do comparison to see if we have a change or not
    digitalWrite(relayPin, LOW);    // alarm not tripped -  relaypin is low
  } else {
        Trip();                    //  alarm is tripped, relaypin goes high
    delay(20);                      // this is to debounce the input
    digitalWrite(relayPin, HIGH);    // turn the relay on
    delay(9000);                      // keep relay on and stop checking for low state for 9 seconds
previousState = currentState;        // set the previous state so we can compare on the next loop through
  }

 currentState=digitalRead(windowPin);      // Read the windowPin and store as currentstate
 if(currentState!=previousState && currentState==LOW){    // do comparisons to see if we have a change or not
   digitalWrite(strobePin,LOW);      // alarm is not tripped - strobe pin is low
}else{
 digitalWrite(strobePin,HIGH);      // alarm is tripped - strobe pin is high
    Trip();                        // alarm function to count alarm and display to lcd
   delay(25000);                  // keep strobe on for 25 seconds 
previousState = currentState;      // set the previous state so we can compare on the next loop through
 }

}

 void Trip(){            // tripped state function
   Tripped++;
  lcd.print("alarm tripped ");    //  Printed on default line on lcd
  lcd.setCursor(0,1);            // moves the cursor to the second line
  lcd.print(Tripped);            // prints on the second line.
  lcd.print(" Times!");
  lcd.home();                    // Returns cursor to first line.
 }

Hope that helps out tyler, seems to work pretty well on my side now.