Привет всем неравнодушным! Сегодня предлагаю поговорить о миниатюрных GSM-модемах на базе чипа SIM800L. Области применения таких модулей весьма обширны: охрана дачи или дома, сигнализация в машине и многое другое, где требуется удаленная связь, а возможности подключиться к Wi-Fi нет. В том числе они прекрасно подходят для проектов IoT, потому что с их помощью можно не только отправлять сообщения или управлять телефонными звонками, но и подключаться к Интернету.
В данной статье рассмотрим:
-
подключение модулей к переходнику USB-TTL для проверки и отладки;
-
подключение модулей к платам Arduino для выхода в Интернет в условиях, когда нет доступа к Wi-Fi;
-
код, который позволяет подключиться к объекту на платформе Rightech IoT Cloud, публиковать данные и получать команды.

Обзор модулей на базе чипа SIM800L
Технические особенности чипа:
-
Напряжение питания: 3,4 В - 4,4 В (рекомендуемое 4 В)
-
Потребляемый ток режима ожидания: 0,7 мА
-
Пиковый ток: 2 А
-
Поверхностный монтаж
-
Голосовые вызовы
-
Встроенный FM-приемник (🎵ребята_прикиньте_тут_есть_радио)
-
Режим сети: 2G
Подавляющее большинство начинающих радиолюбителей не готовы работать с такими чипами напрямую, поэтому производители радиоэлектронных компонентов предлагают большое количество плат с уже размещенным на них чипом SIM800L. Каждый такой модуль — это переходник между чипом и пользователем. Платы в обязательном порядке предоставляют пользователю минимальный функционал в виде обмена данными по UART и имеют слот для SIM-карты формата microSIM.
Для знакомства и изучения взяли два модуля с Aliexpress. Китайцы не стали заморачиваться с придумыванием для них какого-то специального названия (“red plate”, “blue plate”), так что и мы будем различать их по цветам: красный и синий.

Модуль “красный”

Технические особенности:
-
К этой плате можно подключить гарнитуру или микрофон
-
Контакты чипа SIM800L выведены по бокам модуля
-
Для подключения к сотовой сети нужна внешняя антенна, которая идет в комплекте с модулем. Также на плате имеется разъем U.FL, если необходимо подключить выносную антенну, в моем случае она тоже шла в комплекте, одна на два модуля. Мне для работы антенны-пружинки вполне хватило. Если вы размещаете модуль в корпусе, который может снижать уровень сигнала, используйте выносную антенну
-
Максимальный уровень логической единицы на входе RX — 3,1 В (при минимальном 2,1 В), поэтому необходимо понижать напряжение 5 В стандартной логики Arduino, например, с помощью делителя напряжения
-
На задней панели расположено гнездо для SIM-карты (подойдет любая активированная SIM карта). Устанавливать ее необходимо при отключенном питании модуля контактами к чипу SIM800L, а срез ДОЛЖЕН ТОРЧАТЬ СНАРУЖИ. Я первый раз установила срезом внутрь, и, конечно, получила в терминале ошибку о том, что SIM-карта не вставлена.
Чтобы проверить обнаружение SIM-карты, отправьте командуМоя симка вставлена правильно?
AT+CSMINS?
. Второй параметр в ответе должен быть 1. Если 0, значит карта не вставлена. Подробнее об AT-командах будет рассказано ниже.
В верхнем правом углу модуля находится красный светодиод, который показывает состояние сотовой сети:
-
мигает раз в 1 сек — модуль работает, но еще не подключился к сотовой сети;
-
мигает раз в 2 сек — запрошенное соединение для передачи данных GPRS активно;
-
мигает раз в 3 сек — модуль установил связь с сотовой сетью и может отправлять/получать голосовые и SMS-сообщения.
Модуль “синий”

Технические особенности:
-
Не выведено подключение гарнитуры;
-
Стоит два включенных последовательно диода, которые снижают напряжение питания примерно на 1 В. Такое схемотехническое решение позволяет питать от блока на 5 В, не волнуясь о том, что модуль уйдет в защиту и отключится;
-
Присутствует конвертер уровней на двух транзисторах 2N7002, поэтому можно спокойно подключать хоть к пяти-, хоть к трехвольвотовой логике (не нужен делитель напряжения как для красного модуля).
На модуле есть два красных светодиода. Один отвечает за питание и горит постоянно, когда питание подано. Другой показывает состояние сотовой сети аналогично красному модулю - при включении мигает быстро, потом начинает мигать реже.
Подключение модуля к USB-TTL конвертору
Взаимодействие с модулем осуществляется по последовательному порту посредством AT-команд.
AT-команда - это текстовая строка, начинающаяся с букв «AT» (от английского attention - «внимание»). Модуль выполняет полученную команду и отправляет обратно ответ (результат выполнения команды), который также является строкой.AT-команда?
Для начала, чтобы просто проверить работоспособность модуля, вставляем в него рабочую SIM-карту и подключаем через USB-Serial адаптер (например, такой) к компьютеру.
Модуль “красный”
Собираем схему
Из всех 12 контактов понадобятся только 4: VCC, RXD, TXD, GND.
Все контакты на модуле подписаны, только не рядом, а со сдвигом по причине его маленького размера. Подача питания (VCC, GND) В документации сказано, что для стабильной работы модуля SIM800L необходим источник питания с выходным напряжением от 3,4 до 4,4 В и максимальным рабочим током 2 А. Не знаю, как это должно работать, но у меня почему-то при напряжении меньше 5 В модуль совсем никак не хотел регистрироваться в сети. Начиталась советов по сдвиганию SIM-карты в слоте, окислившимся контактам, антеннам… но потом решила подать напряжение от стандартного блока питания 5 В/2 А, и все заработало. Итак, в моем случае контакты VCC и GND соединяем с плюсом и минусом блока питания на 5 В. Примечание 1: У меня заработало не с любым блоком на 5 В. Один блок давал напряжение 5,25 В, и с ним не работало, появлялась ошибка Если нет мультиметра, то после того как подключите модуль, отправьте команду Примечание 2: Запитать можно также от повербанка. Но имейте в виду, что модуль в режиме ожидания потребляет так мало тока, что повербанк через какое-то время самопроизвольно выключится, не принимая всерьез такое незначительное потребление. Поэтому подключите к повербанку что-нибудь еще - например, ту же Arduino после того, как зальете на нее скетч. В режиме же активной работы при передаче данных по протоколу MQTT потребление тока значительно увеличивается, поэтому повербанк выключаться уже не будет. Примечание 3: ЗАПИТЫВАТЬ МОДУЛЬ ОТ ARDUINO НЕЛЬЗЯ. Напомню, что модуль может потреблять до 2 А, а Arduino не в состоянии такой ток выдавать, поэтому произойдет сбой в работе либо модуля, либо Arduino, либо того и другого (вполне вероятен выход Arduino из строя). Аналогичная история и с запитыванием от USB порта компьютера. Подключение к конвертору Собираем схему. SIM800L USB-Serial TX RX RX через делитель напряжения (5 В->3,3 В) TX GND GND Остальные пины не подключены VCCIO, RTS, CTS - не подключены Проверяла без делителя напряжения - работало долго и стабильно. Однако это дело случая, может и сгореть, поэтому так делать не надо. Проще всего сделать равноплечий делитель напряжения на паре резисторов одинакового номинала в диапазоне 1-10 КОм. В таком случае мы получим 2,5 В, что укладывается в необходимый диапазон 2,1 - 3,1 В. Примечание - В некоторых статьях видела, что VDD модуля тоже подключают, но по факту такой вариант не работает, модуль просто не реагирует на AT команды. А вот пин GND подключать нужно обязательно. Теперь проверяем корректность ответов на AT-команды. Для этого нам нужен терминал COM порта. В качестве него используем монитор порта, который есть в IDE Arduino. Никаких скетчей в данном случае писать и загружать никуда не надо, просто открываем монитор порта. Модуль может автоматически подстраиваться под одну из следующих скоростей обмена: 2400, 4800, 9600, 14400, 19200, 28800, 33600, 38400, 57600, 115200, 230400, 460800, 921600. Каждая AT-команда (как и ответ) должна заканчиваться символами перевода строки «\r\n», поэтому в мониторе порта выставляем параметр После этого можно отправлять другие AT-команды, чтобы оценить состояние модуля. Команды можно писать следующим образом: Примеры: 0 – готов к работе 2 – неизвестно (исполнение команд не гарантируется) 3 – входящий звонок 4 – голосовое соединение Первый параметр ответа: 0 – нет кода регистрации сети - плохой знак, позвонить или выйти в интернет не получится 1 – есть код регистрации сети 2 – есть код регистрации сети + доп. параметры Второй параметр ответа: 0 – не зарегистрирован, поиска сети нет 1 – зарегистрирован, домашняя сеть 2 – не зарегистрирован, идет поиск новой сети 3 – регистрация отклонена 4 – неизвестно 5 – роуминг Первый параметр ответа - мощность сигнала rssi (от 10 и выше — нормальная): 0 -115 дБм или меньше 1 -111 дБм 2-30 -110..-54 дБм 31 -52 дБм или больше 99 -неизвестно или нет сигнала. Второй параметр ответа - частота ошибок по битам ber: 0...7 – коэффициент битовых ошибок (меньше — лучше) 99 – неизвестно или нет сигнала Первый параметр ответа: 0 – не заряжается 1 – заряжается 2 – зарядка окончена Второй параметр ответа - уровень заряда батареи (1-100 %) Третий параметр ответа - напряжение питания модуля, мВ Список всех доступных AT-команд >>> В качестве вишенки на торте позвоним на модуль, но перед этим включим определитель номера при помощи команды Контакты модуля разделены на два смысловых блока: POWER Контакты 5VIN и GND соединяем с плюсом и минусом блока питания на 5 В. UART-TTL Собираем схему. SIM800L USB-Serial TX RX RX (делитель уже не нужен) TX GND GND VDD, RST - не подключены VCCIO, RTS, CTS - не подключены После подключения я, воодушевившись успехом красного модуля и решив, что все проблемы, которые только могли быть, я уже поймала, начала тестировать на AT-команды. И что вы думаете? Опять не регистрируется в сети! Блок питания подобран, SIM-карта вставлена правильно, что еще ему нужно? Ковырялась-ковырялась, шаманила, танцевала с бубном, а потом решила отправить команду на проверку наличия SIM-карты, о которой писала выше. Карта не вставлена. Тут я начала вспоминать все советы по сдвиганию карты в слоте на миллиметр и так далее. Однако при внимательном рассмотрении модуля можно обнаружить некоторую неприятность. Посмотрите на фото и найдите ее. =) Да, вы абсолютно правы! Шаловливый производитель устроил нам небольшой квест, забыв допаять один резистор. Припаиваем как надо, и модуль начинает прекрасно работать. Обратите внимание на ответ команды Абсолютно у всех плат Arduino есть как минимум один последовательный порт для связи между платой Arduino и компьютером или другими устройствами (UART/USART). Однако, как вы понимаете, нам нужно таких порта два: один для общения компьютера и Arduino и один для общения Arduino и модуля. Давайте рассмотрим два типа плат Arduino: с одним портом и с несколькими. В первом случае для общения Arduino c модулем пользуемся программным UART (в этом нам поможет библиотека SoftwareSerial), во втором - аппаратным UART. “Библиотека SoftwareSerial позволяет реализовать последовательный интерфейс на любых других цифровых выводах Arduino с помощью программных средств, дублирующих возможности UART (отсюда и название "SoftwareSerial"). Библиотека позволяет программно создавать несколько последовательных портов, работающих на скорости до 115200 бод.” Подключение питания не меняется. Подключение к Arduino UNO для красного модуля. SIM800L Arduino UNO TX 2 RX через делитель напряжения (5 В->3,3 В) 3 GND GND Остальные пины не подключены Остальные пины не подключены Подключение к Arduino UNO для синего модуля. SIM800L Arduino UNO TX 2 RX (делитель уже не нужен) 3 GND GND VDD, RST - не подключены Остальные пины не подключены Копируем приведенный ниже скетч и загружаем его в Arduino. Этот код позволяет пересылать данные между двумя последовательными связями: Arduino и Arduino IDE ( Arduino и SIM800L ( Мы увидели ответ Прежде чем перейти к сложному коду, давайте удостоверимся, что модуль к этому готов. Настройка GPRS-контекста и открытие соединения Ниже представлена последовательность команд и результат выполнения. Команда Результат 1 AT+CIPSTATUS - запрос текущего состояния подключения STATE: IP INITIAL - GPRS-контекст не настроен. Во время активации контекста информация направляется в сеть GPRS и может служить условием доступа к услугам пакетной передачи данных. Сегодня многие операторы сотовой связи дают доступ в GPRS независимо от того, какой контекст был задан. 2 AT+CSTT=<APN>,<USR>,<PASS> - настройка контекста, где <APN> - точка доступа, <USR> - логин, <PASS> - пароль Для моей симки Мегафон сработало так AT+CSTT="internet", хотя потом я заметила, что вполне хорошо работает и с другими APN. Данные по любым операторам легко гуглятся. OK 3 AT+CIPSTATUS - проверяем еще раз текущее состояние подключения STATE: IP START - Успешная настройка контекста 4 AT+CIICR - активация контекста. С этого момента модуль получает доступ в сеть GPRS и на стороне оператора сотовой связи начинается отсчет трафика. OK 5 AT+CIPSTATUS STATE: IP GPRSACT 6 AT+CIFSR - запрос IP-адреса Какой-то присвоенный IP 7 AT+CIPSTATUS STATE: IP STATUS 8 AT+CIPSTART="TCP","dev.rightech.io","1883" - подключение к платформе по MQTT OK CONNECT OK - если на данном этапе мы получаем такой результат, значит модуль исправен и поддается настройке. Через 30 секунд мы получим сообщение CLOSED, так как так и не дали брокеру MQTT понять, к какому же объекту надо подключиться. Подключение к объекту на платформе по протоколу MQTT Для того чтобы взаимодействовать с объектом на платформе, мы можем пойти двумя путями: Прописывать в коде все необходимые для этого AT-команды Воспользоваться готовой библиотекой, которая все эти страсти-мордасти от нас спрячет и нам останется только сформировать необходимую логику Первый путь самурая сложен и похож на написание кода на ассемблере - абсолютно прозрачно и гибко, но долго и сложно. Такую реализацию я встретила тут . Второй путь проще и позволяет без больших заморочек быстро настроить подключение. Самая удачная библиотека, которая решает нашу задачу, - TinyGSM. Она есть в Arduino IDE. Устанавливаем ее, и сразу можно пользоваться. В разделе Примеры есть скетч, который используем как базу. После незначительного упрощения кода получаем скетч, являющийся смысловым аналогом этого за исключением способа выхода в Интернет (там Wi-Fi). В строке указываем адрес нужного MQTT-брокера. В данном случае это адрес платформы Rightech IoT Cloud. В строке задаем идентификатор объекта, заранее созданного на платформе с моделью MQTT. Мой лог выглядит следующим образом. Неспешно, но успешно модуль подключился и начал отправлять данные… …и получать команды. Примечание - Заметила, что периодически происходит разрыв соединения и тут же переподключение. Как только подключила к Arduino Mega, это прошло. Думаю, что проблема в использовании SoftwareSerial. В Интернете пишут, что она подходит для проверки работы модема и отладки, но в устройствах стабильной работы добиться практически невозможно. Наиболее вероятная причина в том, что SoftwareSerial не может нормально переварить поток с модема. Подключение питания не меняется. Подключение к Arduino Mega для красного модуля. SIM800L Arduino MEGA TX 19 RX через делитель напряжения (5 В->3,3 В) 18 GND GND Остальные пины не подключены Остальные пины не подключены Подключение к Arduino Mega для синего модуля. SIM800L Arduino MEGA TX 19 RX (делитель уже не нужен) 18 GND GND VDD, RST - не подключены Остальные пины не подключены Код для взаимодействия по MQTT остается тем же, однако обратите внимание на следующие строки. Благодаря директивам препроцессора автоматически происходит выбор в зависимости от платы, какой вариант UART используем: аппаратный или программный. Для Arduino MEGA это UART Serial1, поэтому модуль мы подключили к соответствующим Serial1 пинам платы (19, 18). Для того чтобы четко определить, что состоялось подключение с новой платы, создадим другой объект на платформе с идентификатором mega_sim800 и изменим соответствующую строку в коде. Мой лог выглядит следующим образом. Выскочило несколько непонятных символов на моменте …и получать команды. Если вам нужно организовать выход в Интернет там, где нет Wi-Fi, то модуль на чипе SIM800L вполне решает эту задачу. Модули капризные по части питания. Возьмите себе за правило - если модуль работает нестабильно, надо попробовать немного поднять напряжения питания. Перед тем как заливать сложный код, проверьте, что модуль вообще зарегистрировался в сети и готов к вашим изысканиям. Если хотите подключать гарнитуру, берите красный модуль. Если хотите более простое подключение к Arduino при отсутствии гарнитуры, берите синий. Не выбирайте программный UART, если есть такая возможность.Где эти контакты?
OVER-VOLTAGE POWER DOWN
(пороговый уровень напряжения сильно превышен), и модуль отключался (уходил в защиту). С блоком на 5,06-5,16 В все заработало отлично.Как понять, какое у меня сейчас напряжение питания на модуле?
AT+CBC
. Последний параметр в ответе - текущее напряжение питания модуля в милливольтах. У меня этот модуль заработал при числе около 5097.Это может выглядеть так
Тестируем
Newline
и отправляем самую простую команду AT
. На нее должен прийти ответ OK
.
AT+КОМАНДА=?
- узнать, какие параметры поддерживает командаAT+КОМАНДА?
- запросить текущие значенияAT+КОМАНДА=ПАРАМЕТР(Ы)
- установить одно или несколько значенийAT+КОМАНДА
- установить/запросить данные, определяемые внутренними процессами модуля
AT+GCAP
- возможности модуляAT+GMM
- идентификатор модуляAT+GMR
- ревизияAT+GSN
- IMEI модуляAT+COPS?
- информация об оператореAT+COPS=?
- доступные операторыAT+CPAS
- состояние модуля:
AT+CREG?
- Тип регистрации сети
AT+CSQ
- Качество сигнала
AT+CCLK?
- текущая дата и время AT+CBC
- монитор напряжения питания модуля
AT+CADC?
- значение АЦП (до 2,8 В)AT+CLIP=1
. В терминале во время звонка появился текст RING
и наш номер телефона, значит все хорошо и модуль работает как надо, переходим к следующему этапу.Модуль “синий”
Собираем схему
Тестируем
Проверить себя
AT+CBC
. При подключении блока питания на 5 В к красному модулю мы видим число чуть больше 5000 мВ. При этом с тем же блоком синий модуль выдает 4000 мВ. Это происходит как раз за счет тех диодов, о которых упоминалось выше.Подключение модуля к Arduino
SoftwareSerial?
Arduino UNO
Аппаратная часть
Serial
)mySerial
)#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); // RX, TX
void setup() {
Serial.begin(9600); // Скорость обмена данными с компьютером
Serial.println("Start!");
mySerial.begin(9600); // Скорость обмена данными с GSM модулем
mySerial.println("AT");
}
void loop() {
if (mySerial.available())
Serial.write(mySerial.read());
if (Serial.available())
mySerial.write(Serial.read());
}OK
, значит, все хорошо и можно работать дальше.Программная часть
const char* broker = "dev.rightech.io";
boolean status = mqtt.connect("uno_sim800");
// Select your modem:
#define TINY_GSM_MODEM_SIM800
// Set serial for debug console (to the Serial Monitor, default speed 115200)
#define SerialMon Serial
// Set serial for AT commands (to the module)
// Use Hardware Serial on Mega, Leonardo, Micro
#ifndef __AVR_ATmega328P__
#define SerialAT Serial1
// or Software Serial on Uno, Nano
#else
#include <SoftwareSerial.h>
SoftwareSerial SerialAT(2, 3); // RX, TX
#endif
// See all AT commands, if wanted
// #define DUMP_AT_COMMANDS
// Define the serial console for debug prints, if needed
#define TINY_GSM_DEBUG SerialMon
// Add a reception delay, if needed.
// This may be needed for a fast processor at a slow baud rate.
#define TINY_GSM_YIELD() { delay(2); }
// Your GPRS credentials, if any
const char apn[] = "internet";
const char gprsUser[] = "";
const char gprsPass[] = "";
// MQTT details
const char* broker = "dev.rightech.io";
#include <TinyGsmClient.h>
#include <PubSubClient.h>
#define PUB_DELAY (5 * 1000) /* 5 seconds */
#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
TinyGsm modem(debugger);
#else
TinyGsm modem(SerialAT);
#endif
TinyGsmClient client(modem);
PubSubClient mqtt(client);
uint32_t lastReconnectAttempt = 0;
void mqttCallback(char* topic, byte* payload, unsigned int len) {
SerialMon.println(topic);
SerialMon.write(payload, len);
SerialMon.println();
}
boolean mqttConnect() {
SerialMon.print("Connecting to ");
SerialMon.print(broker);
// Connect to MQTT Broker
boolean status = mqtt.connect("uno_sim800");
if (status == false) {
SerialMon.println(" fail");
return false;
}
SerialMon.println(" success");
mqtt.subscribe("base/relay/led1");
return mqtt.connected();
}
void setup() {
// Set console baud rate
SerialMon.begin(115200);
delay(10);
SerialMon.println("Wait...");
// Set GSM module baud rate
SerialAT.begin(9600);
delay(6000);
// Restart takes quite some time
// To skip it, call init() instead of restart()
SerialMon.println("Initializing modem...");
modem.restart();
// modem.init();
String modemInfo = modem.getModemInfo();
SerialMon.print("Modem Info: ");
SerialMon.println(modemInfo);
SerialMon.print("Waiting for network...");
if (!modem.waitForNetwork()) {
SerialMon.println(" fail");
delay(10000);
return;
}
SerialMon.println(" success");
if (modem.isNetworkConnected()) {
SerialMon.println("Network connected");
}
// GPRS connection parameters are usually set after network registration
SerialMon.print(F("Connecting to "));
SerialMon.print(apn);
if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
SerialMon.println(" fail");
delay(10000);
return;
}
SerialMon.println(" success");
if (modem.isGprsConnected()) {
SerialMon.println("GPRS connected");
}
// MQTT Broker setup
mqtt.setServer(broker, 1883);
mqtt.setCallback([] (char* topic, byte * payload, unsigned int len) {
SerialMon.write(payload, len);
SerialMon.println();
});
}
long last = 0;
void publishTemperature() {
long now = millis();
if (now - last > PUB_DELAY) {
mqtt.publish("base/state/temperature", String(random(20, 30)).c_str());
mqtt.publish("base/state/humidity", String(random(40, 90)).c_str());
last = now;
}
}
void loop() {
// Make sure we're still registered on the network
if (!modem.isNetworkConnected()) {
SerialMon.println("Network disconnected");
if (!modem.waitForNetwork(180000L, true)) {
SerialMon.println(" fail");
delay(10000);
return;
}
if (modem.isNetworkConnected()) {
SerialMon.println("Network re-connected");
}
// and make sure GPRS/EPS is still connected
if (!modem.isGprsConnected()) {
SerialMon.println("GPRS disconnected!");
SerialMon.print(F("Connecting to "));
SerialMon.print(apn);
if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
SerialMon.println(" fail");
delay(10000);
return;
}
if (modem.isGprsConnected()) {
SerialMon.println("GPRS reconnected");
}
}
}
if (!mqtt.connected()) {
SerialMon.println("=== MQTT NOT CONNECTED ===");
// Reconnect every 10 seconds
uint32_t t = millis();
if (t - lastReconnectAttempt > 10000L) {
lastReconnectAttempt = t;
if (mqttConnect()) {
lastReconnectAttempt = 0;
}
}
delay(100);
return;
}
mqtt.loop();
publishTemperature();
}Arduino Mega
Аппаратная часть
Программная часть
// Set serial for AT commands (to the module)
// Use Hardware Serial on Mega, Leonardo, Micro
#ifndef __AVR_ATmega328P__
#define SerialAT Serial1
// or Software Serial on Uno, Nano
#else
#include <SoftwareSerial.h>
SoftwareSerial SerialAT(2, 3); // RX, TX
#endifboolean status = mqtt.connect("mega_sim800");
Waiting for network
, которые, впрочем, никак не помешали подключиться и начать отправлять данные …Выводы