GSM сигнализация M590+Arduino

b707
Offline
Зарегистрирован: 26.05.2017

замучились с модемом М590 и новый модем А6 тоже не работает? -если читаете тем же кодом, что в сообщении #165 - не удивительно.  Код чтения СМС весьма бредовый

 if (mySerial.available()) {          // есть данные от GSM модуля.
    delay(200);                        // выждем, чтобы строка успела попасть в порт целиком.
    while (mySerial.available()) {     // сохраняем входную строку в переменную val.
      ch = mySerial.read();
      val += char(ch);
      delay(50);
    }

Обьясните, зачем нужны задержки? Первая слишком велика -  буфер SoftwareSerial всего 64 байта. пока вы будете ждать 200мс, есть шанс что он переполнится.  Вторая задержка еще нелепей - 50 мс ПОСЛЕ КАЖДОГО СИМВОЛА! Если у вас типичная СМС вместе с технической информацией 200 символов - вы будете читать ее 10 секунд! Да у вас половина данных должна теряться при таком темпе работы сериала.- что, собственно, у вас и происходит.

pasha413
Offline
Зарегистрирован: 27.11.2016

Задержки вообще удалять? Этот код чтения не раз уже попадался в интернете, ничего другого не знаю. Есть другой вариант?

b707
Offline
Зарегистрирован: 26.05.2017

pasha413 пишет:
Задержки вообще удалять? Этот код чтения не раз уже попадался в интернете, ничего другого не знаю. Есть другой вариант?

Кодов чтения СМС в инете полно. С такими задержками не видел. Для примера посмотрите любую библиотеку для любого GSM-модема - код чтения СМС практически одинаков у любого модема.

Первую задержку можете оставить, но я бы снизил до 20-50мс. Больше не имеет смысла - у вас буфер приема 64 байта. посчитайте, за сколько он заполнится при скорости 9600. Вторую надо убрать ОБЯЗАТЕЛЬНО. Или, хотя бы - поставить минимальную, 2-3 (не более 5) мс.

А вообще, вам на будущее. То, что в вашем коде вы ждете фиксированное время, чтобы от модема пришла полная строка - гнилая на корню идея. Инфа из модема может приходить с перерывами, а может выплевываться по несколько сообщений разом.  Надо читать и разбирать то, что пришло - и если пришло не все, ждать, пока из модема придет остальное. Опять же, примеров полно в любой подобной библиотеке.

ЗЫ собираю свой микропроект на модеме А6, если будут вопросы по этому модему - спрашивайте

pasha413
Offline
Зарегистрирован: 27.11.2016

b707, спасибо, в выходные займусь проектом.

pasha413
Offline
Зарегистрирован: 27.11.2016

как проверить баланс на А6? никак не получается. на команду "ATD#105#;"   (теле2) выдает  +CME ERROR:500

на команду AT+CUSD=1,"*101#",15  приходит ответ  

+CUSD: 2, "⸮!5H}.A0W⸮⸮" ,1
 
pasha413
Offline
Зарегистрирован: 27.11.2016

на модеме А6mini работает.

добавление/удаление номера отрабатывает. смс проверял не все, не разобрался с запросом баланса. если кто знает как, подскажите.

#include <EEPROM.h> 
#include<SoftwareSerial.h>
SoftwareSerial mySerial(2, 3);

#define DOOR 4                              // концевик двери.
#define PIR 6                               // датчик движения.
#define GAS A0                              // датчик дыма.
#define BUZ 11                              // сирена.
#define Led 12                              // состояние системы, моргает - норма.

// DOOR     - если сработал, на входе "+" HIGH.
// PIR      - если сработал, на входе "+" HIGH.
// GAS      - если сработал, на входе "+" HIGH.
// BUZ      - если "-" LOW, то горит. 
// Led     - если "-" LOW, то горит.

int8_t Guard = 0;          // 1. охрана:                         1 - вкл, 0 - выкл.
int8_t AlarmRING = 1;      // 2. вызов:                          1 - вкл, 0 - выкл.
int8_t SendSMS = 1;        // 3. отправка смс:                   1 - вкл, 0 - выкл.
int8_t DOORon = 1;         // 4. контроль концевиков дверей:     1 - вкл, 0 - выкл.    
int8_t PIRon = 1;          // 5. контроль датчика движения:      1 - вкл, 0 - выкл.
int8_t GASon = 1;          // 6. контроль датчика дыма:          1 - вкл, 0 - выкл.

int8_t DOORFlag = 1;       
int8_t PIRFlag = 1;
int8_t GASFlag = 1;
int8_t DOORState = LOW;    // Состояние концевика двери.
int8_t PIRState = LOW;     // Состояние датчика движения.
int8_t LedState = HIGH;    // Состояние светодиода.

int8_t Firststart;         // первый старт.
uint8_t PIRcount = 3;      // Кол-во срабатываний PIR - 3 до тревоги.
uint32_t msAT = 0;

char Bal[4] = "";          // для временного хранения номера баланса   
char Phone[12] = "";       // для временного хранения номера телефона      
byte Adress[5] = {25, 40, 55, 70, 85}; //занимаем ячейки для пяти номеров.

String val = "";          // переменная для хранения данных   
String LastEvent = "";    // полное состояние системы.
String RingPhone = "";    // номер звонившего.
String AlarmPhone[5];     // номера для постановки/снятии с охраны и отправки смс.

int GASThres = 400;          // предельная концентрация газа
uint8_t PIRDetectCount = 0;  // обнуление счетчика PIR датчика.
uint8_t AlarmInterval = 10;  // Секунд до отключения "тревожного" пина.
uint8_t interval = 100;      // для мигания BLed
uint16_t previousMillis = 0;
uint16_t previousAlarmMillis = 0;

/* EEPROM Data:
  № ячейки - значение;
  0 - если записана не 1, то необходимо затереть часть памяти eeprom'a и восстановить стандартную конфигурацию.
  1 - Guard = 0;       // охрана:                         1 - вкл, 0 - выкл.
  2 - AlarmRING = 1;   // звонок:                         1 - вкл, 0 - выкл. 
  3 - SendSMS = 1;     // отправка смс:                   1 - вкл, 0 - выкл.
  4 - DOORon = 1;      // концевик двери:                 1 - вкл, 0 - выкл.
  5 - PIRon = 1;       // датчик движения:                1 - вкл, 0 - выкл.
  6 - GASon = 1;       // датчик дыма:                    1 - вкл, 0 - выкл.
  7 - PIRcount = 3;    // количество срабатываний датчика = 3.
  10 - Firststars = 1; // первый запуск = 1;
  20 - ячейка памяти баланса,
  25, 40, 55, 70, 85 - ячейки памяти телефонов.
*/

void setup() {
    Serial.begin(9600);
  pinMode(DOOR, INPUT_PULLUP);
  pinMode(PIR, INPUT);
  pinMode(GAS, INPUT);
  pinMode(BUZ, OUTPUT);
  pinMode(Led, OUTPUT);
   digitalWrite(BUZ, HIGH);
  InitModem();
  eepromconfig();
   digitalWrite(Led, HIGH);
}

void loop() {
  LED();
  AlarmPinOff();
  Detect();
    if (val.indexOf(F("+PBREADY")) > -1) InitModem();// если модем перезапустился запускаем инициализацию.
    if (mySerial.available()) {          // есть данные от GSM модуля.
    while (mySerial.available()) {       // сохраняем входную строку в переменную val.
      char ch = mySerial.read();
      val += char(ch);                   //собираем принятые символы в строку
      delay(3);
    } 
    if (val.indexOf(F("+CLIP")) > -1) {               // если обнаружен вызов.
  Serial.println(F("Process RING"));                              
      mySerial.println(F("ATH"));                    // сбрасываем вызов.
      if (CheckPhone() == 1) {                       // проверяем номер, если наш.
  Serial.println(F("Master Ring OK!"));
  MasterRing();                      
      } else  Serial.println(F("No Master Ring!"));  
    } else if (val.indexOf(F("+CMT")) > -1) {        //если обнаруженa СМС
  Serial.println(F("Process CMT"));                            
        if (CheckPhone() == 1) {                     //если СМС от хозяина
  Serial.println(F("Master SMS OK!"));
  MasterSMS();
        } else  Serial.println(F("No Master SMS!"));
      } else if (val.indexOf(F("+CUSD")) > -1) { 
  Serial.println(F("Process CUSD"));                            
  Serial.println(val);                            
      val = String(val.substring(val.indexOf(",") + 2,val.indexOf("?")) + String(F("\n"))); 
  Serial.println("Bal" + val);
//  sms(String(val), String("+" + RingPhone));
        } val = ""; 
  }  if (Serial.available()) { 
    while (Serial.available()) { 
      char ch = Serial.read();
      val += char(ch);
      delay(3);
    } 
    ConsolePrint();
    val = "";  
  }
}

int CheckPhone() {        /// === проверка телефона === ///
  if (Firststart == 0) {                         // если не первый старт
  RingPhone = "";  // обнуляем именно здесь, т.к. он нужен в коде. сейчас обновится
    for (int i = 0; i < 5; i++) {
       if (val.indexOf(AlarmPhone[i]) > -1 && val.indexOf(AlarmPhone[i]) != 0) {     // если есть вызов, и он наш
         RingPhone = AlarmPhone[i]; // запоминаем его.
  Serial.println(String(F("RingPhone ")) + RingPhone);          
         return 1;
      } 
    } 
      return 0; 
  } else if (Firststart == 1) {                  // иначе (если первый старт)
      int ind = val.indexOf("+CLIP:") + 8;       // обрезаем номер 
      String num = val.substring(ind, ind + 11);
      num.toCharArray(Phone, 12);
      EEPROM.put(25, Phone);                     // пишем номер в EEPROM
      AlarmPhone[0] = Phone;                     // запишем
      EEPROM.update(10, 0);                      // обновляем Firststart
      Firststart = 0;                            // пишем 0
  Serial.println(String(F("Master0:")) + AlarmPhone[0]); 
  Serial.println(String(F("Firststart:")) + Firststart);
//  sms(("Master0:" + num + " Ok"), String("+" + num)); // смс на звонивший
      Phone[12] = "";
    }   
}

void eepromconfig() {
    pinMode(13, OUTPUT);
    if (EEPROM.read(0) != 1) {          // если записана не 1
      for (int i = 0 ; i < 512 ; i++) {  // переписываем все ячейки
        EEPROM.write(i, 0);
      }                      // и записываем:
      EEPROM.update(1, 0);   // Guard       охрана выкл.
      EEPROM.update(2, 1);   // AlarmRING   вызов вкл.
      EEPROM.update(3, 1);   // SendSMS     смс вкл.
      EEPROM.update(4, 1);   // DOORon      датчики дверей вкл.
      EEPROM.update(5, 1);   // PIRon       датчик движения вкл.
      EEPROM.update(6, 1);   // GASon       датчик газа вкл.
      EEPROM.update(7, 3);   // PIRcount.   3 повторных срабатывания.
      EEPROM.update(10, 1);  // Firststart  первый старт!.
      EEPROM.update(20, 0);  // баланс, записываем массив в EEPROM 
      EEPROM.update(0, 1);   // 
      digitalWrite(13, HIGH);
       for (int i = 0; i < 5 ; i++) {
         EEPROM.put(Adress[i], 0);    // стираем все номера из EEPROM
      } 
  Serial.println(F("EEPROM != 1/ RESET!")); 
}
    if (EEPROM.read(0) == 1) {
      Guard      = EEPROM.read(1);   //
      AlarmRING  = EEPROM.read(2);   //
      SendSMS    = EEPROM.read(3);   //
      DOORon     = EEPROM.read(4);   //
      PIRon      = EEPROM.read(5);   //
      GASon      = EEPROM.read(6);   //
      PIRcount   = EEPROM.read(7);   //
      Firststart = EEPROM.read(10);  //
  Masterphone();    
    }
   String SIGN = "";                         // текущее состояние системы.
   String RING = "";                           // текущее состояние вызов.
   String SMS = "";                            // текущее состояние смс.
   String Pir = "";                            // текущее состояние PIR.
   String Door = "";                           // текущее состояние двери.
   String Gas = "";                           // текущее состояние двери.
    if (Guard == 1) SIGN = String(F("System -> on;\n"));
    if (Guard == 0) SIGN = String(F("System -> off;\n"));
    if (AlarmRING == 1) RING = String(F("Ring -> on;\n"));
    if (AlarmRING == 0) RING = String(F("Ring -> off;\n"));
    if (SendSMS == 1) SMS = String(F("SMS -> on;\n"));
    if (SendSMS == 0) SMS = String(F("SMS -> off;\n"));
    if (PIRon == 1) Pir = String(F("Pir -> on;\n"));
    if (PIRon == 0) Pir = String(F("Pir -> off;\n"));
    if (DOORon == 1) Door = String(F("Door -> on;\n"));
    if (DOORon == 0) Door = String(F("Door -> off;\n"));
    if (GASon == 1) Gas = String(F("Gas -> on;\n"));
    if (GASon == 0) Gas = String(F("Gas -> off;\n"));
    String System = SIGN + RING + SMS;
    String Sensors = Pir + Door + Gas;
    LastEvent = System + Sensors;
  Serial.println(LastEvent);  
}

void Detect() {           /// === чтение датчиков === ///
  DOORState = digitalRead(DOOR);
  PIRState = digitalRead(PIR);
  int Smoky = analogRead(GAS);
  
  if (DOORState == HIGH && DOORFlag == 0 && DOORon == 1) { // датчик сработал
    DOORFlag = 1;
  Serial.println("Dver' otkrita!");
        Alarm(); 
  }
  if (DOORState == LOW && DOORFlag == 1)  {         // Датчик успокоился
    DOORFlag = 0;
  }
  if (PIRState == HIGH && PIRon == 1)             { // датчик сработал
    if (PIRDetectCount == 0) {                      // если первый раз
      PIRDetectCount == 1;
  Serial.println(PIRDetectCount);
      digitalWrite(BUZ, LOW);                       // включаем сирену/предупреждаем
      delay(250);
      digitalWrite(BUZ, HIGH);
    }
    if (PIRDetectCount == 1) {                      // если второй раз
      PIRDetectCount == 2; 
  Serial.println(PIRDetectCount);
      digitalWrite(BUZ, LOW);                       // включаем сирену/отпугиваем
      delay(500);
      digitalWrite(BUZ, HIGH);
    }
    if (PIRDetectCount == 2) {                      //если третий раз
      PIRFlag = 1;
      PIRDetectCount == 0;
  Serial.println(PIRDetectCount);
  Serial.println(String(F("Dvizenie y dveri!")));
      Alarm();                                      // включаем сирену сигнализация!
      digitalWrite(13, HIGH);
    }
  }
  if (PIRState == LOW && PIRFlag == 1)            { // Датчик успокоился
    PIRFlag = 0;
    digitalWrite(13, LOW);
  }
/*  if (Smoky > GASThres && GASFlag == 0 && GASon == 1)   { // датчик сработал
      GASFlag = 1;
  Serial.println(F("Srabotal datchik gasa!"));
      Alarm();
  } 
  if (Smoky < GASThres && GASFlag == 1)           { // Датчик успокоился
      GASFlag = 0; 
  }*/
}

void Alarm() {
  if (Guard == 1) {
    previousAlarmMillis = millis();
    digitalWrite(BUZ, LOW);
  Serial.println(F("Alarm!!!"));  
    if (SendSMS == 1) {
      for (int i = 0; i < 5; i++) {
        if (DOORFlag == 1 && AlarmPhone[i] != 0) {
//  sms(String(Dver' otkrita!"), String("+" + String(AlarmPhone[i]))); // смс на все номера
        }
        if (PIRFlag == 1 && AlarmPhone[i] != 0) {
//  sms(String("Dvizhenie y dveri!"), String("+" + String(AlarmPhone[i]))); // смс на все номера
        }
        if (GASFlag == 1 && AlarmPhone[i] != 0) {
//  sms(String("Srabotal datchik gasa!"), String("+" + String(AlarmPhone[i]))); // смс на все номера
        }
//        delay(1000);
      }
    }
    if (AlarmRING == 1) {
      mySerial.println("ATD+" + String(AlarmPhone[0]) + ";"); // звоним первому номеру
//      delay(1000);  // ????? не решил дождаться отбоя или положить трубку.
    }
  }
}

void AlarmPinOff() {      
  uint16_t currentAlarmMillis = millis();
  if (currentAlarmMillis - previousAlarmMillis > AlarmInterval * 1000) {
    digitalWrite(BUZ, HIGH);
  }
}

void MasterRing() {
  if (Guard == 1) GuardOff();
  else if (Guard == 0) GuardOn();
}

void GuardOff() {
    Guard = 0;
    EEPROM.update(1, Guard);
  Serial.println(String(F("System -> off. Ring:")) + RingPhone);
  for (int i = 0; i < 5; i++) {
     if (AlarmPhone != 0) {
//  sms(String("System -> off"), String("+" + AlarmPhone[i])); // смс на все номера
     }
  }
}

void GuardOn() {         
    Guard = 1;
    EEPROM.update(1, Guard);
  Serial.println(String(F("System -> on. Ring:")) + RingPhone);
  for (int i = 0; i < 5; i++) {
     if (AlarmPhone != 0) {
//  sms(String("System -> on"), String("+" + AlarmPhone[i])); // смс на все номера
     }
  }
}

void LED() {              /// === состояние светодиодов === ///
  if (Guard == 0) {                   // если снят с охраны
    digitalWrite(Led, HIGH);          // светодиод не горит
  }
  if (Guard == 1) {                   // если на охране
  uint16_t currentMillis = millis();  // светодиод моргает
  //проверяем не прошел ли нужный интервал, если прошел то
    if (currentMillis - previousMillis > interval) {
      // сохраняем время последнего переключения
      previousMillis = currentMillis;
      // если светодиод не горит, то зажигаем, и наоборот
      if (LedState == HIGH) LedState = LOW;
      else LedState = HIGH;
      digitalWrite(Led, LedState);
    }
  }
}

void ConsolePrint() {
    val.toLowerCase();
  if (val.indexOf(F("master")) > -1)  { // добавление мастер-номера
      master(val.substring(6, 7).toInt(), val.substring(8, 19));
// sms типа: " master1:79111386232 " - номер в ячейку "1", куда записать номер
  }
  if (val.indexOf(F("balance:")) > -1) { // добавление номера баланса
      balnum(val.substring(8, 13));
// sms типа: " balance:100 " - номер баланса
  }
  if (val.indexOf(F("dell:")) > -1) { // удаление номера из ячейки     
      dellphone(val.substring(5, 6).toInt());
// sms типа: " dell:1 " - удалить номер из ячейки 1
  }
  if (val.indexOf(F("reset")) > -1)    { // сброс ЕЕПРОМ
  Serial.println(F("Reset System!"));  
       EEPROM.write(0, 0);
  eepromconfig();
  }
  if (val.indexOf(F("info")) > -1)     { // инфо о состоянии системы
  eepromconfig();
  }
  if (val.indexOf(F("money")) > -1)    { // запрос баланса
    balance();
  }
  if (val.indexOf(F("guardon")) > -1)  { // вкл сигнализации
    GuardOn();
  }
  if (val.indexOf(F("guardoff")) > -1) { // выкл сигнализации
    GuardOff();
  }
  if (val.indexOf(F("ringon")) > -1)   { // вкл вызов при сработке
    AlarmRING = 1;
    EEPROM.update(2, AlarmRING);
  Serial.println(F("Ring -> on"));      
//  sms(String("Ring -> on"), String("+" + RingPhone)); // смс на последний номер
  }
  if (val.indexOf(F("ringoff")) > -1)  { // выкл вызов при сработке
    AlarmRING = 0;
    EEPROM.update(2, AlarmRING);
  Serial.println(F("Ring -> off"));  
//  sms(String("Ring -> off"), String("+" + RingPhone)); // смс на последний номер
  }
  if (val.indexOf(F("smson")) > -1)    { // вкл смс при сработке
    SendSMS = 1;
    EEPROM.update(3, SendSMS);
  Serial.println(F("SMS -> on"));  
//  sms(String("SMS -> on"), String("+" + RingPhone)); // смс на последний номер
  }
  if (val.indexOf(F("smsoff")) > -1)   { // выкл смс при сработке
    SendSMS = 0;
    EEPROM.update(3, SendSMS);
  Serial.println(F("SMS -> off"));  
//  sms(String("SMS -> off"), String("+" + RingPhone)); // смс на последний номер
  }
}

void MasterSMS() {        /// === мастер смс === ///
    val.toLowerCase();
  if (val.indexOf(F("master")) > -1)  { // добавление мастер-номера
     int tel(val.indexOf(F("master")));
      master(val.substring(tel + 6, tel + 7).toInt(), val.substring(tel + 8, tel + 19));
///// sms типа: " master1:79111234567 " - ячейка + номер
  }
  if (val.indexOf(F("balance:")) > -1) { // добавление номера баланса
      int bal(val.indexOf(F("balance:")));
      balnum(val.substring(bal + 8, bal + 11));
///// sms типа: " balance:100 " - номер
  }
  if (val.indexOf(F("dell:")) > -1) { // удаление номера из ячейки     
     int del(val.indexOf(F("dell:")));
      dellphone(val.substring(del + 5, del + 6).toInt());
///// sms типа: " dell:1 " - удалить номер из ячейки 1
  }
  if (val.indexOf(F("phone")) > -1)     { // инфо о состоянии системы
  Masterphone();
  }
  if (val.indexOf(F("reset")) > -1)    { // полный сброс ЕЕПРОМ
//  sms(String("Reset system Ok!"), String("+" + RingPhone)); // смс на последний номер
  Serial.println(String(F("Reset System Ok!")) + RingPhone);          
       EEPROM.write(0, 0);
  eepromconfig();
  }
  if (val.indexOf(F("info")) > -1)     { // инфо о состоянии системы
  eepromconfig();
  Serial.println("SMS " + RingPhone);  
//  sms(String(LastEvent), String("+" + RingPhone)); // смс на последний номер
  }
  if (val.indexOf(F("money")) > -1)    { // запрос баланса
    balance();
  }
  if (val.indexOf(F("guardon")) > -1)  { // вкл сигнализации
    GuardOn();
  }
  if (val.indexOf(F("guardoff")) > -1) { // выкл сигнализации
    GuardOff();
  }
  if (val.indexOf(F("ringon")) > -1)   { // вкл вызов при сработке
    AlarmRING = 1;
    EEPROM.update(2, AlarmRING);
  Serial.println(F("AlarmRing -> on"));      
//  sms(String("Ring -> on"), String("+" + RingPhone)); // смс на последний номер
  }
  if (val.indexOf(F("ringoff")) > -1)  { // выкл вызов при сработке
    AlarmRING = 0;
    EEPROM.update(2, AlarmRING);
  Serial.println(F("AlarmRing -> off"));  
//  sms(String("Ring -> off"), String("+" + RingPhone)); // смс на последний номер
  }
  if (val.indexOf(F("smson")) > -1)    { // вкл смс при сработке
    SendSMS = 1;
    EEPROM.update(3, SendSMS);
  Serial.println(F("SendSMS -> on"));  
//  sms(String("SMS -> on"), String("+" + RingPhone)); // смс на последний номер
  }
  if (val.indexOf(F("smsoff")) > -1)   { // выкл смс при сработке
    SendSMS = 0;
    EEPROM.update(3, SendSMS);
  Serial.println(F("SendSMS -> off"));  
//  sms(String("SMS -> off"), String("+" + RingPhone)); // смс на последний номер
  }
}

void balance() {          /// === проверка баланса сим-карты === ///
  EEPROM.get(20, Bal);        // считываем массив символов
  mySerial.println("AT+CUSD=1");
  delay(200);
  mySerial.println(String("ATD#") + Bal + String("#;"));
  delay(200);
}

void Masterphone() {     /// === чтение мастер-номеров из EEPROM === ///
      for (int i = 0; i < 5 ; i++) {
        EEPROM.get(Adress[i], Phone);        // считываем массив символов
         AlarmPhone[i] = Phone;
  Serial.println(String(F("Phone[")) + i + String(F("]:")) + AlarmPhone[i]); 
         Phone[12] = "";                    // обнулим, больше не нужен
      }
        EEPROM.get(20, Bal);        // считываем массив символов
  Serial.println(String(F("Balance:")) + Bal);
        Firststart = EEPROM.read(10);    // cчитаем из EEPROM
  Serial.println(String(F("Firststart:")) + Firststart);
}

int master (int i, String num) { /// === добавление мастер-номеров === ///
      if (i < 5 && i != 0) {
        num.toCharArray(Phone, 12); // конвертируем
        AlarmPhone[i] = num;        // запишем номер  
  Serial.println(String(F("Master")) + i + String(F(":")) + AlarmPhone[i]);
        EEPROM.put(Adress[i], Phone);           // записываем массив в EEPROM 
//  sms(String(String("Master") + i + ":" + num + " Ok"), String("+" + RingPhone)); // смс на последний номер
      num = "";
      Phone[12] = "";
      } else Serial.println(F("MAX number 4!"));          // 4 номера максимум! 
                               // 0 номер можно удалить только очисткой, первый старт
}                              

int dellphone (int i) {          /// === удаление мастар-номеров === ///
     if (i < 5 && i != 0) {
  Serial.println(String(F("Master")) + i + String(F(" DELL")));
     AlarmPhone[i] = "";   // обнулим номер
     EEPROM.put(Adress[i], 0);
//  sms(String(String("Master") + i + " Dell Ok"), String("+" + RingPhone)); // смс на последний номер
  }
}

int balnum (String num) { /// === добавляем номер баланса === ///
      num.toCharArray(Bal, 4);   // конвертируем
  Serial.println(String(F("Balance:")) + Bal);
      EEPROM.put(20, Bal);           // записываем массив в EEPROM 
//  sms(String("Balance:" + num + " Ok"), String("+" + RingPhone)); // смс на последний номер
      num = "";
}

void InitModem() {
  Serial.println("Start module");
  mySerial.begin(9600);  //Скорость порта для связи Arduino с GSM модулем
  waitConnect();
  Serial.println("GSM connected");
  waitRegistration();
  delay(1000); 
}

void waitConnect() {  // запуск модема
  int countok = 0;
  String str; 
  while(countok < 5) {                   //ждём пять ОК  
    uint32_t ms = millis();
    if( ( ms - msAT ) > 500 || ms < msAT ) {// Событие срабатывающее каждые 500 мс 
      msAT = ms;
//      Serial.println(">>AT");
      mySerial.println("AT");          // посылаем команду
      str = "";
      delay(100);                      // ждём ответа
      while(mySerial.available()) {
        char ch = mySerial.read();
        str += ch;
      } 
//      Serial.println("C>");
//      Serial.println(str);
      if(str.indexOf(F("OK")) > -1)
        countok++;
      else
        countok = 0;
    }
  }  
  Serial.println("Turn on AOH:");
  mySerial.println("AT+CLIP=1");  // включить АОН
  delay(200);
  Serial.println("GSM registration");
  mySerial.println("AT+CMGF=1");
  delay(200); 
  Serial.println("Mode GSM:");
  mySerial.println("AT+CSCS=GSM");  // кодировка текста - GSM
  delay(300);
  mySerial.println("AT+CNMI=2,2,0,0,0");
  delay(300); 
}

void waitRegistration() { // регистрация модема в сети
  bool ok = 0;
  String str;
  while(!ok) {  
    uint32_t ms = millis();
    if( ( ms - msAT ) > 500 || ms < msAT ) { // Событие срабатывающее каждые 500 мс
      msAT = ms;
      Serial.println(">>AT+CREG?");
      mySerial.println("AT+CREG?");         //посылаем команду
      delay(100);                           //Ждём ответа
      str = "";
      while(mySerial.available()) {
           char ch = mySerial.read();
           str += ch;
      } 
      Serial.println("R>");
      Serial.println(str);
      if(str.indexOf(F("+CREG:"))>-1)
        ok = 1;
    }
  }  
}

void sms(String text, String phone) {      /// === отправка СМС === ///
    Serial.println(F("Start SMS send")); 
    mySerial.println(String(F("AT+CMGS=\"")) + phone + String(F("\"")));
    delay(500);
    mySerial.print(text);
    delay(500);
    mySerial.print((char)26);
    delay(500);
    Serial.println(String(F("SMS sended! Phone: ")) + phone + String(F("; Message: ")) + text);
    delay(2000);
}

 

b707
Offline
Зарегистрирован: 26.05.2017

pasha413 пишет:

как проверить баланс на А6?

на команду AT+CUSD=1,"*101#",15  приходит ответ  

+CUSD: 2, "⸮!5H}.A0W⸮⸮" ,1
 

Это и есть ответ, только он хитро закодирован.

Посмотрите вот эту тему начиная с 13 сообщения

http://arduino.ru/forum/apparatnye-voprosy/gsm-a6-vopros-pro-ring

pasha413
Offline
Зарегистрирован: 27.11.2016

Спасибо, почитаю

pasha413
Offline
Зарегистрирован: 27.11.2016

разобрался с балансом (напомню, модем A6). датчики пока не проверял, но проверил все смс, всё работает.

единственное мастер номера каждый отправляет отдельным sms, как их объединить чтоб приходило в одном смс и выглядело так:

master0:79111234567

master1:79112645321

так считываю номера:

      for (int i = 0; i < 5 ; i++) {         // считываем все ячейки памяти номеров
        EEPROM.get(Adress[i], Phone);        // считываем массив символов по адресу
         AlarmPhone[i] = Phone;
         if (AlarmPhone[i] != 0) {           // если ячейка пустая, не пишем ее
  Serial.println(String(F("Phone[")) + i + String(F("]:")) + AlarmPhone[i]); 
         }
         Phone[12] = " ";                    // обнулим, больше не нужен
      }

А вот весь код:

#include <EEPROM.h> 
#include<SoftwareSerial.h>
SoftwareSerial mySerial(2, 3);

#define DOOR 4                              // концевик двери.
#define PIR 6                               // датчик движения.
#define GAS A0                              // датчик дыма.
#define BUZ 11                              // сирена.
#define Led 12                              // состояние системы, моргает - норма.

// DOOR     - если сработал, на входе "+" HIGH.
// PIR      - если сработал, на входе "+" HIGH.
// GAS      - если сработал, на входе "+" HIGH.
// BUZ      - если "-" LOW, то горит. 
// Led     - если "-" LOW, то горит.

int8_t Guard = 0;          // 1. охрана:                         1 - вкл, 0 - выкл.
int8_t AlarmRING = 1;      // 2. вызов:                          1 - вкл, 0 - выкл.
int8_t SendSMS = 1;        // 3. отправка смс:                   1 - вкл, 0 - выкл.
int8_t DOORon = 1;         // 4. контроль концевиков дверей:     1 - вкл, 0 - выкл.    
int8_t PIRon = 1;          // 5. контроль датчика движения:      1 - вкл, 0 - выкл.
int8_t GASon = 1;          // 6. контроль датчика дыма:          1 - вкл, 0 - выкл.

int8_t DOORFlag = 1;       
int8_t PIRFlag = 1;
int8_t GASFlag = 1;
int8_t DOORState = LOW;    // Состояние концевика двери.
int8_t PIRState = LOW;     // Состояние датчика движения.
int8_t LedState = HIGH;    // Состояние светодиода.

int8_t Firststart;         // первый старт.
uint8_t PIRcount = 3;      // Кол-во срабатываний PIR - 3 до тревоги.
uint32_t msAT = 0;

char Bal[4] = "";          // для временного хранения номера баланса   
char Phone[12] = "";       // для временного хранения номера телефона      
byte Adress[5] = {25, 40, 55, 70, 85}; //занимаем ячейки для пяти номеров.

String val;          // переменная для хранения данных   
String LastEvent;    // полное состояние системы.
String RingPhone;    // номер звонившего.
String AlarmPhone[5];     // номера для постановки/снятии с охраны и отправки смс.

int GASThres = 400;          // предельная концентрация газа
uint8_t PIRDetectCount = 0;  // обнуление счетчика PIR датчика.
uint8_t AlarmInterval = 10;  // Секунд до отключения "тревожного" пина.
uint8_t interval = 100;      // для мигания BLed
uint16_t previousMillis = 0;
uint16_t previousAlarmMillis = 0;

/* EEPROM Data:
  № ячейки - значение;
  0 - если записана не 1, то необходимо затереть eeprom и восстановить стандартную конфигурацию.
  1 - Guard = 0;       // охрана:                         1 - вкл, 0 - выкл.
  2 - AlarmRING = 1;   // звонок:                         1 - вкл, 0 - выкл. 
  3 - SendSMS = 1;     // отправка смс:                   1 - вкл, 0 - выкл.
  4 - DOORon = 1;      // концевик двери:                 1 - вкл, 0 - выкл.
  5 - PIRon = 1;       // датчик движения:                1 - вкл, 0 - выкл.
  6 - GASon = 1;       // датчик дыма:                    1 - вкл, 0 - выкл.
  7 - 
  8 - 
  9 - PIRcount = 2;    // количество срабатываний PIR датчика = 3.
  10 - Firststars = 1; // первый запуск = 1;
  20 - ячейка памяти баланса,
  25, 40, 55, 70, 85 - ячейки памяти телефонов.
  100 - ячейка памяти RingPhone.
*/

void setup() {
    Serial.begin(9600);
  pinMode(DOOR, INPUT_PULLUP);
  pinMode(PIR, INPUT);
  pinMode(GAS, INPUT);
  pinMode(BUZ, OUTPUT);
  pinMode(Led, OUTPUT);
   digitalWrite(BUZ, HIGH);
  InitModem();
  eepromconfig();
   digitalWrite(Led, HIGH);
}

void loop() {
  LED();
  AlarmPinOff();
  Detect();
    if (val.indexOf(F("+PBREADY")) > -1) InitModem(); // если модем перезапустился запускаем инициализацию.
    if (mySerial.available()) {          // если GSM модем что-то послал.
    while (mySerial.available()) {       // сохраняем входную строку в переменную val.
      char ch = mySerial.read();
      val += char(ch);                   // собираем принятые символы в строку
      delay(3);
    } 
    if (val.indexOf(F("+CLIP")) > -1) {            //// если обнаружен вызов.
  Serial.println(F("Process RING"));                              
      mySerial.println(F("ATH"));                    // сбрасываем вызов.
      if (CheckPhone() == 1) {                       // проверяем номер, если наш.
  Serial.println(F("Master Ring OK!"));
  MasterRing();                                      // меняем состояние охраны
      } else  Serial.println(F("No Master Ring!"));  
    } else if (val.indexOf(F("+CMT")) > -1) {      //// если обнаруженa СМС
  Serial.println(F("Process CMT"));                            
        if (CheckPhone() == 1) {                     // если СМС от хозяина
  Serial.println(F("Master SMS OK!"));
  Serial.println(String(F("SMS->")) + val); // что пришло в смс
  MasterSMS();
        } else  Serial.println(F("No Master SMS!"));
      } else if(val.indexOf(F("+CUSD:"))>-1) {     //// если пришел баланс 
        // команда проверки баланса  AT+CUSD=1,#105#,15
        // анализируем строку 
        int p1 = val.indexOf(F("\""));      // начало строки
        int p2 = val.lastIndexOf(F("\""));  // конец строки
        val = val.substring(p1+1,p2);
        Serial.println("");
        Serial.println(F("Input string:"));   // пишем в порт пришедшую строку
        Serial.println(val);
        String decodestr;
        Decode7bit(val, decodestr);
        Serial.println("");
        Serial.println(F("Decode string:"));  // пишем в порт конвертированную строку
        Serial.println(decodestr);
  sms(String("Balance SIM: " + decodestr), String("+" + RingPhone)); // смс на последний звонивший
      } val = ""; 
  }  if (Serial.available()) {           // если в мониторе порта что-то ввели
    while (Serial.available()) {         // сохраняем входную строку в переменную val.
      char ch = Serial.read();
      val += char(ch);                   // собираем принятые символы в строку
      delay(3);
    } 
  ConsolePrint();                        // запускаем консольную программу
    val = "";  
  }
}

int CheckPhone() {        /// === проверка телефона === ///
  if (Firststart == 0) {                         // если не первый старт
    for (int i = 0; i < 5; i++) {
       if (val.indexOf(AlarmPhone[i]) > -1 && val.indexOf(AlarmPhone[i]) != 0) { // если есть вызов, и он наш
         RingPhone = AlarmPhone[i];              // запоминаем его.
         RingPhone.toCharArray(Phone, 12);   
         EEPROM.put(100, Phone);                 // записываем RingPhone в память. 
//  Serial.println(String(F("RingPhone ")) + RingPhone);          
         return 1;                               // возвращаем 1 - номер наш!
      } 
    } Phone[12] = "";
      return 0;                                  // возвращаем 0 - номер не наш!
  } else if (Firststart == 1) {                  // иначе (если первый старт)
      int ind = val.indexOf("+CLIP:") + 8;       // обрезаем номер 
      String num = val.substring(ind, ind + 11); 
      num.toCharArray(Phone, 12);
      EEPROM.put(25, Phone);                     // пишем номер в EEPROM
      AlarmPhone[0] = Phone;                     // запишем
      EEPROM.update(10, 0);                      // обновляем Firststart
      Firststart = 0;                            // пишем 0
  Serial.println(String(F("Master0:")) + AlarmPhone[0]); 
  Serial.println(String(F("Firststart:")) + Firststart);
  sms(String("Master0:" + num + " Ok"), String("+" + num)); // смс на звонивший
      Phone[12] = "";
    }   
}

void eepromconfig() {
    pinMode(13, OUTPUT);
    if (EEPROM.read(0) != 1) {          // если записана не 1
      for (int i = 0 ; i < 512 ; i++) {  // переписываем все ячейки
        EEPROM.write(i, 0);
      }                      // и записываем:
      EEPROM.update(1, 0);   // Guard       охрана выкл.
      EEPROM.update(2, 1);   // AlarmRING   вызов вкл.
      EEPROM.update(3, 1);   // SendSMS     смс вкл.
      EEPROM.update(4, 1);   // DOORon      датчики дверей вкл.
      EEPROM.update(5, 1);   // PIRon       датчик движения вкл.
      EEPROM.update(6, 1);   // GASon       датчик газа вкл.
      EEPROM.update(9, 2);   // PIRcount.   2 повторных срабатывания.
      EEPROM.update(10, 1);  // Firststart  первый старт!.
      EEPROM.update(20, 0);  // баланс, записываем массив в EEPROM 
      EEPROM.update(0, 1);   // 
      digitalWrite(13, HIGH);
  Serial.println(F("EEPROM != 1/ RESET!")); 
    }
    if (EEPROM.read(0) == 1) {
      Guard      = EEPROM.read(1);   // Охрана
      AlarmRING  = EEPROM.read(2);   // Вызов
      SendSMS    = EEPROM.read(3);   // Отправка смс
      DOORon     = EEPROM.read(4);   // Датчик двери
      PIRon      = EEPROM.read(5);   // Датчик движения
      GASon      = EEPROM.read(6);   // Датчик газа/дыма
//               = EEPROM.read(7);   //
//               = EEPROM.read(8);   //      
      PIRcount   = EEPROM.read(9);   //
      Firststart = EEPROM.read(10);  //
  Masterphone();    
    }
   String SIGN = "";         // текущее состояние системы.
   String RING = "";         // текущее состояние вызов.
   String SMS = "";          // текущее состояние смс.
   String Door = "";         // текущее состояние датчика двери.
   String Pir = "";          // текущее состояние датчика движения.
   String Gas = "";          // текущее состояние датчика газа.
    if (Guard == 1) SIGN = String(F("System -> on;\n"));
    if (Guard == 0) SIGN = String(F("System -> off;\n"));
    if (AlarmRING == 1) RING = String(F("Ring -> on;\n"));
    if (AlarmRING == 0) RING = String(F("Ring -> off;\n"));
    if (SendSMS == 1) SMS = String(F("SMS -> on;\n"));
    if (SendSMS == 0) SMS = String(F("SMS -> off;\n"));
    if (PIRon == 1) Pir = String(F("Pir -> on;\n"));
    if (PIRon == 0) Pir = String(F("Pir -> off;\n"));
    if (DOORon == 1) Door = String(F("Door -> on;\n"));
    if (DOORon == 0) Door = String(F("Door -> off;\n"));
    if (GASon == 1) Gas = String(F("Gas -> on;\n"));
    if (GASon == 0) Gas = String(F("Gas -> off;\n"));
    String System = SIGN + RING + SMS;                // состояние (вкл/выкл) системы.
    String Sensors = Pir + Door + Gas;                // состояние (вкл/выкл) датчиков.
    LastEvent = System + Sensors;                     // полное состояние системы и датчиков.
  Serial.println(LastEvent);  
}

void Detect() {           /// === чтение датчиков === ///
  DOORState = digitalRead(DOOR);
  PIRState = digitalRead(PIR);
  int Smoky = analogRead(GAS);
  
  if (DOORState == HIGH && DOORFlag == 0 && DOORon == 1) { // если датчик двери сработал
    DOORFlag = 1;
  Serial.println(F("Dver' otkrita!"));
    Alarm();                                       
  }
  if (DOORState == LOW && DOORFlag == 1) {                 // Датчик успокоился
    DOORFlag = 0;
  }
  if (PIRState == HIGH && PIRon == 1) {                    // если датчик движения сработал
    PIRDetectCount ++; 
  Serial.println(F("Dvizhenie!"));
    if (Guard == 1 && PIRDetectCount < 2) {                // если первый раз 
      digitalWrite(BUZ, LOW);                              // отпугиваем сиреной
      delay(250);
      digitalWrite(BUZ, HIGH);
    }
    if (Guard == 1 && PIRDetectCount == PIRcount) {        // 
  Serial.println(F("Dvizhenie!!!"));
      PIRFlag = 1; 
      Alarm();                                      // включаем сирену сигнализация!
    PIRDetectCount == 0;
    }
  }
  if (PIRState == LOW && PIRFlag == 1)            { // Датчик успокоился
    PIRFlag = 0;
    digitalWrite(13, LOW);
  }
/*  if (Smoky > GASThres && GASFlag == 0 && GASon == 1)   { // датчик сработал
      GASFlag = 1;
  Serial.println(F("Srabotal datchik gasa!"));
      Alarm();
  } 
  if (Smoky < GASThres && GASFlag == 1)           { // Датчик успокоился
      GASFlag = 0; 
  }*/
}

void Alarm() {
  if (Guard == 1) {
    previousAlarmMillis = millis();
    digitalWrite(BUZ, LOW);
  Serial.println(F("Alarm!!!"));  
    if (SendSMS == 1) {
      for (int i = 0; i < 5; i++) {
        if (DOORFlag == 1 && AlarmPhone[i] != 0) {
  sms(String("Dver' otkrita!"), String("+" + String(AlarmPhone[i]))); // смс на все номера
        }
        if (PIRFlag == 1 && AlarmPhone[i] != 0) {
  sms(String("Dvizhenie y dveri!"), String("+" + String(AlarmPhone[i]))); // смс на все номера
        }
        if (GASFlag == 1 && AlarmPhone[i] != 0) {
  sms(String("Gas v dome!"), String("+" + String(AlarmPhone[i]))); // смс на все номера
        }
//        delay(1000);
      }
    }
    if (AlarmRING == 1) {
      mySerial.println("ATD+" + String(AlarmPhone[0]) + ";"); // звоним первому номеру
//      delay(1000);  // ????? не решил дождаться отбоя или положить трубку.
    }
  }
}

void AlarmPinOff() {      
  uint16_t currentAlarmMillis = millis();
  if (currentAlarmMillis - previousAlarmMillis > AlarmInterval * 1000) {
    digitalWrite(BUZ, HIGH);
  }
}

void MasterRing() {
  if (Guard == 1) GuardOff();
  else if (Guard == 0) GuardOn();
}

void GuardOff() {
    Guard = 0;
    EEPROM.update(1, Guard);
  Serial.println(String(F("System -> off. Ring:")) + RingPhone);
  for (int i = 0; i < 5; i++) {
     if (AlarmPhone != 0) {
//  sms(String("System -> off"), String("+" + AlarmPhone[i])); // смс на все номера
     }
  }
    PIRDetectCount = 0;  // сбрасываем счетчик срабатываний PIR датчика.
}

void GuardOn() {         
    Guard = 1;
    EEPROM.update(1, Guard);
  Serial.println(String(F("System -> on. Ring:")) + RingPhone);
  for (int i = 0; i < 5; i++) {
     if (AlarmPhone != 0) {
//  sms(String("System -> on"), String("+" + AlarmPhone[i])); // смс на все номера
     }
  }
}

void LED() {              /// === состояние светодиодов === ///
  if (Guard == 0) {                   // если снят с охраны
    digitalWrite(Led, HIGH);          // светодиод не горит
  }
  if (Guard == 1) {                   // если на охране
  uint16_t currentMillis = millis();  // светодиод моргает
  //проверяем не прошел ли нужный интервал, если прошел то
    if (currentMillis - previousMillis > interval) {
      // сохраняем время последнего переключения
      previousMillis = currentMillis;
      // если светодиод не горит, то зажигаем, и наоборот
      if (LedState == HIGH) LedState = LOW;
      else LedState = HIGH;
      digitalWrite(Led, LedState);
    }
  }
}

void ConsolePrint() {
    val.toLowerCase();
  if (val.indexOf(F("master")) > -1) {   // добавление мастер-номера
      master(val.substring(6, 7).toInt(), val.substring(8, 19));
// sms типа: " master1:79111386232 " - номер в ячейку "1", куда записать номер
  }
  if (val.indexOf(F("balance:")) > -1) { // добавление номера баланса
      balnum(val.substring(8, 13));
// sms типа: " balance:100 " - номер баланса
  }
  if (val.indexOf(F("dell:")) > -1) {    // удаление номера из ячейки     
      dellphone(val.substring(5, 6).toInt());
// sms типа: " dell:1 " - удалить номер из ячейки 1
  }
  if (val.indexOf(F("reset")) > -1) {    // сброс ЕЕПРОМ
  Serial.println(F("Reset System!"));  
       EEPROM.write(0, 0);
  eepromconfig();
  }
  if (val.indexOf(F("info")) > -1) {     // инфо о состоянии системы
  eepromconfig();
  }
  if (val.indexOf(F("money")) > -1) {    // запрос баланса
    balance();
  }
  if (val.indexOf(F("guardon")) > -1) {  // вкл сигнализации
    GuardOn();
  }
  if (val.indexOf(F("guardoff")) > -1) { // выкл сигнализации
    GuardOff();
  }
  if (val.indexOf(F("ringon")) > -1) {   // вкл вызов при сработке
    AlarmRING = 1;
    EEPROM.update(2, AlarmRING);
  Serial.println(F("Ring -> on"));      
//  sms(String("Ring -> on"), String("+" + RingPhone)); // смс на последний номер
  }
  if (val.indexOf(F("ringoff")) > -1) {  // выкл вызов при сработке
    AlarmRING = 0;
    EEPROM.update(2, AlarmRING);
  Serial.println(F("Ring -> off"));  
//  sms(String("Ring -> off"), String("+" + RingPhone)); // смс на последний номер
  }
  if (val.indexOf(F("smson")) > -1) {    // вкл смс при сработке
    SendSMS = 1;
    EEPROM.update(3, SendSMS);
  Serial.println(F("SMS -> on"));  
//  sms(String("SMS -> on"), String("+" + RingPhone)); // смс на последний номер
  }
  if (val.indexOf(F("smsoff")) > -1) {   // выкл смс при сработке
    SendSMS = 0;
    EEPROM.update(3, SendSMS);
  Serial.println(F("SMS -> off"));  
//  sms(String("SMS -> off"), String("+" + RingPhone)); // смс на последний номер
  }
}

void MasterSMS() {        /// === мастер смс === ///
    val.toLowerCase();
  if (val.indexOf(F("master")) > -1)  { // добавление мастер-номера
     int tel(val.indexOf(F("master")));
      master(val.substring(tel + 6, tel + 7).toInt(), val.substring(tel + 8, tel + 19));
///// sms типа: " master1:79111234567 " - ячейка + номер
  }
  if (val.indexOf(F("balance:")) > -1) { // добавление номера баланса
      int bal(val.indexOf(F("balance:")));
      balnum(val.substring(bal + 8, bal + 11));
///// sms типа: " balance:100 " - номер баланса
  }
  if (val.indexOf(F("dell:")) > -1) { // удаление номера из ячейки     
     int del(val.indexOf(F("dell:")));
      dellphone(val.substring(del + 5, del + 6).toInt());
///// sms типа: " dell:1 " - удалить номер из ячейки 1
  }
  if (val.indexOf(F("phone")) > -1)     { // инфо о состоянии системы
  Masterphone();
      for (int i = 0; i < 5 ; i++) {
        if (AlarmPhone[i] != 0) {
  sms(String(String("Master[") + i + String("]:") + AlarmPhone[i]), String("+" + RingPhone)); // смс на последний номер
        }
      }
  }
  if (val.indexOf(F("info")) > -1)     { // инфо о состоянии системы
//  Serial.println(RingPhone + String(F("->SMS")));  
  eepromconfig();
  sms(String(LastEvent), String("+" + RingPhone)); // смс на последний номер
  }
  if (val.indexOf(F("reset")) > -1)    { // полный сброс ЕЕПРОМ
  sms(String("Reset system!!!"), String("+" + RingPhone)); // смс на последний номер
  Serial.println(F("Reset System!!!"));          
       EEPROM.write(0, 0);
  eepromconfig();
  }
  if (val.indexOf(F("money")) > -1)    { // запрос баланса
    delay(500);
    balance();
  }
  if (val.indexOf(F("guardon")) > -1)  { // вкл сигнализации
    GuardOn();
  }
  if (val.indexOf(F("guardoff")) > -1) { // выкл сигнализации
    GuardOff();
  }
  if (val.indexOf(F("ringon")) > -1)   { // вкл вызов при сработке
    AlarmRING = 1;
    EEPROM.update(2, AlarmRING);
  Serial.println(F("AlarmRing -> on"));      
  sms(String("Ring -> on"), String("+" + RingPhone)); // смс на последний номер
  }
  if (val.indexOf(F("ringoff")) > -1)  { // выкл вызов при сработке
    AlarmRING = 0;
    EEPROM.update(2, AlarmRING);
  Serial.println(F("AlarmRing -> off"));  
  sms(String("Ring -> off"), String("+" + RingPhone)); // смс на последний номер
  }
  if (val.indexOf(F("smson")) > -1)    { // вкл смс при сработке
    SendSMS = 1;
    EEPROM.update(3, SendSMS);
  Serial.println(F("SendSMS -> on"));  
  sms(String("SMS -> on"), String("+" + RingPhone)); // смс на последний номер
  }
  if (val.indexOf(F("smsoff")) > -1)   { // выкл смс при сработке
    SendSMS = 0;
    EEPROM.update(3, SendSMS);
  Serial.println(F("SendSMS -> off"));  
  sms(String("SMS -> off"), String("+" + RingPhone)); // смс на последний номер
  }
}

void balance() {          /// === проверка баланса сим-карты === ///
  EEPROM.get(20, Bal);        // считываем массив символов
  mySerial.println(String(F("AT+CUSD=1,#")) + Bal + String(F("#,15")));
  delay(100);
}

void Masterphone() {     /// === чтение мастер-номеров из EEPROM === ///
      for (int i = 0; i < 5 ; i++) {
        EEPROM.get(Adress[i], Phone);        // считываем массив символов
         AlarmPhone[i] = Phone;
         if (AlarmPhone[i] != 0) {
  Serial.println(String(F("Phone[")) + i + String(F("]:")) + AlarmPhone[i]); 
         }
         Phone[12] = "";                    // обнулим, больше не нужен
      }
        EEPROM.get(100, Phone);        // считываем массив символов
          RingPhone = Phone;
  Serial.println(String(F("Ring [ ]:")) + RingPhone);
          Phone[12] = "";                    // обнулим, больше не нужен
        EEPROM.get(20, Bal);        // считываем массив символов
  Serial.println(String(F("Balance:")) + Bal);
        Firststart = EEPROM.read(10);    // cчитаем из EEPROM
  Serial.println(String(F("Firststart:")) + Firststart);
}

int master (int i, String num) { /// === добавление мастер-номеров === ///
      if (i < 5 && i != 0) {
        num.toCharArray(Phone, 12); // конвертируем
        AlarmPhone[i] = num;        // пишем номер  
  Serial.println(String(F("Master[")) + i + String(F("]:")) + num);
        EEPROM.put(Adress[i], Phone);           // записываем массив в EEPROM 
  sms(String(String("Master") + i + ":" + num + " add"), String("+" + RingPhone)); // смс на последний номер.
  sms(String("Tell " + AlarmPhone[i] + " add"), String("+" + AlarmPhone[i])); // смс на добавленный номер.
      Phone[12] = "";
      } else Serial.println(F("MAX number 4!"));          // 4 номера максимум! 
                               // 0 номер можно удалить только очисткой, первый старт
}                              

int dellphone (int i) {          /// === удаление мастар-номеров === ///
     if (i < 5 && i != 0) {
  Serial.println(String(F("Master")) + i + String(F(" dell")));
     EEPROM.put(Adress[i], 0);
  sms(String(String("Master") + i + ":" + AlarmPhone[i] + " dell"), String("+" + RingPhone)); // смс на последний номер
  sms(String("Tell " + AlarmPhone[i] + " dell"), String("+" + AlarmPhone[i])); // смс на добавленный номер.
     AlarmPhone[i] = "";   // обнулим номер
  }
}

int balnum (String num) { /// === добавляем номер баланса === ///
      num.toCharArray(Bal, 4);   // конвертируем
  Serial.println(String(F("Balance:")) + Bal);
      EEPROM.put(20, Bal);           // записываем массив в EEPROM 
  sms(String("Balance: #" + num + "# Ok"), String("+" + RingPhone)); // смс на последний номер
}

void Decode7bit(String &instr, String &outstr)
{
  byte reminder = 0;
  int bitstate = 7;
  for(int i=0; i<instr.length(); i++)
  {
    byte b = instr[i];
    byte bb = b << (7 - bitstate);
    char c = (bb + reminder) & 0x7F;
    outstr += c;
    reminder = b >> bitstate;
    bitstate--;
    if(bitstate == 0)
    {
      char c = reminder;
      outstr += c;
      reminder = 0;
      bitstate = 7;
    }
  }
}

void InitModem() {
  Serial.println(F("Start module"));
  mySerial.begin(9600);  //Скорость порта для связи Arduino с GSM модулем
  waitConnect();
  Serial.println(F("GSM connected"));
  waitRegistration();
  delay(1000); 
}

void waitConnect() {  // запуск модема
  int countok = 0;
  String str; 
  while(countok < 5) {                   //ждём пять ОК  
    uint32_t ms = millis();
    if( ( ms - msAT ) > 500 || ms < msAT ) {// Событие срабатывающее каждые 500 мс 
      msAT = ms;
//      Serial.println(">>AT");
      mySerial.println(F("AT"));          // посылаем команду
      str = "";
      delay(100);                      // ждём ответа
      while(mySerial.available()) {
        char ch = mySerial.read();
        str += ch;
      } 
//      Serial.println("C>");
//      Serial.println(str);
      if(str.indexOf(F("OK")) > -1)
        countok++;
      else
        countok = 0;
    }
  }  
  Serial.println(F("Turn on AOH:"));
  mySerial.println(F("AT+CLIP=1"));  // включить АОН
  delay(200);
  Serial.println(F("GSM registration"));
  mySerial.println(F("AT+CMGF=1"));
  delay(200); 
  Serial.println(F("Mode GSM:"));
  mySerial.println(F("AT+CSCS=GSM"));  // кодировка текста - GSM
  delay(300);
  mySerial.println(F("AT+CNMI=2,2,0,0,0"));
  delay(300); 
}

void waitRegistration() { // регистрация модема в сети
  bool ok = 0;
  String str;
  while(!ok) {  
    uint32_t ms = millis();
    if( ( ms - msAT ) > 500 || ms < msAT ) { // Событие срабатывающее каждые 500 мс
      msAT = ms;
      Serial.println(F(">>AT+CREG?"));
      mySerial.println(F("AT+CREG?"));         //посылаем команду
      delay(100);                           //Ждём ответа
      str = "";
      while(mySerial.available()) {
           char ch = mySerial.read();
           str += ch;
      } 
      Serial.println(F("R>"));
      Serial.println(str);
      if(str.indexOf(F("+CREG:"))>-1)
        ok = 1;
    }
  }  
}

void sms(String text, String phone) {      /// === отправка СМС === ///
    Serial.println(F("Start SMS send")); 
    mySerial.println(String(F("AT+CMGS=\"")) + phone + String(F("\"")));
    delay(300);
    mySerial.print(text);
    delay(300);
    mySerial.print((char)26);
    delay(300);
    Serial.println(String(F("SMS sended! Phone: ")) + phone + String(F("; Message: ")) + text);
    delay(4000);
}

замечания и предложения приветствуются!

Ruslan_Kulibin
Offline
Зарегистрирован: 23.07.2017

в каком режиме должен работать датчик движения? там два режима: Н и L. При Н датчик дает сигнал постоянно пока есть движение в зоне обнаружения. При режиме L обнаружение движение регистрируется задержкой выставленной подстроечником. после срабатывания сигнал прерывается и датчик переходит в режим калибровки примерно 3 секунды. дальше по новой. Вы в "натуре" откатывали программу? просто у меня почему то датчик тупо вешает программу после 2-3 срабатываний. после датчик вообще не как не реагирует на движение. Программный сброс счетчика
 

 PIRDetectCount = 0; // сбрасываем счетчик срабатываний PIR датчика.

не срабатывает.

Ruslan_Kulibin
Offline
Зарегистрирован: 23.07.2017

Ещё вопрос по поводу PIN13- Зачем он нужен?

pasha413
Offline
Зарегистрирован: 27.11.2016

кусок программы с датчиками проверял около месяца назад - все работало. сейчас все собрать в кучу нехватает датчика движения.

PIN13 в принципе незнаю зачем я его использовал при записи/чтении из ЕЕПРОМ. в ближайшее время попробую все собрать в кучу

pasha413
Offline
Зарегистрирован: 27.11.2016

Ruslan_Kulibin. 

у меня PIR датчик в режиме L, оба подстроечника в 0, влево.

решил убрать из ЕЕПРОМ "PIRDetectCount", оставил только: 

uint8_t PIRCount = 0;          // Кол-во срабатываний PIR.

необходимо поудалять везде где он использовался,

и попробуйте заменить кусок кода:

void Detect() {           /// === чтение датчиков === ///
  DOORState = digitalRead(DOOR);
  PIRState = digitalRead(PIR);
  if (DOORon == 1) {
    if (DOORState == HIGH && DOORFlag == 0) {  // если датчик двери сработал
      DOORFlag = 1;
  Serial.println(F("Dver' otkrita!"));
  Alarm();                                       
    }
    if (DOORState == LOW && DOORFlag == 1) {   // Датчик успокоился
      DOORFlag = 0;
    }
  }
  if (PIRon == 1 && PIRState == HIGH) {
    PIRCount ++; 
    if (PIRCount < 2) {                        // если датчик движения сработал
  Serial.println(F("Dvizhenie!"));
      digitalWrite(BUZ, LOW);                  // отпугиваем сиреной
      delay(250);
      digitalWrite(BUZ, HIGH);
    }
    if (PIRCount >= 2) {                        // 
  Serial.println(F("Dvizhenie!"));
      PIRFlag = 1; 
  Alarm();                                      // включаем сирену сигнализация!
      PIRCount == 0;
    }
  }
  if (PIRState == LOW && PIRFlag == 1) {        // Датчик успокоился
    PIRFlag = 0;
  }
}

и добавьте в конец процедуры void GuardOff() строку:

    PIRCount = 0;  // сбрасываем счетчик срабатываний PIR датчика при снятии с охраны

 

-sergius-
Offline
Зарегистрирован: 07.03.2015

Тема заглоха или как, просто давно небыло комментариев. pasha413 скажите есть ли модихикация, или оптимизация в Вашем коде?

pasha413
Offline
Зарегистрирован: 27.11.2016

Пока тестирую, нашел ещё несколько косяков в скетче. единственное не разобрался по поводу отправки всех мастер номеров в одном смс?

pasha413
Offline
Зарегистрирован: 27.11.2016

я человек не жадный, и поэтому вот моя протестированная в домашних условия версия (на макетке), все работает, глюков нет, буду паять на плату и в корпус для полевых испытаний. Arduino nano 328p + Ai-Thinker A6.

#include <EEPROM.h> 
#include <OneWire.h>
#include<SoftwareSerial.h>
SoftwareSerial mySerial(2, 3);

OneWire ds(12);                              // датчик температуры подключен к 9 пину, подтяжка 4.7кОм на +.
#define DOOR 4                              // концевик двери.
#define PIR 5                               // датчик движения.
#define Led 8                               // состояние системы. моргает - на охране.
#define BUZ 10                              // сирена.
#define GAS A0                              // датчик дыма.

// DOOR     - если сработал, на входе "+" HIGH.
// PIR      - если сработал, на входе "+" HIGH.
// GAS      - если сработал, на входе "+" HIGH.
// BUZ      - если "-" LOW, то горит. 
// Led      - если "-" LOW, то горит.

int8_t Guard = 0;          // 1. охрана:                         1 - вкл, 0 - выкл.
int8_t AlarmRING = 1;      // 2. вызов при сработке:             1 - вкл, 0 - выкл.
int8_t SendSMS = 1;        // 3. отправка смс при сработке:      1 - вкл, 0 - выкл.
int8_t DOORon = 1;         // 4. контроль концевиков дверей:     1 - вкл, 0 - выкл.    
int8_t PIRon = 1;          // 5. контроль датчика движения:      1 - вкл, 0 - выкл.
int8_t GASon = 1;          // 6. контроль датчика дыма:          1 - вкл, 0 - выкл.

int8_t DOORFlag = 0;       // флаг состояние датчика двери.
int8_t PIRFlag = 0;        // флаг состояние датчика движения.
int8_t GASFlag = 0;        // флаг состояние датчика газа.
int8_t DOORState = LOW;    // Состояние концевика двери.
int8_t PIRState = LOW;     // Состояние датчика движения.
int8_t LedState = HIGH;    // Состояние светодиода.

int8_t Firststart;         // первый старт.
uint32_t msAT = 0;

char Bal[4] = "";          // для временного хранения номера баланса.   
char Phone[12] = "";       // для временного хранения номера телефона.      
byte Adress[5] = {25, 40, 55, 70, 85}; // ячейки для пяти номеров в ЕЕПРОМ.

String val;                // переменная для хранения пришедших данных.   
String temp;               // переменная для хранения температуры.
String LastEvent;          // полное состояние системы.
String RingPhone;          // номер звонившего.
String AlarmPhone[5];      // номера для постановки/снятии с охраны и отправки смс.

int Smoky = LOW;           // Состояние датчика газа.
int GASThres = 400;        // предельная концентрация газа
int AlarmInterval = 10;    // Секунд до отключения "тревожного" пина.
int interval = 1000;       // для мигания Led
int previousMillis = 0;
int previousAlarmMillis = 0;

/* EEPROM Data:
  № ячейки - значение:
  0 - если записана не 1, то необходимо затереть eeprom и восстановить стандартную конфигурацию.
  1 - Guard = 0;       // охрана:             0 - выкл.
  2 - AlarmRING = 1;   // звонок:             1 - вкл. 
  3 - SendSMS = 1;     // отправка смс:       1 - вкл.
  4 - DOORon = 1;      // концевик двери:     1 - вкл.
  5 - PIRon = 1;       // датчик движения:    1 - вкл.
  6 - GASon = 1;       // датчик дыма:        1 - вкл.
  7 - 
  8 - 
  9 - 
  10 - Firststars = 1;    // первый запуск       1.
  15 - AlarmInterval = 10 // время сирены
  20 - ячейка памяти баланса,
  25, 40, 55, 70, 85 - ячейки памяти телефонов.
  100 - ячейка памяти номера последнего звонившего RingPhone.
*/

void setup() { /// настройка программы
    Serial.begin(9600); 
  pinMode(DOOR, INPUT_PULLUP);      // вход датчика двери с подтяжкой на +.
  pinMode(PIR, INPUT);           
  pinMode(GAS, INPUT);           
  pinMode(BUZ, OUTPUT);
  pinMode(Led, OUTPUT);
   digitalWrite(BUZ, HIGH);         // сирена выкл.
   digitalWrite(PIR, HIGH);         // игнорируем при включении.
  InitModem();                   // запускаем инициализация модема.
  eepromconfig();
   digitalWrite(Led, HIGH);      // гасим светодиод состояния сигнализации, сигнализация готова к работе.
}

void loop() {  /// основной цикл программы.
  LED();          // моргаем светодиодом.
  AlarmPinOff();  // выключаем сирену, если прошло  время.
  Detect();       // проверяем датчики.
    if (mySerial.available()) {     // если GSM модем что-то послал.
    while (mySerial.available()) {  // сохраняем входную строку в переменную val.
      char ch = mySerial.read();
      val += char(ch);              // собираем принятые символы в строку
      delay(3);
    } 
    if (val.indexOf(F("+CLIP")) > -1) {        // если обнаружен вызов.
  Serial.println(F("Process RING"));                              
      delay(2000);                             // дадим гудок
      mySerial.println(F("ATH"));              // сбрасываем вызов.
      if (CheckPhone() == 1) {                 // проверяем номер, если наш.
  Serial.println(F("Master Ring OK!"));
  MasterRing();                                // меняем состояние охраны
      } else  Serial.println(F("No Master Ring!"));  
    } else if (val.indexOf(F("+CMT")) > -1) {  // если обнаруженa СМС
  Serial.println(F("Process CMT"));                            
  Serial.println(String(F("SMS->")) + val);    // что пришло в смс
        if (CheckPhone() == 1) {               // если СМС от хозяина
  Serial.println(F("Master SMS OK!"));
  MasterSMS();
        } else  Serial.println(F("No Master SMS!"));
      } else if(val.indexOf(F("+CUSD:"))>-1) { // если пришел баланс 
        // команда проверки баланса  AT+CUSD=1,#105#,15
        // анализируем строку 
        int p1 = val.indexOf(F("\""));         // начало строки
        int p2 = val.lastIndexOf(F("\""));     // конец строки
        val = val.substring(p1+1,p2);
        Serial.println("");
        Serial.println(F("Input string:"));    // пишем в порт пришедшую строку
        Serial.println(val);
        String decodestr;
        Decode7bit(val, decodestr);
        Serial.println("");
        Serial.println(F("Decode string:"));   // пишем в порт конвертированную строку
        Serial.println(decodestr);
sms(String("SIM " + decodestr), String("+" + RingPhone)); // смс на последний звонивший
      } val = ""; 
  }  if (Serial.available()) {           // если в мониторе порта что-то ввели
    while (Serial.available()) {         // сохраняем входную строку в переменную val.
      char ch = Serial.read();
      val += char(ch);                   // собираем принятые символы в строку
      delay(3);
    } 
  ConsolePrint();                        // запускаем консольную программу
    val = "";  
  }
}

int CheckPhone() { /// === проверка телефона === ///
  if (Firststart == 0) {                         // если не первый старт
    for (int i = 0; i < 5; i++) {
      if (val.indexOf(AlarmPhone[i]) > -1 && val.indexOf(AlarmPhone[i]) != 0) { // если есть вызов, и он наш
        RingPhone = AlarmPhone[i];              // запоминаем его.
        RingPhone.toCharArray(Phone, 12);   
        EEPROM.put(100, Phone);                 // записываем RingPhone в память. 
//  Serial.println(String(F("RingPhone ")) + RingPhone);          
        return 1;                               // возвращаем 1 - номер наш!
      } 
    } Phone[12] = "";
      return 0;                                  // возвращаем 0 - номер не наш!
  } else if (Firststart == 1) {                  // иначе (если первый старт)
// первый звонивший добавляется как основной мастер номер для управления сигнализацией
      int ind = val.indexOf("+CLIP:") + 8;       // обрезаем номер 
      String num = val.substring(ind, ind + 11); 
      num.toCharArray(Phone, 12);
      EEPROM.put(25, Phone);                     // пишем номер в EEPROM
      EEPROM.put(100, Phone);                 // записываем RingPhone в память. 
      AlarmPhone[0] = Phone;                     // запишем
      RingPhone = Phone;              // запоминаем его.
      EEPROM.update(10, 0);                      // обновляем Firststart
      Firststart = 0;                            // пишем 0
  Serial.println(String(F("Master0:")) + AlarmPhone[0]); 
  Serial.println(String(F("Firststart:")) + Firststart);
sms(String("Master0:" + num + " Ok"), String("+" + num)); // смс на звонивший
//  приходит смс в виде: " Master0:79111234567 Ok "
      Phone[12] = "";
    }   
}

void eepromconfig() { /// === конфигурирование сигнализации === ///
    pinMode(13, OUTPUT);
    if (EEPROM.read(0) != 1) {           // если записана не 1
      for (int i = 0 ; i < 512 ; i++) {  // переписываем все ячейки
        EEPROM.write(i, 0);
      }                      // и записываем:
      EEPROM.update(1, 0);   // Guard       охрана выкл.
      EEPROM.update(2, 1);   // AlarmRING   вызов вкл.
      EEPROM.update(3, 1);   // SendSMS     смс вкл.
      EEPROM.update(4, 1);   // DOORon      датчики дверей вкл.
      EEPROM.update(5, 1);   // PIRon       датчик движения вкл.
      EEPROM.update(6, 1);   // GASon       датчик газа вкл.
      EEPROM.update(10, 1);  // Firststart  первый старт!.
      EEPROM.update(15, 10); // время сирены. 
      EEPROM.update(20, 0);  // баланс, записываем массив в EEPROM 
      EEPROM.update(0, 1);   // 
      digitalWrite(13, HIGH);
  Serial.println(F("EEPROM != 1/ RESET!")); 
    }
    if (EEPROM.read(0) == 1) {
      Guard      = EEPROM.read(1);   // Охрана
      AlarmRING  = EEPROM.read(2);   // Вызов
      SendSMS    = EEPROM.read(3);   // Отправка смс
      DOORon     = EEPROM.read(4);   // Датчик двери
      PIRon      = EEPROM.read(5);   // Датчик движения
      GASon      = EEPROM.read(6);   // Датчик газа/дыма
      Firststart = EEPROM.read(10);  //
      EEPROM.get(15, AlarmInterval); // время сирены.
  Masterphone();    
    }
  TempC();
   String SIGN = "";         // текущее состояние системы.
   String RING = "";         // текущее состояние вызов.
   String SMS = "";          // текущее состояние смс.
   String Door = "";         // текущее состояние датчика двери.
   String Pir = "";          // текущее состояние датчика движения.
   String Gas = "";          // текущее состояние датчика газа.
   if (Guard == 1) SIGN = String(F("System ->on\n")); else (SIGN = String(F("System->off\n")));
   if (AlarmRING == 1) RING = String(F("Ring->on\n")); else (RING = String(F("Ring->off\n")));
   if (SendSMS == 1) SMS = String(F("SMS->on\n")); else (SMS = String(F("SMS->off\n")));
   if (PIRon == 1) Pir = String(F("Pir->on\n")); else (Pir = String(F("Pir->off\n")));
   if (DOORon == 1) Door = String(F("Door->on\n")); else (Door = String(F("Door->off\n")));
   if (GASon == 1) Gas = String(F("Gas->on\n")); else (Gas = String(F("Gas->off\n")));
    String AlarmBuz = String("Sirena: ") + AlarmInterval + "sec\n";
    String System = SIGN + RING + SMS;                // состояние (вкл/выкл) системы.
    String Sensors = Pir + Door + Gas;                // состояние (вкл/выкл) датчиков.
    LastEvent = System + Sensors + AlarmBuz + temp;              // полное состояние системы и датчиков.
  Serial.println(LastEvent);  
}

void Detect() { /// === чтение датчиков === ///
  DOORState = digitalRead(DOOR);
  PIRState = digitalRead(PIR);
  Smoky = analogRead(GAS);
  
  if (DOORon == 1) {
    if (DOORState == HIGH && DOORFlag == 0) {
      DOORFlag = 1;
  Alarm();                                // 
    }
    if (DOORState == LOW && DOORFlag == 1) {
      DOORFlag = 0;
    }
  }
  if (PIRon == 1) {
    if (PIRState == HIGH && PIRFlag == 0) {
      PIRFlag = 1;
  Alarm();                                // 
    }
    if (PIRState == LOW && PIRFlag == 1) {
      PIRFlag = 0; 
    }
  }
  if (GASon == 1) {
    if ((Smoky > GASThres) && GASFlag == 0) {
      GASFlag = 1;
  Alarm();                                // 
    }
    if ((Smoky < GASThres) && GASFlag == 1) {
      GASFlag = 0; 
    }
  }
}

void Alarm() { /// === запускаем сирену и отправку смс === ///
  if (Guard == 1) {
    previousAlarmMillis = millis();
    digitalWrite(BUZ, LOW);
  Serial.println(F("Alarm!!!"));  
    if (SendSMS == 1) {
      for (int i = 0; i < 5; i++) if (AlarmPhone[i] != 0)  {
        if (DOORFlag == 1) {
  Serial.println(F("Dver' otkrita!"));
sms(String("Dver' otkrita!"), String("+" + String(AlarmPhone[i]))); // смс на все номера
          DOORFlag == 0;
        }
        if (PIRFlag == 1) {
  Serial.println(F("Dvizhenie u dveri!"));
sms(String("Dvizhenie y dveri!"), String("+" + String(AlarmPhone[i])));
        }
        if (GASFlag == 1) {
  Serial.println(F("Gas v dome!"));
sms(String("Gas v dome!"), String("+" + String(AlarmPhone[i]))); // смс на все номера
        }
      }
    }
    if (AlarmRING == 1) {
      mySerial.println("ATD+" + String(AlarmPhone[0]) + ";"); // звоним первому номеру
    }
  }
}

void AlarmPinOff() { /// === если прошло время, отключаем сирену === ///      
  uint16_t currentAlarmMillis = millis();
  //if ((currentAlarmMillis - previousAlarmMillis > AlarmInterval * 1000)) {//Orig!
  if (((currentAlarmMillis - previousAlarmMillis) / 1000 > AlarmInterval) || Guard == 0) {
    digitalWrite(BUZ, HIGH);
//    DOORFlag = 0; //?????? чтоб не отправлять лишних смс о ложных срабатываниях
//    PIRFlag = 0;  //?????? чтоб не отправлять лишних смс о ложных срабатываниях
//    GASFlag = 0;  //?????? чтоб не отправлять лишних смс о ложных срабатываниях
  }
}

void MasterRing() { /// === мастер звонков === //
  if (Guard == 1) GuardOff();     // меняем состояние
  else if (Guard == 0) GuardOn(); // меняем состояние
}

void GuardOff() { /// === выключение сигнализации === ///
    Guard = 0;
    EEPROM.update(1, Guard);
  Serial.println(String(F("System->off. Ring:")) + RingPhone);
  TempC();
    for (int i = 0; i < 5; i++) if (AlarmPhone[i] != 0)  {
sms(String("System->off " + RingPhone + "\n " + temp), String("+" + AlarmPhone[i])); // смс на все номера
  }
}

void GuardOn() { /// === включение сигнализации === ///       
    Guard = 1;
    EEPROM.update(1, Guard);
  Serial.println(String(F("System->on. Ring:")) + RingPhone);
  TempC();
    for (int i = 0; i < 5; i++) if (AlarmPhone[i] != 0)  {
sms(String("System->on " + RingPhone + "\n " + temp), String("+" + AlarmPhone[i])); // смс на все номера
  }
}

void LED() { /// === состояние светодиода === ///
  if (Guard == 1) {                   // если на охране
  uint16_t currentMillis = millis();  // светодиод моргает
  //проверяем не прошел ли нужный интервал, если прошел то
    if (currentMillis - previousMillis > interval) {
      // сохраняем время последнего переключения
      previousMillis = currentMillis;
      // если светодиод не горит, то зажигаем, и наоборот
      if (LedState == HIGH) LedState = LOW;
      else LedState = HIGH;
      digitalWrite(Led, LedState);
    }
  } else digitalWrite(Led, HIGH); // иначе гасим его
}

void ConsolePrint() { /// === кончсольная программа === ///
    val.toLowerCase();
  if (val.indexOf(F("master")) > -1) {   // добавление мастер-номера
    master(val.substring(6, 7).toInt(), val.substring(8, 19));
// sms типа: " master1:79111234567 " - номер в ячейку "1", куда записать номер
  }
  if (val.indexOf(F("balance:")) > -1) { // добавление номера баланса
    balnum(val.substring(8, 13));
// sms типа: " balance:100 " - номер баланса
  }
  if (val.indexOf(F("dell:")) > -1) {    // удаление номера из ячейки     
    dellphone(val.substring(5, 6).toInt());
// sms типа: " dell:1 " - удалить номер из ячейки 1
  }
  if (val.indexOf(F("reset")) > -1) {    // сброс ЕЕПРОМ
  Serial.println(F("Reset System!"));  
    EEPROM.write(0, 0);
  eepromconfig();
  }
  if (val.indexOf(F("info")) > -1) {     // инфо о состоянии системы
  eepromconfig();
  }
  if (val.indexOf(F("sirena:")) > -1) {
    sirena(val.substring(7, 10).toInt());
  }
  if (val.indexOf(F("money")) > -1) {    // запрос баланса
  balance();
  }
  if (val.indexOf(F("systemon")) > -1) {  // вкл сигнализации
  GuardOn();
  }
  if (val.indexOf(F("systemoff")) > -1) { // выкл сигнализации
  GuardOff();
  }
  if (val.indexOf(F("ringon")) > -1) {   // вкл вызов при сработке
    AlarmRING = 1;
    EEPROM.update(2, AlarmRING);
  Serial.println(F("Ring->on"));      
  }
  if (val.indexOf(F("ringoff")) > -1) {  // выкл вызов при сработке
    AlarmRING = 0;
    EEPROM.update(2, AlarmRING);
  Serial.println(F("Ring->off"));  
  }
  if (val.indexOf(F("smson")) > -1) {    // вкл смс при сработке
    SendSMS = 1;
    EEPROM.update(3, SendSMS);
  Serial.println(F("SMS->on"));  
  }
  if (val.indexOf(F("smsoff")) > -1) {   // выкл смс при сработке
    SendSMS = 0;
    EEPROM.update(3, SendSMS);
  Serial.println(F("SMS->off"));  
  }
  if (val.indexOf(F("dooron")) > -1) {  // выкл вызов при сработке
    DOORon = 1;
    EEPROM.update(4, DOORon);
  Serial.println(F("DOOR->on"));  
  }
  if (val.indexOf(F("dooroff")) > -1) {  // выкл вызов при сработке
    DOORon = 0;
    EEPROM.update(4, DOORon);
  Serial.println(F("DOOR->off"));  
  }
  if (val.indexOf(F("piron")) > -1) {  // выкл вызов при сработке
    PIRon = 1;
    EEPROM.update(5, PIRon);
  Serial.println(F("PIR->on"));  
  }
  if (val.indexOf(F("piroff")) > -1) {  // выкл вызов при сработке
    PIRon = 0;
    EEPROM.update(5, PIRon);
  Serial.println(F("PIR->off"));  
  }
  if (val.indexOf(F("gason")) > -1) {  // выкл вызов при сработке
    GASon = 1;
    EEPROM.update(6, GASon);
  Serial.println(F("GAS->on"));  
  }
  if (val.indexOf(F("gasoff")) > -1) {  // выкл вызов при сработке
    GASon = 0;
    EEPROM.update(6, GASon);
  Serial.println(F("GAS->off"));  
  }
}

void MasterSMS() { /// === мастер смс === ///
    val.toLowerCase();
  if (RingPhone == AlarmPhone[0]) {  // команды выполняются только с 0 мастер номера
    if (val.indexOf(F("reset")) > -1)    { // полный сброс ЕЕПРОМ
  sms(String("All System Reset!!!"), String("+" + RingPhone)); // смс на последний номер
  Serial.println(F("Reset System!!!"));          
      EEPROM.write(0, 0);
  eepromconfig();
    }
    if (val.indexOf(F("master")) > -1)  { // добавление мастер-номера
      int tel(val.indexOf(F("master")));
      master(val.substring(tel + 6, tel + 7).toInt(), val.substring(tel + 8, tel + 19));
///// sms типа: " master1:79111234567 " - ячейка + номер
    }
    if (val.indexOf(F("balance:")) > -1) { // добавление номера баланса
      int bal(val.indexOf(F("balance:")));
      balnum(val.substring(bal + 8, bal + 11));
///// sms типа: " balance:100 " - номер баланса
    } 
    if (val.indexOf(F("dell:")) > -1) { // удаление номера из ячейки     
      int del(val.indexOf(F("dell:")));
      dellphone(val.substring(del + 5, del + 6).toInt());
///// sms типа: " dell:1 " - удалить номер из ячейки 1
    } 
  }  
  if (val.indexOf(F("info")) > -1)     { // инфо о состоянии системы
  eepromconfig();
sms(String(LastEvent), String("+" + RingPhone)); // смс на последний номер
  }
  if (val.indexOf(F("phone")) > -1)     { // инфо о состоянии системы
  Masterphone();
    for (int i = 0; i < 5 ; i++) if (AlarmPhone[i] != 0) {
sms(String(String("Master") + i + String(":") + AlarmPhone[i]), String("+" + RingPhone)); // смс на последний номер
    }
  }
  if (val.indexOf(F("sirena:")) > -1) {
    int buz(val.indexOf(F("sirena")));
    sirena(val.substring(buz + 7, buz + 10).toInt());
  }
  if (val.indexOf(F("money")) > -1)    { // запрос баланса
    balance();
  }
  if (val.indexOf(F("systemon")) > -1)  { // вкл сигнализации
    GuardOn();
  }
  if (val.indexOf(F("systemoff")) > -1) { // выкл сигнализации
    GuardOff();
  }
  for (int i = 0; i < 5 ; i++) if (AlarmPhone[i] != 0) { // смс на все номера          
    if (val.indexOf(F("ringon")) > -1)   { // вкл вызов при сработке
      AlarmRING = 1;
      EEPROM.update(2, AlarmRING);
  Serial.println(F("AlarmRing->on"));      
sms(String("Ring->on " + RingPhone  + "\n " + temp), String("+" + AlarmPhone[i])); // смс на все номера
    }
    if (val.indexOf(F("ringoff")) > -1)  { // выкл вызов при сработке
      AlarmRING = 0;
      EEPROM.update(2, AlarmRING);
  Serial.println(F("AlarmRing->off"));  
sms(String("Ring->off " + RingPhone + "\n " + temp), String("+" + AlarmPhone[i])); // смс на все номера
    }
    if (val.indexOf(F("smson")) > -1)    { // вкл смс при сработке
      SendSMS = 1;
      EEPROM.update(3, SendSMS);
  Serial.println(F("SendSMS->on"));  
sms(String("SMS->on " + RingPhone + "\n " + temp), String("+" + AlarmPhone[i])); // смс на все номера
    }
    if (val.indexOf(F("smsoff")) > -1)   { // выкл смс при сработке
      SendSMS = 0;
      EEPROM.update(3, SendSMS);
  Serial.println(F("SendSMS->off"));  
sms(String("SMS->off " + RingPhone + "\n " + temp), String("+" + AlarmPhone[i])); // смс на все номера
    }
    if (val.indexOf(F("dooron")) > -1) {  // выкл вызов при сработке
    DOORon = 1;
    EEPROM.update(4, DOORon);
  Serial.println(F("DOOR->on"));  
sms(String("DOOR->on " + RingPhone + "\n " + temp), String("+" + AlarmPhone[i])); // смс на все номера
    }
    if (val.indexOf(F("dooroff")) > -1) {  // выкл вызов при сработке
    DOORon = 0;
    EEPROM.update(4, DOORon);
  Serial.println(F("DOOR->off"));  
sms(String("DOOR->off " + RingPhone + "\n " + temp), String("+" + AlarmPhone[i])); // смс на все номера
    }
    if (val.indexOf(F("piron")) > -1) {  // выкл вызов при сработке
    PIRon = 1;
    EEPROM.update(5, PIRon);
  Serial.println(F("PIR->on"));  
sms(String("PIR->on " + RingPhone + "\n " + temp), String("+" + AlarmPhone[i])); // смс на все номера
    }
    if (val.indexOf(F("piroff")) > -1) {  // выкл вызов при сработке
    PIRon = 0;
    EEPROM.update(5, PIRon);
  Serial.println(F("PIR -> off"));  
sms(String("PIR -> off " + RingPhone + "\n " + temp), String("+" + AlarmPhone[i])); // смс на все номера
    }
    if (val.indexOf(F("gason")) > -1) {  // выкл вызов при сработке
    GASon = 1;
    EEPROM.update(6, GASon);
  Serial.println(F("GAS->on"));  
sms(String("GAS->on " + RingPhone + "\n " + temp), String("+" + AlarmPhone[i])); // смс на все номера
    }
    if (val.indexOf(F("gasoff")) > -1) {  // выкл вызов при сработке
    GASon = 0;
    EEPROM.update(6, GASon);
  Serial.println(F("GAS->off"));  
sms(String("GAS->off " + RingPhone + "\n " + temp), String("+" + AlarmPhone[i])); // смс на все номера
    }
  } 
}

void balance() { /// === проверка баланса сим-карты === ///
  EEPROM.get(20, Bal);        // считываем массив символов
  delay(1000);
  mySerial.println(String(F("AT+CUSD=1,#")) + Bal + String(F("#,15")));
  Serial.println(String("Balance#") + Bal + "#"); 
}

void Masterphone() { /// === чтение мастер-номеров из EEPROM === ///
    for (int i = 0; i < 5 ; i++) {
      EEPROM.get(Adress[i], Phone);        // считываем массив символов
      AlarmPhone[i] = Phone;
      if (AlarmPhone[i] != 0) {
  Serial.println(String(F("Phone[")) + i + String(F("]:")) + AlarmPhone[i]); 
      }
      Phone[12] = "";                    // обнулим, больше не нужен
    }
    EEPROM.get(100, Phone);        // считываем массив символов
    RingPhone = Phone;
  Serial.println(String(F("Ring [ ]:")) + RingPhone);
    Phone[12] = "";                    // обнулим, больше не нужен
    EEPROM.get(20, Bal);        // считываем массив символов
  Serial.println(String(F("Balance:")) + Bal);
    Firststart = EEPROM.read(10);    // cчитаем из EEPROM
  Serial.println(String(F("Firststart:")) + Firststart);
}

int sirena (int x) {
   if (x < 601) {      // если менее 10 мин, пишем
     EEPROM.put(15, x);
  Serial.println(String("Buz: ") + x + "sec");
sms(String(String("Sirena ") + x + "sec, ok"), String("+" + RingPhone)); // смс на 0 номер.
   } else Serial.println("Max 600sec!");
}

int master (int i, String num) { /// === добавление мастер-номеров === ///
    if (i < 5 && i != 0) {
      num.toCharArray(Phone, 12); // конвертируем
      AlarmPhone[i] = num;        // пишем номер  
  Serial.println(String(F("Master[")) + i + String(F("]:")) + num);
      EEPROM.put(Adress[i], Phone);           // записываем массив в EEPROM 
sms(String(String("Master") + i + ":" + num + " add"), String("+" + RingPhone)); // смс на 0 номер.
sms(String("Master: " + AlarmPhone[i]), String("+" + AlarmPhone[i])); // смс на добавленный номер.
      Phone[12] = "";
    } else Serial.println(F("MAX number 4!"));          // 4 номера максимум! 
    // 0 номер можно удалить только через RESET!!!
}                              

int dellphone (int i) { /// === удаление мастар-номеров === ///
     if (i < 5 && i != 0) {
  Serial.println(String(F("Master")) + i + String(F(" dell")));
sms(String(String("Master") + i + ":" + AlarmPhone[i] + " dell"), String("+" + RingPhone)); // смс на 0 номер
sms(String("Dell: " + AlarmPhone[i]), String("+" + AlarmPhone[i])); // смс на удаленный номер.
       EEPROM.put(Adress[i], 0);
       AlarmPhone[i] = "";   // обнулим номер
  }
}

int balnum (String num) { /// === добавляем номер баланса === ///
    num.toCharArray(Bal, 4);   // конвертируем
  Serial.println(String(F("Balance:")) + Bal);
    EEPROM.put(20, Bal);           // записываем массив в EEPROM 
sms(String("Balance:*" + num + "# Ok"), String("+" + RingPhone)); // смс на 0 номер
}

void TempC() {      /// === измеряем температуру === ///
  byte data[2];
  ds.reset();
  ds.write(0xCC);
  ds.write(0x44);
  delay(750);
  ds.reset();
  ds.write(0xCC);
  ds.write(0xBE);
  data[0] = ds.read();
  data[1] = ds.read();
  int Temp = (data[1] << 8) + data[0];
  Temp = Temp >> 4;
  temp = String(F("Temp: ")) + Temp + String(F("*C."));
}

void Decode7bit(String &instr, String &outstr) { /// === декодирование баланса === ///
  byte reminder = 0;
  int bitstate = 7;
  for (int i=0; i<instr.length(); i++) {
    byte b = instr[i];
    byte bb = b << (7 - bitstate);
    char c = (bb + reminder) & 0x7F;
    outstr += c;
    reminder = b >> bitstate;
    bitstate--;
    if (bitstate == 0) {
      char c = reminder;
      outstr += c;
      reminder = 0;
      bitstate = 7;
    }
  }
}

void InitModem() { /// === инициализация модема === ///
  Serial.println(F("Start GSM"));
  mySerial.begin(9600);  //Скорость порта для связи Arduino с GSM модулем
  waitConnect();
  Serial.println(F("GSM connected"));
  waitRegistration();
  delay(1000); 
}

void waitConnect() { /// === запуск модема === ///
  int countok = 0;
  String str; 
  while(countok < 5) {                   //ждём пять ОК  
    uint32_t ms = millis();
    if( ( ms - msAT ) > 500 || ms < msAT ) {// Событие срабатывающее каждые 500 мс 
      msAT = ms;
//      Serial.println(">>AT");
      mySerial.println(F("AT"));          // посылаем команду
      str = "";
      delay(100);                      // ждём ответа
      while(mySerial.available()) {
        char ch = mySerial.read();
        str += ch;
      } 
//      Serial.println("C>");
//      Serial.println(str);
      if(str.indexOf(F("OK")) > -1)
        countok++;
      else
        countok = 0;
    }
  }  
  Serial.println(F("Turn on AOH:"));
  mySerial.println(F("AT+CLIP=1"));  // включить АОН
  delay(200);
  Serial.println(F("GSM registration"));
  mySerial.println(F("AT+CMGF=1"));
  delay(200); 
  Serial.println(F("Mode GSM:"));
  mySerial.println(F("AT+CSCS=GSM"));  // кодировка текста - GSM
  delay(300);
  mySerial.println(F("AT+CNMI=2,2,0,0,0"));
  delay(300); 
}

void waitRegistration() { /// === регистрация модема в сети === ///
  bool ok = 0;
  String str;
  while(!ok) {  
    uint32_t ms = millis();
    if( ( ms - msAT ) > 500 || ms < msAT ) { // Событие срабатывающее каждые 500 мс
      msAT = ms;
      Serial.println(F(">>AT+CREG?"));
      mySerial.println(F("AT+CREG?"));      //посылаем команду
      delay(100);                           //Ждём ответа
      str = "";
      while(mySerial.available()) {
           char ch = mySerial.read();
           str += ch;
      } 
      Serial.println(F("R>"));
      Serial.println(str);
      if(str.indexOf(F("+CREG:"))>-1)
        ok = 1;
    }
  }  
}

void sms(String text, String phone) { /// === отправка СМС === ///
    Serial.println(F("Start SMS send")); 
    mySerial.println(String(F("AT+CMGS=\"")) + phone + String(F("\"")));
    delay(300);
    mySerial.print(text);
    delay(300);
    mySerial.print((char)26);
    delay(300);
    Serial.println(String(F("SMS sended! Phone: ")) + phone + String(F("; Message: ")) + text);
    delay(5000);
}

SMS команды управления:

reset - сброс на заводские (стираются все телл номера, номер баланса и сброс настроек).

master - добавление мастер номеров, имеет право добавить только мастер номер 0.

           мастер номер 0 - первый позвонивший на сигнализацию.

           пример:    master1:79111234567    сохранить мастер номер 79111234567 в ячейку 1.

balance - номер баланса симкарты, имеет право добавить только мастер номер 0.

          пример:    balance:100    номер баланса *100#.

dell - удаление мастер номеров, кроме 0, имеет право добавить только мастер номер 0.

         пример: dell:2   удалить номер в ячейке 0.

info - информация о состоянии системы.

System->off
Ring->on
SMS->on
Pir->on
Door->on
Gas->on
Sirena->10sec
Temp: 25*C.

phone - информация о прописанных мастер номерах.

Master0:79111112345
Master1:79112645327

sirena - время сирены при сработке 

         пример:   sirena:60    время звучания сирены 1мин

money - проверка баланса SIM

SIM Balance 100r

systemon / systemoff - вкл/выкл сигнализации.

ringon / ringoff - вкл/выкл вызова при сработке сигнализации.

smson / smsoff - вкл/выкл смс информирования при сработке сигнализации, инфо смс доступны.

dooron / dooroff - вкл/выкл контроля датчика двери.

piron / piroff - вкл/выкл контроля датчика движения.

gason / gasoff - вкл/выкл контроля датчика дыма/газа.

команды в консоли аналогичны смс командам.