7.GPSの利用 (2021.12.11)

Arduinoを使ってGPSの実験をします。GPSは将来的に実験車の自動走行等に利用できるため、ここで基礎的な技術を押さえておきます。使用したGPSはNEO-6Mと呼ばれるGPSモジュールを搭載したボードで、amazonでは1000円程で購入できます。500円程から多くの商品がありますが、粗悪品も多く出回っているようで当たり外れが大きく、私が最初に入手した製品も不良品でした。2回目は動作しましたが感度が十分高いとは言えず、室内では窓際や屋外でないとなかなか受信してくれません(比較対象が無いため、これで正常かもしれない)。LEDが付いていてGPSを受信すると点滅するため、動作状況は一目でわかるようになっています。

GPSの実験だけならターミナル経由でPCでモニター可能ですが、せっかくなので屋外でも情報を確認できるよう、16文字×2桁の表示ができるLCDモジュールと組み合わせることにしました。インターフェースがシリアルとパラレルの2種類あり、接続の簡略化のためシリアル(I2C)タイプの方が好都合です。今回使用するモジュールはRasPiのI2C通信でも実験したもので、OSOYOOの実験セットに入っていたものです。安いものなど複数セット品で1個当たり500円程度でamazonでも入手できるでしょう。

Arduinoとの接続は簡単で、電源は5VとGND、通信用にSDA(A4)とSCL(A5)をつなげばOKです。プログラムもライブラリを利用することで、容易に扱えるようになっています。このライブラリは標準では用意されていないため、別途インストールする必要があります。インストール方法はネットでも色々紹介されているため割愛します。

準備ができたら次のスケッチを書き込んで実行します。簡単な文字表示ですが、これを元にすれば自由に文字を表示することができるでしょう。

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,16,2);

void setup() {
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Hello, world!");
}

void loop(){
}

続いてGPSデータの取得を行います。サンプルでは簡略化のためにターミナルでのモニターとします。GPSの生データを得るもので、インクルードするライブラリは標準で用意されているものです。Arduinoとの接続はGPSのRXD(Arduino側はTX)が11ピン、TXD(Arduino側はRX)が10ピンとします。1PPSは使用しません。今回はArduino側で受信するだけなので、GPS側のRXDは接続しなくても大丈夫です。

#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX

void setup() {
// Open serial communications and wait for port to open:
Serial.begin(57600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}

Serial.println("Goodnight moon!");

// set the data rate for the SoftwareSerial port
mySerial.begin(9600);
mySerial.println("Hello, world?");
}

void loop() { // run over and over
if (mySerial.available()) {
Serial.write(mySerial.read());
}
if (Serial.available()) {
mySerial.write(Serial.read());
}
}

生データでは何だかよくわからない内容なので、これをわかりやすく整形して送るようにしたのが次のスケッチです。GPSデータはNMEAと呼ばれるフォーマットで送られてくるため、それを手軽に扱うことができるArduino用のライブラリを使用します。色々あるようですが、今回は「TinyGPS++」を利用します。サイトからライブラリのzipをダウンロードした後、IDEにインストールして使えるようにします。

#include <TinyGPS++.h>
#include <SoftwareSerial.h>

TinyGPSPlus gps;
SoftwareSerial mySerial(10, 11); // RX, TX
//TinyGPSCustom magneticVariation(gps, "GPRMC", 10);

void setup() {
// Open serial communications and wait for port to open:
Serial.begin(57600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}

Serial.println("Goodnight moon!");

// set the data rate for the SoftwareSerial port
mySerial.begin(9600);
mySerial.println("Hello, world?");
}

void loop() { // run over and over
while (mySerial.available() > 0){
char c = mySerial.read();
//Serial.print(c);
gps.encode(c);
if (gps.location.isUpdated()){
Serial.print("LAT="); Serial.println(gps.location.lat(), 6);
Serial.print("LONG="); Serial.println(gps.location.lng(), 6);
Serial.print("ALT="); Serial.println(gps.altitude.meters());
}
}
}

準備中・・・