皆さんこんにちは。yossyです。
ラズピコで現在地を取得してみたいと思ったことはありませんか?
今回は、GPSモジュールとラズピコを使って、位置情報を取得する方法をご紹介します。
初心者の方でも簡単に試せるように、配線やコード、使い方まで丁寧に解説します!
GPSモジュールとは?
GPSモジュールは、GPS衛星の電波を受信して位置(緯度・経度)や時刻を取得できるモジュールです。
取れるデータはたくさんあります。
項目名 | 説明 |
---|---|
現在時刻 | UTC(協定世界時)で現在の時刻を取得できる |
日付 | 年・月・日が取得できる |
緯度 | 北緯/南緯の座標 |
経度 | 東経/西経の座標 |
高度 | 海抜高度(メートル) |
地上速度 | ノット(または km/h)での移動速度 |
進行方位 | 移動している方向(真北からの角度) |
衛星の数 | 現在使っている衛星の数 |
測位モード | 2D/3Dのモードや、Fixの有無(A=有効, V=無効) |
DOP値(精度) | 測位の精度を示す数値(HDOP/VDOP/PDOP) |
衛星情報 | 衛星ID、仰角、方位角、信号強度など |
磁気偏差 | 真北と磁北のズレ(地域による) |

意外と多い!
何ができる?:場所と時刻がわかる!
GPSモジュールは、地球上のどこにいるか&時刻を知ることができるので、
- 移動ルートの記録
- ロボットの現在位置を送信
- 時刻同期
などに使うことができます。
GPSモジュールの注意点:屋外で使おう!
GPSモジュールは、人工衛星の電波をアンテナで受信するので、電波が遮られる屋内では使うことが出来ません。
そのため、GPSモジュールを使う場合は屋外でアンテナが電波を受信できるようにして使いましょう!
Raspberry Pi PicoでGPSモジュールを使う方法
それでは、Raspberry Pi PicoでGPSモジュールを使う方法を解説します。
必要なもの
- Raspberry Pi Pico
- GPSモジュール(UART接続)
- ジャンパワイヤー
- ブレッドボード


UART接続とは?
UARTは、2本の線を使ってデータをやりとりする通信方式です。
ピンには「TX」と「RX」という名前がついており、それぞれ「送信(Transmit)」と「受信(Receive)」を意味します。
接続の際は、TXを相手のRXに、RXを相手のTXにつなぐ「クロス接続」を行います。
わかりやすく言えば、「糸電話」のようなイメージです。
糸電話では、自分の口から出た声が、相手の耳に届くように糸がつながっています。
UARTでも同じように、自分のTX(送信)から出たデータが、相手のRX(受信)に届くようにつなぎます。


配線
配線はこのようになります。
ラズピコのピン名 | 接続先(GPSモジュール) | 説明 |
---|---|---|
GP0(TX) | RX | ラズピコからGPSへのデータ送信 |
GP1(RX) | TX | GPSからラズピコへのデータ受信 |
3V3(OUT) | VCC | 電源(3.3V供給) |
GND | GND | グラウンド(共通接地) |



クロス配線を間違えないように!
プログラム-1 GPSデータを取得
GPSモジュールから送られてくるデータは、NMEAセンテンスと呼ばれる形式になっています。
種類 | 内容の概要 |
---|---|
$GPRMC | 推奨最小データ:時刻、ステータス、緯度、経度、速度、進行方位、日付など |
$GPGGA | 測位データ:時刻、緯度、経度、FIX品質、衛星数、HDOP、高度など |
$GPGSA | DOP情報:使用衛星のID、測位モード、PDOP/HDOP/VDOPなど |
$GPGSV | 衛星情報:衛星数、各衛星のSNR/方位/仰角など(複数センテンスに分割される) |
$GPVTG | 速度・方位:地上速度(km/h, ノット)、進行方向など |
まずは基本的な情報の$GPRMC
を取得してみましょう!
プログラムはこんな感じです。
from machine import UART, Pin
import time
# UART0 を GPS モジュールと接続(GP0=TX, GP1=RX)
uart = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1))
# NMEAセンテンスと最小の長さ
SENTENCE_MIN_LEN = {
"$GPRMC": 12, # 推奨最小データ(時刻・日付・緯度・経度・速度・方位…)
"$GPGGA": 10, # 測位データ(時刻・緯度・経度・FIX品質・衛星数・HDOP・高度…)
"$GPGSA": 18, # DOP情報(PDOP/HDOP/VDOP、使用衛星ID一覧…)
"$GPGSV": 4, # 衛星情報(衛星数)※実際は可変長ですが、最低4つ目までは必須
"$GPVTG": 9, # 速度・方位(km/h, ノット)
}
def get_sentence(sentence_type):
while True:
# 受信データがあれば一行読み取り
if uart.any():
raw = uart.readline()
if not raw:
continue
#受信データのデコード
try:
line = raw.decode('utf-8', 'ignore').strip()
except:
continue
#正しく始まっているかチェック
if not line.startswith(sentence_type):
continue
#リストに変換
parts = line.split(',')
#要素が揃っているかチェック
if len(parts) < SENTENCE_MIN_LEN.get(sentence_type):
continue
#センテンスが有効かチェック
if sentence_type == "$GPRMC" and parts[2] != 'A':
continue
print(parts)
return parts
time.sleep(0.1)
data = get_sentence("$GPRMC")
print(data)
プログラムの基本的な流れを説明すると
- UARTにデータが来てたら読み取り
- バイナリデータ(そのままでは使えない)を文字に変換(デコード)
- カンマで区切ってリストに変換
という流れになります。
これを実行すると、Thonnyのシェルに受信したデータが表示されます。
(電波を受信するまで時間がかかる場合があります!)


🧾 各データの意味
フィールド番号 | データ | 説明 | 例 |
---|---|---|---|
0 | センテンスの種類 | どの情報か | $GPRMC |
1 | UTC時刻(hhmmss.ss) | 時間(協定世界時) | 075849.00 → 07:58:49 |
2 | ステータス | A=有効, V=無効 | A |
3 | 緯度(ddmm.mmmm) | 度分形式(DMM) | 3456.7890 |
4 | 北緯/南緯(N/S) | 北ならN 、南ならS | N |
5 | 経度(dddmm.mmmm) | 度分形式(DMM) | 13512.3456 |
6 | 東経/西経(E/W) | 東ならE 、西ならW | E |
7 | 地上速度(ノット) | 1ノット ≒ 1.852 km/h | 0.288 |
8 | 進行方位(度) | 真北からの角度(未入力もあり) | 空(未取得) |
9 | 日付(ddmmyy) | 日/月/年(2桁表記) | 120725 → 2025/07/12 |
10 | 磁気偏差(度) | 方位の補正値(未入力もあり) | 空(GPSモジュールが対応していないことが多い) |
11 | 磁気偏差の方向(E/W) | 東(E)または西(W) | 空(上記と同じ) |
12 | 測位モード(NMEA 2.3以降) | A=自律測位、D=DGPS、N=無効など | A |
13 | チェックサム | データ検査用16進値 | *7F |
プログラム-2 緯度経度を取得
お次は、緯度経度を取得してみましょう。
NMEAセンテンスの緯度経度は、度分表記という形になっています。
このままではわかりにくいので、いつも使っている十進度に変換します!
プログラムを紹介する前に、下の度分表記を手動で変換してみます。
- 緯度:
3456.7890
- 経度:
13512.3456
まずは、度と分に分けます。
- 緯度:34度 / 56.7890分
- 経度:135度 / 12.3456分
これを下の変換式に代入します。
十進度 = 度 +(分 ÷ 60)
計算すると…?
- 緯度:34.94648
- 経度:135.20576
こうなります。
ここで次のように符号を変えます。
- 北緯(N)・東経(E) → 正の値
- 南緯(S)・西経(W) → 負の値
今回は北緯・西経で考えます。
- 緯度:34.94648°
- 経度:-135.20576°
度分表記を十進度に変換することができました!



場所は北太平洋の海上ですね!
それではプログラムを紹介します!
プログラム-1の続きにこのプログラムを追加してください。
def nmea_to_decimal(raw, hemi):
"""
入力と出力の解説
raw : 度分表記の緯度/経度(文字列) 例 "3745.1234"(DDMM.MMMM または DDDMM.MMMM)
hemi: 東西南北(文字列) "N"/"S"/"E"/"W"
return: 変換結果(浮動小数点), 例 37.752056
"""
# まず小数点より前の桁数で「度」の桁数を判定
# 緯度は DDMM.MMMM → 最初の2桁が度、経度は DDDMM.MMMM → 最初の3桁が度
if len(raw.split('.')[0]) > 4:
# 経度
deg_len = 3
else:
# 緯度
deg_len = 2
degrees = float(raw[:deg_len])
minutes = float(raw[deg_len:])
dec = degrees + minutes / 60
# 南半球・西経はマイナス
if hemi in ('S', 'W'):
dec = -dec
return dec
#受信データから緯度経度と場所を取得
ido_raw = data[3]
ido_houkou = data[4]
keido_raw = data[5]
keido_houkou = data[6]
#変換
ido = nmea_to_decimal(ido_raw, ido_houkou)
keido = nmea_to_decimal(keido_raw, keido_houkou)
#表示
print(f"緯度: {ido}°, 経度: {keido}°")
これを実行すると、十進度に変換された緯度と経度が表示されます!
まとめ
今回は、Raspberry Pi PicoとGPSモジュールを使って、位置情報(緯度・経度)を取得する方法を紹介しました!
- UART通信を使ってGPSと接続
- NMEAフォーマットの読み取り
- 緯度・経度を変換
GPSのデータは「位置」だけでなく、「速度」や「時間」なども取得できるため、工夫次第でさまざまな応用が可能です。
ラズピコとGPSを使えば、屋外で使える電子工作がグッと広がります。ぜひ今回の記事を参考に、オリジナルのGPSプロジェクトにチャレンジしてみてください!
コメント