PSoC5lpでGPSモジュール使ったロガーを作った

# はじめに
車で移動したときのログがとれたら面白いなと思ってマイコンとGPSを組み合わせてロガーを作りました。
まあなんか躓いたところとか、何を使ってどうしたかとか、どうしてそうしたかとか書いていきます。

## やったこと
PSoC5LPとGPSモジュールでロガーを作成したときのメモ書きになります。今回書くことは以下の3つです。

 - GPSモジュールから送信されるデータをパースする
 - SDカードへ書き込むこみ保存する  
 - OLEDに表示する

## 使用したもの

 - [PSoC5LP Prototyping Kit](http://akizukidenshi.com/catalog/g/gM-09432/)
 - [GPSモジュール](http://akizukidenshi.com/catalog/g/gM-12905/)
 - [128×64 OLED LCDディスプレイ](https://www.amazon.co.jp/HiLetgo-128%C3%9764-LCD%E3%83%87%E3%82%A3%E3%82%B9%E3%83%97%E3%83%AC%E3%82%A4SSD1306%E6%B6%B2%E6%99%B6-MSP430-Arduino%E3%81%AB%E5%AF%BE%E5%BF%9C/dp/B072QYY1S4)
 - マイクロSD

だいたい秋月電子で手に入ります。

# 概略図
最終的にはきれいな箱に入れたいのですがとりあえず動くものを作るということで、ブレッドボードで作っていきます。

![logger.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147601/0c1326b0-fab4-2a95-885b-1871e82f9c11.png)

全体の構成として上の図のようになります。
これをもとにブレッドボードに配線していきます。
大きい液晶や6軸センサーは今回は接続してないので関係ないです。

![IMG_20190620_095732_HDR.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147601/9dcdeaa6-e732-5f0b-97a3-cb3174ac0ad6.jpeg)

電源電圧はSDカードを使うので3.3Vです。USBUART変換がUSBから3.3Vを取り出すのにちょうどよかったので使っています。
PSoCはピンアサインを自由に設定できるので部品の配置が柔軟になるのがいいですね。

PSoCのトップデザインはこんな感じです。
![スクリーンショット 2019-06-08 19.11.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147601/2f1f5bce-6a15-f219-3841-7bb9e8f044f4.png)

左のI2CはOLED用、真ん中のUARTはGPSの受信用、右のSPIはSDカードの書き込み用です。
実際にはデバッグ用にUSBUARTも追加しています。

# GPSモジュールの読み取り
## とりあえず読んでみる
GPSモジュールの動作確認も含めてPC上でGPSのデータを表示します。
GPSモジュールのTXとRXをPSoCにつなぎます。そして受け取ったデータをそのままUSBUARTでPCに流します。

![スクリーンショット 2019-06-17 08.59.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147601/99576088-537f-e70e-227e-93ce3ba81f56.png)

NMEAフォーマットのデータが1秒毎に送られてくることを確認できたらオッケーです。

## ディスプレイに表示するためにパースする
ログとして保存するならばNMEAフォーマットのままSDカードに保存すればいいのですが、ディスプレイに表示するためには、見やすいようにNMEAフォーマットから欲しい情報を取り出さないといけません。そこでArduino用に書かれたMicroNMEAというライブラリを使用します。
>https://github.com/stevemarple/MicroNMEA

MicroNMEAはNMEAフォーマットのコンパクトなパーサです。Arduino用に書かれていると言っても実態はC++のコードなので移植は可能です。今回はちょっとだけPSoC用に書き換えてこのライブラリを使用します。
簡単にArduinoのスケッチを読むと`MicroNMEA.cpp`と`MicroNMEA.h`を追加すれば使えそうです。

手順としては以下になります。

 1. プロジェクトにMicroNMEAのライブラリを追加
 2. PSoC CreatorでC++をコンパイルできるようにする
 3. ライブラリを書き換え

まずPSoCのプロジェクトにライブラリを追加します。
![スクリーンショット 2019-06-17 09.54.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147601/ed47c881-cac2-9621-13bf-1735f55f68be.png)

Projectを開き上の画像のようにWorkspace Explorerの中のHeader Filesという項目で右クリック → Add → Existing Item...を選択します。そして`MicroNMEA.h`を追加します。
同じようにしてSouce Filesに`MicroNMEA.cpp`を追加します。
![スクリーンショット 2019-06-17 10.02.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147601/b733a803-c208-bfaf-45e2-1509d2381e02.png)
成功すれば上の画像のようになります。このとき`MicroNMEA.cpp`のプロパティを開いてFile Typeが上の画像のように**OTHES**になっていたら、**SOURCE_C**に変更してください。私はこれに気づかず1日溶かしましたorz

次に、C++をコンパイルするために一工夫

`main.c`を`main.cpp`に変更します。そして`#include <project.h>`を`extern "C"`で囲います。
具体的には`main.cpp`の先頭を以下のように書き換えます。

```c
#ifdef __cplusplus
extern "C" {
#endif
#include <project.h>
#ifdef __cplusplus
}
#endif
```
これでPSoCでC++が扱えるようになります。

最後にライブラリの書き換えを行います。
`MicroNMEA.hの`12行目の`#include <Arduino.h>`と33行目の`static Stream &sendSentence(Stream &s, const char *sentence);`をコメントアウトします。
`MicroNMEA.h`の`#include <project.h>`を追記します。
`MicroNMEA.cpp`の156行目からの`#ifndef MICRONMEA_DEBUG`から`#endif`までをコメントアウトします。

これでコンパイルできるようになります。

ここまでくればもう一息です。
MicroNMEAのサンプルと同じように、GPSモジュールから流れてくるデータを`nmea.process`に流し込めばパースされた情報を読むことができるようになります。

簡単なコードになります。

```c
char uart_buffer[100];
char gps_buffer[100];
MicroNMEA nmea(gps_buffer, sizeof(gps_buffer));

for(;;){
    if(g_ppsFlag){ //1秒毎にUSBUARTで送信
        sprintf(uart_buffer, "%02d:%02d:%02d\n", ((int)nmea.getHour(), (int)nmea.getMinute(),(int)nmea.getSecond());
        USBUART_1_PutString(uart_buffer);            
        sprintf(uart_buffer, "Lat:%ld\nLng:%ld\n", nmea.getLatitude(), nmea.getLongitude());
        USBUART_1_PutString(uart_buffer);
    }

    if(UART_GPS_GetRxBufferSize()){
        char word;
        word = UART_GPS_GetChar();
        nmea.process(word);
    }
}
```

# 表示機の実装
以前に自分が書いたQiitaの記事を見ながら実装しました。
[PSoC5でI2C極小OLED、SSD1306を使う](https://qiita.com/ringo156/items/db147f18bcdbb6d78f34)

![IMG_20190626_125939_HDR.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147601/bec8d72f-b2be-0315-cb95-c491a92509f0.jpeg)


表示したのは時刻、座標、高度と速度です。

# SDカードへの書き込みの実装
ChaNさんのFatfsをPSoC用に書き換えたやつを使用しました。
>https://github.com/hackingchips/PSoC_FatFs

流れてくるデータをそのままcsvに保存しています。

# 完成したのでドライブした
車のダッシュボードに取り付けてドライブしました。
![gpsLogger](https://pbs.twimg.com/media/D8BuTYUVsAAGmMo.jpg)
香川から高知まで32号線を走りました。
SDカードに保存されたデータをu-bloxが配布しているu-centerというソフトウェアに入れるとログデータを再生することができます。
これは32号線の高度データをグラフにしたものです。途切れている部分はトンネル内だと思うので、だいたい正確に取得できてると思います。
![altitudeGraf](https://pbs.twimg.com/media/D8Eaa8FUcAIS5GQ.png:large)

# 終わりに
PSoC5lpとGPSモジュールを使ってロガーを作ることができました。その過程でPSoCでライブラリなど限定的ではありますがC++をコンパイルできるようにしました。今後は基板を作ったり、他にもセンサーを乗せるなど試みようと思います。

# 参考
 - [GPSのNMEAフォーマット](https://www.hiramine.com/physicalcomputing/general/gps_nmeaformat.html)
 - [えるむ by ChaN](http://elm-chan.org/index_j.html)
 - [PSoC で C++ を使う](http://d.hatena.ne.jp/hijouguchi/20161123/1479906619)
 - [Using C++ With PSoC Creator](https://blog.mbedded.ninja/programming/microcontrollers/psoc/using-cplusplus-with-psoc-creator/)