Невозможно отправить SMS из процедуры прерывания

Я пытаюсь разработать систему оповещения о взломе. Я использую датчик PIR, Arduino Mega и SIM800L. Я подключил датчик PIR к контакту прерывания. Всякий раз, когда обнаруживается движение, будет вызываться функция, соответствующая прерыванию. В этой функции я отправляю SMS для уведомления с тревожным сообщением. Если движение обнаруживается 2 раза, я позвоню на номер экстренного вызова.

Это код, который я написал.

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

SoftwareSerial SMS(11, 10);// rx(11-arduino) подключиться к tx(модуль gsm)
                         // tx(10-arduino) подключаемся к rx(модулю gsm)

String CONTACT1 = "xxxxxxxxxx";  //номер мобильного телефона


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();
  //Если движение не обнаружено в течение 5 минут, выключить сирену.
  if(currentTime - latestMovementTime > 300000 && motionCtr>=1){
    stopSiren(0);  
  }
  delay(500);
}

void activateSystem(byte manual){
  delay(60000); //время прогрева PIR-датчика
  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){
  //Запишите время последнего обнаруженного движения.
  latestMovementTime = millis();

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

  //Включить сирену только если движение обнаружено 2 раза
  if(motionCtr==2){
    digitalWrite(SIREN,HIGH);  
    Serial.println("Siren STARTED.");
    notifyBySMS("Siren STARTED.");
    call(CONTACT1);
// вызов(CONTACT2);
// вызов(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-команда для текстового режима модуля gsm
  SMS.println("AT+CMGF=1"); 
  delay(100);  
  SMS.println("AT+CMGS=\""+mobileNumber+"\"\r"); 
  delay(100);
  // текст, который вы хотите отправить
  SMS.println(msg);
  delay(100);
  // ASCII-код 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-команда для режима PDU модуля gsm
  SMS.println("ATD"+mobileNumber+";");
  delay(45000);
  SMS.println("ATH");
}


void notifyBySMS(String msg){
  sendSMS(CONTACT1,msg);
  delay(1000);
// отправитьSMS(CONTACT2,msg);
// задержка(1000);
// отправитьSMS(CONTACT3,msg);
// задержка(1000);
}

Я получаю SMS от setup(). Но я не получаю SMS, которое я отправил из процедуры прерывания. Также я получаю вызов только иногда, это происходит случайно. Я предполагаю, что это потому, что я использую delay() в процедуре прерывания.

Как реализовать такую логику без delay().

, 👍0

Обсуждение

Никогда не используйте Serial в прерывании!, @Majenko

Для корректной работы Serial и delay() требуются прерывания, но в ISR прерывания уже отключены., @jose can u c

Прерывание устанавливает флаг (булева переменная). Затем в цикле проверяйте этот флаг, выполняйте действия и сбрасывайте флаг. Использование delay, serial и softwareserial внутри ISR не рекомендуется., @Gerben