はじめに
ESP32 - MicroPythonを使い、GPS受信キットから受信方法について記載します。
GPS受信機キット - 1PPS出力付き「みちびき」3機受信対応
今回、秋月電子さんで購入できるGPS受信機キット - 1PPS出力付き「みちびき」3機受信対応を使用します。
以下が主な仕様です。
- GPSモジュール:GYSFDMAXB(太陽誘電)
- 搭載GPS受信チップ:MT3339(MediaTek)
- 受信周波数:1575.42MHz(L1,C/Aコード)
- 受信チャネル数:66(アクイジション)、22(トラッキング)
- 対応測位衛星システム:GPS(米国)、QZSS(日本)
- 受信(トラッキング)感度:-164dBm(typ.)
- 測位確度:2m(typ.緯経度の水平位置)@-135dBm
- 出力データ形式:NMEA0183V3.01準拠
- 測地系:WGS1984(デフォルト)
- 電源電圧:DC5V(3.8V~12V)/・電源電流:40mA
- 入出力信号レベル:C-MOSロジック(3.3V)レベル、非同期シリアル信号
- UART通信速度:9600bps(デフォルト)、4800~115200bps
- 出力データ更新レート:毎秒1回(デフォルト)、毎秒1~10回出力可
- 1PPS出力:C-MOSロジック(3.3V)レベル、パルス幅:100mS(アクティブLow)
- インジケータ:赤色LEDによる通電表示、衛星追尾中(1PPS)表示
- 基板サイズ:30×30×13.5mm(電池ボックス実装時)
- 重量:約11g(バックアップ電池装着時)
!!!本商品は、はんだ付けが必要です。!!!
開発環境
以下が確認した環境となります。
- ホストPC
- windows10 64bit Home
- VSCode - 1.41.1
- Pymakr 1.1.5
- NodeJS - 12.14.1 LTS
- ターゲット
- MicroPython v1.12 on 2019-12-20; ESP32 module with ESP32
機材
※型名が購入先のリンクになっています。
項目 | 型名 | 備考 |
---|---|---|
ESP32-WROOM-32 開発ボード | NodeMCU-32S ESP32-WROOM-32 | - |
GPS受信機キット | 秋月電子 | - |
ダイオード(1N4148) | 秋月電子 | GPS取説 - 推奨回路に記載 |
抵抗 10kΩ | GPS取説 - 推奨回路に記載 | |
ジャンパーケーブル | 指定なし |
接続図
※今回、「1PPS出力」は使用しないので、未接続になっています。
評価基板によって、RX2,TX2は、D16, D17と記載されています。
モジュール
GPSモジュールからNMEAフォーマットで送られてきます。
制御文字などが入っているため、パースする必要があります。
調査したところ、micropyGPSというライブラリを使うとできそうなことがわかりました。
ただ、README.mdに下記の記載があります。
ESP32
You can follow the setup instructions for the pyboard.
The only difference is, that you shoud use micropyGPS as a frozen module.
Otherwise there will be exceptions, because there is not enough heap space available.
ヒープが足りなくなるから、"frozen module"として扱ってねとのこと。
コード
動作確認したコードは以下となります。
ファイル名:sample_gps.py
from machine import UART
from micropyGPS import MicropyGPS
import utime, gc, _thread
uart = UART(2, baudrate=9600, timeout=200)
my_gps = MicropyGPS(local_offset=0, location_formatting='dd')
def test():
n = 0
mem_free = gc.mem_free()
tm_last = 0
while True:
len = uart.any()
if len > 0:
b = uart.read(len)
for x in b:
if 10 <= x <= 126:
stat = my_gps.update(chr(x))
if stat:
tm = my_gps.timestamp
tm_now = (tm[0] * 3600) + (tm[1] * 60) + int(tm[2])
if (tm_now - tm_last) >= 10:
print('=' * 20)
print(my_gps.date_string(), tm[0], tm[1], int(tm[2]))
print("latitude:", my_gps.latitude[0], ", longitude:", my_gps.longitude[0])
print("altitude:", my_gps.altitude)
print("satellites_used:", my_gps.satellites_used)
n += 1
tm_last = tm_now
if (n % 10) == 0:
print("Mem free:", gc.mem_free(), mem_free - gc.mem_free())
gc.collect()
else:
utime.sleep_ms(100)
testth=_thread.start_new_thread(test, ())
ファイル構成
>>> import os
>>> os.listdir()
['boot.py', 'project.pymakr', 'sample_gps.py', 'micropyGPS.py']
実行結果例
10秒ごとに、printのログが表示されます。
※xxxは伏せています。
>>> import sample_gps
I (58850) uart: ALREADY NULL
>>> ====================
00/00/00 12 59 11
latitude: 36.xxxxxx , longitude: 139.xxx
altitude: 139.5
satellites_used: []
====================
02/09/20 12 59 21
latitude: 36.xxxxxx , longitude: 139.xxx
altitude: 139.5
satellites_used: [3, 1, 193, 30, 8, 194]
====================
02/09/20 12 59 31
latitude: 36.xxxxxx , longitude: 139.xxx
altitude: 139.5
satellites_used: [3, 1, 193, 30, 194]
====================
02/09/20 12 59 41
latitude: 36.xxxxxx , longitude: 139.xxx
altitude: 139.5
satellites_used: [11, 3, 1, 17, 193, 30, 8, 194]
...
気づいたことと
最初の起動は時間がかかる
取説にも記載されていますが、時間がかかります
"40秒~数十分"と記載。
私の場合は、2分ほどかかりました。
受信できるとLEDの点滅で教えてくれます。
各項目の精度について
当たり前かもしれませんが、時刻はきっちり取れています。
緯度経度は、数十~100メートルぐらいといった感じでしょうか。
十分な精度だと思います。
ただ、ログ上は同じ値になっていますが、海抜は安定していない気がします。
40メートル ~ 180メートルの値をとってしまう。
ヒープ領域について
gc.collect()を実施しないと、利用可能なヒープが減っていきます。
上記のコードで、数時間ほど走らせてましたが、
とりあえず落ちることはなかったです。
もう少しエージングして確認しますが、
ダメなら別の方法が必要になるかもしれません。