SIM800L и нечитаемые символы

Тема в разделе "Arduino & Shields", создана пользователем obuhanoe, 9 авг 2016.

  1. obuhanoe

    obuhanoe Гик

    Если Serial3 то так
    Код (C++):
    Serial3.begin(9600);
    ну а если цифровые пины как и выше в коде
    Код (C++):
    SoftwareSerial mySerial(10, 11); // RX, TX
    mySerial.begin(9600);
     
     
  2. DIYMan

    DIYMan Guest

    На китайских мегах, кстати сказать, метки напротив Serial2 перепутаны местами бывают - т.е. где должно быть TX - написано RX и наоборот. Т.е. пины как положено, а надписи - крест накрест. Если юзали Serial2 - проверьте этот момент. Все Serial у меня на меге работают без нареканий.
     
    obuhanoe нравится это.
  3. obuhanoe

    obuhanoe Гик

    Просто огромное Вам спасибо. Действительно они перепутаны)

    Но не дает покоя - почему через цифровые пины не хочет работать, их состояние не нужно переключать как-нибудь.
     
  4. DIYMan

    DIYMan Guest

    SoftwareSerial всё сам делает. У меня работает на цифровых пинах, проверяйте правильность указания пинов для RX и TX.
     
  5. obuhanoe

    obuhanoe Гик

    понял, попытаюсь разобраться.

    А подскажите еще - есть ли AT команда, с помощью которой можно узнать активно ли grps-соединение или каким образом вы у себя проверяете активность соединения?

    Спасибо.
     
  6. DIYMan

    DIYMan Guest

    Я GPRS не юзаю, исключительно СМС. Но совет один - даташит на AT-команды модема, там есть всё ;)
     
    obuhanoe нравится это.
  7. obuhanoe

    obuhanoe Гик

    Уважаемый DIYMan , подскажите по следующему вопросу. Почитал АТ команды по данному модулю, по в части СМС и GRPS и возник вопрос:
    если я пытаюсь вычитать смс раз 30 сек, то данные обрезаются, причем если бы это делал SofrSerial - но у меня он расширен до 255, а смс прилетает в 100 символов.
    Код (C++):
    String ReadSim800L() {  //функция чтения данных от GSM модуля
      int c;
      String v;
      while (Serial3.available()) {  //сохраняем входную строку в переменную v
        c = Serial3.read();
        v += char(c);
        delay(10);
      }
      return v;
    }

    void loop() {

    if (millis() - previousMillis_sms > 1000*30) {
        debug_log(/*printTime() +*/ " | 30 sec passed - SMS");
        set_millis_sms();
        //listen_gsm();
        Serial3.println("AT+CMGR=1");
        delay(100);
        Serial.println(ReadSim800L());
      }
      }
    Ну а если в void loop() просто вставить
    Код (C++):
    if (Serial3.available())
        Serial.write(Serial3.read());
      if (Serial.available())
        Serial3.write(Serial.read());
    то вычитывается все что пришло в СМС.

    Спасибо
     
  8. DIYMan

    DIYMan Guest

    Зачем delay(10) то, не пойму? Вы вычитываете всё, что УЖЕ есть в буфере, там delay(10) нужен, как кобыле пятая нога. По поводу "обрезаются" - они не обрезаются, просто вычитывать входящие СМС надо до символа новой строки (говорю за кодировку PDU, правда, т.к. с простой текстовой не работаю).

    Строго говоря, по приходу +CMT в порт - там есть вся необходимая инфа, сколько символов надо вычитывать ;) Почитайте внимательно даташит, и всё станет понятней.
     
  9. obuhanoe

    obuhanoe Гик

    Если Вас не затрудним покажите пожалуйста пример приема СМС по АТ команде. Сижу 2 день и ничего не получается.
    Принимаю СМС хоть с переносом строк хоть без них - получается вычитать только 63 символа.
     
  10. DIYMan

    DIYMan Guest

    sys нравится это.
  11. obuhanoe

    obuhanoe Гик

    DIYMan, Добрый день!
    Подскажите по такому вопросу, так как модуль я соединил с Serial3 Arduino - возник вопрос как реализовать следующие:
    например в данный момент мне нужно отправить по gprs данные, я запрашиваю состояние соединения GPRS
    Код (C++):
    AT+SAPBR 2,1
    получаю в ответ от модуля, а в это время (до выполнения предыдущей команды или после пока не выяснил) приходит СМС.
    После отправки данных, я проверяю нет ли СМС - а его нет.
    Как из такой ситуации найти выход, чтобы и данные отправить(проверить соединение GPRS) и СМС не потерять.

    Спасибо.
     
  12. DIYMan

    DIYMan Guest

    У вас когда СМС приходит - строка начинается с +CMT - в чём проблема анализировать каждую пришедшую строку и понимать, чего пришло?
     
  13. obuhanoe

    obuhanoe Гик

    Чтобы было понятно покажу на примере
    в loop выполняются проверки
    Код (C++):
    //every 10 sec
      if (millis() - previousMillis_sms > 1000*10) {
        debug_log(printTime() + " | 10 sec passed - SMS");
        set_millis_sms();  
        listen_sms();
      }

      //every 30 sec
      if (millis() - previousMillis_CST > 1000*30) {
        debug_log(printTime() + " | 30 sec passed - check_start_time");
        set_millis_CST();
        check_start_time();
      }
    например каждые 30 сек я отправляю данные по GPRS, где есть такой код
    Код (C++):
    Serial3.println("AT+SAPBR=2,1");
        delay(100);  
        // Если нет соединения - подключаемся
        if (Serial3.find("+SAPBR: 1,3,\"0.0.0.0\"")) {
           init_gprs();
        }
    В этом момент приходит СМС.
    После выполнения отправки check_start_time();
    Запускается каждые 10 сек - listen_sms();

    Код (C++):
    Serial3.println("AT+CMGR=1");
         delay(100);
         if (Serial3.find("+CMT")) {
         // Получили СМС
    }
    и вот после этой проверки СМС не вычитывается - как буд-то и не приходила.
    А если СМС отправить и GPRS ничего в этот момент не отправляет - то СМС читается нормально.

    Спасибо
     
  14. DIYMan

    DIYMan Guest

    Ещё раз: у вас неправильная логика. Вы послали команду в порт, и в этот момент пришло СМС - вас это смущает, так? В голове, мысленно - разнесите сущности "послал команду" и "проанализировал ответ" в разные коробки ;) В итоге, алгоритм следующий:

    1. Послали команду соединения по GPRS, в список состояний добавили "мы послали команду соединиться, надо бы этот ответ анализировать".

    2. Вычитываете из порта, чего там приходит. Если пришло +CMT - значит, свалилось SMS, делаете своё дело. Если пришло +SAPBR - значит, ответ о статусе соединения, анализируете, сбрасываете из списка состояний флаг, работаете дальше.

    3. Какие-либо задержки или опрос в цикле - не нужен, от слова "совсем".

    4. В итоге - код может выглядеть примерно так:
    Код (C++):

    String incomingBuffer;

    void ProcessIncomingBuffer()
    {
        if(incomingBuffer.startsWith("+CMT"))
        {
            // пришло СМС
        }
        else
        if(incomingBuffer.startsWith("+SAPBR"))
        {
            // пришёл статус соединения по GPRS
        }
       
        incomingBuffer = ""; // очищаем буфер, он нам не нужен больше
    }

    void loop()
    {
        while(Serial.available())
        {
            char ch = Serial.read();
            if(ch == '\r')
                continue;
               
            if(ch == '\n')
                ProcessIncomingBuffer();
            else
                incomingBuffer += ch;
        }
       
        // тут посылаем любые команды модему, какие душе угодно
    }
     
    В функции ProcessIncomingBuffer обрабатывайте любой ответ модема так, как вам нужно, и всё. Понятное дело, что это я навскидку написал, только для демонстрации возможного подхода. Асинхронная работа алгоритмически не всегда сходу понятна, но - надо вникать ;)
     
  15. sys

    sys Злобный Буратино Модератор

    А while в loop не размножится? Или луп ждать будет выполнения вайла?
     
  16. DIYMan

    DIYMan Guest

    Куда и кто должен размножиться - не понял? while там вычитывает из внутреннего буфера UART во внешний, бьёт по строкам ('\n') и для каждой строки вызывает обработчик-анализатор ответа от модема.
     
  17. sys

    sys Злобный Буратино Модератор

    Что делает вайл я понял. Просто вы сказали про асинхронность и я попытался ее найти... Подумал неужто вайл как setWatch работает...типа бесконечного цикла... Просто хочу помимо JS пощупать вайринг, вот и тонкости выясняю ;)

    А так то я понял, что этот код позволяет отправлять команды после окончания приема. Мне просто надо было сразу взглянуть на serial.available в референсах, а не задавать вопросы :)

    Уж больно тема асинхронности в ардуино интересна, но мной пока не очень изведана..
     
    Последнее редактирование: 24 авг 2016
  18. DIYMan

    DIYMan Guest

    А она там есть ;) Вы можете скормить в loop несколько команд модему, и вывалиться в следующий проход. Ответы от этих команд обработаются асинхронно, по мере поступления данных в порт - т.е. мы специально не висим, не ждём до посинения, чего там ответит модем - мы просто по мере поступления очередной строки ответа анализируем её. Синхронности - ни на грамм ;)
     
  19. sys

    sys Злобный Буратино Модератор

    :) понял, спасибо. Получается в какой-то мере аналог Espruino'вского Serial.on("data",function(data){...})
     
  20. DIYMan

    DIYMan Guest

    Ну типа того, только для строки, а не для каждого отдельного символа. Поскольку мы в ответах от GSM-модема смело можем полагаться на строку как на квант информации. Т.е. весь пакет информации состоит минимум из одной строки ответа, отсюда такой код. Да, перерасход памяти вроде (ведь есть же внутренний буфер у Serial в 64 байта), зато мы отвязаны от возможной утери данных вследствие переполнения приёмного буфера UART, который реализован в кишочках HardwareSerial.cpp ;)
     
    sys нравится это.