GSM A6 вопрос про RING

okta
Offline
Зарегистрирован: 10.01.2015

Заказал потестить GSM модуль A6 такой. Пказался очень достойной заменой M590. При не на много большей цене - больше функционал и меньше энергопотребление.

Пока едет, подробнее полистал доступные доки - не нашел есть ли в нем аналог ноги RING в M590? Т.е. GSM модуль работает автономно, а при получении SMS или входящем звонке будит МК дергая ногу RING.

alex_r61
alex_r61 аватар
Offline
Зарегистрирован: 20.06.2012

Только получил пару A6C, сейчас разбираюсь. И похоже один дохлый. Что мешает будить МК от COM порта.

okta
Offline
Зарегистрирован: 10.01.2015

alex_r61 пишет:

Только получил пару A6C, сейчас разбираюсь. И похоже один дохлый. Что мешает будить МК от COM порта.

Точняк)) Мешает разве что религия воспитанная спец ногой на М590)))

A6C - это который с камерой? А, если не сложно, поделитесь доками про него. С пол пинка сейчас не нашел.

alex_r61
alex_r61 аватар
Offline
Зарегистрирован: 20.06.2012
Sergiy75
Offline
Зарегистрирован: 29.05.2016

А есть готовые библиотеки под этот модуль?

okta
Offline
Зарегистрирован: 10.01.2015

Там ни к чему библиотека. Он управляется АТ командами в духе:

Serial.println("AT+CLIP=1");  //включаем АОН

Список поддерживаемых команд есть в приведенной выше ссылке (спасибо!).

Что он нам отвечает тоже ловим с сериала, и разбираем в соответствии с задачами.

Sergiy75
Offline
Зарегистрирован: 29.05.2016

Спасибо, придет - буду разбираться.

alexlord
Offline
Зарегистрирован: 31.10.2016

Разбираюсь с этим модулем и не могу разобраться с чтением смс.  Ранее стоял МС35 там все работало.

суть вопроса. отравляю несколько смс на модуль.

модуль принимает но не сохраняет их. 



вот к примеру три подряд полученных смс:



+CIEV: "MESSAGE",1

+CMT: "+790********",,"2016/10/31,19:46:29+03

test1



+CIEV: "MESSAGE",1

+CMT: "+790********",,"2016/10/31,19:46:32+03

test2



+CIEV: "MESSAGE",1

+CMT: "+790********",,"2016/10/31,19:46:34+03

test3





везде смс в ячейке 1.... 



при попытке чтения выдает ошибку.

at+cmgr=1

+CMS ERROR:321

и так по любой ячейке.....  никто не разбирался?

 

Sergiy75
Offline
Зарегистрирован: 29.05.2016

alexlord пишет:

Разбираюсь с этим модулем и не могу разобраться с чтением смс.  Ранее стоял МС35 там все работало.

суть вопроса. отравляю несколько смс на модуль.

модуль принимает но не сохраняет их. 



вот к примеру три подряд полученных смс:



+CIEV: "MESSAGE",1

+CMT: "+790********",,"2016/10/31,19:46:29+03

test1



+CIEV: "MESSAGE",1

+CMT: "+790********",,"2016/10/31,19:46:32+03

test2



+CIEV: "MESSAGE",1

+CMT: "+790********",,"2016/10/31,19:46:34+03

test3





везде смс в ячейке 1.... 



при попытке чтения выдает ошибку.

at+cmgr=1

+CMS ERROR:321

и так по любой ячейке.....  никто не разбирался?

 

У меня то же самое, только ошибка +CME ERROR: 58. Причем эту ошибку он выдает на любую команду, даже просто на АТ. Хотя звонить с модуля на другой телефон получается без проблем.

Sergiy75
Offline
Зарегистрирован: 29.05.2016

У меня причина все-таки в коде. Уважаемые гуру, подскажите, пожалуйста, где ошибка?

#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); // RX, TX
int ch = 0;
int led = 13;
String val = "";

void setup() {
  delay(2000);  //время на инициализацию модуля
  pinMode(led, OUTPUT);
  digitalWrite(led, LOW);
  Serial.begin(9600);  //скорость порта
  Serial.println("GSM tester v1.0");
  mySerial.begin(9600);
  mySerial.println("AT+IPR=9600");  //устанавливаем скорость шилда
  delay(100);
  mySerial.println("AT+CLIP=1");  //включаем АОН
  delay(100);
  mySerial.println("AT+CMGF=1");  //режим кодировки СМС - обычный (для англ.)
  delay(100);
  mySerial.println("AT+CSCS=\"GSM\"");  //режим кодировки текста
  delay(100);
}

void loop() {
  if (mySerial.available()) {  //если GSM модуль что-то послал нам, то
    while (mySerial.available()) {  //сохраняем входную строку в переменную val
      ch = mySerial.read();
      val += char(ch);
      delay(10);
    }
    if (val.indexOf("RING") > -1) {  //если звонок обнаружен, то проверяем номер
      if (val.indexOf("79000000000") > -1) {  //если номер звонящего наш. Укажите свой номер без "+"
        Serial.println("--- MASTER RING DETECTED ---");
        mySerial.println("ATH0");  //разрываем связь
        digitalWrite(led, HIGH);  //включаем светодиод на 3 сек
        delay(3000);
        digitalWrite(led, LOW);  //выключаем реле
      }
    } else
      Serial.println(val);  //печатаем в монитор порта пришедшую строку
    val = "";
  }
  if (Serial.available()) {  //если в мониторе порта ввели что-то
    while (Serial.available()) {  //сохраняем строку в переменную val
      ch = Serial.read();
      val += char(ch);
      delay(10);
    }
    mySerial.println(val);  //передача всех команд, набранных в мониторе порта в GSM модуль
    if (val.indexOf("sendsms") > -1) {  //если увидели команду отправки СМС
      sms(String("hello world"), String("+7900000000"));  //отправляем СМС на номер +71234567890
    }
    val = "";  //очищаем
  }
}

void sms(String text, String phone)  //процедура отправки СМС
{
  Serial.println("SMS send started");
  mySerial.println("AT+CMGS=\"" + phone + "\"");
  delay(500);
  mySerial.print(text);
  delay(500);
  mySerial.print((char)26);
  delay(500);
  Serial.println("SMS send complete");
  delay(2000);
}

Команды в setup отрабатываются с ответом ОК, но при вводе команд в мониторе порта выдается ошибка +CME ERROR:58.  

Звонок с моего телефона проходит, но не сбрасывается и диод не моргает. 

Если закомментить строку 49, то смс мне отправляются без ошибок, но тогда команды в шилд не отправляются.

Модуль А6, плата UNO R3. Модуль подключен Tx на 2, Rx на 3, по другому модуль не отзывался. Питание на модуль подал через USB от телефонной зарядки 1,6а. Земли соединил.

alexlord
Offline
Зарегистрирован: 31.10.2016

У меня тоже косяки перли ри попытке работать с софтовым сериал и хардовым одновременно.  потому сделал проще подключил еще один адаптер FTDI им смотрел что там происходит в обмене между  модемом и ардуиной.

 

alexlord
Offline
Зарегистрирован: 31.10.2016

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

придется переделывать.

Dottore
Offline
Зарегистрирован: 19.11.2016

Здравствуйте! Как работает модуль, зависаний нет?  Интересно, как вы его запитывали и как согласовали уровни портов? Ведь судя по ссылке, вы взяли голый модуль практически без обвязки...

Я предполагаю всё-так вместо гасящего диода по питанию использовать DC-DC конвертер на 4В, а вот с Rx/Tx портами, под вопросом. Ведь в модуле на входах Стоят ограничительные диоды, как я понимаю на 2,8В, а с Ардуинки приходят уровни 3,3В. В более дорогих модулях на А6, например в том, что ниже на фото, мы видим предобразователь уровней на МАХ232, явно не зря они его ставят? Может поставить на порты внешние стабилитроны на 2,8В дополнительно? Вопрос в том, насколько надежно Ардуинка будет воспринимать уровни 2,8В?

alexlord
Offline
Зарегистрирован: 31.10.2016
Сломал голову с USSD запросом. максимум что получилось....
 
AT+CUSD=1,#101#,15
OK
+CUSD: 2, "UзТщ:AA(Й" ,15
 
может кто дальше продвинулся?
 
 
 
 
по подключению. У меня вот такой модуль
 
у него встроенный стабилизатор на 4 в. 
ардуина 5 вольтовая, подключено напрямую..... пока все работает. ;) 
максимум что пока  было это сутки тестовой работы с отправкой данных каждые 6 минут на narodmon.ru 
не завис.
 
toc
Offline
Зарегистрирован: 09.02.2013

>> может кто дальше продвинулся?

alexlord, ага

там текст в семибитной кодировке

AT+CUSD=1,#102#,15
Vash balans 90.65 r.
Vnimanie! Poholodanie!

cartelera
Offline
Зарегистрирован: 28.11.2016

Всем привет, проконсультируйте пожалуйста, требуется в офисе поднять gsm шлюз с 10-20 номерами, вот сижу и ломаю голову, удастся ли подключить 10-20 модулей a6 к arduino. Прошу сильно не пинать, я новичек в этом и хочу разобраться с arduino ну и по возможности поднять данную задумку. Заранее благодарен за консультацию.

Sprut
Offline
Зарегистрирован: 26.12.2016

toc пишет:
там текст в семибитной кодировке

А можно сделать в 16bit UCS2, тогда и русские символы будут доступны

 

AT+CSCS="HEX"
OK
AT+CUSD=1,*100#,15
OK

+CUSD: 2, "00310030002E003000300440002E000A0416043C04380020002A00320034003000230
0200020041F043E043B044304470438002000350030003000300440002E002004370430002004320
43D0438043C043004420435043B044C043D043E04410442044C002000200028003300300440002F0
031003000200434043D0029" ,72

Расшифровка: "10.00р.
Жми *240# Получи 5000р. за внимательность (30р/10 дн)"

Это вывод непосредственно с терминала, модуль подключен к компу напрямую

А дальше либо PDU Converter, вводим в окно "USSD Entry/Display" и ставим "UCS2"

либо ручками Таблица кодировки UCS2 для СМС

Sprut
Offline
Зарегистрирован: 26.12.2016

 

alexlord пишет:

сутки тестовой работы с отправкой данных каждые 6 минут на narodmon.ru 

 
Поделитесь пожалуйста кодом
Sprut
Offline
Зарегистрирован: 26.12.2016

alexlord пишет:

отравляю несколько смс на модуль.

модуль принимает но не сохраняет их. 



при попытке чтения выдает ошибку.

at+cmgr=1

+CMS ERROR:321

и так по любой ячейке.....  никто не разбирался?

В этом модуле по умолчанию не задана настройка куда сохранять входящие СМС, т.е. по умолчанию он их вообще нигде не хранит, ни в памяти ни на СИМ-карте, 3й параметр пустой:







AT+CPMS?

+CPMS: "SM",0,30,"SM",0,30,"",0,25

Для того чтобы сохранялись на СИМ-карте нужно дать комманду:







AT+CPMS="SM","SM","SM"

 

 

Dottore
Offline
Зарегистрирован: 19.11.2016

alexlord пишет:

 
по подключению. У меня вот такой модуль у него встроенный стабилизатор на 4 в. 
ардуина 5 вольтовая, подключено напрямую..... пока все работает. ;) 
максимум что пока  было это сутки тестовой работы с отправкой данных каждые 6 минут на narodmon.ru 
не завис.
 
Приветствую Вас!  Тоже нацеливаюсь на этот модуль, выяснил всё про стабилизатор напряжения, применённый в нем, на MP1584EN с SMD дросселем, остается вопрос по согласованию уровней. Вы не могли бы отследить на плате цепи RxD и TxD от модуля до выходных контактов? Если уж они сделали нормальный стабилизатор напряжения, может быть они и цепи передачи данных развели как положено, тем более, что для этого необходимо всего 5 пассивных компонентов, ценой в 3 копейки пучок...
myxaz
Offline
Зарегистрирован: 23.05.2015

.

myxaz
Offline
Зарегистрирован: 23.05.2015

toc пишет:

>> может кто дальше продвинулся?

alexlord, ага

там текст в семибитной кодировке

AT+CUSD=1,#102#,15
Vash balans 90.65 r.
Vnimanie! Poholodanie!

 

Поделитесь пожалуста полным кодом.

novak
Offline
Зарегистрирован: 25.02.2017

myxaz пишет:

...

Поделитесь пожалуста полным кодом.

И я за. Можете оформить в виде функции Decode7bit, у которой на вход два параметра: 1-й ссылка на входной буфер, 2-й ссылка на выходной буфер. Можно и третий - размер выходного буфера, чтобы по памяти не побежать.

novak
Offline
Зарегистрирован: 25.02.2017

Вот моя функция перекодировки.

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

Как пользоваться

      //ответ на USSD запрос AT+CUSD=1,#111#,15
      if(inputstr.indexOf(F("+CUSD:"))>-1)
      {
        //анализируем строку
        int p1 = inputstr.indexOf(F("\"")); //начало строки
        int p2 = inputstr.lastIndexOf(F("\"")); //конец строки
        inputstr = inputstr.substring(p1+1,p2);
        Serial.println("");
        Serial.println("Input string:");
        Serial.println(inputstr);
        String decodestr;
        Decode7bit(inputstr, decodestr);
        Serial.println("");
        Serial.println("Decode string:");
        Serial.println(decodestr);
      }

А вот что получил в терминале

AT+CUSD=1,#111#,15

OK

+CUSD: 2, "В0;мћѓj.-wі@в·»>Б\0Zоv)" ,15
Input string:
В0;мћѓj.-wі@в·»>Б\0Zоv)

Decode string:
Balans 5.00hrn, bonus 0.00hrn.



AT+CUSD=1,#121#,15

OK

+CUSD: 1, "Вў–™l&© wДN›Лг2›НХ`h;ИҐЭstD~ѓd0lжЉЭ\ з»]–ѓИй2€ьЕr.МГ№*•Ja-ПЭй°;џЃљeц[љvџAъ0hZ…Ґ ъ<н~зл­kv–»_±Щќ¶‡Љ‹^+@" ,15
Input string:
Вў–™l&© wДN›Лг2›НХ`h;ИҐЭstD~ѓd0lжЉЭ\ з»]–ѓИй2€ьЕr.МГ№*•Ja-ПЭй°;џЃљeц[љvџAъ0hZ…Ґ ъ<н~зл­kv–»_±Щќ¶‡Љ‹^+@

Decode string:
BEZLIMIT na lifecell, 50hv na inshi do 20.03.17. Nomer die do 19.02.18.
***
Vesnianyy  MeloRing za SUPER tsinoyu-3,3grn/15dniv!

1.Tak
 

Так вот у меня вопрос что обозначает первый параметр в возвращаемом сообщении (1 или 2)?

myxaz
Offline
Зарегистрирован: 23.05.2015

novak пишет:

Вот моя функция перекодировки.


Большое спасибо. Но у меня в терминале ничего не выходит. можете показать весь код пожалусто , либо хотябы ту часть где идет запрос на USSD , и void Setup ?

novak
Offline
Зарегистрирован: 25.02.2017

myxaz пишет:

Большое спасибо. Но у меня в терминале ничего не выходит. можете показать весь код пожалусто , либо хотябы ту часть где идет запрос на USSD , и void Setup ?

SoftwareSerial gsm(2, 3); // RX, TX
String inputstr;

void setup() {
  Serial.begin(9600);  //Скорость порта для связи Arduino с компьютером
  Serial.println("Start module");
  
  gsm.begin(9600);  //Скорость порта для связи Arduino с GSM модулем

  Serial.print("Wait connect to GSM...");
  while( !waitConnect( 10000 ) )
  {
    Serial.println("timeout");
    Serial.print("Wait connect to GSM...");
  }
  Serial.println("ok");
  
  Serial.print("Wait registration in net...");
  while( !waitRegistration( 10000 ) )
  {
    Serial.println("timeout");
    Serial.print("Wait registration in net...");
  }
  Serial.println("ok");

  gsm.println("AT+CLIP=1");
  delay(200); // даём время на усваивание команды
  gsm.println("AT+CMGF=1");
  delay(200); // даём время на усваивание команды
  gsm.println("AT+CNMI=2,2");
  delay(200); // даём время на усваивание команды
  gsm.println("AT+CUSD=1,#121#,15");
  delay(200); // даём время на усваивание команды
  inputstr = "";
}

И цикл программы

void loop() {
  while(gsm.available())
  {
    char ch=gsm.read();
    if( ch == '\r' )
    {
      //ответ на USSD запрос AT+CUSD=1,#111#,15
      if(inputstr.indexOf(F("+CUSD:"))>-1)
      {
        //анализируем строку
        int p1 = inputstr.indexOf(F("\"")); //начало строки
        int p2 = inputstr.lastIndexOf(F("\"")); //конец строки
        inputstr = inputstr.substring(p1+1,p2);
        Serial.println("");
        Serial.println("Input string:");
        Serial.println(inputstr);
        String decodestr;
        Decode7bit(inputstr, decodestr);
        Serial.println("");
        Serial.println("Decode string:");
        Serial.println(decodestr);
      }

      inputstr = "";
    }
    else
    {
      inputstr+=ch;
    }
    Serial.write(ch);
  } 

  if (Serial.available())
    gsm.write(Serial.read());
}

Функции waitConnect и waitRegistration, это ожидание конекта с GSM-модулем, и ожидание регистрации в сети соответственно. Если нужны скину код, но это простой цикл отправки и ожидания ответа опредкоманд.

myxaz
Offline
Зарегистрирован: 23.05.2015

novak пишет:

 

Функции waitConnect и waitRegistration, это ожидание конекта с GSM-модулем, и ожидание регистрации в сети соответственно. Если нужны скину код, но это простой цикл отправки и ожидания ответа опредкоманд.

Большое спасибо. Очень помогло. Ваш код работает. Единственное добавил переход на скорость 9600. т.к.SoftwareSerial я так понял не особо любит эту скорость. Но почемуто не получается заставить работать по событию например проверять состояние счета при наличии входящего звонка. В сериал летят сплошные иероглифы. Не подскажите в чем проблема?

#include <SoftwareSerial.h>
SoftwareSerial gsm(2, 3); // RX, TX
String inputstr;
boolean ok = false;
String str = "";
void setup() {

  Serial.begin(9600);
  do {
    gsm.begin(115200);
    delay(100);
    gsm.println(F("ATZ+IPR=9600"));
    delay(500);
    gsm.end();
    delay(100);
    gsm.begin(9600);
    delay(100);
    gsm.println(F("ATE 0"));//отключаем эхо
    delay(100);
    gsm.println(F("AT"));
    delay(100);
    str = "";
    while (gsm.available())
    {
      char ch1 = gsm.read();
      str += ch1;
      delay(10);
    }
    if (str.indexOf(F("OK")) > -1) {
      ok = true;
      Serial.println("IPR:9600 OK");
    }
    else {
      gsm.end(); delay(500); ok = false;
      Serial.println("IPR not 9600");
    }
  } while (!ok);


  gsm.println("AT+CLIP=1");
  delay(200); // даём время на усваивание команды
  gsm.println("AT+CMGF=1");
  delay(200); // даём время на усваивание команды
  gsm.println("AT+CNMI=2,2");
  delay(200); // даём время на усваивание команды
  inputstr = "";


  Serial.println("Start module");
}

void loop() {
  if (gsm.find("RING")) {
    gsm.println("ATH");
    delay(200);
    gsm.println("AT+CLIP=0");
    delay(200);
    gsm.println("AT+CUSD=1,#101#,15");

    delay(200);
    while (gsm.available())
    {
      char ch = gsm.read();
      if ( ch == '\r' )
      {
        //ответ на USSD запрос AT+CUSD=1,#111#,15
        if (inputstr.indexOf(F("+CUSD:")) > -1)
        {
          //анализируем строку
          int p1 = inputstr.indexOf(F("\"")); //начало строки
          int p2 = inputstr.lastIndexOf(F("\"")); //конец строки
          inputstr = inputstr.substring(p1 + 1, p2);
          Serial.println("");
          Serial.println("Input string:");
          Serial.println(inputstr);
          String decodestr;
          Decode7bit(inputstr, decodestr);
          Serial.println("");
          Serial.println("Decode string:");
          Serial.println(decodestr);
        }

        inputstr = "";
      }
      else
      {
        inputstr += ch;
      }
      Serial.write(ch);
    }

    if (Serial.available())
      gsm.write(Serial.read());
  }
}


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

 

novak
Offline
Зарегистрирован: 25.02.2017

Надеюсь у тебя GSM модуль A6? Так вот у него автоматическая подстройка частоты сериала, нужно только несколько раз в секунду подать простую команду AT и дождаться на неё OK, при этом посылка команду установки скорости (ATZ+IPR=9600) явно не нужна. Это у меня выполняет функция waitConnect, вот её код:

bool waitConnect(long timeout) {
  int countok = 0;
  String str;
  uint32_t tstart = millis();
  while(countok<5) //ждём пять ОК
  {  
    uint32_t ms = millis();
    if( ( ms - tstart) > timeout )
      return false;
      
    // Событие срабатывающее каждые 500 мс   
    if( ( ms - msAT ) > 500|| ms < msAT )
    {
      msAT = ms;
      //посылаем команду
      gsm.println("AT");
      str = "";
      delay(100); //Ждём ответа
      while(gsm.available())
      {
        char ch=gsm.read();
        str+=ch;
      } 
      if(str.indexOf(F("OK"))>-1)
        countok++;
      else
        countok = 0;
    }
  }  
  return true;
}

После этого идёт ожидание регистрации в сети. Ответ на команду должен прийти 1,1. Вот код

bool waitRegistration( long timeout ) {
  bool ok = false;
  String str;
  uint32_t tstart = millis();
  while(!ok)
  {  
    uint32_t ms = millis();
    if( ( ms - tstart) > timeout )
      return false;

    // Событие срабатывающее каждые 500 мс   
    if( ( ms - msAT ) > 500|| ms < msAT )
    {
      msAT = ms;
      //посылаем команду
      gsm.println("AT+CREG?");
      delay(100); //Ждём ответа
      str = "";
      while(gsm.available())
      {
        char ch=gsm.read();
        str+=ch;
      } 
      int p = str.indexOf(F("+CREG: "));
      int a = 0;
      int b = 0;
      if( p > -1 )
      {
        p += 7;
        str = str.substring(p);
        a = str.toInt();
        p = str.indexOf(F(","));
        if( p > -1 )
        {
          p += 1;
          str = str.substring(p);
          b = str.toInt();
        }  
      }
      Serial.print(a);
      Serial.print(",");
      Serial.print(b);
      Serial.print(" ");
      if(a==1 and b==1)
        ok = true;
    }
  }  
  return true;
}

И только после этого можно отсылать команды настройки, такие как

AT+CLIP=1

AT+CMGF=1

AT+CNMI=2,2
 
Иначе они у меня почему то возвращали иногда ERROR
----------------------------------------------------------------------
Теперь поговорим о твоём ожидании RING, кто же в этом месте ждёт??? там может прийти RING разбитый на части как угодно. Т.е. можно за один раз вычитать RIN, а G только в следующем цикле loop. Я это делаю после сбора целой строки. Ожидаю 6 рингов, отбиваю вызов и отсылаю смску со статусом устройства.
void loop() {
  while(gsm.available())
  {
    char ch=gsm.read();
    if( ch == '\r' )
    {
      //сдесь анализ целой входящей строки
      //входящий вызов
      if(inputstr.indexOf(F("RING"))>-1)
      {
        countring++;
        Serial.println(countring);
      }
      //ответ на USSD запрос AT+CUSD=1,#111#,15
      if(inputstr.indexOf(F("+CUSD:"))>-1)
      {
        //анализируем строку
        int p1 = inputstr.indexOf(F("\"")); //начало строки
        int p2 = inputstr.lastIndexOf(F("\"")); //конец строки
        inputstr = inputstr.substring(p1+1,p2);
        Serial.println("");
        Serial.println("Input string:");
        Serial.println(inputstr);
        String decodestr;
        Decode7bit(inputstr, decodestr);
        Serial.println("");
        Serial.println("Decode string:");
        Serial.println(decodestr);
      }
      //если хотим ещё что то ловить, то дописываем сдесь
      //
      //
      
      //после анализа строки очищаем её
      inputstr = "";
    }
    else
    {
      inputstr+=ch;
    }
    Serial.write(ch);
  } 

  if (Serial.available()) //передадим команды из терминала в модуль
    gsm.write(Serial.read());
  
  if(countring==6) //после 6 входящих RING
  {
    countring = 0;
    //отбить вызов
    gsm.println("ATH");
    delay(100); //Ждём ответа
    char text[48];
      
      //послать смс статус
      strcpy(text,"STATUS");
      sendTextMessage(text); //посылка sms
  }
}

 

 
myxaz
Offline
Зарегистрирован: 23.05.2015

novak пишет:

 

Теперь поговорим о твоём ожидании RING, кто же в этом месте ждёт??? там может прийти RING разбитый на части как угодно. Т.е. можно за один раз вычитать RIN, а G только в следующем цикле loop. Я это делаю после сбора целой строки. Ожидаю 6 рингов, отбиваю вызов и отсылаю смску со статусом устройства.

 

Большое спасибо, за совет. Исправил, все заработало.

Iguana
Offline
Зарегистрирован: 22.02.2016

Здравствуйте! А кто нибудь запитывал этот модуль от акб 18650 минуя встроенный стабилизатор? 

Kshkoj
Offline
Зарегистрирован: 17.04.2017

Доброе утро!

Помогите новичку! Заказал GSM модуль A6 mini https://geardx.com/ru/p/gprs-a6-mini-Серийный-gprs-gsm-модуль-ядра-developemnt-совет-для-arduino-443770 , после чего обратил внимание, что у нет примеров подключения. На данной модели 16 контактов, а у большенства моделей - 24. Подскажите - для чего контакты HTX, HRX, IO14, NET, MIC2_P. Если правильно понял, то URX и UNX для подключения к компу или ардуино.

alex_r61
alex_r61 аватар
Offline
Зарегистрирован: 20.06.2012

Сравните с другими моделями и с доками, пост #3. URX и UTX сериал порт.

Kshkoj
Offline
Зарегистрирован: 17.04.2017

Сравнивал.. пока не понятно... Может это для меня и лишние навороты, но интересно все же... Во всех элементарных примерах просто подключают через urx-utx и довольны...  Ничего более полного пока не нашел...

 

 

alex_r61
alex_r61 аватар
Offline
Зарегистрирован: 20.06.2012

Если названия выводов на плате не соответствуют названию в доках надо прозвонить от модема к пинам, ну и китайца пнуть на предмет описания. Из наворотов мне интересна камера, из за неё и брал. Это модель A6C.

Kshkoj
Offline
Зарегистрирован: 17.04.2017

Камера то же интересна, но это другой проект... Я заказал 590 для телеметрии и А6 - друг попросил дисковый сотовый телефон сделать для подарка товарищу... Я так понимаю, то же из Ростова будете?

alex_r61
alex_r61 аватар
Offline
Зарегистрирован: 20.06.2012

Ну если дисковый сотовый с камерой вообще круто будет:) Из Ростова н/Д.

Kshkoj
Offline
Зарегистрирован: 17.04.2017

Круто.... но тогда еще экран приделать надо... и вайбер поставить.... Главное чтоб полифония была цветная ?-) Кстати - звонок оставляю родной.... А аппарат железный... с горгазовой аварийки, кажется... киллограм 5-6 весит :-)

 

Logik
Offline
Зарегистрирован: 05.08.2014

Приехало и мне такое чудо. Вроде даже на АТ отвечает после доработок по опыту камрадов myxaz и novak. За что им спасиба, ибо на 115200 одни краказябы были. Код для старта так

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

void setup() 
{
  Serial.begin(9600);
  mySerial.begin(9600);

  
};

int ww=20;
void loop() {
  if (mySerial.available()) {
    Serial.write(mySerial.read());
  }
  else
  {
    if(ww)
    {
      mySerial.println(F("ATI"));
      delay(100);
      ww--;
    }
  }
  if (Serial.available()) {
    mySerial.write(Serial.read());
  }

}

 

Почитал по ссылке #3, и его первоисточник http://smart-prototyping.com/image/data/9_Modules/101756%20Wireless%20A6C/A6_A7_A6C_datasheet-EN.pdf почитал.

А девайс вобще от 5В нормально работает? Обосную вопрос цитатой "Working voltage : 3.3V-4.2V;" Заодно отвечу  Iguana "А кто нибудь запитывал этот модуль от акб 18650 минуя встроенный стабилизатор? ", судя по диапазону он как раз на такое и заточен.

ПС. Думаю что ответ про 5В нашел на плате в виде стабилизатора. Т.е сам А6 - железная коробочка не расчитан на 5В, но продаваемая плата с А6 (которую называют А6_mini или тоже просто  А6)))) уже с стабилизатором и может держать 5В и наверно даже несколько выше. Я верно понимаю?

Logik
Offline
Зарегистрирован: 05.08.2014

Дело движется, но результат не получен.

скетч

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

void setup() 
{
  Serial.begin(9600);
  mySerial.begin(9600);

  
};

int ww;
void loop() {
  int t=millis();
  if (mySerial.available()) {
    Serial.write(mySerial.read());
  }
  else
  {
    if(ww<10)
    {
      mySerial.println(F("AT"));
      delay(80);
      ww++;
    }
    else
    {
     static int tt;
     static byte Q;
     if(t-tt>100)
     {
       tt=t;
       if(Q)
        Q--;
       else
       { 
        switch(ww)
        {
         case 10: Q=50;break;
         case 11: mySerial.println(F("ati"));Q=2;break;
         case 12: mySerial.println(F("at+ccid"));Q=5;break;
         case 13: mySerial.println(F("AT+CPOF=?"));Q=5;break;
         default: ww--; 
        }
        ww++;
       }
     }
    }
  }
  
  if (Serial.available()) {
    mySerial.write(Serial.read());
  }

}

Выдает

AT
 
OK
AT
 
OK
AT
 
OK
 
^CINIT: 1, 0, 0
 
^CINIT: 2, 32, 41891
 
^STN: 37
 
^CINIT: 4, 8192, 37
 
^CINIT: 8, 2048, 1
 
^CINIT: 16, 0, 1638440
 
^CINIT: 32, 0, 0
 
+CREG: 0
ati
 
Ai Thinker Co.LTD
A6 
V03.03.20161229019H03
 
OK
at+ccid
 
+CCID:8938007100412540498F
 
OK
AT+CPOF=?
 
OK
 
+CIEV: service,  0
+CIEV: roam, 0
 
+CREG: 2
 
+CIEV: service,  0
+CIEV: roam, 0
 
+CREG: 3
 
Причем последние 3 строки через паузу порядка 5 секунд после того как модуль никто не трогает.
Я так понимаю что симку видет но в сети не регится. 
С чего бы это? Пока предпологаю тока от блока питания не хватает.

 

novak
Offline
Зарегистрирован: 25.02.2017

На карте деньги есть? У меня иногда регистрация в сети проходила даже больше минуты.

alex_r61
alex_r61 аватар
Offline
Зарегистрирован: 20.06.2012

У меня один модуль на 5В 0.5А не запустился, думал что убитый. Второй заработал, но были сбои. От 1А БП оба заработали.

Logik
Offline
Зарегистрирован: 05.08.2014

Несмотря на:

1. БП 5В 2А

2. электролит 3300мкФ

оно упрямствует :(

При этом в процессе включения статус регистрации последовательно, секунд за 30-40 проходит состояния

at+creg?
+CREG: 1,10
at+creg?
+CREG: 1,12
at+creg?
+CREG: 1,13
 
И между ними приходят сообщения о смене статуса типа 
+CIEV: service,  0
+CIEV: roam, 0
+CREG: 2
и
+CIEV: service,  0
+CIEV: roam, 0
+CREG: 3
 Регистрация в сети не происходит, что подтверждается расказом что абонент не в сети при звонке на модуль , невозможностью позвонить с модуля и на команду at+cops? ответоом  +COPS: 2 что собственно означает "2    deregister from network".
После этого симка была извлечена и вставлена в телефон, откуда без проблем звонила.
Самое любопытное в истории - коды ответа на at+creg? значения 10,12 и 13, которые напроч отсутствуют в доке :( Вероятно потому что модуль говорит что он V03.03.20161229019H03, а дока есть только V01.01.
Отсюда вопросы:
1. Не встречал ли кто доку на АТ команды поновей?
2. Есть ли у кого идеи?
 
ПС. Заметил что на телефоне уровень сигнала - 2 палки. Сейчас думаю как проверить, не в этом ли проблема.
 
 
 
 
 
 

 

Logik
Offline
Зарегистрирован: 05.08.2014

Ха! Кажется загадка решена. В списке сетей, а его я только что получил командой at+cops=? секунд за 20. Среди 3-х обнаруженых операторов напроч отсутствует мой. Тут я вспомнил "мелочь", он стандарта wcdma. А что с этим делом у A6? Ща почитаю.

ПС. почитал, пойду симку другого оператора искать.
Logik
Offline
Зарегистрирован: 05.08.2014

Наигрался я этим А6. Не плох вроде. Сложноватый конечно набор команд, но терпимо. Стабилен, но без аппаратного ресета бывают неприятности с автоопределением скорости. Модем занимается чем то долгим, МК ребутнулся, пытается достучатся до модема, а он молчит да еще и на нетой скорости:) А потом чего выплевывает непонятное.

Код.

#include <SoftwareSerial.h>
#include "SSD1306.h"

SoftwareSerial mySerial(2,3);

#define OLED_SCL_PIN 6
#define OLED_SDA_PIN 7
ssd1306_i2c(OLED_SCL_PIN, OLED_SDA_PIN, myOLED) ;


typedef void (*pFn)(char* p);
typedef boolean (*pFnb)(char* p);

typedef struct sEventsMap
{
  const char* Name;
  pFn Event;
};

bool NevSpeed;

void ReciveAT_OK(char* p){  NevSpeed=true;};

bool ActivAT;
pFn EventOk=ReciveAT_OK;
void ReciveOK(char* p){digitalWrite(13,LOW);ActivAT=false; if(EventOk) EventOk(p);  };

void SendAT(const __FlashStringHelper* at)
{
 //Serial.print(">>AT>>"); 
 //Serial.println(at); 
 digitalWrite(13,HIGH);
 ActivAT=true;
 mySerial.println(at);
}

char InpStr[100];
void SerialOut(char* p=InpStr){ Serial.println(p);}

void ReciveRING(char* p){  SerialOut();  myOLED.clrScr();myOLED.drawString(6,2,"R I N G");SendAT(F("AT+CLCC"));};

pFn EventERROR;
void ReciveERROR(char* p){digitalWrite(13,LOW); ActivAT=false; if(EventERROR) EventERROR(p);  else SerialOut();};

byte ConnectMode=0;
pFn EventChngReg;
void ChngReg(char* p)
{
  byte r=(*(p+3))-'0';
  if(r!=ConnectMode)
   if(EventChngReg)
   {
     ConnectMode=r;
     EventChngReg(p);
   }
 ConnectMode=r;
}

void DravString(byte str, byte row, char *p)
{
   char *a;
   for(a=p;*a>=' ';a++) {}; *a=0;
   myOLED.drawString(str,row,p);

}

void ReciveCOPS(char* p)
{
  p++;
  SerialOut(p);
  if((*p)!='(')    //список всех сетей
  { 
   DravString(0,7,p);
   return;
  }
  myOLED.clrScr(); 
  byte n=1;
  for(char *a=p, *b=p;*a!=0;a++)
  {
   if((*a==')') && (*(a+1)!='"'))  //life - козлы!!!
   {
     a++;
     *a=0;
     myOLED.drawString(0,n,b);
     n++;
     b=a+1;
   } 
  }
}
void ReciveSMS(char* p)
{
   Serial.println("SMS"); 
   SerialOut();
   
   myOLED.clrScr();
   myOLED.drawString(7,3,"S M S");
   
   SendAT(F("AT+CMGF=1"));
   SendAT(F("AT+CMGR=1"));
 }
void ReadSMS(char* p){ Serial.println("Text"); SerialOut();}
void SignalQuality(char* p){ myOLED.drawString(10,0,"sign:");DravString(15,0,p);Serial.println("Sig:"); SerialOut();}
void ReadICCID(char* p)
{
  char *a=p;
  for(;*a>=' ';a++)
  {
   if(!(((int)a)&3)) *a='*';
  }
  *a=0;
  myOLED.drawString(0,5,p); 
 Serial.println("ICCID:");  
 SerialOut(p);
}

void EndCALL(char* p){DravString(4,7,p);}

void DetaleRING(char* p)
{ 
  char *a=p;for(;*a!='"';a++);
  *a=0;
  DravString(3,4,p);
  *a='"';*(a+4)='*';*(a+7)='*';*(a+9)='*';*(a+11)='*';
  DravString(1,5,a);
}

sEventsMap EventsMap[]={
  {"OK",       ReciveOK},
  {"RING",     ReciveRING},
  {" ERROR:",  ReciveERROR},
  {"+CME",     ReciveERROR},
  {"+CIEV:",   EndCALL},
  {"+CREG:",   ChngReg},
  {"+COPS:",   ReciveCOPS},
  {"^CINIT:",  SerialOut},
  {"+CMTI",    ReciveSMS},
  {"+CMGR",    ReadSMS},
  {"+CSQ:",    SignalQuality},
  {"+CCID:",   ReadICCID},
  {"+CLCC:",   DetaleRING}
};

boolean ReciveATE_OK(char* p){SendAT(F("ati"));return true;};
boolean ReciveATI_OK(char* p)
{
  SerialOut(p);
  myOLED.clrScr();
  myOLED.setFont( SSD1306::FONT_SIZE_1); 
  byte n=0;
  char *b=p;
  for(char *a=p;*a!=0;a++)
  {
   if(*a<' ')
   {
     *a=0;
     myOLED.drawString(0,n,b);
     n++;
     a++;
     b=a+1;
  } 
  }
  *b='@';
  myOLED.drawString(0,n,b);
  SendAT(F("at+ccid"));
  myOLED.drawString(0,4,"маскированый ICCID:");
 return true;
};

boolean ReciveAT_CCID_OK(char* p){ SendAT(F("at+creg?"));  return true;};

boolean ReciveAT_CREG_OK(char* p)
{
  if(ConnectMode!=1)
  {
     SendAT(F("at+creg?"));
     return false; //повторим эту команду
  }
  EventChngReg=ReciveInit_ERROR;  //т.к. не стартует при незавершенной регистрации то перезапустим по её завершению
  myOLED.drawString(5,7,"Поиск сетей...");
  SendAT(F("at+cops=?"));return true;
};
boolean ReciveAT_COPS_OK(char* p){ EventChngReg=0; SerialOut();SendAT(F("at+cops?"));;return true;};
boolean ReciveAT_COPS_sel_OK(char* p){ EventChngReg=0; SerialOut();SendAT(F("at+csq"));return true;};
boolean InitEnd;
boolean ReciveAT_QSQ_OK(char* p){ EventERROR=0; SerialOut();EventOk=SerialOut;InitEnd=true;return true;};

 pFnb InitProc[]={
   ReciveATE_OK,
   ReciveATI_OK,
   ReciveAT_CCID_OK,
   ReciveAT_CREG_OK,
   ReciveAT_COPS_OK,
   ReciveAT_COPS_sel_OK,
   ReciveAT_QSQ_OK,
 };

byte InitID; 

void ReciveInit_OK(char* p)
{
//  p[strlen(p)-6]=0; //удаляем ОК
  if(InitID<sizeof(InitProc)/sizeof(InitProc[0]))
  {
   if(InitProc[InitID](p))
     InitID++;
  }

   
};

void ReciveInit_ERROR(char* p)
{
  InitProc[InitID-1](p);
}

pFn OK_Fn=ReciveAT_OK;

void setup() 
{
  Serial.begin(9600);
  mySerial.begin(9600);
  pinMode(13, OUTPUT);
  
    
  myOLED.begin();
  myOLED.clrScr();
  myOLED.setFont( SSD1306::FONT_SIZE_2); 
  myOLED.drawString(1,1,"Пейджер");
  myOLED.drawString(0,3,"ардуинщика");
  delay(2000);

};

int ww;
void loop() {
  int T=millis();
  if (mySerial.available()) 
  {
    static byte StrEnd;
    static char* pInpStr=InpStr;
    static char* pNewStr=InpStr;
    byte r=mySerial.read();
    if(r==10) StrEnd|=1;
     else if(r==13) StrEnd|=2;
       else
        StrEnd=0;
        
    *pInpStr=r;
    if(pInpStr<(InpStr+sizeof(InpStr)-1))
      pInpStr++;
  //  char s[10];itoa(r,s+2,16);s[0]=r;s[1]='-'; Serial.println(s);  
    if((StrEnd==3) && ((pInpStr-InpStr)==2))
    {
      StrEnd=0;
      pInpStr=InpStr;
    }

    if(StrEnd==3)
    {
//       Serial.println(InpStr);
     *pInpStr=0;
      bool FlPresent;
      FlPresent=false;
      for(byte i=0;i<sizeof(EventsMap)/sizeof(EventsMap[0]);i++)
      {
        if(!memcmp(EventsMap[i].Name,pNewStr,strlen(EventsMap[i].Name)))
        {
         if(EventsMap[i].Event)
         {
           char *p=InpStr;
           if(!i)
             *pNewStr=0; //если ОК - удаляем его
           else
             p+=strlen(EventsMap[i].Name); 
  
            EventsMap[i].Event(p);
         }
         FlPresent=true;
         break;
       }
      }
 //     Serial.println(InpStr);
      if(FlPresent)
      {
        pInpStr=InpStr;
        StrEnd=0;
      }
      pNewStr=pInpStr;
    }   
  }
  else
  {
    
    if(!NevSpeed)
    {
      SendAT(F("AT"));
      digitalWrite(13,ww&1);
      delay(24);
    }
    else
    {
      static bool FlInit;
       if(!FlInit)
       {
         FlInit=true;
         EventOk=ReciveInit_OK;
         EventERROR=ReciveInit_ERROR;
         SendAT(F("ate 0"));
       }
    }
  }
  
  static int TimeCSQ;
  if(ActivAT || !InitEnd)
   TimeCSQ=T;
  else if(T-TimeCSQ>3000)z
  {
    TimeCSQ=T;
  //  SendAT(F("AT+CPMS?"));
  //  SendAT(F("AT+CMGR=1"));
 //   SendAT(F("AT+CMGF=1"));
 //   SendAT(F("AT+CMGL=4"));
    SendAT(F("at+csq"));
  }
   
  
  if(InitEnd)
   if (Serial.available()) {
    mySerial.write(Serial.read());
  }

}

синематограф. https://youtu.be/cx0dIHB1zH8

 

Звонки принимает, номера определяет. А с СМС не так просто. Видать его настроить надо, а то он даже не сохраняет их. Я попробовал парочку прислать. Выдает кучу ошибок, а принятой не появляется в памяти. Я и плюнул. 

novak
Offline
Зарегистрирован: 25.02.2017

Logik пишет:

....

А с СМС не так просто. Видать его настроить надо, а то он даже не сохраняет их. Я попробовал парочку прислать. Выдает кучу ошибок, а принятой не появляется в памяти. Я и плюнул. 

Нужно подать команду куда сохранять СМС. По умолчанию она сразу приходит в терминал. Формат вывода тоже настраивается AT-командами. Разберись сначало с латинскими. Для руских букв особый формат.

Я как раз разбираюсь с USSD-запросами, там разбор тоже особый. Хочу баланс получать.

Logik
Offline
Зарегистрирован: 05.08.2014

novak пишет:

СМС. По умолчанию она сразу приходит в терминал. 

Так вот что мне валилось в сириал! А я смотрю - странные какието ошибки большим потоком, а то наверно SMS была в PDU.

Я вобще не сильно уверен в востребованости функционала SMS. Для обмена данными  TCP по GPRS явно предпочтительный. На крайняк если есть причины не держать его постоянно, можна по входящему звонку без ответа на него подымать TCP.

ПС. Пациент с вчерашнего вечера в сети, ни ребутов ни сбоев. ОК. Да на видео упомянут электролит по питанию на 3300мкФ. Без него включается, начинает работать но поиск сетей не проходит. Питание от USB через ардуино нано. Так что к питанию требователен.

Logik
Offline
Зарегистрирован: 05.08.2014

Продолбавшись с SMS начал замечать некоторые странности в данных поступающих с A6. После исключения всех возможных факторов и  экспериментов с разными скоростями взглянул на реализацию софтового сириала в SoftwareSerial.cpp.

Я много херни видел за жизнь в *.cpp, но такого пи...ватизма не припоминаю даже у джуниора.

Вот так,

inline void SoftwareSerial::handle_interrupt()
{
  if (active_object)
  {
    active_object->recv();

.............................................

потом так

void SoftwareSerial::recv()
{
............................

    for (uint8_t i=0x1; i; i <<= 1)
    {
      tunedDelay(_rx_delay_intrabit);
.................
   }
   tunedDelay(_rx_delay_intrabit);
......................
шахимат в одном пакете
/* static */ 
inline void SoftwareSerial::tunedDelay(uint16_t delay) { 
  uint8_t tmp=0;

  asm volatile("sbiw    %0, 0x01 \n\t"
    "ldi %1, 0xFF \n\t"
    "cpi %A0, 0xFF \n\t"
    "cpc %B0, %1 \n\t"
    "brne .-10 \n\t"
    : "+r" (delay), "+a" (tmp)
    : "0" (delay)
    );
}

Итого: МК уходит в прерывание и висит в нем все время пока не приймет стоповый. А это значить что при сплошном потоке данных  у скетча времени на обработку принятого практически нет. Короткие паузы между стопом и стартом успешно забирает прерывание системного таймера. И на практике именно так выглядит ситуация. При приеме более 64 байт буфер софтового сириала заканчивается. А выбирать данные из него МК просто не успевает, он все время занят выполнением tunedDelay. И внутри прерывания. У остального кода нет шансов. Причем понижение скорости только ухудшает ситуацию.

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

Вот они, безславные ублюдки, выродки рода разработчиков. Будте прокляты в веках.

ladyada (http://ladyada.net)

Mikal Hart (http://www.arduiniana.org)

Paul Stoffregen (http://www.pjrc.com)
 
Garrett Mace (http://www.macetech.com)
 

Я не строю атомные реакторы. Не умею и может й..нуть. Но я писал софтверный сириал и не раз, и на ассемблере для пиков и т.д. Прерывание пина и таймер легко решают задачу, пусть не для высоких скоростей но решает. Почему ублюдки-авторы берутся делать то, чего не умеют? Они надеются на свой фарт, что их не долбанет за их говнокод? А я думаю и надеюсь долбанет, и сильно.

ПС. Я Вам рассказал о своем последнем случае  использования SoftwareSerial. И Вам не советую.

novak
Offline
Зарегистрирован: 25.02.2017

Да, там буфер 64 байта по умолчанию. Измени переменную отвечающую за буфер, советуют менять на 180.

Я отлаживаюсь на софтсериале, потом переключаюсь на аппаратное.

Kshkoj
Offline
Зарегистрирован: 17.04.2017

novak пишет:

Я отлаживаюсь на софтсериале, потом переключаюсь на аппаратное.

Это для тех плат, где аппаратное одно? Те на меге можно сразу на аппаратном пробывать или есть другие причины?

Skarm
Offline
Зарегистрирован: 11.05.2017

Gprs никто ещё не юзал???, поделитесь если есть кодом.

 

Logik
Offline
Зарегистрирован: 05.08.2014

Гммм.. ну как бы раз ТСР юзаю, наверно по GPRS. Код выше. Но вобщето актуальней АТ командами делится. Продолжаю здесь http://arduino.ru/forum/apparatnye-voprosy/gsm-modem-a6-v-rezhime-tcp т.к. к рингу это явно не относится.