GSM Shield SIM 900R от амперки -все вопросы сюда!

Тема в разделе "Arduino & Shields", создана пользователем НКВД, 30 янв 2016.

  1. ATishchenko

    ATishchenko Нерд

    Пару секунд, если батарейка нормальная :) Педантизм, сорри. Можно и не заморачиваться, но возможность иметь приятно.
     
  2. s1984i

    s1984i Нерд

    Спасибо
     
    Последнее редактирование: 30 сен 2016
  3. P-A

    P-A Нуб

    Несколько секунд - мне подходит. конечно же хотелось не заморачиваться и автоматически корректировать время но Ваш вариант мне нравится простотой исполнения (могу установить любое время, которое мне нужно). СПАСИБО за идею. А можно посмотреть часть кода по получению в смс и корректировки часов. Простой код по преобразованию смс в код для корректировки в голову сразу не приходит. Если позволите воспользуюсь Вашим вариантом.
     
  4. ATishchenko

    ATishchenko Нерд

    У меня все на самом деле тривиально:
    Код (Javascript):

    gprs.on("sms", function (index) {
      GLock = true;
      gprs.smsRead(index, parseCommand);
    });

    function parseCommand(err, sms) {
    ...
    var cmd = sms.text.toUpperCase().trim().split(" ");
    switch (cmd[0]) {
    case "ST":
      gprs.setTime(Date(cmd[1]), function(err) {
        if (err !== undefined) {
          print("Unable to set time: "+err.toString());
        } else {
          print("Time corrected");
        }
      });
      response = "setTime request to: "+cmd[1];
      break;
    ...
     
    Я умышленно в на этой стадии не устраиваю жестких проверок на ошибки, синтаксис и прочее. В ответ летит смс с текстом в response. Ничего особенного. (только разрешаю это безобразие со своего телефона - вот уж где засада... Если вдруг сдох или деньги закончились - пока проблема не решится, система будет ко мне глуховата и ручной режим не поможет.)
     
  5. P-A

    P-A Нуб

    Спасибо, попробую Ваш подход реализовать у себя. Также есть идея разместить до 4-х номеров телефона в энергонезависимой памяти и сравнивая с ними получать одно разрешение на действия и отчёта в направлении того номера, с которого пришло смс. Попытаюсь организовать по смс со специальным кодовым словом изменение любого из 3-х номеров (4-ре минус с которого приходит запрос на изменение) в энергонезависимой памяти ардуинки.
     
  6. Код (C++):
    // библиотека для работы с GPRS устройством
    #include <GPRS_Shield_Arduino.h>
    // библиотека для эмуляции Serial порта
    // она нужна для работы библиотеки GPRS_Shield_Arduino
    #include <SoftwareSerial.h>
    // длина сообщения
    #define MESSAGE_LENGTH 160
    // текст сообщения о включении розетки
    #define MESSAGE_ON  "Power is On"
    // текст сообщения о выключении розетки
    #define MESSAGE_OFF  "Power is Off"
    // текст сообщения об ошибке распознавания команды
    #define MESSAGE_ERROR  "Error...unknown command!"
    // пин, к которому подключено реле
    #define RELAY 5
    // номер сообщения в памяти сим-карты
    int messageIndex = 0;
    // текст сообщения
    char message[MESSAGE_LENGTH];
    // номер, с которого пришло сообщение
    char phone[16];
    // дата отправки сообщения
    char datetime[24];
    bool stateRelay = false;
    // создаём объект класса GPRS и передаём ему скорость 9600 бод;
    // с помощью него будем давать команды GPRS шилду
    GPRS gprs(9600);
    void setup()
    {
      // настраиваем пин реле в режим выхода,
      pinMode(RELAY, OUTPUT);
      // подаём на пин реле «низкий уровень» (размыкаем реле)
      digitalWrite(RELAY, LOW);
      // включаем GPRS-шилд
      gprs.powerUpDown();
      // открываем последовательный порт для мониторинга действий в программе
      Serial.begin(9600);
      while (!Serial) {
        // ждём, пока не откроется монитор последовательного порта
        // для того, чтобы отследить все события в программе
      }
      // проверяем, есть ли связь с GPRS-устройством
      while (!gprs.init()) {
        // если связи нет, ждём 1 секунду
        // и выводим сообщение об ошибке;
        // процесс повторяется в цикле,
        // пока не появится ответ от GPRS устройства
        delay(1000);
        Serial.print("Init error\r\n");
      }
      // вывод об удачной инициализации GPRS Shield
      Serial.println("GPRS init success");
    }
    void loop()
    {
      // проверяем наличие непрочитанных сообщений
      // и находим их номер в памяти сим-карты
      messageIndex = gprs.isSMSunread();
      if (messageIndex > 0) {
        // если есть хотя бы одно непрочитанное сообщение,
        // читаем его
        gprs.readSMS(messageIndex, message, MESSAGE_LENGTH, phone, datetime);
        // Удаляем прочитанное сообщение из памяти Сим-карты
        gprs.deleteSMS(messageIndex);
        // выводим номер, с которого пришло смс
        Serial.print("From number: ");
        Serial.println(phone);
        // выводим дату, когда пришло смс
        Serial.print("Datetime: ");
        Serial.println(datetime);
        // выводим текст сообщения
        Serial.print("Recieved Message: ");
        Serial.println(message);
        // вызываем функцию изменения состояния реле
        // в зависимости от текста сообщения
        setRelay(phone, message);
      }
    }
    void setRelay(char f_phone[], char f_message[])
    {
      if (strcmp(f_message, "On") == 0) {
        // если сообщение — с текстом «On»,
        // выводим сообщение в Serial
        // и подаём на замыкаем реле
        Serial.println("OK! Power On");
        digitalWrite(RELAY, HIGH);
        stateRelay = true;
        // на номер, с которого пришёл запрос,
        // отправляем смс с текстом о включении питания
        gprs.sendSMS(f_phone, MESSAGE_ON);
      } else if (strcmp(f_message, "Off") == 0) {
        // если пришло сообщение с текстом «Off»,
        // выводим сообщение в Serial
        // и размыкаем реле
        Serial.println("OK! Power Off");
        digitalWrite(RELAY, LOW);
        stateRelay = false;
        // на номер, с которого пришёл запрос
        // отправляем смс с текстом о выключении питания
        gprs.sendSMS(f_phone, MESSAGE_OFF);
      } else if (strcmp(f_message, "State") == 0) {
        // если пришло сообщение с текстом «State»,
        // отправляем сообщение с состоянием реле
        if (stateRelay) {
          Serial.println("State: Power On");
          gprs.sendSMS(f_phone, MESSAGE_ON);
        } else {
          Serial.println("State: Power Off");
          gprs.sendSMS(f_phone, MESSAGE_OFF);
        }
      } else {
        // если сообщение содержит неизвестный текст,
        // отправляем сообщение с текстом об ошибке
        Serial.println("Error... unknown command!");
        gprs.sendSMS(f_phone, MESSAGE_ERROR);
      }
    }
    Здравствуйте! Посоветуйте пожалуйста что делать. Собрал такую штуку: на китайском Arduino Uno GSM Shield SIM 900 R от амперки плюс реле (Troyka - модуль ) на 16 А, 250 В для коммутации нагрузки.
    Смысл поделки: посылаю смс с билайн (сим карта и в модуле и на телефоне билайн) реле включается, но не всегда. Отчёт о состоянии реле не приходит, хотя в скетче прописана такая функция, если я правильно понимаю.
    Подскажите пожалуйста как сделать чтобы отчёт пришёл. И может кто знает как к этой системе датчик температуры ещё приделать. Заранее спасибо!
     

    Вложения:

    • smart-power.ino
      Размер файла:
      5,3 КБ
      Просмотров:
      399
  7. P-A

    P-A Нуб

    Доброго! Да, отчёт должен приходить. Похоже библиотечные штучки. А что показывает монитор в момент, когда приходит смс? Если в мониторе норм, то попробуйте, в качестве эксперимента поставить задержки по 300 ms перед каждой командой обращения к gprs.sendSMS да и после тоже можно. Могу ошибаться, но похоже тормозит общение с gprs. потом с помощью монитора можно убрать лишние и оптимизировать время задержки.
     

  8. Монитор говорит при включении следующее:
    AT+CMGL="REC UNREAD",1
    AT+CMGF=1
    AT+CMGR=2
    AT+CMGD=2
    From number: +79053763630
    Datetime: 16/10/04,13:58:16+12
    Recieved Message: On
    OK! Power On
    AT+CMGF=1
    AT+CMGL="REC UNREAD",1
     


  9. При отключении приходится последнее время два раза посылать:
    AT+CMGL="REC UNREAD",1
    AT+CMGF=1
    AT+CMGR=2
    AT+CMGD=2
    From number: +79053763630
    Datetime: 16/10/04,14:01:51+12
    Recieved Message: Off
    OK! Power Off
    AT+CMGF=1
    AT+CMGL="REC UNREAD",1
    AT+CMGL="REC UNREAD",1
    AT+CMGF=1
    AT+CMGR=3
    AT+CMGD=3
    From number: +79053763630
    Datetime: 16/10/04,14:02:23+12
    Recieved Message: Off
    OK! Power Off
    AT+CMGF=1
    AT+CMGL="REC UNREAD",1
     
  10. s1984i

    s1984i Нерд

    как выключить AT+CLCC приходящие данные от этой команды мне не нужны.
    +CLCC: 1,1,0,0,0,"+xxxxxxxxxx",145,"" и как считать эту сторочку причем получить нужные цифры (3 цифру)
     
  11. P-A

    P-A Нуб

    Должно работать. Мне пришлось отказаться от библиотек, почему-то нестабильные результаты с ними. Перешел на прямое общение - проблем стало на порядок меньше.
    Попробуйте внимательно посмотреть на провода интерфейса между ардуинкой и gprs платой: покороче и правильная разводка от помех. Возможно проскакивает "шум".
    Попробуйте послать смс следующем способом, только обозначите правильно порт, в примере Serial1, а у Вас может быть свой (задержки условные, если пройдёт попробуйте подобрать оптимальнее):
    delay(5000);
    Serial1.print("AT+CMGS=\"" + phoneNumber + "\"\r"); // отправляем смс
    delay(500);
    Serial1.print("Arduino is ONLINE"); // текст смс
    delay(500);
    Serial1.print((char)26); // символ <ctrl-z> (ASCII character 26)
     
  12. P-A

    P-A Нуб

    Доброго! Пытаюсь реализовать коррекцию времени по СМС. Приходит СМС, читаю, получаю дату и время прихода СМС, сообщение. Потом подставляю данные для коррекции времени и ничего не происходит.
    Причём в setup время устанавливается, а вот в loop ничего не происходит. Странно, команда одна и та же.
    Помогите, что может быть в loop не так?
    Код (C++):
    boolean isStringMessage = false; // Переменная принимает значение True, если текущая строка является сообщением
    String pswKey = "x"; // Слово доступа при принятии СМС
    String phoneNumber = "+7xxxxx"; // Номер телефона по усолчанию
    String smsNumberIn = ""; // Переменная номера телефона входящего СМС
    String smsDateSet = ""; // Дата полученная в СМС для установки времени
    String smsMessage = ""; // Полученное в СМС сообщение
    String currStr = ""; // Получяемая строка от GPRS Shield
    String currStrTmp = ""; // Промежуточная обработка строки для получения разных результатов
    String currDateTime = ""; // Получяемая текущая дата от GPRS Shield

    void setup() {
      gprs_OnOff(); // включаем GPRS-шилд
      Serial.begin(9600); // открываем последовательный порт для вывода на компьютер
      Serial3.begin(9600); // открываем последовательный порт для GPRS-шилд
      while (!Serial) { // ждём, пока не откроется монитор последовательного портадля того, чтобы отследить все события в программе
      }
      get_DateTime(); // Получаем текущие дату и время
      Serial.println("System date: " + currDateTime); // Вывод информации о начале работы
      Serial.println("Start..."); // Вывод информации о начале работы
      // TEST TEST TEST
      get_DateTime(); // Получаем текущие дату и время
      smsDateSet = "16/01/01,15:02:35+20";
      String aK = "AT+CCLK=\"" + smsDateSet + "\"";
      Serial.println(aK);
      delay(1000);
      Serial3.println(aK);
      delay(1000);
      get_DateTime(); // Получаем текущие дату и время
      Serial.println("New system date(0): " + currDateTime);
    }

    void loop() {
      if(Serial3.available())
          {
            char currSymb = Serial3.read();
            if('\r' == currSymb)
               {
                 if(isStringMessage)
                    {
                      if (!currStr.compareTo(pswKey + "INFO")) // блок INFO
                        {
                            delay(100);
                           Serial.println(currStr); // само сообщение
                        }
                       
                      else if (!currStr.compareTo(pswKey + "SETTIME")) // блок SETTIME
                        {
                           smsMessage = currStr;
                           Serial.println("smsMessage: " + smsMessage); // сообщение
                           get_DateTime(); // Получаем текущие дату и время
                           delay(1000);
                           set_DateTime();
                           delay(2000);
                           get_DateTime(); // Получаем текущие дату и время
                           Serial.println("New system date: " + currDateTime);
                        }
                      else if (!currStr.compareTo(pswKey + "BAL")) // блок BAL
                        {
                           Serial3.print("ATD#100#;\r"); // делаем запрос баланса (мтс), а ответ ловится в блоке ниже...
                        }
             
                      isStringMessage = false;
                   }
                else
                   {
                     if(currStr.startsWith("+CMT")) // если текущая строка начинается с "+CMT", то строка является сообщением
                        {
                          Serial.println(currStr); // само сообщение
                          currStrTmp = currStr.substring(currStr.indexOf("\"+")) + "\n";
                          smsNumberIn = currStr.substring(currStr.indexOf("\"+"),currStr.indexOf(","));
                          Serial.println("smsNumberIn = " + smsNumberIn);
                          currStrTmp = currStrTmp.substring(currStrTmp.indexOf(",")+1);
                          currStrTmp = currStrTmp.substring(currStrTmp.indexOf(",")+1);
                          smsDateSet = currStrTmp.substring(1,21);
                           Serial.println("smsDataSet: " + smsDateSet);
                           isStringMessage = true;
                        }
                     if(currStr.startsWith("+CUSD")) // этот блок отлавливает ответ на запрос баланса и отправляет его смской
                        {
                           currStr = currStr.substring(currStr.indexOf("Balance"),currStr.indexOf("\","));
                           delay(2000);
                           Serial.println(currStr);
                           delay(100);
                        }  
                   }
                  currStr = "";
               }
            else if('\n' != currSymb)
              {
                currStr += String(currSymb);
              }
         }
    }

    void get_DateTime() {
      currStr = "";
      Serial3.println("AT+CCLK?");
      delay(200);
      if(Serial3.available()) {
        while (Serial3.available()) {
          char currSymb = Serial3.read();
            if('\r' == currSymb) {
              if(currStr.startsWith("+CCLK")) { // если текущая строка начинается с "+CCLK", то строка является сообщением
                currDateTime = currStr.substring(currStr.indexOf("\""));
                break;
              }
              currStr = "";
            }
            else if('\n' != currSymb)
            {
              currStr += String(currSymb);
            }
        }    
      }
    }

    void set_DateTime()
    {
      delay(1000);
      String aK = "AT+CCLK=\"" + smsDateSet + "\"";
      Serial.println(aK);
      delay(1000);
      Serial3.print(aK);
       delay(1000);
    }




    void gprs_OnOff()
    {
      pinMode(2, OUTPUT); // настраиваем пин №2 в режим выхода
      if (digitalRead(3) != HIGH) { // если на 3 пине «низкий уровень»
        digitalWrite(2, HIGH); // подаём на пин 2 «высокий уровень»
        delay(3000); // ждём 3 секунды
      }
      digitalWrite(2, LOW); // подаём на пин 2 «низкий уровень»
    }
    Монитор:
    System date: "16/01/01,15:02:39+20"
    Start...
    AT+CCLK="16/01/01,15:02:35+20"
    New system date(0): "16/01/01,15:02:39+20" тут время устанавливается
    +CMT: "+7xxxx","","16/10/11,16:09:57+12"
    smsNumberIn = "+7xxxxx"
    smsDataSet: 16/10/11,16:09:57+12
    smsMessage: xSETTIME
    AT+CCLK= "16/10/11,16:09:57+12"
    New system date: "16/01/01,15:02:54+20" тут не устанавливается
     
  13. ATishchenko

    ATishchenko Нерд

    Наверное Serial3.println(aK) все же :)
     
  14. P-A

    P-A Нуб

    Изменил - подставил сразу Serial3.print("AT+CCLK=\"" + smsDateSet + "\""); Результат тот же, но! Елсли нажать ресет на ардуинке, то на монитор придёт уже откорректированное время, т.е. в строчке System date будет порядок, а если обесточить, то всё по старому. мысли три:
    1. Нельзя после установки времени, считывать время, но вряд ли т.к. между записью и считыванием ставил задержку в аж 10 секунд;
    2. Я не правильно записываю время в gprs шилд;
    3. Я не правильно считываю время с gprs шилд.
     
    Последнее редактирование: 12 окт 2016
  15. ATishchenko

    ATishchenko Нерд

    Я имел ввиду, что должен быть не print, а println - как у Вас в setup. Без перевода строки команда выполнена не будет. Модем все-таки.
     
  16. P-A

    P-A Нуб

    Точно, спасибо.
    Работает - время устанавливает, но если сразу запрашивать, то не даёт :( (выше "три мысли").
    Правда в мониторе какой-то "шум" - обрывки строк появляются, думаю какой-то сбой: части того, что должно выводится на монитор, но по алгоритму этого не может быть. причём именно части строк, начиная с какого-то случайного символа и до конца строки. Заккоментировал практически всё, но вывод "шума" продолжается. Не сталкивались? Может помехи на провода RX/TX (4 см. длинной) между ардуиной и шилдом? Разбираюсь...
     
  17. ATishchenko

    ATishchenko Нерд

    Не думаю. Либо комп дурит, либо паузы побольше сделать надо. Я бы ручками терминалом подключился к шилду и на всякий случай замерил задержки на исполнение. К сожалению, в подобных конструкциях управление потоком данных CTS/RTS не предусмотрено, а DTR ресетит плату. Может лучше после подобных команд ждать "OK" прежде , чем кидать новые. И результат исполнения будет понятен и на flow control сильно завязаны не будете. В библиотеке для JS это учтено - она ждет ОК, там где он нужен.
     
  18. P-A

    P-A Нуб

    Развёл провода RX и TX друг от друга подальше слало гораздо лучше. Посмотрел монитор, что получается:
    При "холодном старте" gprs шилд выдаёт разные статусы готовности сим и т.д., а я в это время уже запрашиваю время, соответственно он "не слышит". Статусы бывают разные - зависит от продолжительности времени на которое отключалось питание, при совсем кратковременном бывает, что статусы вообще не выводятся и gprs шилд сразу готов. Описания что должно быть при старте я не нашел. Борюсь методом постоянного запроса в цикле (while), пока не получу нужный результат. Работает без сбоев, время всегда считывается. Понимаю, что не очень красиво, но другого способа в голову не приходит.
     
  19. acos

    acos Официальный гик Администратор

    Немного поправили либу для GPRS Shield
    Теперь можно будет использовать с любым Serial-портом. Библиотека пока в dev-ветке, поскольку нужно поменять все описания на wiki/
    Ветка на GitHub

    Поменяли инициализацию.

    Для хардварных Serial:

    Код (C++):
    GPRS gprs(Serial1, 2,3);
    void setup()
    {
      Serial.begin(9600);

      Serial1.begin(9600);

      // включаем GPRS шилд
      gprs.powerUpDown();

      while (!Serial) {
        // ждём, пока не откроется монитор последовательного порта
        // для того, чтобы отследить все события в программе
      }
      // проверяем есть ли связь с GPRS устройством
      while (!gprs.init()) {
        // если связи нет, ждём 1 секунду
        // и выводим сообщение об ошибке
        // процесс повторяется в цикле,
        // пока не появится ответ от GPRS устройства
        delay(1000);
        Serial.print("Init error\r\n");
      }
      // вывод об удачной инициализации GPRS Shield
      Serial.println("GPRS init success");
      // сообщаем об ожидании звонка
      Serial.println("Wait to call ");
    }
    Для софтварных Serial:

    Код (C++):
    #include <SoftwareSerial.h>

    SoftwareSerial mySerial(10, 11); // RX, TX

    GPRS gprs(mySerial, 2,3);
    void setup()
    {
      Serial.begin(9600);

      mySerial.begin(9600);

      // включаем GPRS шилд
      gprs.powerUpDown();

      while (!Serial) {
        // ждём, пока не откроется монитор последовательного порта
        // для того, чтобы отследить все события в программе
      }
      // проверяем есть ли связь с GPRS устройством
      while (!gprs.init()) {
        // если связи нет, ждём 1 секунду
        // и выводим сообщение об ошибке
        // процесс повторяется в цикле,
        // пока не появится ответ от GPRS устройства
        delay(1000);
        Serial.print("Init error\r\n");
      }
      // вывод об удачной инициализации GPRS Shield
      Serial.println("GPRS init success");
      // сообщаем об ожидании звонка
      Serial.println("Wait to call ");
    }
     
  20. ATishchenko

    ATishchenko Нерд

    Вы все же замерьте, сколько надо времени для SIM очухаться от "холодного" старта и сколько времени она тратит на запись в свой NVRAM или куда она там это время пишет... У Вас же шилд с батарейкой? Нет?