Віримо в перемогу ЗСУ!
Магазин у відпустці до 01.06.2022

Привет друзья! В прошлом видео мы разобрали ручное управление GSM-модулем набирая команды в мониторе порта. А на этот раз разберем тему: SIM800 Arduino автоматические команды.

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

В этом видео я хочу разобрать два практических подхода к автоматическому управлению модемом SIM800 при помощи контроллера Arduino Nano. В своих проектах я использую их оба. И в дальнейших блогах я буду основываться именно на них, рассказывая о применении GSM-модуля.




Самая простая технология автоматической отправки команд от Arduino в SIM800 – это просто в коде программы вставлять стандартные функции для работы с UART-портом. Я модифицирую код из предыдущего видео и получаю следующий простой скетч.

#include <SoftwareSerial.h>

SoftwareSerial SIM800serial (2, 3);

void setup() {
  Serial.begin(9600);
  SIM800serial.begin(9600);
}

void loop() {
  
  SIM800serial.println("AT");
  
  delay(1000);
  
  while (SIM800serial.available()) {
    Serial.print(SIM800serial.readString());
  }
  
}

Все новое здесь собрано в цикле loop(). Функция println – собственно и есть та самая простая технология отправки автоматической АТ-команды. Дальше идут дополнительные не обязательные операнды, которые я здесь вписал только для наглядной демонстрации работы первой рабочей строчки кода. Функция println здесь получает AT-команду в строковом текстовом виде и передает ёё через программный UART-порт контроллера на такой же порт модема SIM800.

Функция задержки времени разделяет каждую отправку этой команды на одну секунду.

Следующий цикл while считывает ответ модема и печатает его в монитор порта тоже в строковом виде.

Загружаем программу в Arduino и запускаем монитор порта. 

Видим получение ответа на команду АТ каждую секунду. Можете попробовать повписывать и другие команды, а так же несколько команд подряд. Такой метод автоматической отправки команд полезен, когда имеем дело с командами, ответ модема на которые нам не очень интересен. Например, после включения питания можно таким способом отправить несколько команд АТ, чтобы SIM800 автоматически определила скорость обмена по последовательному порту. Так же в некоторых случаях, как например отправка текста SMS-сообщения, простые функции println и write, относящиеся к работе с портом UART, придут нам на помощь в следующих видео-блогах. Поэтому оставляем первый пример на заметку и переходим к его усложнению для более ювелирной работы с GSM-модулями.

Разберем три канонические функции, которые опубликованы во множестве статей, описывающих проекты на модемах типа SIM800L. Мы их один раз изучим, прикрепим к скетчу, и постоянно будем использовать в дальнейших блогах и проектах.

#define OK 1
#define NOTOK 2
#define TIMEOUT 3

byte SIM800command(String command, String response1, String response2, uint16_t timeOut, uint16_t repetitions) {
  byte returnValue = NOTOK;
  byte countt = 0;
  
  while (countt < repetitions && returnValue != OK) {
    SIM800serial.println(command);
    
    if (SIM800waitFor(response1, response2, timeOut) == OK) {
      returnValue = OK;
    } else {returnValue = NOTOK;}
    countt++;
  }
  return returnValue;
}

byte SIM800waitFor(String response1, String response2, uint16_t timeOut) {
  uint16_t entry = 0;
  uint16_t count = 0;
  String reply = SIM800read();
  byte retVal = 99;

  do {
    reply = SIM800read();
    delay(1);
    entry ++;
  } while ((reply.indexOf(response1) + reply.indexOf(response2) == -2) && entry < timeOut );

  if (entry >= timeOut) {
    retVal = TIMEOUT;
  } else {
    if (reply.indexOf(response1) + reply.indexOf(response2) > -2) retVal = OK;
    else retVal = NOTOK;
  }
  return retVal;
}

String SIM800read() {
  String reply = "";

  if (SIM800serial.available())  {
    reply = SIM800serial.readString();
  }

  if (reply!=""){
    Serial.print("Reply: ");
    Serial.println(reply);
  }
  return reply;
}

Основная функция здесь это SIM800command. Обращаться из программы мы будем напрямую только к ней, а она уже будет вызывать остальные две по мере выполнения своих операндов. 

Первый аргумент в ней получает строковую команду, которую нужно отправить в GSM-модем. 

Второй аргумент – это ожидаемый строковый ответ или часть ответа при положительной реакции SIM800. Например, строка OK. Сюда будем вписывать часть строки ответа, который ожидаем увидеть при правильной сработке запроса.

Третий аргумент функции – это ожидаемая строка при отрицательном ответе SIM800. Например строка ERROR.

Четвертая переменная для задания времени ожидания заданной положительной строки или отрицательной. Время в миллисекундах. По-простому это называется таймаут. И, если вы неправильно зададите ожидаемые строки ответа, то функция при каждом её вызове будет крутиться до таймаута. Даже, когда SIM800 уже давно ответила на запрос.

Последний пятый аргумент содержит количество попыток отправить запрос с положительным или отрицательным ответом. И на каждую попытку отводится заданное время таймаута.

Переменная returnValue содержит возвращаемое функцией значение типа byte. Вначале текста скетча мы видим объявление констант. Здесь задаются имена для трех типов ответа функций: OK, NOTOK и TIMEOUT. Здесь OK будет, если первая функция получила искомый положительный или отрицательный ответ. NOTOK для этой функции означает выход по таймауту после всех заданных попыток. Константа TIMEOUT используется только во второй функции.

В цикле while содержится отправка текста команды в порт SIM800, а так же запуск функции waitFor. Этот цикл остановится после заданного количества попыток или после поступления одного из двух ожидаемых ответов GSM-модуля. Функция вернет единицу или OK, если ответ получен, и двойку NOTOK, если прошло время таймаута для всех заданных попыток.

Вторая функция waitFor принимает три аргумента: две ожидаемые строки ответа и время таймаута. В цикле do…while идет обращение к третьей функции SIM800read каждую миллисекунду пока не закончится отведённое время timeout или не поступит одна из искомых строк в ответе.

Дальше идет формирование возвращаемого функцией ответа. Этим ответом может быть 1, 2 или 3, или в именованных константах OK, NOTOK или TIMEOUT.

А третья функция SIM800read без аргументов и возвращает строку ответа во вторую функцию, чтобы она в нём поискала ожидаемые ответы. В третьей функции идет проверка поступления данных на вход порта и чтение их в переменную reply. Дальше, если эта переменная действительно получила текст, то активируется распечатка его в монитор порта для диагностики. Чтобы мы имели представление, о чем переговаривается контроллер и SIM800.

Теперь набросаем самую простую программу для проверки работы наших функций. В секции setup() добавлено ожидание 10сек после включения контроллера на самодиагностику GSM-модуля и готовность к приему запросов. А в цикле loop() каждую секунду запускается функция SIM800command. Ожидаемые ответы OK и ERROR. Таймаут 500мс и число попыток – одна.

#include <SoftwareSerial.h>

SoftwareSerial SIM800serial (2, 3);

#define OK 1
#define NOTOK 2
#define TIMEOUT 3

void setup() {
  Serial.begin(9600);
  SIM800serial.begin(9600);
  delay(10000);
}

void loop() {
  SIM800command("AT", "OK", "ERROR", 500, 1);
  delay(1000);
}

Загружаю скетч в контроллер и запускаю монитор порта. 

Сначала контроллер ждет 10сек, потом циклически начинает отправлять автоматические запросы и печатает ответы на них нам для диагностики.

Теперь взглянем на вырезку из инструкции по АТ-командам для SIM800L и ознакомимся с типами AT-запросов, с которыми она заточена работать. Здесь 4 типа. Они отличаются синтаксисом. Первый – это тестовая команда. Она возвращает список параметров, которые мы можем изменять, обращаясь к этой команде третьим типом. В автоматическом режиме этот тип нам не интересен. Второй тип команд возвращает текущее значение параметра, хранящееся в памяти SIM800. Третий тип позволяет изменять пользовательские настройки в SIM800. Четвертый тип – это исполняемая команда без переменных аргументов. 

Для дальнейших экспериментов я выбрал возможно малополезную, но довольно интересную АТ-команду AT+CCLK. Вот её расшифровка из документации. Она нужна для работы с внутренними часами реального времени модуля SIM800. У самой микросхемы SIM800 должен быть вывод на часовую батарейку, но на данном модуле к нему нет доступа и часы могут отсчитывать время только пока есть питание на выводе VCC. Здесь показано в каком виде задается и выводится время. Сначала идет дата, потом время и в конце часовой пояс со знаком плюс или минус.

#include <SoftwareSerial.h>

SoftwareSerial SIM800serial (2, 3);

#define OK 1
#define NOTOK 2
#define TIMEOUT 3

void setup() {
  Serial.begin(9600);
  SIM800serial.begin(9600);
  delay(10000);
  SIM800command("AT", "OK", "ERROR", 500, 5);
}

void loop() {
  SIM800command("AT+CCLK?", "OK", "ERROR", 500, 1); //date & time of SIM800
  delay(1000);
}

Вот пример программы для считывания текущих даты-времени в модуле SIM800. Здесь после включения Arduino ждет 10сек, потом пытается 5 раз отправить AT до получения ответа от модема, и дальше в основном цикле программы каждую секунду отправляем запрос на чтение часов SIM800. AT-команда CCLK. Положительный ответ OK. Отрицательный ответ ERROR. Таймаут 500мс и количество попыток 1. 

Загружаю прогу в Arduino Nano, и запускаю монитор порта. 

Контроллер сначала ждет 10сек, потом отправляет проверочную команду AT, затем получает ответ от часов. Они показывают на 2004 год, первое число первого месяца, какое-то время и часовой пояс +2. Они всегда так будут показывать после подачи питания.

А теперь попробуем назначить внутренним часам GSM-модуля свои дату и время. 

Скетч будет следующим: вначале ожидание 10сек, проверочная команда АТ, ожидание 1сек, считываем исходные дату-время. Потом ожидание 1сек и запись своих даты-времени. 2021 год, 12-й месяц, 12-е число, время и киевский часовой пояс. И, наконец в цикле loop() каждую секунду просто считываем ход времени. 

#include <SoftwareSerial.h>

SoftwareSerial SIM800serial (2, 3);

#define OK 1
#define NOTOK 2
#define TIMEOUT 3

void setup() {
  Serial.begin(9600);
  SIM800serial.begin(9600);
  delay(10000);
  SIM800command("AT", "OK", "ERROR", 500, 5);
  delay(1000);
  SIM800command("AT+CCLK?", "OK", "ERROR", 500, 1); //date time of SIM800
  delay(1000);
  SIM800command("AT+CCLK=\"21/12/12,16:25:33+02\"", "OK", "ERROR", 500, 1); //yy/mm/dd,hh:mm:ss+zz
}

void loop() {
  SIM800command("AT+CCLK?", "OK", "ERROR", 500, 1); //date time of SIM800
  delay(1000);
}

Загружаю в Arduino,  запускаю монитор порта. 

Видим ожидание 10сек, команду АТ. Потом чтение исходного времени, потом удачная попытка записать свои дату-время. И дальше в цикле видим отсчет правильного времени.

Так как здесь мы видим второй, третий и четвертый типы AT-запросов, можно сказать, что мы научились обрабатывать в автоматическом режиме все три полезные для этого режима типы команд. И теперь нас ничто не сможет остановить в написании скетчей под свои проекты. Так же мы изучили набор из трех распространенных функций для автоматической реализации команд при работе с SIM800. Возможно, они кому-то покажутся несовершенными. Пишите свои предложения по улучшению. Но могу сказать, что они вполне рабочие, и я их постоянно использую в своих проектах.

В следующих видео будем развивать свои умения –  изучать AT-команды. Тема будет зависеть от ваших комментов, а скорость выхода от количества лайков. На этом я прощаюсь - до новых встреч!

<< Проекты << Все товары >> Статьи, уроки >>

Написать отзыв

Примечание: HTML разметка не поддерживается! Используйте обычный текст.
    Плохо           Хорошо
Ремень зубчатый 6 мм 400 мм

Ремень зубчатый 6 мм 400 мм

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

41.56грн.

3-осевой акселерометр ADXL346Z

3-осевой акселерометр ADXL346Z

Акселерометр - это датчик ускорения. Данный датчик показывает статическое (гравитацию - наклон к зем..

119.59грн.

Концевой выключатель или концевик

Концевой выключатель или концевик

Имеет одну группу переключающихся контактов. На кончике рычага установлен подвижный ролик.Максимальн..

16.84грн.

Концевик с колесом для 3D принтера или CNC ramps 1.4

Концевик с колесом для 3D принтера или CNC ramps 1.4

Концевой выключатель для установки на 3D-принтер или CNC-станок системы ramps 1.4В комплекте ка..

37.33грн.

Ниодимовый магнит 12mm x 3mm N35

Ниодимовый магнит 12mm x 3mm N35

Цилиндрический ниодимовый магнит N35Размеры 12мм x 3ммИдеально подходит для работы в связке с магнит..

10.00грн.