0

I am still struggling to get this sketch functional. The problem seems to lie with the interrupts, and relying on them to turn on and off the PIRtrigger when needed. Everything else seems to be OK. This is a slightly modified sketch from what I had uploaded earlier, with some changes that I thought would fix the problem. In general, a "correct" PIN disables the alarm from firing as it sets the "away" flag to "false", which works. An "incorrect" PIN sets "away" to "true" which, when a trigger is activated via an Interrupt, sounds the alarm. The program should then go to readKeypad for further function, which it appears to do. The following shows the result after an incorrect PIN:

Key_input[0] = #
@ checkPIN 
@ incorrect PIN 
away=1 PIRtrigger=0
at Alarm
after alarm

The trigger then doesn't seem to get activated. Can anyone HELP!? Thanks.

///////////////////////// initialize & includes //////////////////////////
#include "SIM900.h"
#include "sms.h"
#include "Keypad.h"
#include <GSM.h>
SMSGSM sms;
//To change pins for Software Serial, use the two lines in GSM.cpp.
int PIR_SensorPin = 2;
int LED_OutPin = 11; //green
int Alarm_OutPin = 12; //red
int alarm_count;
volatile boolean PIRtrigger = false;
boolean away = false;
const byte interruptPin = 2;
int z = 0;
int i = 0;
int timeout = 10000;
unsigned long time = millis();
//////////////////////////// setup keyPad //////////////////////////
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
char keys[ROWS][COLS] =
{
 {
 '1', '2', '3', 'A'
 }
 ,
 {
 '4', '5', '6', 'B'
 }
 ,
 {
 '7', '8', '9', 'C'
 }
 ,
 {
 '*', '0', '#', 'D'
 }
};
byte rowPins[ROWS] = {
 6, 7, A2, A3 // row pin# on keypad to Arduino pin#, ie Row Pin #1 goes to Arduino Pin #6, etc.
}; // connect to the row pinouts of the keypad
byte colPins[COLS] = {
 3, A0, A1, A4
}; // connect to the column pinouts of the keypad
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS );
const char PIN[5] = {
 '9', '6', '7', '9', '#'
}; // PIN number
char key_input[5] = {
 0, 0, 0, 0, 0
}; // used for comparison
//////////////////////////////// setup ///////////////////////////////////
void setup() {
 Serial.begin (9600); // Establish Serial connection;
 pinMode (LED_OutPin, OUTPUT); // Set pinMode.
 pinMode (Alarm_OutPin, OUTPUT); // Set pinMode.
 pinMode (PIR_SensorPin, INPUT); // Set pinMode.
 digitalWrite (LED_OutPin, LOW); // Set output pins to LOW for start.
 digitalWrite (Alarm_OutPin, LOW); // Set output pins to LOW for start.
 digitalWrite (PIR_SensorPin, LOW);
 Serial.println ("Studio Alarm starting up."); // Serial message that GSM shield is starting up
 if (gsm.begin(4800)) { // Set GSM shield to recommended 4800 baud rate.
 Serial.println ("Status = Network READY");
 digitalWrite (LED_OutPin, HIGH);
 }
 attachInterrupt (digitalPinToInterrupt (2), trigger, HIGH); // PIR as interrupt
 Serial.println ("System Ready");
}
//////////////////////////////// void loop ///////////////////////////////////
void loop()
{
 interrupts();
 readKeypad(); Serial.println ("at keypad");
 alarm();
}
////////////////////////// void trigger ///////////////////////////////////
void trigger() {
 PIRtrigger = true;
 // alarm();
}
///////////////////////////// void alarm ///////////////////////////////////
void alarm() {
// PIRtrigger = false;
 time = millis(); // reset time.
 interrupts();
 Serial.print ("away="); Serial.print (away); Serial.print (" "); Serial.print ("PIRtrigger="); Serial.println (PIRtrigger);
 Serial.println ("at Alarm");
 if (away == true && PIRtrigger == true) {
 // (sms.SendSMS("**********", "***Motion Detected in Studio!***"));
 Serial.println ("MOTION detected: SMS Sent");
 for (alarm_count = 0; alarm_count <= 5; alarm_count++) { // Cycle outputs if triggered
 digitalWrite (Alarm_OutPin, HIGH); delay (1000); // On/Off/On/Off/Off
 digitalWrite (Alarm_OutPin, LOW); delay (500);
 digitalWrite (LED_OutPin, HIGH); // delay (1000);
 Serial.println (alarm_count);
 }
 }
 PIRtrigger = false;
 // away = false;
 Serial.println ("after alarm");
 Serial.print ("away="); Serial.print (away); Serial.print (" "); Serial.print ("PIRtrigger="); Serial.println (PIRtrigger);
 noInterrupts(); /////////////////////////////////
 readKeypad();
}
///////////////////////////// read Keypad ///////////////////////////////////
void readKeypad() {
 char key = keypad.getKey();
 if (key != NO_KEY) { // if a keypad input
 key_input[z] = key;
 tone(10, 900, 100);
 Serial.print ("Key_input["); Serial.print(z); Serial.print ("] = "); Serial.println(key);
 z++;
 if (z >= sizeof(key_input)) {
 z = 0;
 }
 switch (key) {
 case '*': // resets key_inputs to "0"
 z = 0;
 break;
 case '#': // pressed to "enter"
 z = 0;
 for ( i = 0; i < 4 ; i++ ) {
 // Serial.print(key_input[i]);
 }
 // Serial.println ("-------");
 delay(100); // for extra de-bounce
 checkPIN();
 break;
 }
 }
}
///////////////////////////// check PIN ///////////////////////////////////
void checkPIN() {
 Serial.println ("@ checkPIN ");
 int correct = 0;
 int i;
 for ( i = 0; i < (sizeof(PIN) - 1) ; i++ ) {
 if (key_input[i] == PIN[i]) {
 correct++;
 }
 }
 if (correct >= sizeof(PIN) - 1) {
 // Serial.print ("# correct = "); Serial.println (correct); Serial.println (sizeof(PIN) - 1);
 correctPIN();// go to correct PIN instructions
 }
 else {
 incorrectPIN(); // go to incorrect PIN instructions
 }
}
///////////////////////////// correct PIN ///////////////////////////////////
void correctPIN() { // do this if correct PIN entered
 Serial.println ("@ correct PIN ");
 // digitalWrite (LED_OutPin, HIGH);
 digitalWrite (LED_OutPin, LOW); // on-board LED to show the status of alarm
 PIRtrigger = false; // turn the PIR state to off
 away = false; // turn the away state to off
 noInterrupts();
 readKeypad();
}
///////////////////////// incorrect PIN ///////////////////////////////////
void incorrectPIN() { // do this if incorrect PIN entered
 // noInterrupts(); // Serial.println ("interrupt off 1");
 Serial.println ("@ incorrect PIN ");
 away = true;
 digitalWrite (LED_OutPin, HIGH); // tied to Alarm output level
 //Has time passed? delay(timeout) - allow time to leave premises
 PIRtrigger = false;
 alarm();
 }
KIIV
4,9071 gold badge14 silver badges21 bronze badges
asked Mar 12, 2017 at 21:11

2 Answers 2

1

First, as AH L said, there is no HIGH interrupt on a Uno. Looking at Arduino.h we see:

#define HIGH 0x1
#define LOW 0x0
...
#define CHANGE 1
#define FALLING 2
#define RISING 3

Thus your HIGH interrupt (which doesn't exist) is really a CHANGE interrupt.

Next, you seem to be recursively calling stuff.

  • loop calls readKeypad.
  • readKeypad calls checkPIN
  • checkPIN calls correctPIN
  • correctPIN calls readKeypad

So this code is digging itself deeper and deeper into function calls. It will eventually run out of stack.

i.e.

readKeypad -> checkPIN -> correctPIN -> readKeypad -> checkPIN ...

You need to restructure.

See my page about interrupts.

Also see my page about state machines.

answered Mar 13, 2017 at 6:02
4
  • I know that it is ugly code; from repeatedly making changes/additions to try to get it to work. I have cleaned up some and will continue on others. Thanks for your feedback. I wasn't thinking about a stack issue. Commented Mar 13, 2017 at 10:47
  • How do I better manage the stack? Commented Mar 13, 2017 at 11:36
  • Don't do recursive calls. For example don't have a call b and inside b call a. Read the link I gave about state machines. Commented Mar 13, 2017 at 23:06
  • Thanks. I plan to try state machines in the very near future. Commented Mar 13, 2017 at 23:08
0

Most Arduinos don't support interrupting when a pin is HIGH. Try changing attachInterrupt (digitalPinToInterrupt (2), trigger, HIGH) to attachInterrupt (digitalPinToInterrupt (2), trigger, RISING).

answered Mar 13, 2017 at 5:28
1
  • Thanks. I had tried CHANGE and HIGH with same results. I will try RISING to see what happens. Commented Mar 13, 2017 at 10:40

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.