
Arduinoを使った自作GPS方位計を車に装着したことを、別の記事で紹介しました。
solocamptouring.hatenablog.com
今回は、その制作内容を紹介します。スケッチ(プログラム)も記事の最後に載せておきます。
使用するモジュールなど
Arduino
Arduino本体、いろいろ種類がありますが私はunoとnanoをよく使います。
どちらも同じ使い勝手です。このGPSモニターにはnanoの互換機を使っています。
LCDモニター

写真で上のLCDが、横16x縦2文字を表示するもの(1602)、
下のLCDが、横20x縦4文字(2004)です。
配線はどちらも同じなので、表示させる文字数に応じて使い分けます。
今回は、1602を使って、
を表示します。
GPSセンサーモジュール
今回のメイン部品は、人工衛星から様々な情報をいただけるGPSセンサーです。アンテナ一体や別体などいろいろなものがありますが、どれも使い方はほぼ同じです。今回は、約1,000円で入手したアンテナ別体のものを使いました。

回路図

回路図はFritzingで作成しています。
写この記事で使っている16x2LCDモジュールは、I2C通信を使えば、少ない電線でArduinoと接続することができます。
今回は、あえてパラレル通信で、多くの電線を使って接続しています。LCDのピンについて、簡単に紹介します。
- D0~D7;実際にデータを送受信する。今回の通信レベルならD4~D7の4本だけでも可能
- RS;レジスターセレクト。Arduinoに接続
- R/W;送受信の切り替え。今回は一方通行なので、グランドに接続
- E;データ取り込みの信号。Arduinoに接続
- VO;コントラスト調整。10KΩの可変抵抗に接続
- VDD;+(5V)電源
- VSS;グランド
- A;バックライト(LED)電源。220Ωの抵抗を使用
- K;バックライト(LED)のグランド
GPSユニットは、回路図と実際に使っているものが違いますが、接続は一緒です。
最初、RXとTX(データの送受信)が、GPSユニットとArduino側で逆転させないといけないことに気づかずに接続してしまい、作動しない理由がわからずに悩みました。
開封後の初回使用時は、緯度経度を特定してデータを送信し始めるまで時間がかかります。私は15分くらいかかりました。
気長に待っていると、GPSユニットのLEDが点滅して、各種情報がArduinoに送られてきます。
次回の電源投入時からは、前回の位置情報を記憶しているので、すぐに自位置特定して起動します。

GPSモジュールがやっていること
GPSモジュールは、NMEAフォーマットという数列で、多くの情報を送ってきます。
モジュール自体が計算してアウトプットする情報が多いですが、こんな小さなモジュールなのに賢くて感心します。
その多くの情報の中から、私が使いたい情報は、
- 緯度経度
- 速度
- 高度
- 協定世界時(UTC)
- 進行方位
の5種類です。
TinyGPS++を使ったサンプルスケッチ
GPSモジュール用のライブラリは、tinygpsplusから入手します。
ベテランが作るともっと短く完結なスケッチにできる筈ですが、初心者なので”if---else”を多用して、動けば良し!というスケッチになっています。
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd( 12, 11, 5, 4, 3, 2 );
byte smiley[8] = {
B00100,
B01110,
B11111,
B00000,
B00100,
B01110,
B11111,
};
byte sat1[8] = {
B00110,
B01110,
B01110,
B01111,
B01110,
B01110,
B01100,
};
byte sat2[8] = {
B01110,
B00100,
B01110,
B11111,
B01110,
B00100,
B11111,
};
byte sat3[8] = {
B01100,
B01110,
B01110,
B11110,
B01110,
B01110,
B00110,
};
TinyGPSPlus gps;
SoftwareSerial gpsSerial(6, 7);
const int serialTime = 200;
void setup()
{
lcd.createChar(1, smiley);
lcd.createChar(2, sat1);
lcd.createChar(3, sat2);
lcd.createChar(4, sat3);
lcd.begin(16,2);
lcd.clear();
gpsSerial.begin(9600);
lcd.setCursor(0,0);
lcd.print(" CAPTURING ");
delay(1000);
lcd.setCursor(0,1);
lcd.print(" SATELLITES");
lcd.setCursor(12,1);
lcd.write(2);
lcd.write(3);
lcd.write(4);
delay(10000);
lcd.clear();
}
void loop()
{
int start = millis();
int now = millis();
do {
while (gpsSerial.available() > 0) {
gps.encode(gpsSerial.read());
}
now = millis();
} while ((now - start) < serialTime);
if (gps.altitude.isUpdated())
{
int h;
h = (gps.time.hour()) + 9;
if( 24 <= h ) {
h = h - 24;
}
if (h < 10) {
lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(1,0);
lcd.print(h);
} else {
lcd.setCursor(0,0);
lcd.print(h);
}
lcd.setCursor(2,0);
lcd.print(":");
int m;
m = gps.time.minute();
if (m < 10) {
lcd.setCursor(3,0);
lcd.print("0");
lcd.setCursor(4,0);
lcd.print(m);
} else {
lcd.setCursor(3,0);
lcd.print(m);
}
}
if (gps.altitude.isUpdated())
{
lcd.setCursor(7,0);
lcd.print("Alt:");
int koudo;
koudo = (int)(gps.altitude.meters());
if (koudo == 0) {
lcd.setCursor(11,0);
lcd.print("----");
} else if (koudo < 10) {
lcd.setCursor(11,0);
lcd.print(" ");
lcd.setCursor(14,0);
lcd.print(koudo);
} else if (koudo < 100) {
lcd.setCursor(11,0);
lcd.print(" ");
lcd.setCursor(13,0);
lcd.print(koudo);
} else if (koudo < 1000) {
lcd.setCursor(11,0);
lcd.print(" ");
lcd.setCursor(12,0);
lcd.print(koudo);
} else {
lcd.setCursor(11,0);
lcd.print(koudo);
}
lcd.setCursor(15,0);
lcd.print("m");
}
if (gps.speed.isUpdated())
{
int s;
s = (int)(gps.speed.kmph());
if (s == 0) {
int satV;
satV = (int)(gps.satellites.value());
if (satV < 10){
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(1,1);
lcd.print(satV);
} else {
lcd.setCursor(0,1);
lcd.print(satV);
}
lcd.setCursor(2,1);
lcd.write(2);
lcd.write(3);
lcd.write(4);
lcd.print("s ");
} else if (s < 10) {
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(2,1);
lcd.print(s);
lcd.print("Km/h");
} else if (s < 100) {
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(1,1);
lcd.print(s);
lcd.print("Km/h");
} else {
lcd.setCursor(0,1);
lcd.print(s);
lcd.print("Km/h");
}
}
if (gps.course.isUpdated())
{
if ((gps.course.deg()) == 0) {
lcd.setCursor(9,1);
lcd.print("WAITING");
}
else if ((gps.course.deg()) < 11.3) {
lcd.setCursor(9,1);
lcd.print("W--N--E");
}
else if ((gps.course.deg()) < 33.8) {
lcd.setCursor(9,1);
lcd.print("--N");
lcd.setCursor(12,1);
lcd.write(1);
lcd.setCursor(13,1);
lcd.print("--E");
}
else if ((gps.course.deg()) < 56.3) {
lcd.setCursor(9,1);
lcd.print("-N-");
lcd.setCursor(12,1);
lcd.write(1);
lcd.setCursor(13,1);
lcd.print("-E-");
}
else if ((gps.course.deg()) < 78.8) {
lcd.setCursor(9,1);
lcd.print("N--");
lcd.setCursor(12,1);
lcd.write(1);
lcd.setCursor(13,1);
lcd.print("E--");
}
else if ((gps.course.deg()) < 101.3) {
lcd.setCursor(9,1);
lcd.print("N--E--S");
}
else if ((gps.course.deg()) < 123.8) {
lcd.setCursor(9,1);
lcd.print("--E");
lcd.setCursor(12,1);
lcd.write(1);
lcd.setCursor(13,1);
lcd.print("--S");
}
else if ((gps.course.deg()) < 146.3) {
lcd.setCursor(9,1);
lcd.print("-E-");
lcd.setCursor(12,1);
lcd.write(1);
lcd.setCursor(13,1);
lcd.print("-S-");
}
else if ((gps.course.deg()) < 168.8) {
lcd.setCursor(9,1);
lcd.print("E--");
lcd.setCursor(12,1);
lcd.write(1);
lcd.setCursor(13,1);
lcd.print("S--");
}
else if ((gps.course.deg()) < 191.3) {
lcd.setCursor(9,1);
lcd.print("E--S--W");
}
else if ((gps.course.deg()) < 213.8) {
lcd.setCursor(9,1);
lcd.print("--S");
lcd.setCursor(12,1);
lcd.write(1);
lcd.setCursor(13,1);
lcd.print("--W");
}
else if ((gps.course.deg()) < 236.3) {
lcd.setCursor(9,1);
lcd.print("-S-");
lcd.setCursor(12,1);
lcd.write(1);
lcd.setCursor(13,1);
lcd.print("-W-");
}
else if ((gps.course.deg()) < 258.8) {
lcd.setCursor(9,1);
lcd.print("S--");
lcd.setCursor(12,1);
lcd.write(1);
lcd.setCursor(13,1);
lcd.print("W--");
}
else if ((gps.course.deg()) < 281.3) {
lcd.setCursor(9,1);
lcd.print("S--W--N");
}
else if ((gps.course.deg()) < 303.8) {
lcd.setCursor(9,1);
lcd.print("--W");
lcd.setCursor(12,1);
lcd.write(1);
lcd.setCursor(13,1);
lcd.print("--N");
}
else if ((gps.course.deg()) < 326.3) {
lcd.setCursor(9,1);
lcd.print("-W-");
lcd.setCursor(12,1);
lcd.write(1);
lcd.setCursor(13,1);
lcd.print("-N-");
}
else if ((gps.course.deg()) < 348.8) {
lcd.setCursor(9,1);
lcd.print("W--");
lcd.setCursor(12,1);
lcd.write(1);
lcd.setCursor(13,1);
lcd.print("N--");
}
else {
lcd.setCursor(9,1);
lcd.print("W--N--E");
}
}
}