Arduino Nano SIM800 SMS команды

Мы с каждым разом разбираем все более интересные применения GSM-модуля SIM800. В этот раз я покажу, как принимать SMS сообщения и обрабатывать команды, которые могут в них храниться.

На основании программы из предыдущего видео я набросал следующие строки из двух команд, отправляемых в SIM800 для чтения SMS. 

//https://geekmatic.in.ua | https://pinout.uno
#include <SoftwareSerial.h>
SoftwareSerial SIM800serial (2, 3);

#define OK 1
#define NOTOK 2
#define TIMEOUT 3
String txt;

void setup() {
  pinMode(5, OUTPUT);
  digitalWrite(5, HIGH); //SIM800 ON only for this module
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  Serial.begin(9600);
  SIM800serial.begin(9600);
  delay(5000);
  SIM800command("AT", "OK", "ERROR", 500, 5);
}

void loop() {
  SIM800command("AT+CMGF=1", "OK", "ERROR", 2000, 1); //SMS to text mode - not PDU mode
  SIM800command("AT+CMGL=\"ALL\"", "OK", "ERROR", 5000, 1);////sms list
  SIM800command("AT+CMGD=1,3", "OK", "ERROR", 10000, 1);//sms delete
  delay(2000);
}
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);
    txt = reply;
  }
  
  return reply;
}
 

Первая команда включает текстовый режим отображения SMS. 

Вторая команда выводит список всех входящих SMS из памяти SIM-карты. Существует так же отдельная команда у SIM800 для отображения одной SMS, но надо знать номер ячейки, где она сейчас хранится. Нам все-таки более интересен вывод всего списка.

Вот расшифровка этой команды. Тут можно задавать такие фильтрующие параметры, как полученные непрочтенные, полученные прочтенные, не отправленные, отправленные или вообще все. 

У меня в команде стоит параметр ALL – значит SIM800 выдаст список всех входящих и выходящих SMS, которые сохранены в памяти. Загружаю скетч в контроллер. Программа будет проверять наличие текстовых сообщений каждые 2 секунды и выводить их список.

Открываю монитор порта.

Отправляю текст Sms на номер SIM-карты, вставленной в SIM800.

В мониторе порта видим, что в памяти появилось одно сообщение с текстом, который я написал в телефоне. Кстати, обратите внимание, что в начале, в момент прихода SMS, GSM-модуль ругнулся кодом CMTI: SM, 1, что означает, что пришло текстовое сообщение и оно помещено в ячейку 1 памяти SIM-карты. Такой отчет SIM800 пишет в UART без запросов от контроллера.

Так же здесь видим, что нам желательно очищать память, где хранятся сообщения после их прочтения. Для чего, добавляем в скетч команду удаления CMGD.

Вот расшифровка этой команды. Первый параметр – номер ячейки памяти. Второй – это фильтр:

0  удалить одну ячейку;

1 удалить все прочитанные;

2 удалить все прочитанные и отправленные;

3 удалить все прочитанные входящие и все исходящие.

4 удалить абсолютно все.

Я выбрал третий вариант, удаляющий все входящие и исходящие SMS, оставляющий непрочитанные, чтобы случайно не удалить входящее сообщение, которое еще не обработано.

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

Видим ответ команды удаления сообщений CMGD OK.

Отправляю сообщение Sms2.

Сообщение пришло и прочитано. И повторно уже не читается. Потому, что память очищена.

Приём SMS – это чудесно, но давайте же перейдем в практическую плоскость и заставим Arduino Nano выполнять команды.

Для тестирования SMS-команд соберём следующую схему. Я к своему шилду добавлю два светодиода, которыми попробую управлять при помощи SMS.

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

Получилось красиво!

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

//https://geekmatic.in.ua | https://pinout.uno
#include <SoftwareSerial.h>
SoftwareSerial SIM800serial (2, 3);

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

String txt;

void setup() {
  pinMode(5, OUTPUT);
  digitalWrite(5, HIGH); //SIM800 ON only for this module
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  Serial.begin(9600);
  SIM800serial.begin(9600);
  delay(5000);
  SIM800command("AT", "OK", "ERROR", 500, 5);
  SIM800command("AT+CMGF=1", "OK", "ERROR", 2000, 1); //SMS to text mode - not PDU mode
}

void loop() {
  SIM800command("AT+CMGL=\"ALL\"", "OK", "ERROR", 5000, 1);////sms list
  parse_cmd( txt );
  SIM800command("AT+CMGD=1,3", "OK", "ERROR", 10000, 1);//sms delete
  delay(2000);
}

void parse_cmd( String str){
  String part1;
  Serial.println("read_cmd start"); 

  if (str.indexOf("sms")>-1) { //sms
    SIM800command("AT+CMGS=\"+380934158245\"", ">", "ERROR", 5000, 1);
    String str = "Hello from Arduino and SIM800!"; //SMS text
    SIM800serial.print(str);//the content of the message
    char j=0x1A;
    SIM800command((String)j, ">", "ERROR", 2000, 1);
    Serial.println("Sms");
    delay(4000);
  }
  
  if (str.indexOf("ring")>-1) { //ring
    Serial.println("Ring"); 
    SIM800command("ATD+380934158245;", "OK", "ERROR", 1000, 1);
    delay(10000);
    SIM800command("ATH", "OK", "ERROR", 500, 5);
  }
  
  //on
  if (str.indexOf("on")>-1) { digitalWrite(7, HIGH); Serial.println("On");} 

  //off
  if (str.indexOf("off")>-1) { digitalWrite(7, LOW); Serial.println("Off");} 
  
  if (str.indexOf("pwm")>-1) {//pwm
    part1 = str.substring(str.indexOf("pwm") + 4, str.length());
    int brightness = part1.toInt();
    Serial.print("Pwm = "); 
    Serial.println(brightness); 
    analogWrite(6, brightness);
  }
}
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);
    txt = reply;
  }
  
  return reply;
}
 

Дальше в loop идет команда чтения списка текстовых сообщений.

Потом новая функция для отсеивания команд из сообщений. В неё передаётся текст списка всех сообщений из памяти SIM-карты.

И команда удаления прочитанных SMS.

Вот наша хитрая функция. Если в тексте будет найдена строка sms, то устройство отправит ответное сообщение: "Hello from Arduino and SIM800!".

Если будет найдена строка ring, то Arduino позвонит по заданному номеру телефона.

Следующие две текстовые команды – on и off. Они должны включать и выключать первый светодиод.

Последняя отслеживаемая команда – это pwm. Она будет управлять яркостью второго светодиода.

Сначала в переменную brightness записывается выделенное из текста сообщения значение яркости.

Потом функцией analogWrite мы активируем ШИМ управление пином номер 6 с заданным заполнением, то есть яркостью.

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

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

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

Есть выключение.

Теперь задам яркость второму светодиоду – 100 (в диапазоне от 0 до 255).

Команда выполнилась. Теперь 10.

Светодиод почти потух. Отправлю значение яркости 254.

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

Теперь проверим команду sms.

Получил очень быстрый ответ. Так же ввожу команду ring. А вот пришла и неожиданная вторая SMS. Попробуем это исправить.

Команда ring хорошо сработала – устройство мне перезвонило.

Отправляю команду sms ещё раз. Может это была случайность?

Нет, это не случайность. Я вроде понял в чем дело. Увеличу delay на 2 секунды после отправки сообщения. Так как команда удаления не успевает обработаться в модуле SIM800. 

Проверяю команду sms еще раз.

Получаю ответ и удаление прошло удачно.

Отправляю еще раз.

И снова удачный ответ без повторов. Думаю на сегодня достаточно команд.

В ответных SMS можно вставлять значения различных датчиков, подключенных к Arduino Nano. Вместо светодиодов можно управлять различными исполнительными механизмами и другими приборами. Так же вы можете добавлять множество других текстовых команд редактируя функцию parse_cmd. 

 https://youtu.be/qvxCPU1mhoc

Додати коментар


Захисний код
Оновити

EcoMonitoring

ЛІЧІЛЬНИК ВІДВІДУВАННЬ

Сьогодні 354
Вчора386
Цього тижня 740
Минулого тижня 2264
Цей місяць 8301
Минулий місяць 9310
За весь час 172335
Ваш IP: 3.22.68.71
Сегодня: 2025-04-28
Пользователей на сайте: 0
Гостей на сайте: 24