ESP32 t-call Не получается парсить ответ модема.

Allleksey
Offline
Зарегистрирован: 28.11.2020

Добрый день, коллеги!

В наличие плата ESP32 t-call (это которая с SIM800L на борту). Пытаюсь разобраться с платкой. Начал с того, что скетч должен отправить АТ команды. Отправлять последовательно не интересно. Решил дожидаться от модема ответа. Написал скетч, который отправляет команду, после чего ждем ответ от модема. Далее попытался парсить ответ, что бы выделить из него "ОК" ну для начала проверять, есть ли в ответе искомая подстрока. Вот такой скетч получился. 

#define DEBUG             1                                                           // 0 - Debug OFF, 1 - Debug ON

/*********************************************
 * Натройка SIM800
 * ******************************************/
#define MODEM_RST             5             // Pin RST SIM800L
#define MODEM_PWRKEY          4             // Pin PWRKEY SIM800L 
#define MODEM_POWER_ON       23             // Pin PowerOn SIM800K
#define MODEM_TX             27             // Pin TX SIM800L
#define MODEM_RX             26             // Pin RX SIM800L
#define LED_GPIO             13             // Pin 
#define LED_ON               HIGH
#define LED_OFF              LOW
#define SIM800Ready          15             // Пин светодиода готовности SIM800
#define SerialMon           Serial          // Set serial for debug console (to the Serial Monitor, default speed 115200)
#define SerialAT            Serial1         // Set serial for AT commands (to the module)
/*********************************************************
   Подключение библиотек
*********************************************************/
#include <Arduino.h>   
/*********************************************************
   Объявление переменных
*********************************************************/
boolean firstStart = HIGH;                  // Признак первого запуска системы для настройки
uint8_t caseNumber = 0;                     // Этапы отправки команд при начальной настройке
uint32_t firstStartTime;                    // Переменная для хранения переменной паузы ввода команд
/*********************************************************
   Объявление функций
*********************************************************/
void setupModem();
void firstStartModem();
String sendCommand(String command, boolean weitingResponse);
String waitResponse();
void pause(uint16_t pauseLenght);

void setup() {                                                                        // Функция первого запуска
#if (DEBUG == 1)
  SerialMon.begin(115200);                                                            // Инициирование работы с монитором порта
  delay(300);
  SerialMon.println("Debug is ON. Print LOG information.");
#endif
  SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);                             // инициирование работы с модемом
  setupModem();
  firstStartTime = millis();
}

void loop() {

  if (firstStart){                                                                    // Если установлен признак первого запуска системы, то...
    firstStartModem();                                                                // ... запуск функции ввода АТ команд настройки модема
  }

  while (SerialAT.available()) SerialMon.write(SerialAT.read());
  while (SerialMon.available()) SerialAT.write(SerialMon.read());
}

/*********************************************************
* ФУНКЦИИ РАБОТЫ С МОДЕМОМ
*********************************************************/
void setupModem(){                                                                    // Функция инициирование модема на плате ESP32 t-call
  pinMode(SIM800Ready, OUTPUT);
  digitalWrite(SIM800Ready, LOW);
  pinMode(MODEM_RST, OUTPUT);
  digitalWrite(MODEM_RST, HIGH);  

  pinMode(MODEM_PWRKEY, OUTPUT);
  pinMode(MODEM_POWER_ON, OUTPUT);

  // Turn on the Modem power first
  digitalWrite(MODEM_POWER_ON, HIGH);

  // Pull down PWRKEY for more than 1 second according to manual requirements
  digitalWrite(MODEM_PWRKEY, HIGH);
  delay(100);
  digitalWrite(MODEM_PWRKEY, LOW);
  delay(1000);
  digitalWrite(MODEM_PWRKEY, HIGH);

  // Initialize the indicator as an output
  pinMode(LED_GPIO, OUTPUT);
  digitalWrite(LED_GPIO, LED_OFF);

  // Временная задержка на 5 секунд перед стартом системы и началом настройки модема
  uint32_t TimePause = millis();
  SerialMon.println("Pause to boot the system");
  pause(9000);
  SerialMon.println("Start entering AT commands");
}

void firstStartModem(){                                                               // Функция отправки АТ команд при начальной настройке
  if (caseNumber == 0){
    String response_firstStartModem = sendCommand("AT", HIGH);
    firstStartTime = millis();
    caseNumber++;
  }
  else if (caseNumber == 1 && millis() - firstStartTime >500){
    sendCommand("ATE1", LOW);
    firstStartTime = millis();
    caseNumber++;
  }
  else if (caseNumber == 2 && millis() - firstStartTime >500){
    sendCommand("ATV1", LOW);
    firstStartTime = millis();
    caseNumber++;
  }
  else if (caseNumber == 3 && millis() - firstStartTime >500){
    sendCommand("AT+CMEE=1", LOW);
    firstStartTime = millis();
    caseNumber++;
  }
  else if (caseNumber == 4 && millis() - firstStartTime >500){
    sendCommand("AT+CLIP=1", LOW);
    firstStartTime = millis();
    caseNumber++;
  }
  else if (caseNumber == 5 && millis() - firstStartTime >500){
    sendCommand("AT+CMGF=1", LOW);
    firstStartTime = millis();
    caseNumber++;
  }
  else if (caseNumber == 6 && millis() - firstStartTime >500){
    sendCommand("AT&W", LOW);
    firstStartTime = millis();
    caseNumber++;
  }
  else if (caseNumber == 7){
    firstStart = LOW;
  }
}

String sendCommand(String command, boolean weitingResponse){
  String response_sendCommand = "No response was expected";
  SerialAT.println(command);
  if (weitingResponse){
    response_sendCommand = waitResponse(); 
    //response_sendCommand = response_sendCommand.substring(0, response_sendCommand.indexOf("\r"));   
    SerialMon.println("Команда: " + command);
    SerialMon.println("Ответ: " + response_sendCommand);
    if (response_sendCommand.startsWith(command)) {  // Убираем из ответа дублирующуюся команду
      SerialMon.println("совпадает с командой");
      response_sendCommand = response_sendCommand.substring(response_sendCommand.indexOf("\r", command.length()) + 2);
    }
  }
  return response_sendCommand;
  
}

String waitResponse(){                                                                // Ожидание ответа от модема
  String response_WeitResponse = "";                                                                  // Переменная для хранения результата
  uint32_t timeout_WeitResponse = millis() + 10000;                                                   // Переменная для отслеживания таймаута (10 секунд)
  while (!SerialAT.available() && millis() < timeout_WeitResponse)  {};                             // Ждем ответа 10 секунд, если пришел ответ или наступил таймаут, то...
  if (SerialAT.available()) {                                                           // Если есть, что считывать...
    response_WeitResponse = SerialAT.readString();                                                      // ... считываем и запоминаем
    response_WeitResponse.trim();
  }
  else {                                                                              // Если пришел таймаут, то...
#if (DEBUG == 1)
    SerialMon.println("Timeout...");                                                     // ... оповещаем об этом и...
#endif
  }
  return response_WeitResponse; 
}

/*********************************************************
* ФУНКЦИИ СОПУТСТВУЮЩЕЙ РАБОТЫ
*********************************************************/
void pause(uint16_t pauseLenght){                                                     // Функция паузы в миллисекундах
  uint32_t timeNow = millis();
  while(millis() - timeNow < pauseLenght){}
}

По сути 146 строка должна была определять, что в ответе есть дубль команды и далее удалить ее. LOG в мониторе порта вот такой.... 

Debug is ON. Print LOG information.
Pause to boot the system
Start entering AT commands
Комманда: AT
Ответ: ...
 
И вот даже сюда не копируется текст из монитора. После слова "Ответ:" есть какой то символ... естественно его не видно. По программе я не понимаю, какой там символ вставляется. Соответственно я не могу удалить его программно.
Прошу помощи в исправлении кривизны рук. Как удалить не нужные символы?

 

Allleksey
Offline
Зарегистрирован: 28.11.2020

Так выглядит ответ в мониторе порта.

Allleksey
Offline
Зарегистрирован: 28.11.2020

Изменил код на ожидание ответа во второй строке.

Сейчас распознает, что в ответе есть исходная команда, но все равно ответ содержит перенос на другую строку. И снова не понимаю, откуда он берется и как от него избавиться.

void firstStartModem(){                                                               // Функция отправки АТ команд при начальной настройке
  if (caseNumber == 0){
    sendCommand("AT", LOW);
    firstStartTime = millis();
    caseNumber++;
  }
  else if (caseNumber == 1 && millis() - firstStartTime >500){
    sendCommand("ATE1", HIGH);
    firstStartTime = millis();
    caseNumber++;
  }
  else if (caseNumber == 2 && millis() - firstStartTime >500){
    sendCommand("ATV1", LOW);
    firstStartTime = millis();
    caseNumber++;
  }
  else if (caseNumber == 3 && millis() - firstStartTime >500){
    sendCommand("AT+CMEE=1", LOW);
    firstStartTime = millis();
    caseNumber++;
  }
  else if (caseNumber == 4 && millis() - firstStartTime >500){
    sendCommand("AT+CLIP=1", LOW);
    firstStartTime = millis();
    caseNumber++;
  }
  else if (caseNumber == 5 && millis() - firstStartTime >500){
    sendCommand("AT+CMGF=1", LOW);
    firstStartTime = millis();
    caseNumber++;
  }
  else if (caseNumber == 6 && millis() - firstStartTime >500){
    sendCommand("AT&W", LOW);
    firstStartTime = millis();
    caseNumber++;
  }
  else if (caseNumber == 7){
    firstStart = LOW;
  }
}

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Allleksey пишет:

И вот даже сюда не копируется текст из монитора. После слова "Ответ:" есть какой то символ... естественно его не видно. По программе я не понимаю, какой там символ вставляется. Соответственно я не могу удалить его программно.

 
Распечатайте кроме текста ответа еще то же самое, только кодами символов (скажем, в HEX).
(Исходник не смотрел)

 

Allleksey
Offline
Зарегистрирован: 28.11.2020

Переписал код вот так:

String sendCommand(String command, boolean weitingResponse){
  String response_sendCommand = "No response was expected";
  SerialAT.println(command);
  if (weitingResponse){
    response_sendCommand = waitResponse();  
    if (response_sendCommand.startsWith(command)) {  // Убираем из ответа дублирующуюся команду
      response_sendCommand = response_sendCommand.substring(response_sendCommand.indexOf("\r", command.length()) + 2);
    }
    if (response_sendCommand = "OK") SerialMon.println("Команда: " + command + " Ответ: ОК");
  }
  return response_sendCommand;
  
}

Можно считать вопрос решеным. Хотя я не понимаю, в чем разница. Почему по разному отображает монитор порта информацию. 

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

я бы так не радовался, ибо в коде ошибка и в 9 строке всегда будет "ОК" :)

Allleksey
Offline
Зарегистрирован: 28.11.2020

не долго музыка играла...

Так в чем же причина? :(

String sendCommand(String command, boolean weitingResponse){
  String response_sendCommand = "No response was expected";
  SerialAT.println(command);
  if (weitingResponse){
    response_sendCommand = waitResponse();  
    if (response_sendCommand.startsWith(command)) {  // Убираем из ответа дублирующуюся команду
      response_sendCommand = response_sendCommand.substring(response_sendCommand.indexOf("\r", command.length()) + 2);
    }
    if (response_sendCommand == "OK") SerialMon.println("Команда: " + command + " Ответ: ОК");
  }
  return response_sendCommand;
  
}

Поправил... естественно работать перестала программа. 

Allleksey
Offline
Зарегистрирован: 28.11.2020

Никак не соображу, как преобразовать переменную String в массив (например char) и вывести цифровые значения в монитор порта.

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

надо смотреть что там вы "нарезаете"

SerialMon.println("Команда: " + command + " Ответ: " + response_sendCommand);

 

Allleksey
Offline
Зарегистрирован: 28.11.2020

Вот такой код

String sendCommand(String command, boolean weitingResponse){
  String response_sendCommand = "No response was expected";
  SerialAT.println(command);
  if (weitingResponse){
    response_sendCommand = waitResponse();  
    if (response_sendCommand.startsWith(command)) {  // Убираем из ответа дублирующуюся команду
      //response_sendCommand = response_sendCommand.substring(response_sendCommand.indexOf("\r", command.length()) + 2);
    }
    //if (response_sendCommand == "OK") SerialMon.println("Команда: " + command + " Ответ: ОК");
    SerialMon.println("Команда: " + command);
    SerialMon.println("Ответ: " + response_sendCommand);
    char charToString[15];
    strcpy(charToString, response_sendCommand.c_str());
    for (int i=0; i<15; i++){
      SerialMon.println(int(charToString[i]));
    }
  }
  return response_sendCommand;
}

Вот такой ответ в мониторе

Debug is ON. Print LOG information.
Pause to boot the system
Start entering AT commands
Команда: AT
Ответ: AT
 
OK
0
0
0
0
0
0
0
0
0
249
0
0
255
255
255
Команда: ATE1
Ответ: ATE1
 
OK
65
84
69
49
13
13
10
79
75
0
251
63
236
235
251
Команда: ATV1
Ответ: ATV1
 
OK
65
84
86
49
13
13
10
79
75
0
251
63
236
235
251
Команда: AT+CMEE=1
Ответ: AT+CMEE=1
 
OK
65
84
43
67
77
69
69
61
49
13
13
10
79
75
0
Команда: AT+CLIP=1
Ответ: AT+CLIP=1
 
OK
65
84
43
67
76
73
80
61
49
13
13
10
79
75
0
Команда: AT+CMGF=1
Ответ: AT+CMGF=1
 
OK
65
84
43
67
77
71
70
61
49
13
13
10
79
75
0
Команда: AT&W
Ответ: AT&W
 
OK
65
84
38
87
13
13
10
79
75
0
251
63
236
235
251
xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

может эхо для начала выключить? я не помню как там - АТЕ0 чтоль, не помню...

Allleksey
Offline
Зарегистрирован: 28.11.2020

Со всеми ответами разобрался. Усекаю исходный ответ до символа char(10) и остается только ответ "ОК". А вот с форматом и содержанием ответа на запрос "АТ" не понятно.

andriano пишет:

Распечатайте кроме текста ответа еще то же самое, только кодами символов (скажем, в HEX).
(Исходник не смотрел)

Спасибо за подсказку. После реализации Вашего предложения стало понятно, что нужно сделать.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Allleksey пишет:

Усекаю исходный ответ до символа char(10) 

зря, некоторые команды после ОК еще что то нужное/важное могут прислать, если уж вам необходимо искать именно последний ответ ОК то я например ищу строку "OK\r\n"

http://arduino.ru/forum/apparatnye-voprosy/vse-o-sim800l-i-vse-chto-s-ni...

if (s800lib::findResp((char *)"OK\r\n", br)) {