Урок 22. Модуль SIM800L
-
Цель урока
Привет! Сегодня мы познакомимся с отличным модулем SIM800L и научимся принимать SMS-сообщения (рисунок 1).

Рисунок 1
Этот урок научит: обмениваться данными по UART с модулем; производить инициализацию и конфигурацию модуля; получать и читать текстовые SMS.
Краткая справка
- Назначение: применяют получения услуг сотовой связи
- Сфера применения: сельское хозяйство, умный дом и другие
- Интерфейс подключения: UART2 (MBUS)
- Напряжение питания: от 3.4 до 4.4 В
- Совместимость: M5STACK и M5FIRE (со снятым GO-модулем)
- Форм-фактор: STACK
Краткий обзор
SIM800L — один из большого семейства дополнительных модулей (MODULES), предназначенных прежде всего для М5STACK. Поставляется данный модуль в пластиковом футляре (рисунок 2).

Рисунок 2
На лицевой стороне модуля имеется вилка шины MBUS, слот для MicroSIM, канавка под антенну-пружинку (рисунок 3).
Примечание: контакты: G5 -> RST, G16 -> TXD, G17 -> RXD (Serial2).

Рисунок 3
Примечание: если модуль присоединён к М5, то вставить и извлечь SIM-карту нельзя.
На обратной стороне модуля имеется розетка шины MBUS, модуль SIM800L, антенна-пружинка на GSM-диапазон, разъём (3.5 мм mini-jack) для подключения наушников и встроенный микрофон (рисунок 4).

Рисунок 4
Начнём!
Blockly (UI Flow)
Для того, чтобы приступить к использованию нашего модуля необходимо его инициализировать (рисунок 5). Это займет некоторое время (приблизительно около 1 минуты). В это время нельзя беспокоить модем и выполнять какие-либо операции с ним, поэтому мы временно окрасим LED BAR красным цветом. С помощью функции InitSIM800L мы сообщим модему некоторые параметры работы, которые интересны нам в будущем. Обратите внимание на переменную isMessage, которая принимает значение 0. Для чего она нужна - рассмотрим далее.

Рисунок 5
Для того, чтобы модем начал реагировать на внешние команды после подачи питания ему потребуется приблизительно 10 секунд. Далее нам необходимо инициализировать UART-интерфейс на соответсвующих контактах устройства с помощью блока set UART.
Обратите внимание: TX 17, RX 16
Затем с помощью блока read UART available в цикле убедимся, что есть какой-то мусор в UART-буфере и считаем его посимвольно с помощью блока read UART. Отлично! Порт готов к работе. Теперь перезагрузим модуль, отправив команду AT+CFUN=1,1\r с помощью блока write. Дадим модему на нормальный запуск 45 секунд. Выключим ЭХО с помощью ATE0\r. Установим GSM-кодировку текстового режима AT+CSCS="GSM"\r. Включим текстовый режим AT+CMGF=1\r. Очистим память сообщений AT+CMGD=1,4\r. Попросим модуль читать входящие сообщения при получении AT+CNMI=1,2,2,1,0\r. Опять очистим буфер от возможного мусора. Всё, на этом модуль полностью готов к работе (рисунок 5.1).

Рисунок 5.1
Функция LiveSIM800L будет постоянно вызываться из цикла Loop (рисунок 5.2). В ней мы будем смотреть если ли входящие данные от модуля. Если есть, то считаем и приведем их к строковому виду. Теперь посмотрим есть ли флаг CMT:, если есть, то это входящее сообщение поставим флаг isMessage в состояние 1, это нам необходимо для того, чтобы прочесть текст сообщения. Помните функцию parseString, которую мы писали в прошлых уроках для Arduino IDE? Она отлично нам пригодится здесь. Я её перевел на MicroPython, а Вам её необходимо просто скопировать и вставить в Ваш проект ;)
def parseString(idSeparator, separator, str2): global parseStringGlobalVar1 parseStringGlobalVar1 = '' separatorCount = 0 for i in range(len(str2)): if str2[i] == separator: separatorCount += 1 else: if separatorCount == idSeparator: parseStringGlobalVar1 += str2[i] elif separatorCount > idSeparator: break return parseStringGlobalVar1Для тех, кто не помнит или не читал прошлые уроки - функция parseString принимает три аргумента и возращает участок строки, расположенный между разделителями: idSeparator (int), separator (char), str2 (String). Где idSeparator - порядковый номер разделителя; separator - разделитель; str2 - строка из которой извлекаем подстроку.
Например:
cmtStr = '+CMT: "+7XXXXXX0001","","01/01/01,09:30:00+12"\r\n'; print(parseStr(1, '"', cmtStr))Будет выведено:
+7XXXXXX0001А если сделать так:
print(parseStr(3, '"', cmtStr))То будет выведено:
01/01/01,09:30:00+12
Рисунок 5.2
К сожалению Blockly не позволяет сегодня нам нормально реализовать нашу функцию, но ничего страшного - есть обходной вариант сделать MicroPython-вставку (рисунок 5.3.1).

Рисунок 5.3

Рисунок 5.3.1
Когда будут приходить SMS будет вызываться функция-событие IncomingSms. А номер отправителя и текст сообщения будет находиться в глобальных переменных IncomingSmsPhone и IncomingSmsMessage, соответственно.

Рисунок 5.4
На этом урок закончен! :)
MicroPython (UI Flow)
from m5stack import * from m5ui import * import machine clear_bg(0xffffff) rgb = RGB_Bar() btnA = M5Button(name="ButtonA", text="ButtonA", visibility=False) btnB = M5Button(name="ButtonB", text="ButtonB", visibility=False) btnC = M5Button(name="ButtonC", text="ButtonC", visibility=False) label1 = M5TextBox(18, 90, "...", lcd.FONT_DejaVu24, 0x000000) label2 = M5TextBox(22, 192, "...", lcd.FONT_DejaVu18, 0x000000) title0 = M5Title(title="SIM800L Module", fgcolor=0xFFFFFF, bgcolor=0x000000) label4 = M5TextBox(24, 48, "Phone number:", lcd.FONT_DejaVu24, 0x000000) label3 = M5TextBox(48, 145, "Message:", lcd.FONT_DejaVu24, 0x000000) from numbers import Number idSeparator = None separator = None str2 = None parseStringGlobalVar1 = None IncomingSmsPhone = None uart = None buf = None IncomingSmsMessage = None isMessage = None def parseString(idSeparator, separator, str2): global parseStringGlobalVar1 parseStringGlobalVar1 = '' separatorCount = 0 for i in range(len(str2)): if str2[i] == separator: separatorCount += 1 else: if separatorCount == idSeparator: parseStringGlobalVar1 += str2[i] elif separatorCount > idSeparator: break return parseStringGlobalVar1 def IncomingSms(): global idSeparator, separator, str2, parseStringGlobalVar1, IncomingSmsPhone, uart, buf, IncomingSmsMessage, isMessage label1.setText(str(IncomingSmsPhone)) label2.setText(str(IncomingSmsMessage)) speaker.volume(1) for count in range(4): rgb.set_all(0x00cccc) speaker.sing(659, 1/8) wait(0.125) rgb.set_all(0x000000) wait(0.125) def InitSIM800L(): global idSeparator, separator, str2, parseStringGlobalVar1, IncomingSmsPhone, uart, buf, IncomingSmsMessage, isMessage wait(10) uart = machine.UART(1, tx=17, rx=16) uart.init(115200, bits=8, parity=None, stop=1) while uart.any(): if uart.read(1): pass uart.write('AT+CFUN=1,1\r') wait(45) uart.write('ATE0\r') wait(1) uart.write('AT+CSCS="GSM"\r') wait(1) uart.write('AT+CMGF=1\r') wait(1) uart.write('AT+CMGD=1,4\r') wait(1) uart.write('AT+CNMI=1,2,2,1,0\r') wait(1) while uart.any(): if uart.read(1): pass def LiveSIM800L(): global idSeparator, separator, str2, parseStringGlobalVar1, IncomingSmsPhone, uart, buf, IncomingSmsMessage, isMessage if uart.any(): buf = str((uart.readline())) if isMessage == 0: if buf.count('CMT:') == 1: isMessage = (isMessage if isinstance(isMessage, Number) else 0) + 1 IncomingSmsPhone = parseString(1, '"', buf) else: if buf.count('\\x') == 0: isMessage = (isMessage if isinstance(isMessage, Number) else 0) + 0 buf = buf[2:-5] if buf.count('CMT:') == 0 and len(buf) != 0: IncomingSmsMessage = buf IncomingSms() wait(1) rgb.set_all(0xff0000) InitSIM800L() rgb.set_all(0x000000) isMessage = (isMessage if isinstance(isMessage, Number) else 0) + 0 while True: LiveSIM800L() wait(0.001)C & C++ (Arduino IDE)
Пример ещё не написан ^_^
Downloads
Увы, тут сегодня ничего нет :)
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register Login