Alarm Switch keeps triggering

Hello

Hoping for some ideas to help me with my alarm project. I have an Arduino controlling a 4 zone alarm. The Zone switches are connected as shown in the attached picture to digital pins which are all set to INPUT.

My problem is the zone keeps triggering every couple of hours. I expect this is something to do with the switch set up. If I remove the resistor and put a local link from ground to the zone pin it never triggers.

Have I set this up correct. should I increase the resistor size or the voltage supply.

Or should i change the set up to trigger on a HIGH input instead of a low input.

Snipped of the zone code is below

 readZone1 = (digitalRead(zone1)); // read Zones see what state the input is, LOW or HIGH
 readZone2 = (digitalRead(zone2));
 readZone3 = (digitalRead(zone3));
 readZone4 = (digitalRead(zone4));
 
 if (alarmActive == 1){
   if(readZone1 == HIGH){   // garage alarm always set when alarm set
     zoneTriggered = 1;
     lcd.clear();
     lcd.print("Enter Pin:");
     lcd.setCursor(0,1);
     lcd.print("Alarm Triggered");
     lcd.setCursor(0,3);
     lcd.print("Zone 1");
     alarmTriggered();
   }             
   if(readZone2 == HIGH && zoneSet > 1){     // Zone 2 front door and garage door with timer
    zoneCount ++;
    callDelay ();
        if (alarmActive == 1 && zoneCount > 1){
             zoneTriggered = 2;
             lcd.clear();
             lcd.print("Enter Pin:");
             lcd.setCursor(0,1);
             lcd.print("Alarm Triggered");
             lcd.setCursor(0,3);
             lcd.print("Zone 2");
             alarmTriggered(); 
           } 
   }
   if(readZone3 == HIGH  && zoneSet > 2){    
     zoneTriggered = 3; 
     lcd.clear();
     lcd.print("Enter Pin:");
     lcd.setCursor(0,1);
     lcd.print("Alarm Triggered");
     lcd.setCursor(0,3);
     lcd.print("Zone 3");
     alarmTriggered();
   }
  if(readZone4 == HIGH && zoneSet > 3){
     zoneTriggered = 4;
     lcd.clear();
     lcd.print("Enter Pin:");
     lcd.setCursor(0,1);
     lcd.print("Alarm Triggered");
     lcd.setCursor(0,3);
     lcd.print("Zone 4");
     alarmTriggered();
   }
  }
 }

zone set in the code is where i can set what zones are active. So far I only have zone 3 connected the rest are locally shorted out. Zone 3 is what keeps triggering. The door switch is about 8 meters from the arduino.

Any ideas on what i can do will be much appreciated

zone1.jpg

Or should i change the set up to trigger on a HIGH input instead of a low input.

From the picture it looks like you should trigger when the pin goes HIGH, ie the switch opens. Personally I would do away with the external resistor and use INPUT_PULLUP in the pinMode command to activate the internal pullup resistor.

Your right wrong wording. It currently is set to trigger on a HIGH input. Was wondering if I should have it set to trigger on LOW input with different resistor set up. Not sure this is what is causing the zone triggering by itself in the first place. Maybe it the length of run to the switch that is causing the failure. in which case i will need to increase the voltage. but by doing this I need to ensure I don't go over the arduino pin input levels.

I have read about using internal resistor pull up but never used this yet. I will have a go at this as it saves on connecting up the resistor network.

If the wires between the switches and the Arduino inputs are long, reducing the pullup resistance from 10K might help. Try 4.7K, but no lower than 1K.

cheers groundfungus didn't think of that. Will do some quick calculations, this might be the problem.

If I use the internal arduino pull up resistor will this still work on over 10 meter runs to switches.

The internal pullups are around 20K to 50K so that is the wrong way to go. For the wire long runs lower resistance (stronger pullup) is needed.

I would have thought that increasing the pull-up resistor would work better. Is it not the case that the resistance of the long wire is preventing the pin being pulled below V-Lo - I'm seeing this as a simple voltage divider.

If all else fails, you could change to an analogue read and compare this to a threshold value.
It's also quite likely that the long wires are picking up interference, and that's another problem all together.

Thanks Martin I agree this is a simple voltage divider. Maybe the switch and cable resistance are close to the pull down level and so I'm getting intermittent triggering.

Also interference could well be a problem didn't take this into account. May need to think about the swithes controlling a relay to then input into the arduino or a transistor network. only thing is more work then.

Like the idea of the Analogue input and measuring the input level. This will also mean I can use a Serial debugger to monitor it and see what fluctuations im getting.

So would you ever want to use an external pull up resistor when there are internal ones fitted? The answer is a yes, this is because the internal pull up resistors are only weak pull ups, that is the value is about 30K and it is not so strongly pulling up. This could be a cause of problems if you have a noisy environment or run long leads to the Arduino. In these situations a stronger external pull up resistor of say 3K or even 1K could reduce the circuits susceptibility to noise or interference.

From GrumpyMike's site.

I will have to try the lower resistor be believe it. I still believe that the pin has no problems going HIGH when the switch is open so therefore the pull up part is ok.

I will first try the lower resistor and higher one. If all fail then the analog idea sound a good solution

Trial and error - the best way to find out. I'm not convinced that GrumpyMike's logic applies here, that's fine for a normally open switch, but your normally closed set-up is creating a battle between pull-up and tie-down. Let me know which one wins !

I agree

Will be carrying out the experiments tomorrow will let you know how it all goes :smiley:

So carried out some testing today. removed the switch from the door and shorted the cables out. Thought this might be the problem as it was all ok (not triggering the alarm) until this afternoon when the alarm triggered 3 times. So its not the switch.

I tried using the Arduino internal resistors but this triggered all zones more often.

So went for the Analogue approach that Martin-x suggested. when running in serial monitor the zone 3 to the door with out the switch connected was reading from 0 to 100. So a lot of noise on the cables alone. (will try with the switch tomorrow and see if this noise is a lot bigger)

Maybe the noise on the cables are higher at night due to the amount of wifi devices switching on. This would explain why it was not triggering during the day.

so I've set it up so far that if the analog reading is greater than 900 then trigger the alarm. So far so good. will have to see if it triggers now over night.

If the problem is caused by interference then the false triggers will be fleeting in nature. If you code waits for the digital input to be high for a full second before triggering, it'll likely eliminate any spurious alarms caused by RF.

I did think of doing this and agree this would eliminate the problem. I could have easily put a delay in like the debounce delay.

However I need to be certain this is the problem. What I like about the analog reading of the switch is I can see exactly what is going on.

I will probable use the delay for the final project when I know it all works ok

steve8428:
I could have easily put a delay in like the debounce delay.

This wouldn't be the way to go. Because during a delay, you would be ignoring the input. So potentially you'd have a spurious high, ignore it for a second, then just happen to find a high again when you next sample it.

So you need to keep monitoring your input during that "delay"

Just off the top of my head, I'm thinking something like this

//one for each of your four zones
unsigned long lastLow[4];
byte sensorPin[4];

void setup()
{
unsigned long t=millis();
for (int n=0;n<4;n++)
  {
   pinMode(sensorPin[n], INPUT_PULLUP);
   lastLow[n]=t;
  }
  
}

void loop()
{
unsigned long t=millis();
bool currentState[4];

for (int n=0; n<4; n++)
  {
  currentState[n]=digitalRead(sensorPin[n]);
  if (currentState[n] == LOW)
    lastLow[n]=t;

  if ( ( t - lastLow[n]) > 1000)
    makeALoudNoise();
  }
}

WOW that was quick of the top of your head. I'm very new to this programming and don't quite understand all you've put down.

Thanks for the snippet I will have to go over this a few times to understand it propely

steve8428:
WOW that was quick of the top of your head. I'm very new to this programming and don't quite understand all you've put down.

Thanks for the snippet I will have to go over this a few times to understand it propely

What's happening (hopefully as I haven't tested it) is every time through the loop all four counters (lastLow) are being set to the current count of millis. This assumes that they are, indeed low.

If any of the sensors is HIGH, the respective counter doesn't get set. If it remains HIGH for a whole second, then eventually the time stored in it's counter is will be over 1000 milliseconds behind the current time. This triggers the loudNoise.

I like the sound of it, I will have to learn this properly to implement it into my code. its the best way forward by the look of it

Thanks