Обработка команд от SIM800

Тема в разделе "Arduino & Shields", создана пользователем Irinka, 26 окт 2019.

  1. Irinka

    Irinka Нерд

    Здравствуйте. Нужно обрабатывать команды от SIM800, как запрашиваемые так и нет.
    До недавнего времени пользовалась кодом от уважаемого Кравченко Виктора
    http://codius.ru/articles/GSM_модуль_SIM800L_часть_2
    Но для новых задач он не подходит, так как есть задержка в коде, а именно:
    Код (C++):
    long _timeout = millis() + 10000;                               // Переменная для отслеживания таймаута (10 секунд)
      while (!SIM800.available() && millis() < _timeout)  {};         // Ждем ответа 10 секунд, если пришел ответ или наступил таймаут, то...
      if (SIM800.available()) {                                       // Если есть, что считывать...
        _resp = SIM800.readString();                                  // ... считываем и запоминаем
      }
      else {                                                          // Если пришел таймаут, то...
        Serial.println("Timeout...");                                 // ... оповещаем об этом и...
      }
      return _resp;                                                   // ... возвращаем результат. Пусто, если проблема
    }
    Соответственно если в течении 10 секунд не будет ответа от модуля, то другие действия выполняться не будут (нет многозадачности).
    Как от этого избавиться, при этом сохранить главную функцию, получение ответа именно на запрашиваемую команду?
     
  2. b707

    b707 Гуру

    Иринка, для многозадачности недостаточно будет изменить только этот кусок кода - нужно переписать весь скетч в многозадачном духе - то есть убрать все задержки, как явные (в виде delay()). так и скрытые - типа тех что приведены в вашем обрывке скетча.
    Ничего не знаю про уважаемого Вами Виктора - но в приведенном коде он сделал как минимум две грубые, прямо-таки детские ошибки.
    Во-первых, интервал для времени вычисляется неправильно, при переполнении будет глючить. И второе - для задержки использован цикл while- что по сути делает этот код аналогичным коду с delay()
    Если и остальной код этого автора написан в этом стиле - проще его не переписывать, а написать заново
     
    Irinka, Daniil, Andrey12 и ещё 1-му нравится это.
  3. Irinka

    Irinka Нерд

    У меня больше нигде нет задержек.
    Код (C++):
    #include <SoftwareSerial.h>
    SoftwareSerial SIM800(6,7);

    unsigned long TimeOtpr;
    unsigned long Timeout;
    bool FlagTimeout=false;
    bool FlagVup=false;
    #define Interval 2000
    String Komanda="";

    void setup() {
      SIM800.begin(19200);
      Serial.begin(19200);
      Serial.println("Zagruzka");
      TimeOtpr=millis();
      FlagVup=true;
    }


    //Функция отправки команд
    void sendATCommand(String cmd,bool waiting){
      Komanda=cmd;
      SIM800.println(cmd);
      Serial.println(cmd);
      if (waiting){
        FlagTimeout=true;
        Timeout=millis();
      }
    }




    void loop() {

    //Отправляю команды
    if (FlagVup && millis()-TimeOtpr>=Interval){
      sendATCommand("AT+CCALR?",true);
      TimeOtpr=millis();
    }
    //Отправляю команды


     

    if(SIM800.available()){
      String Otvet="";
      FlagTimeout=false;//Ответ пришёл быстрее чем настал таймаут
      Timeout=millis();
      Otvet = SIM800.readString();
        if (Otvet.startsWith(Komanda)) {//Если ответ начинается как запрашиваемая команда
          Otvet = Otvet.substring(Otvet.indexOf("\r", Komanda.length()) + 2);//Удаляем из ответа запрашиваемую команду
        }
      Otvet.trim(); //Удаляем пробелы
      Serial.println(Otvet);
    }else{
      if (FlagTimeout && millis()-Timeout>=2000){//Если ответа нет в течении 2 сек, то настал таймаут
        FlagTimeout=false;
        Serial.print("Timeout");
      }
    }




    }//loop
    Вот мой примерный скетч обработки команд. Таймаут работает.
    Но я не уверена что ответы будут приходить именно на ту команду, которую я отправила, потому как есть ещё и не запрашиваемые сообщения
     
  4. Irinka

    Irinka Нерд

    И второй мой вариант проверять все нужные мне команды, остальное считать не запрашиваемыми сообщениями
    Код (C++):
    #include <SoftwareSerial.h>
    SoftwareSerial SIM800(6,7);

    unsigned long TimeOtpr;
    unsigned long Timeout;
    bool FlagTimeout=false;
    bool FlagVup=false;
    #define Interval 5000
    String Komanda="";

    void setup() {
      SIM800.begin(19200);
      Serial.begin(19200);
      Serial.println("Zagruzka");
      TimeOtpr=millis();
      FlagVup=true;
    }


    //Функция отправки команд
    void sendATCommand(String cmd,bool waiting){
      Komanda=cmd;
      SIM800.println(cmd);
      Serial.println("Komanda: "+cmd);
      if (waiting){
        FlagTimeout=true;
        Timeout=millis();
      }
    }




    void loop() {

    //Отправляю команды
    if (FlagVup && millis()-TimeOtpr>=Interval){
      sendATCommand("AT",true);
      TimeOtpr=millis();
    }
    //Отправляю команды


       

    if(SIM800.available()){
      String Otvet="";
      FlagTimeout=false;
      Otvet = SIM800.readString();
      Otvet.trim();

      //Проверяем ответы на нужные команды
    if (Otvet.startsWith("AT+CCALR?")) {//Если ответ начинается на текст запрашиваемой команды
    //Otvet = Otvet.substring(Otvet.indexOf("\r", Komanda.length()) + 2);//Удаляем из ответа запрашиваемую команду и выводим текст ответа
      if (Otvet.indexOf("+CCALR: 1") > -1) {//Если ответ нас устраивает
        Serial.println("Set` nai`dena");
      }
    }else if (Otvet.startsWith("AT")) {
      if (Otvet.indexOf("OK") > -1) {
        Serial.println("SIM800 otvechaet");
      }
     
    }else{
    Serial.println("Bez zaprosa: " + Otvet);
    }




     
     
      //Serial.println("Otvet: "+Otvet);
    }else{
      if (FlagTimeout && millis()-Timeout>=2000){//Если ответа нет в течении 2 сек, то настал таймаут
        FlagTimeout=false;
        Serial.print("Timeout");
      }
    }




    }//loop
     
  5. Irinka

    Irinka Нерд

    Код (C++):
    }else{

    if (Otvet.startsWith("RING")) {
      sendATCommand("ATH",false);
    }
     
    Serial.println("Bez zaprosa: " + Otvet);
    }
    Добавила в незапрашиваемые команду сброс всех входящих вызовов, нас корости в 19200 не всегда с первого раза получаю строку:

    RING
    +CLIP: "+7888888888",145,"",0,"",0

    Соответственно и вызов сбрасывается не сразу.

    Добавила скорости, 57600 вроде бы стабильно сбрасывает при первом же гудке.
     
  6. Irinka

    Irinka Нерд

    На скорости 115200 получаю:
    Код (C++):
    Komanda: AT+CCALR?
    Bez zaprosa: AJ⸮⸮⸮PJ⸮j
    +CCALR: 0
    ⸮j⸮H⸮
    Komanda: AT
    SIM800 otvechaet
    Komanda: AT+CCALR?
    Bez zaprosa: AJ⸮⸮⸮PJ⸮j
        +CCALR: 1
    OK
    Komanda: AT
    Bez zaprosa: AJ

    O⸮
    Komanda: AT+CCALR?
    Bez zaprosa: AJ⸮⸮⸮PJ⸮j
    )⸮CALR: 1

        OK
    Komanda: AT
    SIM800 otvechaet
    Komanda: AT+CCALR?
    Bez zaprosa: AJ⸮⸮⸮PJ⸮j
        +CCALR: 1
    C⸮j⸮H⸮
    Komanda: AT
    SIM800 otvechaet
     
     
  7. Irinka

    Irinka Нерд

    Нет, и на 57600 пропускает незапрашиваемую команду о входящем звонке
     
  8. Irinka

    Irinka Нерд

    SoftSerial - 38400, максимальная скорость, накосячила
     
  9. Irinka

    Irinka Нерд

    Код (C++):
    #include <SoftwareSerial.h>
    SoftwareSerial SIM800(6,7);

    unsigned long TimeOtpr;
    unsigned long Timeout;
    bool FlagTimeout=false;
    bool FlagVup=false;
    #define Interval 3000
    String Komanda="";
    byte i;

    void setup() {
      SIM800.begin(38400);
      Serial.begin(38400);
      Serial.println("Zagruzka");
      TimeOtpr=millis();
      FlagVup=true;
      SIM800.println("AT");
    }


    //Функция отправки команд
    void sendATCommand(String cmd,bool waiting){
      Komanda=cmd;
      SIM800.println(cmd);
      Serial.println("Komanda: "+cmd);
      if (waiting){
        FlagTimeout=true;
        Timeout=millis();
      }
    }




    void loop() {

    //Отправляю команды
    if (FlagVup && millis()-TimeOtpr>=Interval){
      if(i>2)i=0;
        i++;
        if (i==1)  sendATCommand("AT",true);
        if (i==2)  sendATCommand("AT+CCALR?",true);

      TimeOtpr=millis();
    }
    //Отправляю команды


     

    if(SIM800.available()){
      String Otvet="";
      FlagTimeout=false;
      Otvet = SIM800.readString();
      Otvet.trim();

      //Проверяем ответы на нужные команды
    if (Otvet.startsWith("AT+CCALR?")) {//Если ответ начинается на текст запрашиваемой команды
    //Otvet = Otvet.substring(Otvet.indexOf("\r", Komanda.length()) + 2);//Удаляем из ответа запрашиваемую команду и выводим текст ответа
      if (Otvet.indexOf("+CCALR: 1") > -1) {//Если ответ нас устраивает
        Serial.println("Set` nai`dena");
      }
    }else if (Otvet.startsWith("AT")) {
      if (Otvet.indexOf("OK") > -1) {
        Serial.println("SIM800 otvechaet");
      }
    }else{

    if (Otvet.startsWith("RING")) {
      sendATCommand("ATH",false);
    }
     
    Serial.println("Bez zaprosa: " + Otvet);
    }




      //Serial.println("Otvet: "+Otvet);
    }else{
      if (FlagTimeout && millis()-Timeout>=2000){//Если ответа нет в течении 2 сек, то настал таймаут
        FlagTimeout=false;
        Serial.print("Timeout");
      }
    }




    }//loop
    Не всегда с первого раза (или с задержкой) модуль понимает что на него происходит звонок.
     
  10. Irinka

    Irinka Нерд

    Или эта задержка и должна быть, потому что модуль не закончил выполнение предыдущей команды?
     
  11. SergeiL

    SergeiL Гуру

    А какая цель? Что за устройство? Что должно делать?
     
  12. Irinka

    Irinka Нерд

    Система умного дома, так сказать.
    По звонку, к примеру, будут открываться ворота.
     
  13. Irinka

    Irinka Нерд

    Код (C++):
    if (Otvet.startsWith("AT")) {//Если ответ начинается на...
    Тут я тоже накосясила, все ответы начинаются на AT... работать будет неправильно
     
  14. Irinka

    Irinka Нерд

    Но, алгоритм обработки команд я выбрала верный?...
     
  15. SergeiL

    SergeiL Гуру

    А Wi-Fi с Интернет в этом умном доме есть?
    Может все проще можно сделать, с использованием "готовых" решений?
     
  16. Irinka

    Irinka Нерд

    Есть. Готовые решения мне не интересны.
     
  17. SergeiL

    SergeiL Гуру

    Готовые - это исходные коды, которые можно изменять как душе нравится.
    Есть идеи, которые можно развивать!
    Для себя понимаю, что нет того, что нельзя сделать самому в принципе.:)
    Просто изобретать велосипед можно, но для чего?
     
  18. Irinka

    Irinka Нерд

    Для меня сторонним, готовым, понятным мне, исходным кодом был код, указанный в первом сообщении, но он оказался немного кривоватым, прошу прощения за слова такие.
    Других разработок в области обработки команд Sim800 я не нахожу.
     
  19. Irinka

    Irinka Нерд

  20. SergeiL

    SergeiL Гуру

    А SIM800 принципиально?
    Я в последнем решении тоже использовал SIM800C, но это там, где нет Wi-Fi.
    Работает устойчиво, уже неделю, вчера оставил дома на время отпуска для теста на стабильность.
    А так, дома, именно под "умный дом" работает порядка 15 устройств на ESP8266. Работают с конца 2017-го года.
    Работают очень стабильно. И дешевле, и программируются намного проще.
    Поэтому и спрашивал, SIM800 принципиально? Или есть Wi-Fi?