Arduinoで遊ぼう - GPSを使った高精度な時計
Posted by arms22 on 2010年03月13日

GPS衛星から発信される信号には、衛星に搭載された原子時計の時刻情報が入っている。GPS受信機はこの時刻情報をもとにGPS受信機に搭載されている時計の時刻を校正することで、高精度な時刻情報を得ている。この時刻情報を使って高精度なGPS時計を作った。
GPS受信機をArduinoに接続し、1秒周期で送られてくる時刻情報をLCDに表示している。赤く光っている部品がGPS受信機「LS20031」。このGPS時計は電池一本で何年も動かすことはできないし、屋内ではGPS衛星からの信号を受信することもできない。GPS受信機から送られてくる時刻情報は確かに正確だが、Arduino間の通信時間やArduinoの処理時間などでLCDに表示される時間は数100ms秒遅れる。
Arduinoと接続する

キャラクタLCDとArduinoは次のように接続する。
RS→アナログ0番GPS受信機とArduinoは次のように接続する。
R/W→GND
E→アナログ1番
DB4→アナログ2番
DB5→アナログ3番
DB6→アナログ4番
DB7→アナログ5番
VCC→3.3V
RX→(未接続)
TX→デジタル2番
GND→GND

バックライトLEDのアノード端子は基板上のJ3をショートさせてVCCと接続し、カソード端子は110Ω(R9)抵抗をかいしてGNDに接続している。
ライブラリのインストール
GPS受信機からはNMEAフォーマットと呼ばれるテキスト形式のデータが送られてくる。
$GPGGA,125333.000,3444.4637,N,13532.4905,E,1,5,1.41,32.7,M,34.4,M,,*62
$GPRMC,125333.000,A,3444.4637,N,13532.4905,E,0.09,1.94,110310,,,A*63
NMEAフォーマットは人が理解するには都合が良いが、マイコンのプログラムで扱うには都合が悪い。そこでNMEAパーサー「TinyGPS」ライブラリを使ってNMEAフォーマットをプログラムで扱いやすい形に変換する。
次のURLからライブラリをダウンロードし、Arduinoのライブラリフォルダにコピーする。
TinyGPS | Arduiniana
http://arduiniana.org/libraries/tinygps/
GPS受信機との通信にソフトウェアシリアルを使うので、次のライブラリもダウンロードする。
NewSoftSerial | Arduiniana
http://arduiniana.org/libraries/newsoftserial/
サンプルスケッチ
#include <NewSoftSerial.h>
#include <TinyGPS.h>
#include <LiquidCrystal.h>
// NMEAパーサー TinyGPS
TinyGPS gps;
// ソフトウェアシリアル(RX=2, TX=3)
NewSoftSerial nss(2, 3);
// LCD(RS=14, E=15, DB4=16, DB5=17, DB6=18, DB7=19)
LiquidCrystal lcd(14, 15, 16, 17, 18, 19); // analog 0, 1, 2, 3, 4, 5
void setup()
{
// LCD初期化(16文字、2行)
lcd.begin(16,2);
// PCとのシリアル通信初期化
Serial.begin(115200);
// 最初のメッセージ表示
lcd.print("No GPS Signal.");
// ソフトウェアシリアル初期化(9600bps)
nss.begin(9600);
}
void loop()
{
int year;
byte month, day, hour, minute, second, hundredths;
bool newdata = false;
// GPS受信機から送られたデータがある間
while(nss.available()){
char c = nss.read();
// シリアルモニタに受信した文字を送る
Serial.print(c);
// encode()で1文字ずつ解析
if(gps.encode(c)){
newdata = true;
}
}
if(newdata){
// 画面をクリア
lcd.clear();
// 日付、時間を取得
gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths);
// 1行目、1文字目にカーソルを移動
lcd.setCursor(0, 0);
lcd.print(static_cast<int>(year));
lcd.print("/");
lcd.print(static_cast<int>(month));
lcd.print("/");
lcd.print(static_cast<int>(day));
// 2行目、3文字目にカーソルを移動
lcd.setCursor(2, 1);
// GPSの時間はUTC(協定世界時)なので+9時間してJSTにする
lcd.print(static_cast<int>((hour + 9) % 24));
lcd.print(":");
lcd.print(static_cast<int>(minute));
lcd.print(":");
lcd.print(static_cast<int>(second));
lcd.print(".");
lcd.print(static_cast<int>(hundredths));
}
}
Arduinoをはじめよう (Make:PROJECTS)
posted with amazlet at 11.02.04
Massimo Banzi
オライリージャパン
売り上げランキング: 3176
オライリージャパン
売り上げランキング: 3176
Ads by Google
12 Comments
LS20031の転送速度を調べたいと考えています。
転送速度を調べるため、以下のスケッチを作成しました。
#include <SoftwareSerial.h>
#include <TinyGPS.h>
// NMEAパーサー TinyGPS
TinyGPS gps;
// ソフトウェアシリアル(RX=1, TX=0)
SoftwareSerial nss(1, 0);
void setup()
{
// ソフトウェアシリアル初期化(57600bps)
nss.begin(38400);//この値を手動で変更し、書き込む
pinMode(12,OUTPUT);
}
void loop()
{
if(nss.available()){
digitalWrite (12, HIGH);
}
}
動作の概要として、
(1)シリアル通信が出来たら12番ピンにつけたLEDが点灯する
(2)上記が行われるまで、nss.begin(38400)の値を変更し、プログラムを書き換える
というものです。
ただ、転送速度を115200,57600等に変更してもLEDは点灯しませんでした。
つきましては
(1)LS20031の転送速度を調査された手順 または
(2)上記スケッチの問題点
をご回答いただければ幸いです。
開発環境は以下のとおりです
(1)IDE Ver1.0.3
(2)ARDUINO LEONARDO
(3)Mac OS Ver 10.8.2
以上、よろしくお願い致します。
転送速度を調べるため、以下のスケッチを作成しました。
#include <SoftwareSerial.h>
#include <TinyGPS.h>
// NMEAパーサー TinyGPS
TinyGPS gps;
// ソフトウェアシリアル(RX=1, TX=0)
SoftwareSerial nss(1, 0);
void setup()
{
// ソフトウェアシリアル初期化(57600bps)
nss.begin(38400);//この値を手動で変更し、書き込む
pinMode(12,OUTPUT);
}
void loop()
{
if(nss.available()){
digitalWrite (12, HIGH);
}
}
動作の概要として、
(1)シリアル通信が出来たら12番ピンにつけたLEDが点灯する
(2)上記が行われるまで、nss.begin(38400)の値を変更し、プログラムを書き換える
というものです。
ただ、転送速度を115200,57600等に変更してもLEDは点灯しませんでした。
つきましては
(1)LS20031の転送速度を調査された手順 または
(2)上記スケッチの問題点
をご回答いただければ幸いです。
開発環境は以下のとおりです
(1)IDE Ver1.0.3
(2)ARDUINO LEONARDO
(3)Mac OS Ver 10.8.2
以上、よろしくお願い致します。
[追記]
配線は
LS20031 ARDUINO
3番ピン---1番ピン
としています。
配線は
LS20031 ARDUINO
3番ピン---1番ピン
としています。
単純にボーレートが知りたい場合は、
ソフトウェアシリアルで受信したデータを、
そのままPC側に出力すれば、判断できると思います。
if(nss.available()){
Serial.write( nss.read() );
}
ソフトウェアシリアルで受信したデータを、
そのままPC側に出力すれば、判断できると思います。
if(nss.available()){
Serial.write( nss.read() );
}
お返事ありがとうございます。
LS20013を直接PCと接続したろころ、57600bpsで通信ができることを確認しました(ターミナルでGPSのデータを受信していることを確認しました)。
ただ、LEONARDOでは受信出来ないようでした。
スケッチを以下に記します。
#include <SoftwareSerial.h>
// ソフトウェアシリアル(RX=1, TX=0)
SoftwareSerial nss(1, 0);
void setup()
{
// ソフトウェアシリアル初期化(57600bps)
nss.begin(57600);
pinMode(12,OUTPUT);
}
void loop()
{
if(nss.available()>0){
digitalWrite (12, HIGH);
}
else{
digitalWrite (12, LOW);
}
}
シリアル通信ができている場合に12番ピンがHIGHになるようにしていますが、接続しているLEDが点灯しません。
この状態でデータの送信先をPCにつなぎ替えると正常に受信しているので、LS20031からデータの送信は行われているようです。
なお、LS20031との接続は
LS20031 ARDUINO
3番ピン---1番ピン
としています。
もし、何か思いつかれることがありましたら、お時間あるときでかまいませんので、お返事頂ければとおもいます。
LS20013を直接PCと接続したろころ、57600bpsで通信ができることを確認しました(ターミナルでGPSのデータを受信していることを確認しました)。
ただ、LEONARDOでは受信出来ないようでした。
スケッチを以下に記します。
#include <SoftwareSerial.h>
// ソフトウェアシリアル(RX=1, TX=0)
SoftwareSerial nss(1, 0);
void setup()
{
// ソフトウェアシリアル初期化(57600bps)
nss.begin(57600);
pinMode(12,OUTPUT);
}
void loop()
{
if(nss.available()>0){
digitalWrite (12, HIGH);
}
else{
digitalWrite (12, LOW);
}
}
シリアル通信ができている場合に12番ピンがHIGHになるようにしていますが、接続しているLEDが点灯しません。
この状態でデータの送信先をPCにつなぎ替えると正常に受信しているので、LS20031からデータの送信は行われているようです。
なお、LS20031との接続は
LS20031 ARDUINO
3番ピン---1番ピン
としています。
もし、何か思いつかれることがありましたら、お時間あるときでかまいませんので、お返事頂ければとおもいます。
Leonardoの場合、ソフトウェアシリアルの受信ポートに使えるポートに制限があります。下記のポートを受信ポートに使用してみてください。
RX: 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI).
http://arduino.cc/en/Reference/SoftwareSerial
RX: 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI).
http://arduino.cc/en/Reference/SoftwareSerial
何度も返信頂き、ありがとうございます。
上記返信先のリンクにありますサンプルを打ち込みましたところ、無事に動作しました。
休日に夜遅くまで対応頂き、ありがとうございました。
上記返信先のリンクにありますサンプルを打ち込みましたところ、無事に動作しました。
休日に夜遅くまで対応頂き、ありがとうございました。
TinyGPSのencodeに関して質問をさせて頂きたいと思います。
LeonardoとLS20031をソフトウェアシリアルで接続し、TinyGPSで時刻を抽出する様にしたいと考えています。
現在、LeonardoとLS20031の接続は9600bpsで接続できていることを確認している(LS20031からLeonardoへ送信される内容と、Leonardoからハードウェアシリアルで出力される内容が一致している)のですが、TinyGPSのencode関数でNGと判断されてしまいます。
そこで
(1)導入の際、ソフトウェアに対して設定の変更等実施されたでしょうか
(2)以下のスケッチで相違点等あればご指摘いただけないでしょうか
本来なら作者のHPで質問すれば良いのですが、英語が苦手であり、また、使用された実績があるため、こちらで質問させて頂きました。
お手数をおかけしますが、お時間ある時にご回答いただければと思います。
スケッチを以下に記します。
#include <SoftwareSerial.h>
#include <TimerOne.h>
#include <TinyGPS.h>
// ソフトウェアシリアル(RX=10, TX=11)
TinyGPS gps;
SoftwareSerial ss(10, 11);
void setup() {
Serial.begin(9600);
ss.begin(9600);
pinMode(13,OUTPUT);
digitalWrite(13,LOW);
}
void loop() {
if (ss.available()) {
char c = ss.read();
Serial.print(c);
if(gps.encode(c)){
digitalWrite(13,HIGH);//テスト用
}
}
}
また、LE20031からの出力を以下に記します。
$GPRMC,055003.399,V,,,,,0.00,107.33,160213,,,N*4C
$GPGGA,055003.599,,,,,0,0,,,M,,M,,*4E
$GPRMC,055003.599,V,,,,,0.00,107.33,160213,,,N*4A
$GPGGA,055003.799,,,,,0,0,,,M,,M,,*4C
$GPRMC,055003.799,V,,,,,0.00,107.33,160213,,,N*48
$GPGGA,055003.999,,,,,0,0,,,M,,M,,*42
LeonardoとLS20031をソフトウェアシリアルで接続し、TinyGPSで時刻を抽出する様にしたいと考えています。
現在、LeonardoとLS20031の接続は9600bpsで接続できていることを確認している(LS20031からLeonardoへ送信される内容と、Leonardoからハードウェアシリアルで出力される内容が一致している)のですが、TinyGPSのencode関数でNGと判断されてしまいます。
そこで
(1)導入の際、ソフトウェアに対して設定の変更等実施されたでしょうか
(2)以下のスケッチで相違点等あればご指摘いただけないでしょうか
本来なら作者のHPで質問すれば良いのですが、英語が苦手であり、また、使用された実績があるため、こちらで質問させて頂きました。
お手数をおかけしますが、お時間ある時にご回答いただければと思います。
スケッチを以下に記します。
#include <SoftwareSerial.h>
#include <TimerOne.h>
#include <TinyGPS.h>
// ソフトウェアシリアル(RX=10, TX=11)
TinyGPS gps;
SoftwareSerial ss(10, 11);
void setup() {
Serial.begin(9600);
ss.begin(9600);
pinMode(13,OUTPUT);
digitalWrite(13,LOW);
}
void loop() {
if (ss.available()) {
char c = ss.read();
Serial.print(c);
if(gps.encode(c)){
digitalWrite(13,HIGH);//テスト用
}
}
}
また、LE20031からの出力を以下に記します。
$GPRMC,055003.399,V,,,,,0.00,107.33,160213,,,N*4C
$GPGGA,055003.599,,,,,0,0,,,M,,M,,*4E
$GPRMC,055003.599,V,,,,,0.00,107.33,160213,,,N*4A
$GPGGA,055003.799,,,,,0,0,,,M,,M,,*4C
$GPRMC,055003.799,V,,,,,0.00,107.33,160213,,,N*48
$GPGGA,055003.999,,,,,0,0,,,M,,M,,*42
お世話になります。上記で質問させて頂いた点ですが、衛星を補足していなかったことが原因であることがわかりました。
ご迷惑をおかけしました。
ご迷惑をおかけしました。
そうですね、衛生を補足するまでNGが返ってきますね。
GPSのLEDが周期的に点滅しはじめたら、衛生を補足しているはずですよ。
GPSのLEDが周期的に点滅しはじめたら、衛生を補足しているはずですよ。
初めまして。電子工作初心者です。
接続図を見て分からないところが二点だけあります。
一点目は抵抗に関してです。
LCDの1番ピンから5番ピンに抵抗値がつながっていますが、これは何Ωの抵抗ですか?
それと、LCDからも抵抗につながっていますが、この抵抗は可変抵抗で、中間電圧を採る形の接続でしょうか?
二点目はプログラムに関してです。
同じように接続図を見ると、
LiquidCrystal lcd(14, 15, 16, 17, 18, 19);
のところは、
LiquidCrystal lcd(4, 6, 11, 12, 13, 14);
ではないでしょうか?LCDに19番ピンってありませんよね・・・?
接続図を見て分からないところが二点だけあります。
一点目は抵抗に関してです。
LCDの1番ピンから5番ピンに抵抗値がつながっていますが、これは何Ωの抵抗ですか?
それと、LCDからも抵抗につながっていますが、この抵抗は可変抵抗で、中間電圧を採る形の接続でしょうか?
二点目はプログラムに関してです。
同じように接続図を見ると、
LiquidCrystal lcd(14, 15, 16, 17, 18, 19);
のところは、
LiquidCrystal lcd(4, 6, 11, 12, 13, 14);
ではないでしょうか?LCDに19番ピンってありませんよね・・・?
連投してしまってすみません。先ほど投稿した質問文のうち、以下の部分を訂正します。
それと、LCDからも抵抗につながっていますが、この抵抗は可変抵抗で、中間電圧を採る形の接続でしょうか?
>>それと、LCDの3番ピンからも抵抗につながっていますが、この抵抗は可変抵抗で、中間電圧を採る形の接続でしょうか?
どなたか分かる方回答お願いいたします。
それと、LCDからも抵抗につながっていますが、この抵抗は可変抵抗で、中間電圧を採る形の接続でしょうか?
>>それと、LCDの3番ピンからも抵抗につながっていますが、この抵抗は可変抵抗で、中間電圧を採る形の接続でしょうか?
どなたか分かる方回答お願いいたします。
Leave a reply
該当の記事は見つかりませんでした。