Пишем первую простую прошивку для Telit

image
Доброго времени суток, уважаемое сообщество!

Так уж свершилось, что пришлось столкнуться с задачей написания прошивки для довольно интересного модема Telit GL865-DUAL. И в данном топике мне хотелось бы хотя бы в общих чертах описать процесс разработки прошивки для него.

Итак, начнем, пожалуй, с общего представления о том, в каком месте «торчит» прошивка у Телита. Это очень наглядно демонстрирует схема из официальной документации:

image

Как прекрасно видно из данной схемы, прошивка работает с устройством, общаясь с ним через уже готовые интерфейсы, находясь при этом в достаточно стесненных условиях. Кстати, сразу хотелось бы оговориться — указанные на схеме объемы памяти очень абстрактны. У Telit GL865-DUAL, к примеру, только 1 мегабайт оперативной памяти доступен и всего лишь 2 мегабайта flash памяти.

Пару слов о доступных интерфейсах. Всего их 9, но число рабочих напрямую зависит от железки, на которой запускается скрипт.
MDM

Интерфейс является самым важным. Он позволяет отправлять отправлять и принимать АТ команды, отправлять и принимать данные из сети и так далее и тому подобное. Отправляемые через него данные обрабатываются при помощи обработчика АТ команд. MDM модуль не взаимодействует с реальным последовательным портом, поэтому не важно, какие настройки стоят на порту — данные все равно дойдут до модуля.

MDM2

Это второй интерфейс между Python и обработчиком AT команд. Через него можно отправлять и получать ответы на АТ команды, когда MDM интерфейс занят.

SER

Данный интерфейс позволяет Python скрипту читать и отправлять данные в физический последовательный порт ASC0, обычно используемый для отправки AT команд в модуль (когда общаемся с модулем извне, с компа например). Когда Python скрипт работает, этот последовательный порт поступает в его полное распоряжение и не используется обработчиком АТ команд (то есть в это время на этот порт слать команды не получится). На данном порту при помощи скриптов Python нельзя управлять flow-control.

SER2

Интерфейс позволяет Python скрипту читать и писать данные в физический последовательный порт ASC1, который обычно используется для отладки.

GPIO

Интерфейс позволяет управлять портами ввода-вывода (или по простому — дергать ногами) в обход обработчика АТ команд, что выходит быстрее.

MOD

Интерфейс представляет собой набор пользовательских функций.

IIC

Интерфейс представляет собой реализацию IIC Bus Master в ядре Python. Он позволяет Python создавать одну или более IIC шин на существующих GPIO пинах.

SPI

Интерфейс представляет собой реализацию SPI Master Bus в ядре Python. Он позволяет Python создавать одну или более SPI шин на существующих GPIO пинах.

GPS

Интерфейс обеспечивает взаимодействие между Python и встроенным в модуль GPS контроллером. Он позволяет работать с ним в обход АТ команд.

Данный набор интерфейсов позволяет выполнять, в принципе, любые махинации с железом на достаточно приемлемых скоростях. Но не обошлось и без подводных камней. При портировании Python, ребята из Telit зачем-то удалили поддержку языком таких простых типов данных как:
  • complex;
  • float;
  • docstring.


Так что каких-то сложных вычислений, к сожалению, на железке не попроизводить. Ну хватит о грустном — пора перейти непосредственно к написанию и тестированию первой простой прошивки. Будем считать, что устройство уже подготовлено к работе. Если нет, то добро пожаловать сюда и сюда.

Для обеспечения связи с устройством я, лично, использую терминал RSTerm. Он удобен, портативен и даже, кажется, бесплатен.

Итак, приступим к написанию самой прошивки. Я не придумал ничего глупее, чем отправить СМС с текстом «Hello world» на свой телефон.

В самом начале скрипта подключим необходимые интерфейсы
import MOD
import MDM


Далее, по логике вещей, нам необходимо проверить, зарегистрировался ли модуль в сети. Для этого я набросал простую функцию, которая отправляет AT команду AT+CREG? и обрабатывает результаты.
def checkNetwork():
	MOD.sleep(20)
	REC_TIME = 200
	for _ in range(10):
		MDM.send("AT+CREG?\r",0)
		res = MDM.receive(REC_TIME)
		if (res.find('0,1')!=-1): return 1
		else: MOD.sleep(50) 
	return 0


Да, чуть не забыл. Python в Telit-е не знает такого типа как bool, поэтому приходится работать с 0 и 1.

Следом нам, конечно-же, понадобится функция, которая поможет нам отправить СМС. У меня получилось нечто такое.
def sendSMS( number, smstext, csca):
	if number=="" or smstext=="" or csca == "" : return 0
	MDM.send('AT+CSCA='+csca+'\r',2)
	MDM.receive(20)
	MDM.send('AT+CMGF=1\r',2)
	MDM.receive(20)
	a = MDM.send('AT+CMGS="' + number + '"\r', 2)
	res = MDM.receive(10)          
	a = MDM.send(smstext, 2)
	a = MDM.sendbyte(0x1A, 2)
	a=''
	while a=='':
		a = MDM.receive(20)
	return ( a.find('OK')!=-1 )

Параметрами ее являются соответственно:
  1. Номер телефона;
  2. Текст сообщения;
  3. Номер центра сообщений оператора.


Ну и теперь осталось только обернуть все это в логику и обеспечить хотя бы простой дебаг. Да, для дебага можно использовать второй порт последовательный порт устройства, но для меня это было излишним шиком, поэтому для своего же удобства я переопределил вывод команды print в первый последовательный порт.
import SER2

SER.set_speed('115200','8N1')
class SerWriter:
	def __init__(self):
		SER.set_speed('115200','8N1')

	def write(self,s):
		SER.send(s+'\r')
sys.stdout = sys.stderr = SerWriter()


Ну и весь исходник целиком
import MOD
import MDM
import SER

SER.set_speed('115200','8N1')
class SerWriter:
	def __init__(self):
		SER.set_speed('115200','8N1')

	def write(self,s):
		SER.send(s+'\r')

sys.stdout = sys.stderr = SerWriter()

def checkNetwork():
	MOD.sleep(20)
	REC_TIME = 200
	for _ in range(10):
		MDM.send("AT+CREG?\r",0)
		res = MDM.receive(REC_TIME)
		if (res.find('0,1')!=-1): return 1
		else: MOD.sleep(50)
	return 0

def sendSMS( number, smstext, csca):
	if number=="" or smstext=="" or csca == "" : return 0
	MDM.send('AT+CSCA='+csca+'\r',2)
	MDM.receive(20)
	MDM.send('AT+CMGF=1\r',2)
	MDM.receive(20)
	a = MDM.send('AT+CMGS="' + number + '"\r', 2)
	res = MDM.receive(10)          
	a = MDM.send(smstext, 2)
	a = MDM.sendbyte(0x1A, 2)
	a=''
	while a=='':
		a = MDM.receive(20)
	return ( a.find('OK')!=-1 )

print "Start"
while not checkNetwork():
	print "No network"
	MOD.sleep(10)
print "I find network"

myNumber = "+7960*******"
myText = "Hello world"
smsGate = "+79037011111"
print "Try to send SMS"
if sendSMS(myNumber,myText,smsGate):
	print "SMS sended"
else:
	print "SMS not sended"


Я сохранил этот скрипт под именем hello.py

Теперь остается только открыть RSTerm, выбрать меню Telit Python, залить файл при помощи кнопки Upload selected file(s) from PC to module, активировать его при помощи кнопки AT#ESCRIPT=«hello.py» и запустить кнопкой AT#EXECSCR.

Надеюсь данный материал хоть кому-нибудь пригодится. Спасибо за внимание.
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 10

    +1
    Еще б про железку пару слов услышать хотелось бы
      +1
      У на с товарищем в блоге есть краткий обзор. Я уж не стал переопубликовывать.
        0
        Платка с GL868-DUAL на борту jt5.ru/avr32/genesis-gsm/
        Тока там AVR32
          +1
          Использовали бы вместо Telit-а GSM модуль попроще — неплохо бы скостили цену. Да и работать он будет от силы в четверть нагрузки как просто GSM модем. Нерационально как-то, мне кажется.
            0
            GL868-DUAL стоит гораздо дешевле GL865-DUAL.

            Отличие между моделями только в сертификатах, GL868 будет работать только с операторами стран СНГ (+ некоторые другие страны, кроме Европы), а GL865 — будет работать везде, т.е. с любыми операторами.
        0
        Чем обусловлен выбор GL865-DUAL? Почему например не SIM900? Последний ведь существенно дешевле… И также есть возможность написания программ — Embedded AT Не на Питоне, правда
          0
          У них разница 100-200 рублей, что было не так критично. Да и сыграл свою роль фактор скорости разработки прошивки — на Питоне ее написать куда как проще и быстрее.
          0
          работаю с 863 чипом, на котором базируется GPS-трекер компании M2M (привет их дружному коллективу :) )
          как по мне, так некоторые моменты в коде или не обязательны или нужны только раз, например:
          MDM.send('AT+CSCA='+csca+'\r',2)
          

          не обязательная секция, т.к. при регистрации в GSM сети номер СМС-центра устанавливается автоматически
          MDM.send('AT+CMGF=1\r',2)
          

          достаточно вызывать единожды при инициализации… (кстати, Вы забыли упомянуть, что эта команда устанавливает текстовый режим приема-передачи, в то время как значение 0 установит PDU формат приемо-передачи и является форматом по-умолчанию) так же при инициализации я бы добавил такие команды (не обязательно, но на всякий случай):
          # New Message Indications: Buffer unsolicited result codes in the TA in case the DTE is busy and flush them to the TE after reservation. Otherwise forward them directly to the TE.
          MDM.send('AT+CNMI=2,1\r',2)
          # Set Text Mode Parameters: outgoing message with 24 hours of validity period and default properties
          MDM.send('AT+CSMP=17,167,0,0\r',2)
          

          еще не совсем понятна логика:
          a = MDM.send('AT+CMGS="' + number + '"\r', 2)
          res = MDM.receive(10)          
          a = MDM.send(smstext, 2)
          a = MDM.sendbyte(0x1A, 2)
          a=''
          

          «res» в коде больше нигде не используется, а «а» — просто «обнуляется». Да и сократить можно было:
          MDM.send(smstext + chr(26), 2)
          Кстати, в функции проверки сети Вы зря так категоричны, что не допускаете роуминга ;)

          Спасибо за внимание.
            0
            Забыл уточнить — именно в приведенном коде, т.к. например те же СМС один раз можно принимать в текстовом формате, а следующее — в PDU
              0
              Спасибо за уточнения. Обязательно учту.
              Да и целью статьи было написание самого простого приложения без заморочек.

              Насчет
              MDM.send('AT+CMGF=1\r',2)
              


              На GL865 с симкой Мегафона Северозапада у меня такой трюк не прокатил. МТС тоже раз через полтора выставляется.

          Only users with full accounts can post comments. Log in, please.