0

I am trying to develop a burglar alert system. I am using PIR sensor, Arduino Mega and SIM800L. I have connected PIR sensor to interrupt pin. Whenever motion is dected, a function corresponding to the interrupt will be called. In that function I am sending a SMS to notify with an alert message. If motion is detected 2 times, I will call the emergency contact number.

This is the code I have written.

#include <SoftwareSerial.h>
#define PIR1 2
#define SIREN 13
#define statusLED 12

SoftwareSerial SMS(11, 10);// rx(11-arduino) connect to tx(gsm module)
                         // tx(10-arduino) connect to rx(gsm module)

String CONTACT1 = "xxxxxxxxxx";  //mobile number


boolean status;
byte motionCtr = 0;
unsigned long latestMovementTime = 0;

void setup() {
  pinMode(PIR1,INPUT);
  pinMode(SIREN,OUTPUT);
  pinMode(statusLED,OUTPUT);

  Serial.begin(9600);
  SMS.begin(9600); 
  SMS.println("AT+CNMI=2,2,0,0,0");

  delay(5000);
  activateSystem(0);
}


void loop() {
  unsigned long currentTime = millis();
  //If motion is not dected for 5 minutes, turn off the siren.
  if(currentTime - latestMovementTime > 300000 && motionCtr>=1){
    stopSiren(0);  
  }
  delay(500);
}

void activateSystem(byte manual){
  delay(60000); //warm up time for PIR sensor
  attachInterrupt(0,motionDetected,RISING);

  status = true; 
  digitalWrite(statusLED,HIGH);

  if(manual){
    Serial.println("System ACTIVATED by SMS.");
    notifyBySMS("System ACTIVATED SMS.");
  }else{
    Serial.println("System ACTIVATED.");
    notifyBySMS("System ACTIVATED.");
  }
}

void deactivateSystem(byte manual){
  detachInterrupt(0);

  status = false;
  digitalWrite(statusLED,LOW);

  if(manual){
    Serial.println("System DEACTIVATED by SMS.");
    notifyBySMS("System DEACTIVATED SMS.");
  }else{
    Serial.println("System DEACTIVATED.");
    notifyBySMS("System DEACTIVATED.");
  }
}

void motionDetected(){
  startSiren("Motion at bedroom door.");
}


void startSiren(String msg){
  //Record the time of latest motion dected.
  latestMovementTime = millis();

  motionCtr++;
  Serial.print("Ctr="+motionCtr);
  Serial.println(msg);
  notifyBySMS(msg);

  //Start the siren only if motion is detected 2 times
  if(motionCtr==2){
    digitalWrite(SIREN,HIGH);  
    Serial.println("Siren STARTED.");
    notifyBySMS("Siren STARTED.");
    call(CONTACT1);
//    call(CONTACT2);
//    call(CONTACT3);
  }
}


void stopSiren(byte manual){
  motionCtr = 0;
  Serial.println("Ctr="+motionCtr);
  digitalWrite(SIREN,LOW);
  if(manual){
    Serial.println("Siren STOPPED manually.");
    notifyBySMS("Siren STOPPED manually.");
  }else{
    Serial.println("Siren STOPPED");
    notifyBySMS("Siren STOPPED.");
  }
}


void sendSMS(String mobileNumber, String msg){
  Serial.println("Sending SMS to "+mobileNumber);
  //AT command for text mode of gsm module 
  SMS.println("AT+CMGF=1"); 
  delay(100);  
  SMS.println("AT+CMGS=\""+mobileNumber+"\"\r"); 
  delay(100);
  // the text you want to send
  SMS.println(msg);
  delay(100);
  // ASCII code of CTRL+Z
  SMS.println((char)26);
  delay(5000);
  Serial.println("SMS sent to "+mobileNumber);
}

void call(String mobileNumber){
  Serial.println("Calling..."+mobileNumber);
  SMS.println("AT+CMGF=0"); //AT command for PDU mode of gsm module 
  SMS.println("ATD"+mobileNumber+";");
  delay(45000);
  SMS.println("ATH");
}


void notifyBySMS(String msg){
  sendSMS(CONTACT1,msg);
  delay(1000);
//  sendSMS(CONTACT2,msg);
//  delay(1000);
//  sendSMS(CONTACT3,msg);
//  delay(1000);
}

I am receiving the SMS from setup(). But I am not receiving the SMS that I have sent from interrupt routine. Also I am receiving the call only sometime, it is random. I guess this is because I am using delay() in interrupt routine.

How can I implement such logic without delay().

  • 1
    Never use Serial in an interrupt! – Majenko Jul 3 '18 at 14:59
  • 1
    Serial and delay() both require interrupts in order to work right, but within an ISR, interrupts are already disabled. – jose can u c Jul 3 '18 at 15:20
  • Have the interrupt set a flag (boolean variable). Then in the loop, check that flag, do your actions and reset the flag. Using delay, serial, and softwareserial inside the ISR is not adviced. – Gerben Jul 3 '18 at 15:30
1

As mentioned in the comments Serial won't work in an ISR. Generally, you should do as little as possible in an ISR. Often an ISR will just set a flag to be handled in loop()

You will then need to refactor loop() to handle the flag set in the ISR. A common method is to use a finite state machine.

  • don't forget to declare the flag volatile! – esoterik Aug 2 '18 at 19:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.