GPSデータを取得しLCDに表示してみた

# 1. 今回のやりたいこと
今回は、タイトルの通り、GPSのデータを取得しLCDに表示させる時刻表示システムを作りたいと思います。システムの概要を簡単に以下に示します。
![システム概要_キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782242/fe4c9a29-0aff-9181-7dfd-1f9eef5689e9.png)


# 2. 環境
* __使用ボード__：nucleo l4r5zi
Cortex-M4搭載、2MBのFlash、640KのSRAM、USB OTG
* __開発環境__：Atollic TrueSTUDIO® for STM32, Built on Eclipse Neon.1a.(Version: 9.3.0 )
* __OS__：KOZOS
[12ステップで作る 組込みOS自作入門](http://kozos.jp/books/makeos/)で紹介されているOSになります。ソースコードも展開されています。
* __LCD__ : [ＡＱＭ１６０２Ｙ－ＮＬＷ－ＢＢＷ](https://akizukidenshi.com/catalog/g/gP-12485/)
* __GPS__ : [みちびき](https://akizukidenshi.com/catalog/faq/goodsfaq.aspx?goods=K-09991)

# 3. 時刻表示システム
### 3.1 使用ハードウェア
使用するLCDとGPSの詳細を説明します。
##### 2.1.1 LCD
使用するLCDは、ＡＱＭ１６０２Ｙ－ＮＬＷ－ＢＢＷで、通信IFはI2Cとなっています。このLCDでは、16文字×2行のキャラクタを表示することができます。キャラクタのパターンは、CGROM(Character Generator ROM)と呼ばれているROMに格納されており、下記の通りとなっています。表の行は下位4ビット、列は上位4ビットのデータを表していて、例えば'A'を表示させたい場合は0b01000001(0x41)をLCDに送信すればよいことになります。
![文字列パターン.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782242/448c0253-40e5-5035-5ba3-9695de39ba11.png)


##### 3.1.1 GPS
使用するGPSは、みちびきで、通信IFはUARTとなっています。GPSモジュールとしてGYSFDMAXBを搭載しており、NMEA0183 に準拠した緯度・経度・高度・時刻などの各種ナビケーション情報を出力します。

GYSFDMAXBは、以下のデータを出力します。
|種別  |内容  |
|---|---|
| GPGLL |位置情報（緯度、経度）を出力  |
|GPRMC  |位置情報と時刻（UTC時刻）、速度と方位を出力  |
|GPVTG  |方位と速度を出力  |
|GPGGA  |位置情報（緯度、経度）、GPS測位状態、測位衛星数を出力  |
|GPGSA  |GPS衛星の使用衛星番号、各種DOP、動作モードを出力  |
|GPGSV  |GPS衛星の生成情報を出力  |
|GPZDA  |時刻（UTC時刻）と日付を出力  |

### 3.2 仕様
時刻表示システムの仕様を簡単に示します。
表示する情報は、日付/時刻、経度、緯度で、LCDには以下のレイアウトで表示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782242/c4e8d148-81b2-dbbb-0d3d-be14a9b828ff.png)

例えば、2023/11/5(日) 17:00 東京（経度139 緯度35）の場合、以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782242/e24594bd-b9ed-bbbb-bd13-5a0b8ed856e4.png)

LCDに表示する情報は、「2.1.1 GPS」に記載したデータのうちGPRMCにあります。このため、GPRMCのみを受信しその他のデータはソフト側で破棄します。

### 3.3 ソフトウェア構成図
ソフトウェア構成図を以下に示します。
![ソフトウェア構成図.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782242/54f6dd9d-5049-9cc7-ed4f-dfd165a05514.png)

* __表示アプリ__
GPSからのデータをGPSドライバから取得し、LCDへの表示を行います。

* __GPSデバイスドライバ__
みちびきからのデータを解析し、正常なデータであれば表示アプリへ渡します。

* __UARTドライバ__
UARTのドライバになります。みちびきの通信IFはUARTのため、本ドライバを使用しみちびきと通信をおこないます。

* __LCDデバイスドライバ__
表示アプリから渡される文字列を今回使用するＡＱＭ１６０２Ｙ－ＮＬＷ－ＢＢＷ上に表示するための値に変換し、LCDにI2C経由で送信します。

* __I2Cドライバ__
I2Cのドライバになります。LCDのＡＱＭ１６０２Ｙ－ＮＬＷ－ＢＢＷの通信IFはI2Cのため、本ドライバを使用して通信を行います。

### 3.4 実装
ソースコードは以下に格納しています。
[Nucleo-L4R5ZI_System](https://github.com/Yas-Mi/Nucleo-L4R5ZI_System)

GPSデバイスドライバについて簡単に説明したいと思います。
GPSデバイスドライバは上記リンクのsrc\dev\gysfdmaxb.cになります。

「3.2 仕様」でも記載したように、GPSから送信されるデータのうちGPRMCのみを受信します。
GPRMCの実際の値を以下に示します。

`$GPRMC,153718.000,A,3500.0000,N,13900.0000,E,0.40,166.35,061123,,,D*65`

「,」でデータが区切られており、各データの意味は以下の通りです。
|データ  |内容  |意味  |
|---|---|---|
|153718.000|協定世界時(UTC）での時刻|UTC時刻:15時37分18秒000|
|A|測位状態　V = 警告, A = 有効  |有効|
|3500.0000|緯度　dddmm.mmmm  |35度|
|N|北緯/南緯　N = 北緯,S = 南緯  |北緯|
|13900.0000|経度　dddmm.mmmm  |139度|
|E|東経/西経　E = 東経,W = 西経  |東経|
|0.40|速度[knot]  |0.4[knot]|
|166.35|真方位[度]  |166.35度|
|061123|協定世界時(UTC）での日付  |UTC日付:2023年11月6日|
|D|モード　N = データなし,A = 自律方式,D = 干渉測位方式,E = 推定|干渉測位方式|
|*65|チェックサム('*'の後の数値)  |65|

GPSデバイスドライバで、GPRMCデータを受信した際に上記のフォーマットに従い、データを抽出し表示アプリへ渡します。詳細については、ソースコードを参照ください。

制限事項がいくつかあるため以下に示しておきます。
* GPSへの送信は行わず、デフォルトの設定で通信を行う
* 経度は北緯、緯度は東経にしか対応しない
（日本の場合、北緯、東経しかありえないため）
* 表示する時刻は日本時間ではなくUTC
（+9すれば日本時間になりますが、日付もそれに合わせて変更することが面倒のため）

### 3.5 動作
実際に動作させてみました。
動画の貼り方がわからないため載せられないのが残念ですが、画像だけでも貼っておきます。
![動作.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782242/51344584-5b95-7b20-2ec1-cd23b41eebd9.png)

左にあるのがLCD、右にあるのがGPSになります。
いい感じに表示できています。

# 4. 最後に
今回は初めてGPSデバイスを触ってみました。電源を入れるとデフォルトの設定で勝手にGPSがデータを送信し始めるので、特に初期化する必要もなく簡単に扱うことができました。現状、制限事項がいくつかあるためゆくゆくは対応していきたいと考えています。