なんでも作っちゃう、かも。

Arduino/Make/フィジカルコンピューティング/電子工作あたりで活動しています。スタバの空きカップを使ったスタバカップアンプなど製作。最近はもっぱらArduinoと3Dプリンタの自作に興味があります。

Arduinoで遊ぼう - GPSデータをSDカードに保存する

Posted by arms22 on 2010年04月27日 6  0

Google Earthサンプル

GPSモジュールとSDカードを組み合わせてGPSロガーを作ったよ。SDカードに保存したGPSデータをこんな風にGoogle EarthやGoogle Mapsで表示すると楽しい。

ピンクのラインがこの日、僕が移動した跡だ。最寄り駅から最近良く通う京都のクライミングジムまでの道のりを表している。1秒間隔でGPSデータを保存していたので、ちょっとした寄り道まで正確に記録されていた。あまりにも正確だったのすべてのデータを公開するのはやめた。公開するとあんな所やそんな所に寄り道してることがばれちゃうからね!


回路図



GPSロガー回路図

GPSモジュールとSDカードとの通信ラインには抵抗による分圧回路が入っている。5V動作のArduinoと接続する時にはこの抵抗が必要だけど、3.3V動作のArduinoと接続するときは省略しても良い。LEDはデバッグ用なので省略しても良い。


ライブラリ


SDカードへの書き込みにFatFsライブラリ、GPSモジュールとの通信にNewSoftSerialライブラリを使います。次のURLからライブラリをダウンロードしライブラリフォルダ(OSXの場合 ~/Documents/Arduino/libraries、Windowsの場合 ¥My Documents¥Arduino¥libraries)にコピーしてください。

FatFs
http://arms22.googlecode.com/files/FatFs-003.zip

NewSoftSerial | Arduiniana
http://arduiniana.org/libraries/newsoftserial/


スケッチ


GPSデータのファイルへの書き込みは1バイトづつ行わず、一度バッファにためてからいっきに書き込んでいる。gps_fetchでバッファにGPSデータをためて、gps_writeDataでファイルへ書き込む。

※GPSモジュールの通信レートは 9600bps、通信間隔は1秒、情報の種類はGGA+RMCにあらかじめ設定しておく。詳しくはこちらのスケッチを参照。

#include <FatFs.h>
#include <NewSoftSerial.h>

// GPS制御端子
const int gpsRxPin = 2;
const int gpsTxPin = 4;
const int gpsPowerPin = 8;

// LED端子
const int ledRedPin = 5;
const int ledGrnPin = 6;

// GPS通信
NewSoftSerial gpsPort(gpsRxPin, gpsTxPin);

// GPS受信データ
uint8_t fetchDataLength;
char fetchData[200];

void setup()
{
  delay(5000);

  pinMode(ledRedPin, OUTPUT);
  pinMode(ledGrnPin, OUTPUT);

  pinMode(gpsPowerPin, OUTPUT);
  digitalWrite(gpsPowerPin, HIGH);

  // ソフトウェアシリアルを初期化
  gpsPort.begin(9600);

  // FATファイルシステム初期化
  if( FatFs.initialize() ){
    // ログ保存用のファイルを作成する
    FatFs.createFile("gps.log");
  }
  else{
    digitalWrite(ledRedPin, HIGH);
    while(1);
  }
}

void loop()
{
  // GPSデータ受信
  if(gps_fetch()){
    digitalWrite(ledGrnPin, HIGH);
    // GPSデータ書き込み
    gps_writeData();
    digitalWrite(ledGrnPin, LOW);
  }
}

bool gps_fetch(void)
{
  if( gpsPort.available() ){
    unsigned long last_time = millis();
    uint8_t preamble = 0;
    uint8_t len = 0;
    fetchDataLength = 0;
    do {
      while( gpsPort.available() ){
        char c = gpsPort.read();
        if( c == '$' ){
          preamble++;
        } 
        if( preamble ){
          if( len < sizeof(fetchData) ){
            fetchData[len++] = c;
          }
          if( c == '\n'){
            fetchDataLength = len;
          }
        }
        last_time = millis();
      }
      delay(1);
    }
    while( millis() - last_time < 10 );
    return fetchDataLength > 0;
  }
  return false;
}

void gps_writeData(void)
{
  File file;
  file.open("gps.log");
  file.seekToEnd();
  file.write((const uint8_t *)fetchData, fetchDataLength);
  file.close();
}



GPSデータの変換


Google EarthやGoogle MapsにGPSデータを表示するにはGPSデータをKML形式に変換する必要がある。変換にはHoudahGPSというソフトを使った。シンプルなUIで使いやすい。

HoudahGPSスクリーンショット

変換の仕方
  • SourceにFileを選ぶ
  • FormatはNMEAを選択する
    GPSモジュールから送られてくるデータはNMEA形式。
    GPSデータを保存したテキストファイルの拡張子は .nmea に変更しておく。
  • DestinationにKMLを選ぶ
  • 左上のConvertボタンを押す
  • 保存先を指定し、OKボタンを押す

Houdah Software - HoudahGPS 4.0
http://www.houdah.com/houdahGPS/


Google Earth、Google Mapsに表示する


Google EarthにGPSデータを表示させるのは簡単。Google Earthのメニューからファイル、開くでKMLファイルを選ぶだけ。

Google MapsにGPSデータを表示させるのは少々面倒だ。一度、HTTPサーバにKMLファイルをアップロードし、そのファイルのURLをGoogle Mapsの検索窓に入力して"地図を検索"ボタンを押す必要がある。サンプルをアップロードしておいたので、次のURLをコピーしGoogle Mapsで検索してみてほしい。
http://arms22.web.fc2.com/geotagging_sample.kmz
KMLファイルのサイズが大きくなりすぎた場合、Google EarthでKMZファイルで保存しなおすとデータが圧縮される。


Arduinoで遊ぼう - GPSを使った高精度な時計
http://arms22.blog91.fc2.com/blog-entry-313.html

Arduinoで遊ぼう - GPSで現在位置を取得する
http://arms22.blog91.fc2.com/blog-entry-299.html

GPSデータをGoogle Maps/Earthで可視化する
http://bg66.soc.i.kyoto-u.ac.jp/forestgps/gpsdiary/archives/2008/05/gpsgoogle_mapsearth.html

HoudahGPS:GPSトラックログのファイル形式を変換
http://geolife.style.coocan.jp/blog/?p=264

GPS付きArduinoカメラ(3)

Posted by arms22 on 2010年04月01日 5  0

cupcake-1.jpg cupcake-2.jpg

cupcake-3.jpg cupcake-4.jpg

Arduinoカメラ用のスケッチを作成して写真を撮ってみました。画像はあまり綺麗ではありませんが、まぁまぁよく撮れています。撮った写真は家に帰ってパソコンにSDカードを繋ぐまで確認できませんが、帰ってからの楽しみが増えたと考えればいいよね。



スケッチにちょこっと手を入れてインターバル撮影もできるようにしました。会社の窓から撮影した写真をiMovieに取り込んで動画にしました。iMovieがいけてなくて写真1枚あたりの表示時間を0.1秒以下にできなくて、ちょっとのんびりした映像になっています。

Arduinoカメラ用のスケッチは次のURLからダウンロードできます。続きを読むにスケッチの全文を掲載しています。興味がある人はどうぞ。

arduino_digicam
http://arms22.googlecode.com/files/arduino_digicam-001.zip

スケッチにはまだGPSの制御を入れていません。また何らかの原因で511枚以上の写真を撮ることができません。FATの制限なのか、使っているFATライブラリのバグか制限か解析中です。それと内蔵RC発信器を使用している為、カメラモジュールとの通信速度が 38400bps 以上に上げれません。38400bps 以上に上げると通信エラーになります。外付けのクリスタルを使えば直ると思う。部品代をケチると良いことないなぁ。

次にやること

  • GPS制御の処理を入れる
  • FATの問題解析
  • クリスタルを実装する
  • 省電力制御の処理を入れる
  • バッテリー電圧の監視処理を入れる


GPS付きArduinoカメラ(2)
http://arms22.blog91.fc2.com/blog-entry-314.html

GPS付きArduinoカメラ
http://arms22.blog91.fc2.com/blog-entry-311.html

Arduino camera and geotagger
http://jarv.org/sdcam.shtml



GPS付きArduinoカメラ(2)

Posted by arms22 on 2010年03月14日 3  0

arduino_camera_case.jpg
スタイリングワックスの空き箱でArduinoカメラのケースを作った。左側の青マルは電源オン/オフ兼用シャッタースイッチ、右側のニョキっと飛び出した部分はカメラのレンズ、上側の丸の部分からはGPSのアンテナが見えている。

arduino_camera_case_inside.jpg
箱の内側に貼付けた1mmの厚紙で箱の強度を上げている。GPS、カメラモジュール、シャッタースイッチは両面テープで固定し、基板は中に入れるだけという超テキトー仕上げ。


最近は作品をケースに入れて仕上げることを心がけてきたけど、これからは壊れにくい物の作り方も考えて行きたいと思う。基板に半田付けしたワイヤが根元から折れては困るからね。これはコネクタを使って部品同士を繋げるようにすれば大丈夫だと思う。壊れにくい物作りのノウハウみたいなことがまとめて書かれた本とかWEBページないかな?


GPS付きArduinoカメラ
http://arms22.blog91.fc2.com/blog-entry-311.html



圧着ペンチ買わないと!

エンジニア 精密圧着ペンチ PA-20
エンジニア
売り上げランキング: 1520


Arduinoで遊ぼう - GPSを使った高精度な時計

Posted by arms22 on 2010年03月13日 12  0

Arduino+GPS時計
GPS衛星から発信される信号には、衛星に搭載された原子時計の時刻情報が入っている。GPS受信機はこの時刻情報をもとにGPS受信機に搭載されている時計の時刻を校正することで、高精度な時刻情報を得ている。この時刻情報を使って高精度なGPS時計を作った。

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


Arduinoと接続する



Arduino+GPS時計の回路図

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

Arduino+GPS時計
バックライト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)
Massimo Banzi
オライリージャパン
売り上げランキング: 3176




GPS付きArduinoカメラ

Posted by arms22 on 2010年03月07日 0  0

GPSロガーを作るつもりでしたが、GPS付きカメラを作ることになりました。カメラ付きGPSロガーともいう。。

arduino_camera_shield.jpg
左からリチウムポリマーシールド、自作Arduino(Arduino Pro互換機)、SDカード+GPS+カメラシールド。カメラとGPSはまだ半田付けしていませんが、ハードウェアはほぼ完成。

arduino_camera_stacked.jpg
こんな感じでシールドを重ねます。60x60x60mmの立方体紙ケースに収納予定。


主な仕様はこんな感じで。

  • マイコン:Arduino Pro 3.3V 8MHz 328互換
  • カメラ:JPEGカラーカメラC328
  • GPS:LS20031
  • 電源:リチウムポリマーバッテリー 3.7V 1000mA
  • メディア:SDカード
  • ディスプレイ:なし



Arduino camera and geotagger
http://jarv.org/sdcam.shtml

Arduinoで遊ぼう - GPSで現在位置を取得する

Posted by arms22 on 2010年02月04日 18  0

ls20031_w_arduino.jpg

SparkFun Electronicsの32 Channel LS20031 GPS 5Hz Receiverはアンテナ内蔵型の32チャンネルGPSモジュールで秒間最大5回、位置情報を出力する。消費電流が3.3V動作時に41mAと少なくバッテリー動作に最適のGPSモジュールだ。サイズも30x30mmとかなり小さい。

このモジュールの仕様は次の通り。

  • MediaTek MT3318チップ搭載
  • シリアルインターフェース
  • 32チャンネル対応
  • 秒間最大5回更新
  • ホットスタート2秒
  • コールドスタート32秒
  • 動作電圧3V~4.2V、消費電流41mA
  • 外形30x30mm

今回、このGPSモジュールから送られてくる位置情報をArduino経由して、パソコンに取り込んでみるよ。

※LS20031はスイッチサイエンスで取り寄せてもらいました。入荷までに少し時間がかかるけど、送料が気になる人は取り寄せてもらうといいよ。

LS20031のピンアサイン


LS20031ピン配置
このGPSモジュールはワイヤが接続されていませんが、パッドの間隔が2.54mmなので十分手で半田付けできます。

Arduinoに接続する


LS20031とArduino接続実体配線図

LS20031とArduino接続回路図

GPSモジュールとArduinoは次のように接続する。
3.3V --> VCC端子
2番 <-- TX端子
3番 --> RX端子
GND --> GND端子
例によって5V動作のArduinoと接続する時は、3番 --> RX端子の間に抵抗(R1=1.8KΩ、R2=3.3KΩ)を入れて接続する。

ライブラリをインストールする


GPSモジュールとの通信にはソフトウェアシリアルを利用する。その為、次のURLからソフトウェアシリアルライブラリをダウンロードしてください。Arduinoのハードウェアシリアル(0番、1番)はパソコンとの通信に使用する。

Arduiniana - NewSoftSerial
http://arduiniana.org/libraries/newsoftserial/

ダウンロードして解凍したフォルダを~/Documents/Arduino/librariesフォルダにコピーしてください。librariesフォルダがない場合は新しく作成してください。

サンプルスケッチ


#include <NewSoftSerial.h>
#include <ctype.h>

NewSoftSerial gps(2,3);

void setup()
{
  Serial.begin(9600);

  delay(2000);

  auto_detect_baud_rate();

  send_pmtk_packet("PMTK220,1000");
  send_pmtk_packet("PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0");
  send_pmtk_packet("PMTK251,9600");

  auto_detect_baud_rate();
}

void loop()
{
  if(gps.available()){
    Serial.print((char)gps.read());
  }
}

void auto_detect_baud_rate(void)
{
  const unsigned int bauds[] = {
    57600, 38400, 28800, 14400, 9600, 4800 };

  Serial.print("auto detect... ");

  for(int i=0; i<(sizeof(bauds)/sizeof(bauds[0]));i++){
    int p = 0;
    int r = 0;
    gps.begin(bauds[i]);
    gps.flush();
    do{
      if(gps.available()){
        if(isprint(gps.read())){
          p++;
        }
        r++;
      }
    }
    while(r < 20);
    if(p > 15){
      Serial.print(bauds[i]);
      Serial.println(" ok");
      return;
    }
    delay(100);
  }

  Serial.println("fail");
  while(1);
}

void send_pmtk_packet(char *p)
{
  uint8_t checksum = 0;
  gps.print('$');
  do {
    char c = *p++;
    if(c){
      checksum ^= (uint8_t)c;
      gps.print(c);
    }
    else{
      break;
    }
  }
  while(1);
  gps.print('*');
  gps.println(checksum,HEX);
}



setup()でGPSモジュールにいくつかのコマンドを送信します。
位置情報の出力間隔をミリ秒で指定します。
PMTK220,1000

出力する位置情報の種類を設定します。RMC(Recommended Minimum Specific GNSS Data)とGGA(Global Positioning System Fix Data)。
PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

ボーレートを設定します。
PMTK251,9600

※注意※
このスケッチではgpsとのシリアル通信のボーレートを自動検出しています。このGPSモジュールのデフォルトのボーレートは9600bpsとデーターシートに書かれていますが、実際には57600bpsでした。他にも38400bpsだったりすることもあるみたいなので、自動検出できるようにしています。時々、間違ったボーレートにしてしまうので、予めボーレートが分かっている場合は、自動検出を使わず、直接ボーレートを指定してください。

loop()でgpsが出力したデータをパソコン側に送信します。シリアルモニタを開くと次のような文字列が送られてきます。これらの文字列はNMEA-0186フォーマットと呼ばれています。カンマで区切られた数値が測位時刻、経度、緯度、対地速度、進行方向などの情報です。詳しくは下記、URLを参照してください。

NMEA-0183フォーマット
http://bg66.soc.i.kyoto-u.ac.jp/forestgps/nmea.html

$GPRMC,145059.000,V,3445.7660,N,13531.3476,E,0.00,0.00,030210,,,N*78
$GPGGA,145100.000,3445.7663,N,13531.3474,E,0,1,,41.5,M,34.3,M,,*74
$GPRMC,145100.000,V,3445.7663,N,13531.3474,E,0.00,0.00,030210,,,N*74
$GPGGA,145101.000,3445.7655,N,13531.3480,E,0,1,,41.5,M,34.3,M,,*7B
$GPRMC,145101.000,V,3445.7655,N,13531.3480,E,0.00,0.00,030210,,,N*7B
$GPGGA,145102.000,3445.7656,N,13531.3479,E,0,1,,41.5,M,34.3,M,,*7D
$GPRMC,145102.000,V,3445.7656,N,13531.3479,E,0.00,0.00,030210,,,N*7D
$GPGGA,145103.000,3445.7653,N,13531.3481,E,0,1,,41.5,M,34.3,M,,*7E
$GPRMC,145103.000,V,3445.7653,N,13531.3481,E,0.00,0.00,030210,,,N*7E
$GPGGA,145104.000,3445.7660,N,13531.3476,E,0,1,,41.5,M,34.3,M,,*71
この文字列をGoogle Mapコンバータに入力するとGoogle Map上にその位置が表示されるよ。

GPS NMEA data to Google Map converter
http://www.gonmad.co.uk/nmea.php

電源投入直後、GPSモジュールから有効な位置情報が送られてくるまでに30秒以上かかります。空が見えるベランダにモジュールを出してしばらく待ちましょう。モジュールが衛星を補足し、有効な位置情報を送りだすとモジュール上のLEDが1秒間隔で点滅します。



SparkFun Electronics - 32 Channel LS20031 GPS 5Hz Receiver
http://www.sparkfun.com/commerce/product_info.php?products_id=8975

Leadtek NMEA Protocol Manual for MTK
ftp://ftp.leadtek.com.tw/gps/9023/LeadtekNMEAProtocolManualforMTKV1.0.pdf



Arduinoをはじめようキット
スイッチサイエンス
売り上げランキング: 983




該当の記事は見つかりませんでした。