Удаленное управление домом по GSM/GPRS

Введение:

В этом уроке мы создадим систему удаленного управления домом по смс, используя GSM/GPRS Shield.

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

Видео:

Нам понадобится:

Для реализации проекта нам необходимо установить библиотеки:

  • iarduino_GSM- для работы с GSM/GPRS Shield;
  • Библиотеки SoftwareSerial входит в базовый набор Arduino IDE и не требует установки;

О том, как устанавливать библиотеки, Вы можете ознакомиться на странице Wiki - Установка библиотек в Arduino IDE.

Описание работы системы удалённого управления:

    • После подачи питания дождитесь получения смс с уведомлением о том, что инициализация прошла успешно и модем GSM зарегистрировался в сети. После этого устройство готово к работе.
    • Устройство может принимать сообщения, содержащие параметры "Действие", "Устройство", "Яркость".
    • Для управления устройством вам необходимо сформировать смс по следующему алгоритму:
      • Основные функции:
        • [ДЕЙСТВИЕ] [УСТРОЙСТВО];
      • Дополнительные функции:
        • [ЗНАЧЕНИЕ%]; — задаём значение ШИМ-сигнала для яркости/скорости;
    • После правильно написанной и отправленной информации дождитесь обратного сообщения с уведомлением о том, что ваша команда прошла.

    Схема сборки:

    Arduino / Piranha UNO:

    Batery Shield:

    Установите Battery Shield на Arduino / Piranha UNO:
    Во время установки Battery Shield должен быть в выключенном состоянии.

    GSM/GPRS Shield:

    На Battery Shield установите GSM/GPRS Shield A6:

    На плате GSM/GPRS Shield A6 имеется слот для SIM-карт и переключатель UART. Установите SIM-карту в слот, выберите положение переключателя RX-7/TX-8.

    Trema Shield:

    На GSM/GPRS Shield A6 установите Trema Shield:

    Линейный привод:

    Подключим линейный привод к Trema Shield. Для этого необходимо 2 электромеханических реле подключить к выводу 4.

    После этого установить перемычки согласно рисунку.

    Далее подключить к реле линейный привод и подвести внешнее питание 12В.

    Лампочки:

    Подключите к выводу 2 и 3 Trema Shield 2 твердотельных реле.

    Далее согласно схеме подключите к реле лампочки и питание 220В.

    Будьте предельно внимательны и осторожны!

    Светодиодная лента:

    Подключите к 6 выводу Trema Shield Trema-модуль Силовой ключ, а к нему подключите светодиодную ленту, пустив провод питания ленты (красный) напрямую к источнику питания 12В, а провод GND ленты (чёрный) в разрыв через Trema-модуль Силовой ключ.

    Вентилятор(кулер):

    Подключите к 5 выводу Trema Shield Trema-модуль Силовой ключ, а к нему подключите вентилятор (кулер), пустив провод питания вентилятора (красный) напрямую к источнику питания 12В, а провод GND вентилятора (чёрный) в разрыв через Trema-модуль Силовой ключ.

    Код программы (скетч):

    В скетче используются библиотеки iarduino_GSM и SoftwareSerial.

                  // БИБЛИОТЕКИ
    #include       <iarduino_GSM.h>                                                                       // Подключаем библиотеку iarduino_GSM для работы с GSM/GPRS Shield.
    #include       <SoftwareSerial.h>                                                                     // Подключаем библиотеку SoftwareSerial для программной реализации шины UART.
    iarduino_GSM    gsm;                                                                                  // Создаём объект gsm для работы с функциями и методами библиотеки iarduino_GSM.
    SoftwareSerial  softSerial(7, 8);                                                                     // Создаём объект softSerial для работы по программной шине UATR, указывая выводы RX и TX платы Arduino (выводы 7 и 8)
                  // ПЕРЕМЕННЫЕ
    uint8_t         Sum        = 0;                                                                       // Переменная для хранения процентного значения ШИМ-сигнала
                  // Для отправки СМС о удачном запуске устройства, укажите в строке ниже номер телефона без пробелов.
    char            SMSnum[13] = "+7_ВАШ_НОМЕР_ТЕЛЕФОНА";                                                 // Объявляем строку для хранения номера отправителя SMS сообщений.
    char            SMStxt[161];                                                                          // Объявляем строку для хранения текста принятых SMS сообщений.
    String          strSMStxt;                                                                            // переменная типа String для более удобной работы
    uint8_t         flgFunc;                                                                              // флаг наличия действия
    uint8_t         flgDev;                                                                               // флаг наличия устройства
    uint8_t         flgPWM;                                                                               // флаг наличия ШИМ
    uint8_t         lvlPWM;                                                                               // Переменная количества символов в строке
    const char*     Func[2][5] = {{"ВКЛЮЧИТЬ", "ВЫКЛЮЧИТЬ"},                                              // Двумерный массив с функциями и устройствами
                                  {"СВЕТ КУХНЯ" , "СВЕТ КОМНАТА", "ДВЕРЬ", "ВЕНТИЛЯТОР", "ПОДСВЕТКА"}};   // 
    const char      Pins[]     =  {     2,             3,            4,         5,           6       };   // Массив с номерами выводов устройств
                                                                                                          // 
    void setup() {                                                                                        //
                    // Инициируем GSM/GPRS Shield и проверяем его готовность к работе:
      gsm.begin(softSerial);                                                                              // Инициируем работу GSM/GPRS Shield, указывая объект шины UART.
      while (gsm.status() != GSM_OK) { delay(1000); }                                                     // Ждём завершения регистрации модема в сети оператора связи.
                    // Установка кодировки для символов Кириллицы:
      gsm.TXTsendCodingDetect("п");                                                                       // Выполняем автоопределение кодировки скетча для отправки текста на Русском языке.
                    // Отправка сообщения об удачном запуске:
      gsm.SMSsend( F("Инициализация прошла успешно."), SMSnum);                                           // Данная строка будет отвечать отправителю указанным SMS сообщением.
                    // Настраиваем выводы
      pinMode(Pins[0],   OUTPUT);                                                                         // настройка вывода на работу в режиме выхода
      pinMode(Pins[1],   OUTPUT);                                                                         // настройка вывода на работу в режиме выхода
      pinMode(Pins[2],   OUTPUT);                                                                         // настройка вывода на работу в режиме выхода
      pinMode(Pins[3],   OUTPUT);                                                                         // настройка вывода на работу в режиме выхода
      pinMode(Pins[4],   OUTPUT);                                                                         // настройка вывода на работу в режиме выхода
      digitalWrite(Pins[0], LOW);                                                                         // устанавливаем на выходе значение сигнала равным LOW
      digitalWrite(Pins[1], LOW);                                                                         // устанавливаем на выходе значение сигнала равным LOW
      digitalWrite(Pins[2], LOW);                                                                         // устанавливаем на выходе значение сигнала равным LOW
      digitalWrite(Pins[3], LOW);                                                                         // устанавливаем на выходе значение сигнала равным LOW
      digitalWrite(Pins[4], LOW);                                                                         // устанавливаем на выходе значение сигнала равным LOW
      flgFunc = 20;                                                                                       // Сбрасываем флаг
      flgDev  = 20;                                                                                       // Сбрасываем флаг
      flgPWM  =  0;                                                                                       // Сбрасываем флаг
    }                                                                                                     // 
                                                                                                          // 
    void loop () {                                                                                        // 
      if (millis() % 1000 < 100) {                                                                        // Выполняем код в теле оператора if первые 100 мс каждой секунды.
        delay(100);                                                                                       // Устанавливаем задержку в 100 мс, чтоб не выполнить код более 1 раза за секунду.
        if (gsm.SMSavailable()) {                                                                         // Функция SMSavailable() возвращает количество входящих непрочитанных SMS сообщений.
          gsm.SMSread(SMStxt, SMSnum);                                                                    // Читаем SMS сообщение в ранее объявленные переменные (текст SMS сообщения, адрес отправителя, дата отправки, идентификатор SMS, количество SMS, номер SMS).
          strSMStxt = SMStxt;                                                                             // Присваиваем массиву atrSMStxt значения массива SMStxt для дальнейшей проверки на совпадения
          for (int m = 0; m < (sizeof(Func[0]) / 2); m++) {                                               // проверяем в цикле, совпадает ли команда из массива с тем, что пришло в СМС
            if (strSMStxt.indexOf(Func[0][m]) > -1 && *Func[0][m] != 0) {                                 // если совпадения есть, то
              flgFunc = m;                                                                                // присваиваем флагу порядковый номер совпавшего слова из массива Func
              for (int i = 0; i < (sizeof(Func[1]) / 2); i++) {                                           // проверяем в цикле, совпадает ли имя устройства из массива с тем, что пришло в СМС
                if (strSMStxt.indexOf(Func[1][i]) > -1 && *Func[1][i] != 0) {                             // если совпадения есть и это не пустая строка, то
                  flgDev = i;                                                                             // присваиваем флагу порядковый номер совпавшего слова из массива Device
                  if (strchr(SMStxt, '%')) {                                                              // проверяем, есть ли в тексте СМС символ %
                    flgPWM = 1;                                                                           // и если есть, то устанавливаем флаг
                  }                                                                                       //
                }                                                                                         //
              }                                                                                           //
            }                                                                                             //
          }                                                                                               //
          if (flgPWM == 1) {                                                                              // если установлен флаг flgPWM, то
            lvlPWM = uint8_t(strchr(SMStxt, '%' ) - SMStxt);                                              // определяем количество символов в строке до совпадения с символом %
            if (SMStxt[lvlPWM - 1] >= '0' && SMStxt[lvlPWM - 1] <= '9') {                                 // Проверяем, является ли символ, расположенный в строке на 1 позицию левее символа %, цифрой от 0 до 9, и если да, то
              Sum = uint8_t(SMStxt[lvlPWM - 1] - '0');                                                    // прибавляем эту цифру к переменной (единицы)
              if (SMStxt[lvlPWM - 2] >= '0' && SMStxt[lvlPWM - 2] <= '9') {                               // Проверяем, является ли символ, расположенный в строке на 2 позиции левее символа %, цифрой от 0 до 9, и если да, то
                Sum += uint8_t((SMStxt[lvlPWM - 2] - '0') * 10);                                          // прибавляем эту цифру к переменной, умножив на 10 (десятки)
                if (SMStxt[lvlPWM - 3] > '0' && SMStxt[lvlPWM - 3] <= '1') {                              // Проверяем, является ли символ, расположенный в строке на 3 позиции левее символа %, цифрой от 0 до 1, и если да, то
                  Sum += uint8_t((SMStxt[lvlPWM - 3] - '0') * 100) ;                                      // прибавляем эту цифру к переменной, умножив на 100 (сотни)
                } else                                                                                    // иначе проверяем, что
                  if (SMStxt[lvlPWM - 3] >= '2' && SMStxt[lvlPWM - 3] <= '9') {                           // число "сотен" не больше 1, и если больше то
                    flgPWM = 0;                                                                           // сбрасываем флаг ШИМ
                  }                                                                                       // 
              }                                                                                           //
            }                                                                                             //
          }                                                                                               //
          if (flgFunc != 20) {                                                                            // если флаг flgFunc установлен, то
            switch (flgFunc) {                                                                            // проверяем значение флага flgFunc с определёнными в операторе case
              case 0:                                                                                     // Если 0 - значит указано действие ВКЛЮЧИТЬ
                if (flgDev != 20) {                                                                       // Если установлен флаг наличия устройства, то
                  if (flgPWM == 1) {                                                                      // проверяем флаг ШИМ. Если он установлен, то
                    uint8_t mapPWM = map(Sum, 0, 100, 0, 255);                                            // переопределяем множество для ШИМ и
                    analogWrite(Pins[flgDev], mapPWM );                                                   // подаём ШИМ-сигнал на вывод и
                    gsm.SMSsend(F("Процент задан!"), SMSnum);                                             // отправляем сообщение об успешном выполнении.
                    Sum    = 0;                                                                           // сбрасываем количество процентов для задания ШИМ-сигнала после выполнения
                    flgPWM = 0;                                                                           // сбрасываем флаг ШИМ после выполнения
                  }                                                                                       //
                  else {                                                                                  // Если же флага ШИМ нет, то
                    digitalWrite(Pins[flgDev], HIGH);                                                     // подаём высокий сигнал на вывод для включения и
                    gsm.SMSsend(F("Устройство включено!"), SMSnum);                                       // отправляем сообщение об успешном выполнении.
                  }                                                                                       //
                  flgDev = 20;                                                                            // сбрасываем флаг устройства после выполнения
                } else {                                                                                  // если в СМС не указано устройство, то
                  gsm.SMSsend(F("Что включить?"), SMSnum);                                                // отправляем об этом сообщение
                }                                                                                         // 
                flgFunc = 20;                                                                             // сбрасываем флаг действия после выполнения
                break;                                                                                    //
              case 1:                                                                                     // Если 1 - значит указано действие ВЫКЛЮЧИТЬ
                if (flgDev != 20) {                                                                       // Если установлен флаг наличия устройства, то
                  digitalWrite(Pins[flgDev], LOW);                                                        // подаём низкий сигнал на вывод для выключения
                  gsm.SMSsend(F("Устройство выключено!"), SMSnum);                                        // и отправляем сообщение об успешном выполнении.
                  flgDev = 20;                                                                            // сбрасываем флаг устройства после выполнения
                } else {                                                                                  // если в СМС не указано устройство, то
                  gsm.SMSsend(F("Что выключить?"), SMSnum);                                               // отправляем об этом сообщение
                }                                                                                         // 
                flgFunc = 20;                                                                             // сбрасываем флаг действия после выполнения
                break;                                                                                    //
            }                                                                                             //
          } else {                                                                                        //
            gsm.SMSsend(F("Ошибка в тексте!"), SMSnum);                                                   // Если текст пришёл не верный, то отправляем об этом сообщение
          }                                                                                               //
        }                                                                                                 //
      }                                                                                                   //
    }                                                                                                     //

    Алгоритм работы скетча:

    До кода void setup() определяются номера выводов, объявляются переменные и функции, подключаются библиотеки, и создаются объекты для работы с ними.

    Перед загрузкой скетча не забудьте задать в переменной SMSnum номер телефона, куда будет приходить смс-уведомление о пройденной идентификации!

    В коде void setup() конфигурируются выбранные выводы, инициируется работа GSM/GPRS Shield, выполняется цикл ожидания готовности GSM/GPRS Shield к работе (регистрация в сети оператора). И после выполнения всех указанных действий выполняется оповещение о готовности к работе, путем отправки смс на указанный номер.

    Код void loop() выполняется только при получении смс сообщения. Сам блок разделён на две основные части: приём входящих сообщений и выполнение указанных в сообщении действий.

    Приём входящих сообщений состоит из следующих действий:

    • Считывание сообщения из памяти SIM-карты, после чего функция автоматически их оттуда удаляет.
    • После считывания сообщения запускается цикл, в котором текст сообщения проверяется на наличие в нём управляющих команд;
    • Если команда найдена, то внутри него запускается второй цикл, в котором текст так же проверяется, но уже на наличие в нём имени устройства;
    • Если имя устройства найдено, то выполняется проверка на наличие дополнительного параметра, указанного с символом "%" - процент (от 0 до 100) яркости/скорости, с которым будет работать указанное устройство.
    • Если дополнительный параметр был указан, то ставится флаг о его наличии в полученном смс.

    Выполнение указанных в сообщении действий:

    • После того, как все флаги были выставлены, происходит проверка наличия флага дополнительного параметра. Если он присутствует, тогда выполняется вычисление значения числа, указанного перед символом %:
      • Для этого мы находим количество символов в строке, расположенных слева от символа %;
      • Полученное число покажет нам порядковый номер символа % в массиве strSMStxt;
      • Для того, чтобы узнать, какое значение было указано, проверим 3 ближайшие ячейки массива, расположенные слева от символа %:
        • Если 1 ячейка, расположенная ближе всего к символу %, содержит число от 0 до 9, то тогда мы заносим её значение в переменную Sum. Это будет разряд "единицы";
        • После этого внутри первой проверки выполняется вторая проверка 2 ячейки на наличие числа от 0 до 9. Если число найдено, то оно умножается на 10 и прибавляется к переменной Sum. Это будет разряд "десятки";
        • После этого внутри второй проверки производится третья проверка 3 ячейки. Если в ней найдена 1, то она умножается на 100 и прибавляется к переменной Sum. Это будет разряд "сотни".
        • Если же в третьей проверке окажется, что в "сотнях" указано больше 1, то флаг flgPWM будет сброшен;
    • Выполняется проверка наличия флага flgFunc:
      • Если флаг flgFunc был установлен, тогда выполняется проверка наличия флага flgDev:
        • Если флаг flgDev был установлен, тогда выполняется проверка наличия флага flgPWM:
          • Если флаг flgPWM установлен, тогда выполняется подача ШИМ-сигнала на вывод с указанным в сообщении устройством и отправка смс с уведомлением об успешном выполнении;
          • Если флаг flgPWM не установлен, тогда выполняется подача сигнала HIGH на вывод с указанным устройством и отправка смс с уведомлением об успешном выполнении;
        • Если флаг flgDev не установлен, тогда производится отправка смс уведомления о том, что в сообщении не указано устройство;
      • Если флаг flgFunc не установлен, тогда производится отправка смс уведомления о том, что пришло ошибочное сообщение.

    Ссылки:

    Обсуждение