はじめに
RaspberryPi Pico2 + MicroPythonでGPSを使う方法を解説します。
カーナビやスマホなど、今や当たり前のように使っているGPSですが、Picoシリーズでも「GPSモジュール」と「MicroGPSライブラリ」を使って、座標を取得することができます。
オリジナルのGPSロガーや、位置情報を使うプロジェクトも作れるようになるので、GPSについて気になっている方はぜひご覧ください。
記事ではRaspberryPi Pico2を使っていますが、Pico、PicoWでも同じ配線・プログラムで動作します。
ぜひお手持ちのPicoシリーズで、試してみてください。
~ この記事の内容 / Contents ~
環境
この記事で使用する環境は以下の通りです。
環境 | バージョンなど | 備考 |
開発用PCのOS | Windows11 | Windows10でもOKです |
言語 | MicroPython Ver.1.24.0 | |
開発環境 | Thonny Ver.4.1.4 | |
ボード | RaspberryPi Pico2 | Pico, PicoWでもOKです |
GPSモジュール「BE-180」
今回はBeitian社のGPSモジュールである「BE-180」を使用します。
GPS、ガリレオ、グロナス、北斗、みちびきと主要な衛星を網羅しており、4種類の変換ケーブルも付属しているので、ブレッドボードや拡張ボードですぐに使うことができます。
モジュール自体は中国製ですが、チップはスイス u-blox社の「M10050」を使用しているので、データシートや公式ツールなどの詳細情報は、u-blox社のサイトを参照することをおすすめします。
RaspberryPi Pico2とBE-180の接続
以下のように、Pico2とBE-180を接続します。
ピン番号 | 内容 | 接続先 | 備考 |
1 | TX | RX | |
2 | RX | TX | |
36 | 3V3 | 電源 | |
38 | GND | グラウンド |
Picoピンアサイン(Pin-Out)
※ Pico公式サイトより引用
使用する部品
RaspberryPi Pico 2
今からPicoを揃えるなら、RaspberryPi Pico2がおすすめです。Picoに比べて1.5倍高速で、値段はほぼ一緒です。
すぐに使えるキットもあります
ピンヘッダが半田付けされて、USBケーブルやピンのレイアウト表までついた、すぐに使えるセットもあります。
GPSモジュール「BE-180」
今回使用するGPSモジュールです、小型・軽量。3.3V ~ 5.0Vで動作。ドローン用ですが、Picoシリーズで使うにもぴったりです。
接続用の配線も付属しているので、別途配線を用意しなくてもすぐに使えます。
ブレッドボード
国内サンハヤト製のブレッドボードです。少々堅めの指し心地ですが、海外製と違ってピン穴の番号がすべて印刷されており、品質も高いのでおすすめです。
BE-180を使う際の注意点
BE-180は、通電すると「Tx」のLEDが青く点滅してデータが送信されますが、以下のように「PPS」のLEDが赤点滅するまでは、「99.99」「0.00」などの無効な座標が出力されます。
購入先の機械翻訳は分かりずらいのですが、GPSの仕組上、現在地の特定には複数の衛星の電波が必要で、その状態(2D~3D Fix)になると、PPSの赤色LEDが点滅するという仕様のようです。
また、このモジュールは屋内でも電波を受信できますが、間取りや場所によっては全く受信できないこともあります。まずは空の見える屋外や車の中、部屋の窓際で使ってみることをおすすめします。
「GPS Test」など、電波を確認できる無料のスマホアプリもあるので、併用して使うとさらに電波が探しやすいです。
BE-180の通信フォーマット
BE-180は、GPSなどの衛星から信号を受信し、「NMEA0183」というフォーマットに沿ってASCIIコードで送られます。
NMEAは公開されているため、自身で解析するプログラムもかけますが、後述するmicroGPSライブラリ( パーサー)を使用することで、楽に座標を取得することができます。
ライブラリ「microGPS」のインストール
microGPSはNMEA-0183フォーマットに対応したライブラリ(パーサー)です。
GPSを利用するプログラムを作る場合、本来であればフォーマットに基づいてデータを分割や、終端処理をするプログラムを書く必要があります。
しかし、このライブラリを使えばBE-180からのデータを渡すだけで、内容をパース(解析)してくれるので、緯度・経度など必要な情報を、少ないコードで簡単に取り出すことができます。
GitHubページ | https://github.com/inmcm/micropyGPS |
ライセンス | MIT(商用フリー) |
GitHub Star | 364 |
※ GitHub Starは、2025年1月現在の値です。
microGPSのインストール方法
下記の手順で「microGPS」をインストールします。Thonnyの「パッケージの管理」からは取得できないため、Githubから「microgps.py」を直接ダウウンロードします。
ダウンロードが完了したら、Thonnyで保存したファイルの場所を開いてmicroGPS.pyを右クリックします。
「/にアップロード」をクリックすれば、microGPSのインストールは完了です。
プログラム概要
今回のプログラムの概要は以下の通りです。
- シリアル通信の初期化とmicroGPSの生成
- microGPSへのデータの受け渡し
- 緯度・経度・海抜を表示する
実行結果
後述するプログラムの実行結果です。
GPSモジュールからのデータを解析(パース)し、現在の緯度・経度・海抜を出力します。GoogleMapの検索ボックスに「緯度,経度」とカンマで区切って貼り付けると、現在の地図が表示されます。
全体コード
全体コードは以下の通りです。詳細な内容は後述する「コードのポイント」で解説します。
from micropyGPS import MicropyGPS
from machine import UART
import time
# ポート番号とボーレートで初期化
uart = UART(0, 38400)
# microGPSのオブジェクトを生成
my_gps = MicropyGPS()
while True:
# 受信データが存在していたら
if uart.any() > 0 :
# 1byte受信
byteWord = uart.read(1)
try:
# byte配列 -> ascii文字列へ
ascii_word = byteWord.decode("ascii")
except:
print("except error")
continue
# microGPSにASCII文字をセット
stat = my_gps.update( ascii_word )
# 受信データが1センテンス揃ったら
if stat != None:
# センテンスの種類
print( "stat " + stat )
#緯度
print( "緯度 " + my_gps.latitude_string() )
#経度
print( "経度 " + my_gps.longitude_string() )
# 平均的な海水面(geoid)からの高さ(海抜)
print( "海抜 " + str(my_gps.geoid_height) +"m")
コードのポイント
シリアル通信の初期化とmicroGPSの生成
ポート番号とボーレートを指定して、シリアル通信(UART)を初期化します。BE-180はデフォルトで「38400」のボーレートとなっているので、38400を指定します。
microGPSは特に引数無しで生成します。
# ポート番号とボーレートで初期化
uart = UART(0, 38400)
# microGPSのオブジェクトを生成
my_gps = MicropyGPS()
microGPSへのデータの受け渡し
any関数で受信データの有無を確認し、データがある場合はread関数で1byteずつ受信します。
read関数で取得したデータはbyte型(≒数字)ですが、microGPSは文字型を受け取るため、decode関数でASCIIコード(≒文字)に変換します。
なお、プログラムの再実行時など、受け取るデータが異常になると、変換時に例外が発生する場合があるため、try-exceptで例外を無視するようにしています。
文字を変換した後は、microGPSのupdate関数にデータセットします。受け渡したデータの解析・結合・変換などは全てライブラリ側が処理してくれるため、利用者側はupdate関数の戻り値を確認するだけでOKです。
# 受信データが存在していたら
if uart.any() > 0 :
# 1byte受信
byteWord = uart.read(1)
try:
# byte配列 -> ascii文字列へ
ascii_word = byteWord.decode("ascii")
except:
print("except error")
pass
# microGPSにASCII文字をセット
stat = my_gps.update( ascii_word )
緯度・経度・海抜を表示する
NMEA0183では1つの位置情報をまとめたものを「センテンス(メッセージ)」と呼び、改行コードが終端になります。
前述したupdate関数は、改行コードまでのセットされると、センテンスの種類を返し、それまではNoneを返すため、update関数の戻り値を使ってセンテンスの受信完了をチェックします。
1センテンスの受信が完了すると、位置情報や海抜が取得できるようになるので、latitude_string関数などで緯度・経度・海抜を取得します。
# 受信データが1センテンス揃ったら
if stat != None:
# センテンスの種類
print( "stat " + stat )
#緯度
print( "緯度 " + my_gps.latitude_string() )
#経度
print( "経度 " + my_gps.longitude_string() )
# 平均的な海水面(geoid)からの高さ(海抜)
print( "海抜 " + str(my_gps.geoid_height) +"m")
表示された高さ(海抜)の確認は、国土地理院のマップMapでみることができますが、東京湾を基準とする「標高」とは差があります。さらにGPSの計測誤差もあるため、実際の高さと70m程度違いがでるようです。
まとめ
RaspberryPi Pico2 + MicroPythonでGPSを使う方法を解説しました。
普段何気なく使っているGPSですが、自分で使おうとすると、以外と電波が弱いことがわかったり、通信フォーマットを調べてみたりと、かなり勉強になりました。
今回の記事のコードとライブラリがあれば、フォーマットを覚える必要はありませんが、「NMEA0183」はオートパイロットやソナーなどに幅広く使われているようなので、軽く見るだけでも知見が広がって面白いです。
GPSモジュールを使えば、IoTだけではなく、GIS (Geographic Information System)のプロダクト/プログラムも使れるようになります。みなさんもぜひ使ってみてください。
参考になればうれしいです。
お知らせ
MicroPythonのプログラミングガイドブックが遂に発売!
「MicroPython」の本が遂にでました。
この一冊で、MicroPythonの言語仕様から、プログラミングの仕方まで”ガッツリ”学べます!
内容は、普段別言語で開発している人や、これからマイコンを始める(工学系の)学生を対象としているので「初心者向け」ではありません。しかし、「自前のライブラリの作成」が目標なので、これ一冊で「ガッツリ」とMicroPythonを学ぶことができます。
全ての内容はここでは紹介しきれないので、詳細は以下のAmazonページをご覧ください。目次だけでも”ガッツリ”なのが確認できると思います。
Pico/Pico W関連のおすすめ本
RaspberryPi Pico / Pico W関連のおすすめ本を独断と偏見で3つ選んでみました。Picoやるならとりあえずこれ買っとけ的な本や、電子工作全般で使える本などを厳選しています。
質問・要望 大歓迎です
「こんな解説記事作って」「こんなことがしたいけど、〇〇で困ってる」など、コメント欄で教えてください。 質問・要望に、中の人ができる限り対応します。
使えたよ・設定できたよの一言コメントも大歓迎。気軽に足跡を残してみてください。記事を紹介したい方はブログ、SNSにバシバシ貼ってもらってOKです。