🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
GPS

GPSは、Global Positioning Systemの略です。衛星信号を使用して受信機の地上又は空中内の居場所を特定するナビゲーションシステムです。"GPS"は受信機のことも指します。

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

3回答

510閲覧

GPSモジュール:AE-GYSFDMAXBから緯度・経度のデータを取得したい

kta.0120

総合スコア1

GPS

GPSは、Global Positioning Systemの略です。衛星信号を使用して受信機の地上又は空中内の居場所を特定するナビゲーションシステムです。"GPS"は受信機のことも指します。

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2024/09/04 16:19

編集2024/09/12 22:41

この質問はQiitaにも同じ文面で投稿しています。
Qiitaの同じ質問
マルチポストの理由:できる限り多くの人の目に触れることで、より多くの回答を得る。
Qiitaにて解決しました
謝辞
今回の質問に回答・コメントを送ってくださった皆様、ありがとうございました。
Qiitaでいただいた回答で問題は解決しましたが、teratailでのコメント・回答からも参考になる点があり、解決に近づくことができました。ありがとうございました。詳しくはこちらをご覧ください。また、質問サイトを使い始めて間もないため、知らなかったマナーや、プログラムをする上での心構えも教えていただきました。そちらにも感謝します。
以下が解決したプログラムです。

py

1from machine import Pin, UART 2import utime 3 4def byte2string(bData): 5 try: 6 return bData.decode('utf-8') 7 except: 8 return ''.join(map(chr, bData)) 9 10def nmea2dd(val): 11 val = float(val) 12 d = val // 100 13 m = ((val / 100 - d) * 100) // 60 14 s = (((val / 100 - d) * 100 - m) * 60) / 3600 15 return d + m + s 16 17#gps = UART(0, 9600) 18gps = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5)) 19 20buf = '' 21satellites = [] 22n_use, latitude, longitude, altitude = 0, 0, 0, 0 23 24print("Start!") 25 26for _ in range(100): #⭐️ 27 if gps.any() > 0: 28 while gps.any() > 0: 29 buf += byte2string(gps.read()) 30 sentences = buf.split('\r\n') 31 for sentence in sentences: 32 if len(sentence) == 0 or sentence[0] != '$': continue 33 part = sentence.split(',') 34 if part[-1].find('*') < 0: #checksum 35 buf = sentence 36 break 37 38 #print(sentence) #すべてのNMEAデータを見る 39 if part[0] == '$GPGGA': 40 if part[6] == '0': continue #is invalid 41 n_use, latitude, longitude, altitude = part[7], part[2], part[4], part[9] 42 if len(latitude) == 0 or len(longitude) == 0: continue 43 latitude, longitude = nmea2dd(latitude), nmea2dd(longitude) 44 if part[0] == '$GPGSA': 45 satellites = [] 46 for n in range(12): 47 if len(part[3 + n]) == 0: continue 48 satellites.append(int(part[3 + n])) 49 if part[0] == '$GPRMC': 50 dmy, hms = part[9], part[1] 51 if len(dmy) == 0 or len(hms) == 0: continue 52 year, month, mday, hour, minute, second = \ 53 int(dmy[4:6]) + 2000, int(dmy[2:4]), int(dmy[0:2]), \ 54 int(hms[0:2]), int(hms[2:4]), int(hms[4:6]) 55 # UTC to JST 56 secs = utime.mktime((year, month, mday, hour, minute, second, 0, 0)) 57 secs += 9 * 3600 # +09:00 58 year, month, mday, hour, minute, second, weekday, yearday = utime.localtime(secs) 59 print(f"時刻:{year:04}/{month:02}/{mday:02} {hour:02}:{minute:02}:{second:02}") 60 if n_use == 0: continue 61 print(f'測位利用衛星:{n_use}{satellites}') 62 print("緯度:%.8f" % (latitude)) 63 print("経度:%.8f" % (longitude)) 64 print(f"高度:{altitude}") 65 if part[0] == '$GPZDA': 66 print() 67 68 else: #end of for 69 buf = '' 70 71 utime.sleep(0.1) 72 73print("End;") 74

質問
Raspberry Pi PicoでGPS受信モジュール「AE-GYSFDMAXB」を使う必要があり、ネットで調べ、マイコンとの接続、プログラムまで進み、屋外で実行してみました。ですが、シェルの欄には、大半が

py

1Request Timeout: No GPS data is found.

と表示され、稀に緯度・経度が表示されます。これは、プログラムの問題なのか、それとも、GPS受信モジュールの故障か、もしくは、通信環境が悪いか、何が原因と思われるか教えていただきたいです。もし、プログラムの問題であれば、修正案も教えていただけると助かります。わからないことがありましたら、聞いてください。
マイコン:Raspberry Pi Pico
GPSモジュール:AE-GYSFDMAXB

プログラムの出展を見つけられませんでした。すいません

py

1from machine import Pin, UART, I2C 2 3#Import utime library to implement delay 4import utime, time 5 6#GPS Module UART Connection 7gps_module = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5)) 8 9#print gps module connection details 10print(gps_module) 11 12#Used to Store NMEA Sentences 13buff = bytearray(255) 14 15TIMEOUT = False 16 17#store the status of satellite is fixed or not 18FIX_STATUS = False 19 20#Store GPS Coordinates 21latitude = "" 22longitude = "" 23satellites = "" 24gpsTime = "" 25 26 27#function to get gps Coordinates 28def getPositionData(gps_module): 29 global FIX_STATUS, TIMEOUT, latitude, longitude, satellites, gpsTime 30 31 #run while loop to get gps data 32 #or terminate while loop after 5 seconds timeout 33 timeout = time.time() + 8 # 8 seconds from now 34 while True: 35 gps_module.readline() 36 buff = str(gps_module.readline()) 37 #parse $GPGGA term 38 #b'$GPGGA,094840.000,2941.8543,N,07232.5745,E,1,09,0.9,102.1,M,0.0,M,,*6C\r\n' 39 #print(buff) 40 parts = buff.split(',') 41 42 #if no gps displayed remove "and len(parts) == 15" from below if condition 43 if (parts[0] == "b'$GPGGA" and len(parts) == 15): 44 if(parts[1] and parts[2] and parts[3] and parts[4] and parts[5] and parts[6] and parts[7]): 45 print(buff) 46 #print("Message ID : " + parts[0]) 47 #print("UTC time : " + parts[1]) 48 #print("Latitude : " + parts[2]) 49 #print("N/S : " + parts[3]) 50 #print("Longitude : " + parts[4]) 51 #print("E/W : " + parts[5]) 52 #print("Position Fix: " + parts[6]) 53 #print("n sat : " + parts[7]) 54 55 latitude = convertToDigree(parts[2]) 56 # parts[3] contain 'N' or 'S' 57 if (parts[3] == 'S'): 58 latitude = -latitude 59 longitude = convertToDigree(parts[4]) 60 # parts[5] contain 'E' or 'W' 61 if (parts[5] == 'W'): 62 longitude = -longitude 63 satellites = parts[7] 64 gpsTime = parts[1][0:2] + ":" + parts[1][2:4] + ":" + parts[1][4:6] 65 FIX_STATUS = True 66 break 67 68 if (time.time() > timeout): 69 TIMEOUT = True 70 break 71 utime.sleep_ms(500) 72 73#function to convert raw Latitude and Longitude 74#to actual Latitude and Longitude 75def convertToDigree(RawDegrees): 76 77 RawAsFloat = float(RawDegrees) 78 firstdigits = int(RawAsFloat/100) #degrees 79 nexttwodigits = RawAsFloat - float(firstdigits*100) #minutes 80 81 Converted = float(firstdigits + nexttwodigits/60.0) 82 Converted = '{0:.6f}'.format(Converted) # to 6 decimal places 83 return str(Converted) 84 85 86while True: 87 88 getPositionData(gps_module) 89 90 #if gps data is found then print it on lcd 91 if(FIX_STATUS == True): 92 print("fix....................................................") 93 print("緯度:",latitude) 94 print("経度:",longitude) 95 print(satellites) 96 print(gpsTime) 97 98 FIX_STATUS = False 99 100 if(TIMEOUT == True): 101 print("Request Timeout: No GPS data is found.") 102 #-------------------------------------------------- 103 #updated on 5-May-2022 104 #-------------------------------------------------- 105 TIMEOUT = False 106

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

thkana

2024/09/04 23:08

症状は「通信精度が悪い」というものでは全くないように思います。 まずは、NMEAの解析など抜きに、モジュールから流れてくるシリアルデータをそのまま表示することを試してみてはいかがでしょう? 加工結果だけ眺めて「プログラムの問題なのか、それとも、GPS受信モジュールの故障か、もしくは、通信環境が悪いか、何が原因と思われるか」悩んでみても得られる情報は少ないです。情報の源流を辿るべきです。
kta.0120

2024/09/05 03:15

プログラムをする上での必要な問題解決の術を教えていただきありがとうございます。いただいた助言の通りに「シリアルデータをそのまま表示」というのをしてみます。また、情報の源流もたどってみます。回答ありがとうございました。
dodox86

2024/09/05 04:10

@質問者 kta.0120 さん Qiitaのアカウントと同一の方でしたら、本質問はマルチポストですね。 https://qiita.com/kta_0120/questions/1d91c6979788e65cb4f2 恐らくご存じなかったのだと思いますが、マルチポストはteratailでは非推奨の行為です。 [他のサービスにも質問投稿をしたい(してしまった)] https://teratail.com/help#posted-otherservice また、teratailに限らず一般的にQ&Aサイトではマルチポストはマナー違反とされています。
kta.0120

2024/09/05 07:47

ご指摘ありがとうございます。質問サイトを使うのが初めてでしたので、マルチポストというものを初めて知りました。記載されているリンクに従った対応をさせていただきます。ご指摘ありがとうございました。
thkana

2024/09/05 14:14

'#if no gps displayed remove "and len(parts) == 15" ' をキーにググってみると https://みんなでdx.tech/2024/03/05/gps受信モジュールで現在位置を確認できます。/onsitu が元のようですね。y_waiwai氏指摘のように「正しい」プログラムとは言いがたい気はしますが。 いやしかし、コールドスタート10~20分というのはよほどの悪環境... GPSは、基本「全天を見渡せる」環境で使うものですよ。いまどきのモジュールなら全天見える環境ならコールドスタートでも一分以内に測位できるのではないかと思います。逆に、窓際であれ室内で使えることを期待しちゃいけません。 > まだQiitaでも解決していません。 いや、それは「誰かの言うとおりにすれば解決」というのを求めていればそういう話になるかも知れないけれど、結局いまは「あなたの環境でなにが起こっているか」を調べないと解決しないわけで...
kta.0120

2024/09/05 15:01

コメントありがとうございます。自分もプログラムを初めてから3か月ほどのため自分だけで問題をすべて解決することが難しい状態です。ですので、teratailのような質問プラットフォームで解決策等の助言をいただいています。他サイトでは解決策をすぐに教えてくださる方はいますが、それでは、これから自分だけで問題を解決する能力が養われないと思っていたりもします。ですので、thkana様やy_waiwai様のように「問題解決」をするために必要な本質的な力を得る機会をいただけて感謝しています。まだまだ力不足ですが、お時間があれば解決に力を貸していただければ幸いです。
guest

回答3

0

ベストアンサー

「AE-GYSFDMAXB」に通電し、アンテナを天空に向け3~5分後に基板上の赤いLEDは1秒ごとに点滅していますか?GPS測位できているとそのLEDが1秒毎に点滅しますのでGPSモジュールの故障切り分けができると思います。また結線も確認してください。

このGPSモジュールは測位できなくとも1秒ごとに$GPGGAは出力していますが起動後の数分は緯度経度演算できるまで位置情報が空で出力されます。
しかし質問に記載のプログラムでは位置情報がない場合Timeoutと出力される作りになっています。

そのため動作確認するには39行目の #print(buff)のコメントを外してシリアル出力を確認してください。

動作していれば1秒ごとに数行表示されます。その中に $GPGGAで始まる行があるはずです。その2カラム目の値が衛星からの時刻ですので、衛星を捕捉できている確認できます。
たとえば $GPGGA,070631.097, ...となっていればUTC7時6分31秒(=9時間加算して日本時刻16:06:31)と読み、現在時と合っていれば衛星の捕捉はできているはずです。

そこまでできていれば複数の衛星を捕捉し緯度経度が計算できる(LEDが点滅する)まで根気よく待ってください。

投稿2024/09/05 07:53

編集2024/09/05 09:03
hqf00342

総合スコア360

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kta.0120

2024/09/05 12:03

細かな部分の指摘ありがとうございます!いただいた助言をもとに、根気強く待ってみます。解決ができましたら、報告させていただきます。回答ありがとうございました。
thkana

2024/09/05 22:38

(あれ? 昨夜書くだけ書いて送信してなかった) なかなか測位に至らない、というだけなら待てばいいかも知れませんが、 > 稀に緯度・経度が表示されます というところがちょっと引っかかります。一度測位すると、受信が途切れたとしてもNMEA出力にはそのデータを当面は保持するものが多いので。
hqf00342

2024/09/06 00:04

thkana様 気になる点を全部は書けていないので (例えばこのモジュールはロジックレベルは3V3ですがVccは5Vなのでどう給電しているのか等) 稀にうまくいくケース等は少しずつ切り分けをしていくのかと思います。
kta.0120

2024/09/06 10:22

@thkanaa様 @hqf00342様 お話合いありがとうございます。もし、不明点などがありましたらお聞きください。わかる範囲でお答えします。
kta.0120

2024/09/08 09:28

解決しました。hqf00342様の回答からも参考になった点がありました。ありがとうございました。
thkana

2024/09/08 11:13

https://teratail.com/help#posted-otherservice > 解決した際には必ずteratail及びすべての投稿に解決した旨と、どのように解決したかを記載してください。 とも重なりますが、 https://teratail.com/help#about-teratail teratailは、 > プログラミングをする中で起きた解決できない課題について本当に困っている人をサポートすること、また、価値のあるコンテンツを世の中に残し届ける事を目的としています。 前半はあなたの問題が解決することで果たされました。 後半の目的を果たすために、以下をお願いします。 https://teratail.com/help#resolve-myself > また後から読む人のためにも、具体的な解決手順を記載してください。
kta.0120

2024/09/12 22:43

ご指摘ありがとうございます。対応します。
guest

0

そのGPSユニットのことは全く知りませんが、、
ぱっと見て気になったところを

while True: gps_module.readline() buff = str(gps_module.readline()) #parse $GPGGA term

gps_module.readline という関数は、GPSからの通信電文を1行分取得するもの、だと思いますが(そこらへんどういう動作をするのか確認しましょう)、
1行分の電文を捨てて、次の行を取得してそれを使用する、という動作となってます

なぜそんなことをしているのか、を説明できるでしょうか

投稿2024/09/04 22:44

y_waiwai

総合スコア88030

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kta.0120

2024/09/05 03:21

回答ありがとうございます。プログラムはサイトからのコピペしたものですので、そのサイトにもう一度戻り、このプログラムの動作を確認してみます。問題にぶつかったとき、このコードはどういうことなのか説明できる力をつけていきたいと思います。回答ありがとうございました。
kta.0120

2024/09/08 09:27

解決しました。ご助言を下さりありがとうございました。
guest

0

自己解決しました

開発環境
・raspberry pi pico
・micro python
・GPSモジュール:AE-GYSFDMAXB
接続(AE-GYSFDMAXBーPico)
5VーVBUS
GNDーGND
RXDーGP3(5番ピン)
TXDーGP2(4番ピン) #UARTです

窓際だけだと誤差が大きかったりしますが、外で受信すると誤差はありませんでした。誤差が大きいようであれば、hqf00342さんのコメントの通り、一度外で受信してみてください。

プログラム

py

1from machine import Pin, UART 2import utime 3 4def byte2string(bData): 5 try: 6 return bData.decode('utf-8') 7 except: 8 return ''.join(map(chr, bData)) 9 10def nmea2dd(val): 11 val = float(val) 12 d = val // 100 13 m = ((val / 100 - d) * 100) // 60 14 s = (((val / 100 - d) * 100 - m) * 60) / 3600 15 return d + m + s 16 17#gps = UART(0, 9600) 18gps = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5)) 19 20buf = '' 21satellites = [] 22n_use, latitude, longitude, altitude = 0, 0, 0, 0 23 24print("Start!") 25 26for _ in range(100): #⭐️ 27 if gps.any() > 0: 28 while gps.any() > 0: 29 buf += byte2string(gps.read()) 30 sentences = buf.split('\r\n') 31 for sentence in sentences: 32 if len(sentence) == 0 or sentence[0] != '$': continue 33 part = sentence.split(',') 34 if part[-1].find('*') < 0: #checksum 35 buf = sentence 36 break 37 38 #print(sentence) #すべてのNMEAデータを見る 39 if part[0] == '$GPGGA': 40 if part[6] == '0': continue #is invalid 41 n_use, latitude, longitude, altitude = part[7], part[2], part[4], part[9] 42 if len(latitude) == 0 or len(longitude) == 0: continue 43 latitude, longitude = nmea2dd(latitude), nmea2dd(longitude) 44 if part[0] == '$GPGSA': 45 satellites = [] 46 for n in range(12): 47 if len(part[3 + n]) == 0: continue 48 satellites.append(int(part[3 + n])) 49 if part[0] == '$GPRMC': 50 dmy, hms = part[9], part[1] 51 if len(dmy) == 0 or len(hms) == 0: continue 52 year, month, mday, hour, minute, second = \ 53 int(dmy[4:6]) + 2000, int(dmy[2:4]), int(dmy[0:2]), \ 54 int(hms[0:2]), int(hms[2:4]), int(hms[4:6]) 55 # UTC to JST 56 secs = utime.mktime((year, month, mday, hour, minute, second, 0, 0)) 57 secs += 9 * 3600 # +09:00 58 year, month, mday, hour, minute, second, weekday, yearday = utime.localtime(secs) 59 print(f"時刻:{year:04}/{month:02}/{mday:02} {hour:02}:{minute:02}:{second:02}") 60 if n_use == 0: continue 61 print(f'測位利用衛星:{n_use}{satellites}') 62 print("緯度:%.8f" % (latitude)) 63 print("経度:%.8f" % (longitude)) 64 print(f"高度:{altitude}") 65 if part[0] == '$GPZDA': 66 print() 67 68 else: #end of for 69 buf = '' 70 71 utime.sleep(0.1) 72 73print("End;")

投稿2024/09/13 07:56

kta.0120

総合スコア1

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問