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 - вкл/выкл контроля датчика дыма/газа.

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

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

Что не так? Где ошибка? Arduino IDE 1.6.6

belousovev
Offline
Зарегистрирован: 14.02.2017

функцию sms можно посмотреть?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

-sergius- пишет:

Что не так? Где ошибка? Arduino IDE 1.6.6

Phone[12] - одиночный символ, а Вы пытаетесь ему присвоить строку "". В этом и ошибка.

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

Эта ошибка выходит при компиляции последнего скетчя от pasha413. Непонимаю каким образом автор этого скетча скомпилировал его рас говорит (все работает, глюков нет)? 

#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);
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, это к автору. Суть ошибки я Вам объяснил, исправлять её Вы, как я понял, самостоятельно не планируете. Тогда к автору.

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

Благодарю за ответ. Попробую исправить сам!

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

У меня норм компиллируется, 1.8.2 версия ide

Скетч использует 21278 байт (69%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 759 байт (37%) динамической памяти, оставляя 1289 байт для локальных переменных. Максимум: 2048 байт.

 

bester
Offline
Зарегистрирован: 25.06.2016

Компиляция прошла

Скетч использует 21278 байт (69%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 759 байт (37%) динамической памяти, оставляя 1289 байт для локальных переменных. Максимум: 2048 байт.
 
-sergius-
Offline
Зарегистрирован: 07.03.2015

Подтверждаю на ide 1.8.2 всё откомпилировалось. Странно почему на версиях 1.6.5 и 16.6 выдаёт ошибку при компиляции.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

То, что разработчики IDE выставили идиотские опции не означает, что это не ошибка. В строках 148 и 165 идёт распашка памяти. Можете не исправлять, если не хотите, но будьте готовы к необъяснимым глюкам программы.

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

В смысле. распашка?
В этих строках хотел обнулить переменную для временного хранения номера.
И, вообще, был бы благодарен за предложения по оптимизации кода с примерами.
прикручиваю ещё lcd 5110 для вывода информации.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

pasha413 пишет:
В смысле. распашка?
Вы присваиваете что-то 12-му элементу массива, у которого этого 12-го элемента просто нет. Значит Вы пишете что-то в постороннюю память.

pasha413 пишет:
В этих строках хотел обнулить переменную для временного хранения номера.

И Вы, конечно, проверяли обнуляется она или нет? Попробуйте запустить вот такой скетч

char Phone[12] = "";

void setup(void) {
	Serial.begin(115200);
	strcpy(Phone, (char *) "123456");
	Serial.print("DO::: Phone="); Serial.println(Phone);
	Phone[12] = "";
	Serial.print("POSLE::: Phone="); Serial.print(Phone);
}
void loop() {}

//
// РЕЗУЛЬТАТ
// DO::: Phone=123456
// POSLE::: Phone=123456
//

Как видите, ни хрена не обнуляется.

Запомните, конструкция "Phone[12] = "";" Неправильна в принципе. При нормальных опциях компилятора - он выдал ошибку и был прав. В восьмых IDE разработчики задушили ошибки, чтобы типа лоха-юзера не беспокоить. Но, Вы хотя бы предупреждения включите! Зайдите в "Настройки", там есть "Предупреждения компилятора". По умолчанию стоит "None" или "Нет". Такая настройка только для страусов - чтоб голову в песок прятать. Включите. Читайте предупрежденя и думайте.

pasha413 пишет:
И, вообще, был бы благодарен за предложения по оптимизации кода с примерами.
К автору. Это не мой код.

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

Спасибо.

включил подробные сообщения компиллятора. выдало:



C:\Users\pzhukov\Documents\Arduino\projekt\arduino\GSM\Alarm\+Alarm eeprom\GSM-alarm_no_TEMP\GSM-alarm_no_TEMP.ino: In function 'void Alarm()':

C:\Users\pzhukov\Documents\Arduino\projekt\arduino\GSM\Alarm\+Alarm eeprom\GSM-alarm_no_TEMP\GSM-alarm_no_TEMP.ino:265:20: warning: statement has no effect [-Wunused-value]

           DOORFlag == 0;

                    ^

C:\Users\pzhukov\Documents\Arduino\projekt\arduino\GSM\Alarm\+Alarm eeprom\GSM-alarm_no_TEMP\GSM-alarm_no_TEMP.ino: In function 'void AlarmPinOff()':

C:\Users\pzhukov\Documents\Arduino\projekt\arduino\GSM\Alarm\+Alarm eeprom\GSM-alarm_no_TEMP\GSM-alarm_no_TEMP.ino:286:58: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]

   if (((currentAlarmMillis - previousAlarmMillis) / 1000 > AlarmInterval) || Guard == 0) {

                                                          ^

C:\Users\pzhukov\Documents\Arduino\projekt\arduino\GSM\Alarm\+Alarm eeprom\GSM-alarm_no_TEMP\GSM-alarm_no_TEMP.ino: In function 'void LED()':

C:\Users\pzhukov\Documents\Arduino\projekt\arduino\GSM\Alarm\+Alarm eeprom\GSM-alarm_no_TEMP\GSM-alarm_no_TEMP.ino:323:40: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]

     if (currentMillis - previousMillis > interval) {

                                        ^

C:\Users\pzhukov\Documents\Arduino\projekt\arduino\GSM\Alarm\+Alarm eeprom\GSM-alarm_no_TEMP\GSM-alarm_no_TEMP.ino: In function 'int sirena(int)':

C:\Users\pzhukov\Documents\Arduino\projekt\arduino\GSM\Alarm\+Alarm eeprom\GSM-alarm_no_TEMP\GSM-alarm_no_TEMP.ino:564:1: warning: no return statement in function returning non-void [-Wreturn-type]

 }

 ^

C:\Users\pzhukov\Documents\Arduino\projekt\arduino\GSM\Alarm\+Alarm eeprom\GSM-alarm_no_TEMP\GSM-alarm_no_TEMP.ino: In function 'int master(int, String)':

C:\Users\pzhukov\Documents\Arduino\projekt\arduino\GSM\Alarm\+Alarm eeprom\GSM-alarm_no_TEMP\GSM-alarm_no_TEMP.ino:577:1: warning: no return statement in function returning non-void [-Wreturn-type]

 }                              

 ^

C:\Users\pzhukov\Documents\Arduino\projekt\arduino\GSM\Alarm\+Alarm eeprom\GSM-alarm_no_TEMP\GSM-alarm_no_TEMP.ino: In function 'int dellphone(int)':

C:\Users\pzhukov\Documents\Arduino\projekt\arduino\GSM\Alarm\+Alarm eeprom\GSM-alarm_no_TEMP\GSM-alarm_no_TEMP.ino:587:1: warning: no return statement in function returning non-void [-Wreturn-type]

 }

 ^

C:\Users\pzhukov\Documents\Arduino\projekt\arduino\GSM\Alarm\+Alarm eeprom\GSM-alarm_no_TEMP\GSM-alarm_no_TEMP.ino: In function 'int balnum(String)':

C:\Users\pzhukov\Documents\Arduino\projekt\arduino\GSM\Alarm\+Alarm eeprom\GSM-alarm_no_TEMP\GSM-alarm_no_TEMP.ino:594:1: warning: no return statement in function returning non-void [-Wreturn-type]

 }

 ^

C:\Users\pzhukov\Documents\Arduino\projekt\arduino\GSM\Alarm\+Alarm eeprom\GSM-alarm_no_TEMP\GSM-alarm_no_TEMP.ino: In function 'void Decode7bit(String&, String&)':

C:\Users\pzhukov\Documents\Arduino\projekt\arduino\GSM\Alarm\+Alarm eeprom\GSM-alarm_no_TEMP\GSM-alarm_no_TEMP.ino:615:18: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]

   for (int i=0; i<instr.length(); i++) {

                  ^

C:\Users\pzhukov\Documents\Arduino\projekt\arduino\GSM\Alarm\+Alarm eeprom\GSM-alarm_no_TEMP\GSM-alarm_no_TEMP.ino: In function 'int CheckPhone()':

C:\Users\pzhukov\Documents\Arduino\projekt\arduino\GSM\Alarm\+Alarm eeprom\GSM-alarm_no_TEMP\GSM-alarm_no_TEMP.ino:169:1: warning: control reaches end of non-void function [-Wreturn-type]

 }

 ^

Скетч использует 21142 байт (68%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 773 байт (37%) динамической памяти, оставляя 1275 байт для локальных переменных. Максимум: 2048 байт.

закоментировал строки Phone[12] = "". все норм работает. в принципе смысла нет обнулять  Phone[12]. т.к она по идее перезаписывается.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, вот, видите. Большинство сообщений выглядит вполне себе тревожно и, скорее всего, говорят об ошибках. Не знаю, какой Вы код компилировали, так что посмотреть не могу. В л.бом случае такая портянка очень полезна. Это профессиональный подход, а не страусиный, который навязывают разработчики IDE.

А про "обнуление" мой пример попробовали? Не обнуляется? Вот, как-то так. Если Вам нужно "обнулить" строку, надо присвоить 0 её нулевому элементу (Phone[0] = 0; или, чуть более "кошерно" Phone[0] = '\0';). Попробуйте.

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

не складывается в LCD5110. пример работает:

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

Nokia_5110 lcd = Nokia_5110(8, 9, 10, 11, 12);

String val;                // переменная для хранения пришедших данных.   

void setup() {
  mySerial.begin(9600); //Скорость порта для связи Arduino с GSM модулем
      lcd.setContrast(50); // 60 is the default value set by the driver
      lcd.clear();
      lcd.print("boot...");
      delay(3000);  
}

void loop() {
      lcd.clear();
      lcd.print("waiting ring...");
      delay(2000);
    if (mySerial.available()) {     // если GSM модем что-то послал.
    while (mySerial.available()) {  // сохраняем входную строку в переменную val.
      char ch = mySerial.read();
      val += char(ch);              // собираем принятые символы в строку
      delay(3);
    } 
    if (val.indexOf(F("+CLIP")) > -1) {      // если обнаружен вызов.
      delay(2000);                           // дадим гудок
      mySerial.println(F("ATH"));            // сбрасываем вызов.
      int ind = val.indexOf("+CLIP:");       // обрезаем номер 
      String num = val.substring(ind + 8, ind + 19); 
      lcd.clear();
      lcd.print(num);
      delay(2000);
      }  
    } val = "";
  
}

а если вставить в мой код, то код перестает работать, смс не читает, и не отправляет

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

Nokia_5110 lcd = Nokia_5110(8, 9, 10, 11, 12);
OneWire ds(13);                             // датчик температуры подключен к 9 пину, подтяжка 4.7кОм на +.
#define DOOR 4                              // концевик двери.
#define PIR 5                               // датчик движения.
#define Led 6                               // состояние системы. моргает - на охране.
#define BUZ 7                               // сирена.
#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;

extern uint8_t SmallFont[]; // малый шрифт (из библиотеки)
extern uint8_t MediumNumbers[]; // средний шрифт для цифр (из библиотеки)
int seconds = 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); 
      lcd.setContrast(50); // 60 is the default value set by the driver
      lcd.clear();
      lcd.print("boot...");
  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() {  /// основной цикл программы.
      lcd.clear();
      lcd.print("waiting ring...");
      delay(1000);
  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 в память. 
      lcd.clear();
      lcd.print(RingPhone);
      delay(2000);
  Serial.println(String(F("RingPhone ")) + RingPhone);          
        return 1;                               // возвращаем 1 - номер наш!
      } 
    } Phone[12] = "";
      return 0;                                  // возвращаем 0 - номер не наш!
  } else if (Firststart == 1) {                  // иначе (если первый старт)
// первый звонивший добавляется как основной мастер номер для управления сигнализацией
      if (val.indexOf("+CLIP: \"7") > -1) {
      int ind = val.indexOf("+CLIP:");       // обрезаем номер 
      String num = val.substring(ind + 8, ind + 19); 
      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);
}

 

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

вроде как подружил LCD5110, но наворотил конечно....

переназначил порты. 

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

Nokia_5110 lcd = Nokia_5110(8, 9, 10, 11, 12);
OneWire ds(13);                  // датчик температуры подключен к 9 пину, подтяжка 4.7кОм на +.
#define GAS 14          // A0    // датчик дыма.
#define DOOR 15         // A1    // концевик двери.
#define PIR 16          // A2    // датчик движения.
#define Led 17          // A3    // состояние системы. моргает - на охране.
#define BUZ 18          // A4    // сирена.

// 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); 
      lcd.setContrast(50); // 60 is the default value set by the driver
      lcd.clear();
      lcd.setCursor(15, 0);
      lcd.print("Alarm  v1.4");
      lcd.setCursor(0, 5);
      lcd.print("Boot...");
      delay(1000);  
  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() {  /// основной цикл программы.
//  LCD();
  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) {                  // иначе (если первый старт)
// первый звонивший добавляется как основной мастер номер для управления сигнализацией
      if (val.indexOf("+CLIP: \"7") > -1) {
      int ind = val.indexOf("+CLIP:");       // обрезаем номер 
      String num = val.substring(ind + 8, ind + 19); 
      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);  
 LCD();
}

void LCD() {
     lcd.clear();
   Guard      = EEPROM.read(1);   // Охрана
     lcd.setCursor(20, 0); lcd.print("Guard ");
     lcd.setCursor(55, 0); lcd.print(Guard);
   AlarmRING  = EEPROM.read(2);   // Вызов
     lcd.setCursor(0, 1); lcd.print("Ring ");
     lcd.setCursor(30, 1); lcd.print(AlarmRING);
   SendSMS    = EEPROM.read(3);   // Отправка смс
     lcd.setCursor(45, 1); lcd.print("SMS ");
     lcd.setCursor(70, 1); lcd.print(SendSMS);
   DOORon     = EEPROM.read(4);   // Датчик двери
     lcd.setCursor(0, 2); lcd.print("DOOR ");
     lcd.setCursor(30, 2); lcd.print(DOORon);
   PIRon      = EEPROM.read(5);   // Датчик движения
     lcd.setCursor(45, 2); lcd.print("PIR ");
     lcd.setCursor(70, 2); lcd.print(PIRon);
   GASon      = EEPROM.read(6);   // Датчик газа/дыма
     lcd.setCursor(0, 3); lcd.print("GAS ");
     lcd.setCursor(30, 3); lcd.print(GASon);
   Firststart = EEPROM.read(10);  //
     lcd.setCursor(45, 3); lcd.print("FSt ");
     lcd.setCursor(70, 3); lcd.print(Firststart);
   EEPROM.get(15, AlarmInterval); // время сирены.
     lcd.setCursor(0, 4); lcd.print("Sirena ");
     lcd.setCursor(40, 4); lcd.print(AlarmInterval);
  TempC();
   lcd.setCursor(0, 5); lcd.print(temp);
}

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);
  }
}

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

void GuardOff() { /// === выключение сигнализации === ///
    Guard = 0;
     lcd.clear();
     lcd.setCursor(0, 2); lcd.print("Guard ");
     lcd.setCursor(3, 3); lcd.print("Off");

  LCD();
    EEPROM.update(1, Guard);
  Serial.println(String(F("System->off. Ring:")) + RingPhone);
    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;
     lcd.clear();
     lcd.setCursor(0, 2); lcd.print("Guard ");
     lcd.setCursor(3, 3); lcd.print("On");
  LCD();
    EEPROM.update(1, Guard);
  Serial.println(String(F("System->on. Ring:")) + RingPhone);
    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)  { // вкл сигнализации
  LCD();
  GuardOn();
  }
  if (val.indexOf(F("systemoff")) > -1) { // выкл сигнализации
  LCD();
  GuardOff();
  }
  for (int i = 0; i < 5 ; i++) if (AlarmPhone[i] != 0) { // смс на все номера          
    if (val.indexOf(F("ringon")) > -1)   { // вкл вызов при сработке
      AlarmRING = 1;
  LCD();
      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;
  LCD();
      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;
  LCD();
      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;
  LCD();
      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;
  LCD();
    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;
  LCD();
    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;
  LCD();
    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;
  LCD();
    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;
  LCD();
    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;
  LCD();
    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);
  LCD();
  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);
}

 

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

pasha413 пишет:
И, вообще, был бы благодарен за предложения по оптимизации кода

Паша, в качестве оптимизации кода - надо обязательно исправить ВСЕ! все ошибки из сообщения #279, ну и проверьте, не налепили ли новых, добавляя дисплей.

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

остались только 

In function 'int sirena(int)':
.ino:566:1: warning: no return statement in function returning non-void [-Wreturn-type]

 

In function 'void Decode7bit(String&, String&)':
.ino:617:21: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]  
for (int i = 0; i < instr.length(); i++) {

вот код: 

#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];      // номера для постановки/снятии с охраны и отправки смс.

int8_t Smoky = LOW;           // Состояние датчика газа.
int GASThres = 400;        // предельная концентрация газа
int8_t AlarmInterval = 10;    // Секунд до отключения "тревожного" пина.
int interval = 1000;       // для мигания Led
int8_t previousMillis = 0;
int8_t 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); 
  Serial.println(F("Alarm v1.2"));                              
  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(("SIM " + decodestr), 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) {                  // иначе (если первый старт)
// первый звонивший добавляется как основной мастер номер для управления сигнализацией
      if (val.indexOf("+CLIP: \"7") > -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(("Master0:" + RingPhone + " Ok"), RingPhone); // смс на звонивший
//  приходит смс в виде: " 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("Dver' otkrita!", AlarmPhone[i]); // смс на все номера
//////          DOORFlag == 0;
        }
        if (PIRFlag == 1) {
  Serial.println(F("Dvizhenie u dveri!"));
sms("Dvizhenie y dveri!", AlarmPhone[i]);
        }
        if (GASFlag == 1) {
  Serial.println(F("Gas v dome!"));
sms("Gas v dome!", AlarmPhone[i]); // смс на все номера
        }
      }
    }
    if (AlarmRING == 1) {
      mySerial.println("ATD+" + String(AlarmPhone[0]) + ";"); // звоним первому номеру
    }
  }
}

void AlarmPinOff() { /// === если прошло время, отключаем сирену === ///      
  int8_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(("System->off " + RingPhone + "\n" + temp), 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(("System->on " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
  }
}

void LED() { /// === состояние светодиода === ///
  if (Guard == 1) {                   // если на охране
  int8_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("All System Reset!!!", 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(LastEvent, RingPhone); // смс на последний номер
  }
  if (val.indexOf(F("phone")) > -1)     { // инфо о состоянии системы
  Masterphone();
    for (int i = 0; i < 5 ; i++) if (AlarmPhone[i] != 0) {
sms((("Master") + i + String(":") + AlarmPhone[i]), 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(("Ring->on " + RingPhone  + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
    if (val.indexOf(F("ringoff")) > -1)  { // выкл вызов при сработке
      AlarmRING = 0;
      EEPROM.update(2, AlarmRING);
  Serial.println(F("AlarmRing->off"));  
sms(("Ring->off " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
    if (val.indexOf(F("smson")) > -1)    { // вкл смс при сработке
      SendSMS = 1;
      EEPROM.update(3, SendSMS);
  Serial.println(F("SendSMS->on"));  
sms(("SMS->on " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
    if (val.indexOf(F("smsoff")) > -1)   { // выкл смс при сработке
      SendSMS = 0;
      EEPROM.update(3, SendSMS);
  Serial.println(F("SendSMS->off"));  
sms(("SMS->off " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
    if (val.indexOf(F("dooron")) > -1) {  // выкл вызов при сработке
    DOORon = 1;
    EEPROM.update(4, DOORon);
  Serial.println(F("DOOR->on"));  
sms(("DOOR->on " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
    if (val.indexOf(F("dooroff")) > -1) {  // выкл вызов при сработке
    DOORon = 0;
    EEPROM.update(4, DOORon);
  Serial.println(F("DOOR->off"));  
sms(("DOOR->off " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
    if (val.indexOf(F("piron")) > -1) {  // выкл вызов при сработке
    PIRon = 1;
    EEPROM.update(5, PIRon);
  Serial.println(F("PIR->on"));  
sms(("PIR->on " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
    if (val.indexOf(F("piroff")) > -1) {  // выкл вызов при сработке
    PIRon = 0;
    EEPROM.update(5, PIRon);
  Serial.println(F("PIR -> off"));  
sms(("PIR -> off " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
    if (val.indexOf(F("gason")) > -1) {  // выкл вызов при сработке
    GASon = 1;
    EEPROM.update(6, GASon);
  Serial.println(F("GAS->on"));  
sms(("GAS->on " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
    }
    if (val.indexOf(F("gasoff")) > -1) {  // выкл вызов при сработке
    GASon = 0;
    EEPROM.update(6, GASon);
  Serial.println(F("GAS->off"));  
sms(("GAS->off " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
////sms((val + RingPhone + "\n " + temp), 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("Sirena ") + x + "sec, ok"), 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("Master") + i + ":" + num + " add"), RingPhone); // смс на 0 номер.
sms(("Master: " + AlarmPhone[i]), 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("Master") + i + ":" + AlarmPhone[i] + " dell"), RingPhone); // смс на 0 номер
sms(("Dell: " + AlarmPhone[i]), 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(("Balance:*" + num + "# Ok"), 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) { /// === отправка СМС === ///
    phone = "+" + 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);
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Так исправьте, чего сюда-то вываливать.

Baks
Baks аватар
Offline
Зарегистрирован: 11.01.2016

Молодцы ребята, схему не скиньте как и что подключали?

#define DOOR 4 // концевик двери. Какой геркон тут используете? Питание 5 вольт на них или 12 и через промежуточное реле?

#define PIR 5 // датчик движения. Какой датчик используете ? Ссылочку можно?

#define Led 8 // состояние системы. моргает - на охране. Это обычный светодиод ?

#define BUZ 10 // сирена. Активный или пассивный буззер?

#define GAS A0 // датчик дыма. Какой датчик задымления? Тоже бы ссылочка не помешала.

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

датчик двери - геркон нормально замкнутый, одним концом на "-" второй на 4pin.

PIR датчик движения -  HC-SR501 с установкой потенциометров в минимум.

сечас  пришел PIRmini.PIR mini

работает на расстоянии до 3м, 

для моих нужн самое то.

Led - светодиод через резистор 330 Ом на "+5V", вторым концом 8pin.

BUZ - сирена, на время теста стоит светодиод через резистор 330 Ом на "+5V", вторым концом 10pin,

далее будет 5V реле, контакты реле подают 12V на сирену.

GAS - датчик широкого спектра газов MQ-2, подключен аналоговый пин, цифровой не используется.

со ссылками пока не могу помочь. все бралось давно, найти по названию проще некуда

схему постараюсь чуть позже накидать.

Baks
Baks аватар
Offline
Зарегистрирован: 11.01.2016

Я посмотрел ваш код. Довольно таки не плохо получается. Есть один затык в коде. Отсутствует проверка на обнуление милис нужно одну строчку добавить. Могу подсказать какую если хотите... И ещё возможно не заметил удаление входящих смс, память у модема не безразмерная, там одной командой делается...
И кстати я не совсем понял на каком модеме вы настраиваете? Ссылочку если можно)))

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

конечно. подскажите.

модем Ai-Thinker A6, заметил что у него лучше сигнал. Сейчас пришел A6C  с камерой.

про удаление смс знаю. команда AT+CMGD=1,4 , но смс не сохраняются в память, а сразу выводятся в терминал. В любом случае подтверждение смс команд с ответным смс от сигнализации.

Baks
Baks аватар
Offline
Зарегистрирован: 11.01.2016

Вот тот первая строчка проверка на сброс милис http://arduino.ru/forum/programmirovanie/millis-sbrasyvaetsya-na-nol-pri...
У меня без проверки чуть котел зимой не разорвало, насос не включился..
И да по поводу сохранённых смс там есть команда вывести цыфру количества смс-ок, у меня на sim800 она почему-то постоянно увеличивается )))

Baks
Baks аватар
Offline
Зарегистрирован: 11.01.2016

Вот тот первая строчка проверка на сброс милис http://arduino.ru/forum/programmirovanie/millis-sbrasyvaetsya-na-nol-pri...
У меня без проверки чуть котел зимой не разорвало, насос не включился..
И да по поводу сохранённых смс там есть команда вывести цыфру количества смс-ок, у меня на sim800 она почему-то постоянно увеличивается )))

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Baks пишет:
Вот тот первая строчка проверка на сброс милис http://arduino.ru/forum/programmirovanie/millis-sbrasyvaetsya-na-nol-pri...

Кто-нибудь, когда-нибудь запретит заменять батарейки?

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

на модеме А6 по умолчанию смс не сохраняются в память

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

есть интересная штука "Real Time Clock", как раз можно работать без millis(). но пока не разобрался...

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

А если сделать прерывание для мигания и сирены:

#define DOOR 4             // концевик двери.
#define Led 11             // состояние системы. моргает - на охране.
#define BUZ 12             // сирена.
int8_t DOORState = LOW;    // Состояние концевика двери.
int8_t LedState = HIGH;    // Состояние светодиода.
int8_t DOORFlag = 0;       // флаг состояние датчика двери.
int8_t timeflag = 0;       
int AlarmInterval = 10;    // Секунд до отключения "тревожного" пина, max 300сек 
int interval = 1000;       // для мигания Led
int previousMillis = 0;
int TIME;                  //

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

void loop() {
 LED();
 DOORState = digitalRead(DOOR);
 if (DOORState == HIGH && DOORFlag == 0) { // если открыли дверь
    DOORFlag = 1;
    digitalWrite(BUZ, LOW);       // включаем сирену
    timeflag = 1;
 } 
 if (DOORState == LOW && DOORFlag == 1) { // если открыли дверь
    DOORFlag = 0;
 }
 if (TIME >= AlarmInterval) {
    digitalWrite(BUZ, HIGH);
    TIME = 0;                     // сбрасываем счетчик
    timeflag = 0;
  }
}

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

 

Baks
Baks аватар
Offline
Зарегистрирован: 11.01.2016

Real Time Clock считаю что не подходит так как модуль может глюкануть и каким будет реакция на это у ардуинки трудно предусмотреть.
По прерыванию я не советчик особо не пользовался этим, но можно почитать на форуме много тем по прерыванию.

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

Baks пишет:
Вот тот первая строчка проверка на сброс милис

Не тиражируйте бред, если правильно написать проверку времени, "сброс millis" проверять не нужно.

pasha413 пишет:

на модеме А6 по умолчанию смс не сохраняются в память

Паша, это легко настраивается. Я вам уже писал - у меня на А6 СМС отлично сохраняются.

pasha413 пишет:

есть интересная штука "Real Time Clock", как раз можно работать без millis(). но пока не разобрался...

где, в А6? - да есть. Но у нее время при ресете сбрасывается, так что за ним нужно следить. А так да, удобная вещь, у меня в коде используется.

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

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

Baks
Baks аватар
Offline
Зарегистрирован: 11.01.2016

Dell