ソロでたのしむ

キャンプ、電子工作、DIY、乗り物などの趣味を紹介

車の天井GPSモニター作成編~16x2LCDとパラレル通信するArduino回路とスケッチ

LCD1602でGPSモニター自作

Arduinoを使った自作GPS方位計を車に装着したことを、別の記事で紹介しました。

solocamptouring.hatenablog.com

今回は、その制作内容を紹介します。スケッチ(プログラム)も記事の最後に載せておきます。

 

使用するモジュールなど

Arduino

Arduino本体、いろいろ種類がありますが私はunoとnanoをよく使います。

どちらも同じ使い勝手です。このGPSモニターにはnanoの互換機を使っています。

LCDモニター

1602と2004 LCDモニター

 

写真で上のLCDが、横16x縦2文字を表示するもの(1602)、
下のLCDが、横20x縦4文字(2004)です。

配線はどちらも同じなので、表示させる文字数に応じて使い分けます。

今回は、1602を使って、

  • 時刻
  • 高度
  • 速度
  • 方位

を表示します。

GPSセンサーモジュール

今回のメイン部品は、人工衛星から様々な情報をいただけるGPSセンサーです。アンテナ一体や別体などいろいろなものがありますが、どれも使い方はほぼ同じです。今回は、約1,000円で入手したアンテナ別体のものを使いました。

f:id:solocamptouring:20171218162800j:plain

回路図

車の天井GPSモニター作成編~Arduinoとパラレル通信する回路図とスケッチ

回路図は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に送られてきます。

次回の電源投入時からは、前回の位置情報を記憶しているので、すぐに自位置特定して起動します。

TinyGPS++を使用して、正確な時間、高度、速度、進行方向を、LCDディスプレイに表示

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(); 
} // end setup
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");
     }   
  }
}