Raspberry PiでRTKLIBとBluetoothを使ってAgriBus-NAVIにNMEAデータを流す


#全体図（仮）

![zerow-rtk (1).png](https://qiita-image-store.s3.amazonaws.com/0/181687/3b212cd8-0b37-cfa3-d13f-49e4a9de7c43.png)

#想定している利用シーン
- スマホやWiFiルータから繋げられる基地局が近く(自分が実験した限りでは2km以内)にある
- 基地局とトラクターのGPS受信機はRTKLIBでFIXできるように設定済み
ttyACM0,115200,ubxフォーマット出力されていて、RaspberrPiで使用可能なものとして扱っています
- トラクターにRaspberryPi zeroWを設置して、WiFiルータ等でネットに出られる
- RTKLIBで処理した結果をNMEAとして出力し、Bluetooth(RN-42)でAndroidに送り、AgribusNAVIで使う

#充電の都合
[（株）農業情報設計社](http://agri-info-design.com/)の提供している[AgriBus-NAVI](https://play.google.com/store/apps/details?id=com.agri_info_design.AgriBusNavi&hl=ja)はAndroidで使用可能な、トラクター農作業のGPS支援情報アプリです。
トラクターでの作業は作業速度が遅いため、どうしても長い作業時間が前提。そのため充電しながら動かしたい。

- でもAndroidってmicroUSBが１個しかない。
- USB-OTGという手もあるけど、USB供給電流が不足してシリアルUSBが不安定になったり、Androidの充電が減る速度に間に合わなかったりして色々微妙。
- rtkgps+という手もあるけれど、SNR Maskや仰角マスクが指定できなかったりして微妙。
CPUの発熱やバッテリー消費も激しくなるし、熱暴走しやすくなる点も問題。
AgribusNAVI自体もかなり重いので、輪をかけて重くなる。（最近のAndroidだとスペックも上がってるでしょうから、違うのかもしれません）

いいとこ取りでAndroidのUSBは充電専用にして、RTKLIBはRaspberryPiで動かし、GPS受信機もRaspberryPiに接続、zeroWならWiFiあるからテザリングして基地局のデータをゲット、そしてAndroidへ流すシリアルを無線化できれば・・

そうだ、Bluetoothがあるじゃないか！

#Bluetooth SPP対応モジュール
BluetoothにはSPP(Serial Port Profile)というプロファイルがあり、シリアル通信が可能。
(プロが使う測量用の機器にも、ここ数年の機材だとBluetooth SPP対応のものがあります。)
「充電の都合」にも書いたとおり、microUSBは充電専用にしておいて、BluetoothでRTKLIBが処理したGPS情報をゲットしよう！という作戦です。
#RaspberryPi zeroW
「zeroWにはbluetoothあるんだから、それ使えば？」と思われた方、スペック確認を細かくなさってますね！
結論から言えば自分なりに調べて試しましたが、いまいち安定しませんでした。
安定稼働させる方法をご存知の方、ぜひご一報お願いします。

今回はWiFiのみ使います。

##今回用意したもの
[RN-42評価モジュール](http://akizukidenshi.com/catalog/g/gK-07378/)
FTDIのシリアルUSB変換チップが乗ってるので、ドライバ入れてTeraTermなどですぐに使える。
でも電源容量が不足しているのか、FTDI経由でデータ流すと不安定になりがち。USBは初期設定専用と割り切ったほうがいいかも。

###先人がコマンドをまとめてくださっています。
[RN-42モジュールのコマンド](https://qiita.com/TakeoChan/items/a1148546d2e56b8173b8)

通信速度や名前などが変更可能。初期設定は115.2kbpsなので、後述するRTKLIBの設定と合わせること。

##RaspberryPiの設定
最低限の設定のみ。

- [WiFiの設定](https://github.com/citbrains/OpenPlatform/wiki/Raspberry-PI-3-%E3%81%AE%E8%A8%AD%E5%AE%9A#%E7%84%A1%E7%B7%9Alan%E3%81%AE%E6%8E%A5%E7%B6%9A)
AgribusNAVIの実用面を考え、トラクターに乗ったときzeroWがネットに出るために、スマホやWiFiルータも登録しておきましょう。

- [シリアル通信の設定](https://github.com/citbrains/OpenPlatform/wiki/Raspberry-PI-3-%E3%81%AE%E8%A8%AD%E5%AE%9A#%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%AB%E9%80%9A%E4%BF%A1%E3%81%AE%E8%A8%AD%E5%AE%9A)
raspi-config→Interfacing Options→Serial→No→Yesでも可能になる？（未確認）

##RN-42とRaspberryPiを接続
RN-42は秋月電子のマニュアルを参照。Raspberry PiのGPIOはググれば出てくるので省略。
最低限配線する必要があるのは、3.3V,GND,TXD,RXDのみです。

#RTKLIB

現時点での最新版は rtklib 2.4.3b29ですが、コンパイルする際にちょっとコツが必要です。

https://github.com/tomojitakasu/RTKLIB/issues/306

```bash
$ sudo apt install -y gfortrun
$ cd ~/RTKLIB/lib/iers/gcc/
$ make
$ cd ~/RTKLIB/app/
$ make
```

設定ファイルの主要部分のみ抜粋

```conf
pos1-posmode       =kinematic
pos1-elmask        =20         # (deg)
pos1-snrmask_L1    =40,40,40,40,40,40,40,40,40
pos1-exclsats      =C02
pos1-navsys        =51 #GPS+QZSS+BDS
pos2-armode        =fix-and-hold
inpstr1-type       =serial     
inpstr2-type       =tcpcli     
inpstr1-path       =ttyACM0:115200:8:n:1:off #移動局のu-blox
inpstr2-path       =[基地局のアドレス]:[ポート番号]
inpstr1-format     =ubx        
inpstr2-format     =rtcm3      
outstr1-type       =serial
outstr1-path       =ttyAMA0:19200:8:n:1:off
outstr1-format     =nmea
```

RTKLIBは設定ファイルチェックが厳しいため、バックアップを忘れずに。
elmask,snrmaskはWindows版のRTKLIBでグラフ見ながら微調整してください。

自分はTW2710+M8Tの組み合わせで使用していますが、体感的にはそれぞれ15-20,40-42の間ぐらいがFIXしやすいようです。

#Androidに接続

Androidの「設定」→bluetooth→RNBT-[MACアドレスの末端４桁]が出てくるので接続します。

##RTKLIBの動作確認
RN-42からNMEAが流れてきてるかチェック

[Serial Bluetooth Terminal](https://play.google.com/store/apps/details?id=de.kai_morich.serial_bluetooth_terminal)

![IMG_3638_01.png](https://qiita-image-store.s3.amazonaws.com/0/181687/c73b6aba-0240-1108-7607-82de999d07f3.png)


#Agribus-NAVIに接続

おつかれさまでした。

#自動起動

/home/pi/rtkrcv
/home/pi/rtk.conf
RTKLIBをmakeして出来上がったファイルを上記の場所にコピーして配置されている、という前提です。

```bash
$ sudo apt install -y screen telnet
```

```/etc/rc.local
sudo -u pi sh /home/pi/rtkrcv.sh 
```

```/home/pi/rtkrcv.sh
#!/bin/sh

cd /home/pi
screen -AmdS rtkrcv ./rtkrcv  -o ./rtk.conf -s -p 2101 -w ""
```

telnetでrtkrcvの操作が可能。

```telnet
$ telnet localhost 2101
```

パスワードはrtk.confに設定したものです。

#シャットダウン処理の問題
RaspberryPiの仕様上、シャットダウンボタンの一つも無いので、GPIOに物理的なシャットダウンボタンを付け、自前でスクリプト書いてシャットダウンさせるか、ファイルシステムの破損覚悟で電源引っこ抜くかしかありません。

- シャットダウンボタンの作成例
[ラズパイでシャットダウンボタンを付ける(ついでに起動ボタン)](https://qiita.com/clses/items/e701c1cb6490751a6040)

- 書き込み禁止
しかし次回の仕事を始める時の不安を残してしまうのは精神衛生上よくありませんし、意図しないタイミングで電源が切れる場合にはshutdownボタンは効果がありません。

###Alpine Linux
選択肢その１

FATフォーマットされているSDカードに、tar.gzを解凍するだけで使える超軽量Linuxディストリビューション。
クラウドとかDocker界隈では、容量が少なくて起動が早い特性が気に入られて人気なようです。
起動後はルートファイルシステムがtmpfsに展開されているため、電源ブッチしても大丈夫。
lbu commitを実行しない限りSDカードに変更内容を書き込まない仕様です。

一方でその軽量さを実現するためにBusyBox使われていたり、アレがないコレが無いという点もありますので一長一短。
この記事で使用しているRTKLIBはalpine-sdkを入れるだけでコンパイルできました。

##aufs
選択肢その２

対策としてSDカードをLinuxのOS上で書き込み禁止にします。

[RaspberryPi2 の SD カードを aufs と fsprotect で保護する]
(https://qiita.com/zakkied/items/c22faa3f22b4167e7024)
記事中にはありませんが、/boot/cmdline.txtに追記したfsprotectを削除すると、元の通り書き込みできるようになります。

kernelのビルドが必要なので、zeroWだと7時間くらいかかります。
そんなに待てるか！という方はpi3で行う（２０〜３０分位？）とか、Virtual Box等（i7とかなら数分）でのクロスコンパイルをおすすめします。

#kernelのバージョンを固定する
せっかく作ったkernelもupdateで消し去ってくれたりするので、バージョンを固定しておきましょう。

```sh
# apt-mark hold raspberrypi-kernel
```

#完成
下から順に12Vから5Vのレギュレータ、RaspberryPi zeroW、シリアルと5Vを引き回すだけの基盤、RN-42です。
12Vを直接RaspberryPiの5Vに入れると、電源ICから煙吹いて壊れます。（壊しました）
レギュレータは適当な7805とかでももちろんOKですが、実験してみたところ放熱板が必要な程度には発熱するので、今回はジャンク箱にあった適当なレギュレータを使いました。
また、バッテリーから直接12Vを取り出す場合、安全のためにヒューズボックスも別途必要です。

![IMG_1036_01.JPG](https://qiita-image-store.s3.amazonaws.com/0/181687/3eec95e4-7854-7469-4df9-8c79b04f8d3b.jpeg)

#忙しい人のためにイメージファイル作りました
<del>
https://drive.google.com/file/d/1XeHxPLVUDYVc8NkWpDiQIWl97ilXdE7f/view?usp=sharing</del>
GoogleDriveの容量足りなくなったので公開停止しました。

---使い方
前記のイメージファイルをダウンロードする。どうにかしてSDカードに焼いてsshでログインする。
ユーザ名pi Pass raspberryでログイン後、<del>sudo sh ./fsprotect.sh を実行。（しばらくかかります。Pi3とか使うと早いです。）
 /boot/cmdline.txtの最後尾にfsprotectを入れる。</del>
追記：スクリプト入れてたつもりが、awsインスタンスの彼方へと消えていってしまいました・・・。しばらく時間とれないので、後日組み直します。

オマケでpps（超高精度な時計）のkernelモジュールも有効化してあります。使い方はググってください。

設定ファイルなどに変更を加える場合は /boot/cmdline.txt の最後にあるfsprotectを消去してから、RaspberryPiに入れてください。
aufsを有効化するには同じ手順でfsprotectを書き込んでください。


#ESP32 M5Stack用のNTRIP clientクラス
を作って公開されている方がいます。自分の環境では１６時間程度安定して使えました。
https://twitter.com/love_richman/status/1067738209889611777

#謝辞
岩崎、奥山、小野に下読みをしていだただき、岩崎には全体図のアイディアをいただきました。この場にて感謝の意を伝えます。（敬称略）