Урок 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
Увы, тут сегодня ничего нет :)