LoginSignup
5
1

More than 3 years have passed since last update.

Wio LTEのMicroPythonの通信処理を使いやすくする (未完)

Last updated at Posted at 2019-12-23

はじめに

1年半前くらいにMicroPythonをWio LTEに移植して使ってきましたが、LTEの通信機能は一応使えるものの、使いやすいものとは言えませんでした。

そこで、M5Stack 3G 拡張ボードをMicroPythonで動かしたときの知見をもとに、Wio LTEのLTE通信を使いやすく方法を検討しました。

現状の問題点

現状、Wio LTE上のMicroPythonからLTEの通信機能を使うためには、MicroPythonで実装したLTE通信モジュール・ドライバを使って通信処理を記述する必要があります。
このLTE通信モジュール・ドライバには、基地局への接続機能と、TCP,UDPでの通信機能があります。

一方、MicroPython用のHTTP通信ライブラリやMQTT通信ライブラリは、socketモジュールに依存しているため、これらのライブラリを使うためにはsocketモジュール経由で通信できる必要があります。

よって、現状のLTE通信モジュールのドライバの実装では、既存の通信ライブラリを使用できず、一から実装しなおす必要があります。

そこで、socketモジュールから扱えるネットワーク・インターフェースとしてLTE通信モジュールを扱えるようにすることを考えます。

実装方法

以下の2つの方法があります。

  1. EC21Jを使うためのMicroPythonのネットワーク・インターフェース・モジュールを実装する。
  2. PPP通信モジュールを実装し、EC21JをPPPモードで使用する。

(1)の方法は、MicroPythonのnetworkモジュールから使うネットワーク・インターフェースとして、新たにEC21Jを追加する方法です。既存のネットワーク・インターフェースの実装としては、WIZnetのハードウェアTCP/IPモジュールを使う実装があります。networkモジュール管理下のネットワーク・インターフェースは、socketモジュール経由での通信処理で使うことができます。

(2)の方法は、MicroPythonの通信処理を組み込み用TCP/IPスタックであるlwIPを使うように設定し、lwIPのPPP通信機能を使って通信します。lwIPのPPP通信機能は、lwIPの管理下のネットワーク・インターフェースとして扱われるため、socketモジュール経由で通信処理を行うことができます。

今回は、M5Stack 3G 拡張ボードでもPPP通信機能を扱った経験から、(2)のlwIPのPPP通信機能を使う方針で実装を試みました。

MicroPythonの変更内容

MicroPythonのESP32ポートには、pppモジュールがすでに実装されていますので、このpppモジュールの実装をSTM32に移植することにしました。

ESP32では、OSとしてFreeRTOSが使われるため、ESP32ポートのpppモジュールにもFreeRTOSに依存している部分があります。
これらの依存部分をFreeRTOSを使わない実装に変更しました。

EC21Jの初期化処理

EC21Jの初期化処理は、基本的にEC21Jで直接TCP/IPの通信を扱う場合と同じですが、通信コンテキストの初期化処理だけ異なります。

EC21JのTCP/IP通信機能を使う場合、通信コンテキストの初期化には、+QIで始まるQuectel独自のTCP/IP通信用独自コマンドを用います。

例としてbeam.soracom.ioのポート80版に接続する場合は次のようになります。

AT+QICSGP=1,1,"soracom.io","sora","sora",1    // TCP/IP通信コンテキストを初期化
AT+QIOPEN=1,TCP,"beam.soracom.io",80,0,0      // TCP接続開始

代わりに、PPP通信を開始するには、+CGDCONTコマンドでPPP上のプロトコルにIPを指定して通信コンテキストを作成したのち、+CGDATAでPPP通信を開始します。

AT+CGDCONT=1,"IP","soracom.io"
AT+CGDATA="PPP",1

+CGDATAの代わりにATD*99***1#などでも良いようです。

これ以降は、PPPに則った通信を行えるようになります。

結果

残念ながら、PPPでの通信処理はうまくいきませんでした。

以下に実験時の通信ログを示します。

[DEBUG] initialize
[DEBUG] Waiting busy...
[DEBUG] wait_response: target=b'RDY'
[DEBUG] wait_response: response=bytearray(b'RDY')
[DEBUG] <- b'AT'
[DEBUG] wait_response: target=b'OK'
[DEBUG] wait_response: response=bytearray(b'OK')
[DEBUG] <- b'ATZ'
[DEBUG] wait_response: target=b'OK'
[DEBUG] wait_response: response=bytearray(b'OK')
[DEBUG] <- b'ATE0'
[DEBUG] wait_response: target=b'OK'
[DEBUG] wait_response: response=bytearray(b'+CFUN: 1')
[DEBUG] wait_response: response=bytearray(b'OK')
[DEBUG] <- b'AT+CFUN=1'
[DEBUG] wait_response: target=b'OK'
[DEBUG] wait_response: response=bytearray(b'OK')
[DEBUG] <- b'AT+QSCLK=1'
[INFO] Waiting SIM goes active...
[DEBUG] <- b'AT+CPIN?'
[INFO] AT+CPIN result=True, response=2
[INFO] Activating network...
[DEBUG] <- b'AT+CGREG?'
[DEBUG] -> b'+CGREG: 0,2'
[DEBUG] AT+CGREG?:+CGREG: 0,2
[DEBUG] <- b'AT+CGREG?'
[DEBUG] -> b'+CGREG: 0,2'
(...省略...)
[DEBUG] AT+CGREG?:+CGREG: 0,1
[DEBUG] <- b'AT+CEREG?'
[DEBUG] -> b'+CEREG: 0,1'
[DEBUG] AT+CEREG?:+CEREG: 0,1
[DEBUG] <- b'AT+CNMI: 0,0,0,0,0'
[DEBUG] wait_response: target=b'OK'
[DEBUG] wait_response: response=bytearray(b'OK')
[DEBUG] <- b'AT&D0'
[DEBUG] wait_response: target=b'OK'
[DEBUG] wait_response: response=bytearray(b'ERROR')
[DEBUG] wait_response: response=bytearray(b'OK')
[DEBUG] <- b'AT+CMEE=2'
[DEBUG] wait_response: target=b'OK'
[DEBUG] wait_response: response=bytearray(b'OK')
[DEBUG] <- b'AT+CGDCONT=1,"IP","soracom.io"'
[DEBUG] wait_response: target=b'OK'
[DEBUG] wait_response: response=bytearray(b'OK')
[DEBUG] <- b'ATD*99***1#'
[DEBUG] -> b'CONNECT 150000000'
[INFO] creating PPP
[INFO] activate PPP
ppp phase changed[2]: phase=0
[INFO] connect PPP
ppp_connect[2]: holdoff=0
ppp phase changed[2]: phase=3
pppos_connect: unit 2: connecting
ppp_start[2]
ppp phase changed[2]: phase=6
pppos_send_config[2]: out_accm=FF FF FF FF
ppp_send_config[2]
pppos_recv_config[2]: in_accm=FF FF FF FF
ppp_recv_config[2]
ppp: auth protocols: PAP=0 CHAP=1 CHAP_MD5=1
output: 7e ff 7d 23 c0 21 7d 21 7d 21 7d 20 7d 34 7d 22 7d 26 7d 20 7d 20 7d 20 7d 20 7d 25 7d 26 ea ef fc 5f 7d 27 7d 22 7d 28 7d 22 ba fa 7e
pppos_write[2]: len=24
ppp_start[2]: finished
>>> input: 7e ff 7d 23 c0 21 7d 21 7d 20 7d 20 7d 39 7d 22 7d 26 7d 20 7d 20 7d 20 7d 20 7d 23 7d 25 c2 23 7d 25 7d 25 7d 26 74 21 7d 36 d5 7d 27 7d 22 7d 28 7d 22 7d 32 ef 7e 7e ff 7d 23 c0 21 7d 22 7d 21 7d 20 7d 34 7d 22 7d 26 7d 20 7d 20 7d 20 7d 20 7d 25 7d 26 ea ef fc 5f 7d 27 7d 22 7d 28 7d 22 51 93 7e
pppos_input[2]: got 100 bytes
output: ff 7d 23 c0 21 7d 22 7d 20 7d 20 7d 39 7d 22 7d 26 7d 20 7d 20 7d 20 7d 20 7d 23 7d 25 c2 23 7d 25 7d 25 7d 26 74 21 7d 36 d5 7d 27 7d 22 7d 28 7d 22 9f e3 7e
pppos_write[2]: len=29
netif_set_mtu[2]: mtu=1500
pppos_send_config[2]: out_accm=0 0 0 0
ppp_send_config[2]
pppos_recv_config[2]: in_accm=0 0 0 0
ppp_recv_config[2]
ppp phase changed[2]: phase=7
input: 7e ff 7d 23 c0 21 7d 2b 7d 21 7d 20 7d 28 74 21 7d 36 d5 2e cb 7e 7e c2 23 01 01 00 23 10 89 c6 1f 37 f2 7d 5d df 79 6a da ef 32 7d 5d 19 e7 cc 55 4d 54 53 5f 43 48 41 50 5f 53 52 56 52 2a d9 7e
pppos_input[2]: got 65 bytes
output: ff 03 c2 23 02 01 00 19 10 33 40 e7 b6 d6 2a ce cf 1e 44 f4 c7 6d f5 d5 aa 73 6f 72 61 15 95 7e
pppos_write[2]: len=29
input: 7e c2 23 03 01 00 04 c2 bc 7e
pppos_input[2]: got 10 bytes
CHAP authentication succeeded
CHAP authentication succeeded
ppp phase changed[2]: phase=9
output: ff 03 80 21 01 01 00 16 03 06 00 00 00 00 81 06 00 00 00 00 83 06 00 00 00 00 6e db 7e
pppos_write[2]: len=26
input: 0d 0a 4e 4f 20 43 41 52 52 49 45 52 0d 0a
pppos_input[2]: got 14 bytes
input: 0d 0a 2b 51 49 4e 44 3a 20 50 42 20 44 4f 4e 45 0d 0a
pppos_input[2]: got 18 bytes
output: 7e ff 03 80 21 01 01 00 16 03 06 00 00 00 00 81 06 00 00 00 00 83 06 00 00 00 00 6e db 7e
pppos_write[2]: len=26
output: 7e ff 03 80 21 01 01 00 16 03 06 00 00 00 00 81 06 00 00 00 00 83 06 00 00 00 00 6e db 7e
pppos_write[2]: len=26
output: 7e ff 03 80 21 01 01 00 16 03 06 00 00 00 00 81 06 00 00 00 00 83 06 00 00 00 00 6e db 7e
pppos_write[2]: len=26
output: 7e ff 03 80 21 01 01 00 16 03 06 00 00 00 00 81 06 00 00 00 00 83 06 00 00 00 00 6e db 7e
pppos_write[2]: len=26
output: 7e ff 03 80 21 01 01 00 16 03 06 00 00 00 00 81 06 00 00 00 00 83 06 00 00 00 00 6e db 7e
pppos_write[2]: len=26
output: 7e ff 03 80 21 01 01 00 16 03 06 00 00 00 00 81 06 00 00 00 00 83 06 00 00 00 00 6e db 7e
pppos_write[2]: len=26
output: 7e ff 03 80 21 01 01 00 16 03 06 00 00 00 00 81 06 00 00 00 00 83 06 00 00 00 00 6e db 7e
pppos_write[2]: len=26
output: 7e ff 03 80 21 01 01 00 16 03 06 00 00 00 00 81 06 00 00 00 00 83 06 00 00 00 00 6e db 7e
pppos_write[2]: len=26
output: 7e ff 03 80 21 01 01 00 16 03 06 00 00 00 00 81 06 00 00 00 00 83 06 00 00 00 00 6e db 7e
pppos_write[2]: len=26
IPCP: timeout sending Config-Requests
ppp phase changed[2]: phase=11
ppp phase changed[2]: phase=6
pppos_send_config[2]: out_accm=FF FF FF FF
ppp_send_config[2]
pppos_recv_config[2]: in_accm=0 0 0 0
ppp_recv_config[2]
output: 7e ff 7d 23 c0 21 7d 25 7d 22 7d 20 20 4e 6f 20 6e 65 74 77 6f 72 6b 20 70 72 6f 74 6f 63 6f 6c 73 20 72 75 6e 6e 69 6e 67 7d 37 7d 38 7e
pppos_write[2]: len=36
output: 7e ff 7d 23 c0 21 7d 25 7d 23 7d 20 20 4e 6f 20 6e 65 74 77 6f 72 6b 20 70 72 6f 74 6f 63 6f 6c 73 20 72 75 6e 6e 69 6e 67 23 dd 7e
pppos_write[2]: len=36
ppp phase changed[2]: phase=12
Connection terminated.
ppp_link_terminated[2]
ppp_link_end[2]
ppp phase changed[2]: phase=0
ppp_link_terminated[2]: finished.

activate PPP以降、lwIPの通信ログが出力されています。output:の行は送信したPPPのパケットの内容、input:の行は受信したPPPのパケットの内容を表します。

CHAP authentication succeeded と表示されて、CHAPによる認証が完了後、IPCPでIPアドレスを取得するため、IPCPのConfigure-Requestを送信しています。

output: ff 03 80 21 01 01 00 16 03 06 00 00 00 00 81 06 00 00 00 00 83 06 00 00 00 00 6e db 7e

このパケットの内容は以下の通り、IPCPにて基地局側にIPの割り当てを要求しています。

ff 03 80 21 // IPCP
01 01 00 16 // Configure-Request, ID=0x01, Length=0x0016
03 06 00 00 00 00 // Self IP address = 0.0.0.0 (Request to assign IP)
81 06 00 00 00 00 // 
83 06 00 00 00 00 
6e db 7e // FCS+Flag

この直後、基地局側から以下の内容が返信されています。

input: 0d 0a 4e 4f 20 43 41 52 52 49 45 52 0d 0a

これは、文字列に直すと \r\nNO CARRIER\r\nとなり、通信が切断されたことを表しています。
これ以降、基地局側はPPPのパケットに応答しなくなります。

現在のところ、なぜ通信が切断されるのか分からず解決できていません。詳しい方がいましたら教えていただけるとありがたいです。

おわりに

Advent Calendarの担当日までに通信処理を実装して、通信できた!という内容を書ければいいなという予定でしたが、残念ながら間に合いませんでした。

この後しばらくPPPで通信できない原因を調査して、解決出来なければ、(1)の方針にてEC21のネットワーク・ドライバを実装しようと思います。

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1