ノートPCでPCカーナビをやっていますが、使うときのセッティングが面倒なのです。
そのため使用するのは遠出の時くらいでした。
せっかくGPSモジュールがあるのに、眠らせておくのはもったいない。
しかし使うにはPCが必要、というジレンマがありました。
そこで、日常的にナビはできなくても、最低限トラックログは記録しておきたいと思うようになり、PCが不要の単体で動くロガーを作ってみることにしました。
製作目標は毎日の通勤にもストレスなく使えることです。
記録メディアは SDカードの制御を勉強した こともあり、このカードを選びました。
また、カードへの記録はFATに対応するため、FATファイルシステムを実装します。
これは、カードをWindowsのエクスプローラなどから読めるようにするためです。
仕様は下記のようになっています。
マイコン | PIC16F877 20MHz 3.3V駆動 |
一時記憶 | 日立 HM62256LP-10(256Kbits SRAM) PICのポートに直結 |
記録メディア | SD/MMCカード 現在は松下の64MBのSDで確認済み |
ファイルシステム | FAT16 |
ファイルフォーマット | 似非NMEA $GPRMCセンテンスを加工して記録。 このセンテンスを64バイトに収めて1レコードとし、固定長で記録。 |
ファイル名 | ログ記録を開始するごとに、ルートディレクトリへ NMEA0000.LOG、NMEA0001.LOG、‥‥と連番で作成。 |
記録ポイント数 | 64MBのSDカードで約104万ポイント≒288時間≒12日間 |
電源 | 5V GPSモジュールはそのまま5Vを供給 マイコンはレギュレータで3.3Vを生成して供給 |
動作状態の表示 | ・電源LED ・センテンス受信LED ・カードアクセスLED |
圧縮や独自フォーマット化すれば記録ポイントを増やせますが、チープなマイコンでは荷が重いです。
記録したログはツールを使用して完全なNMEAフォーマットに戻します。
その後は gigo さんの汎用ログコンバータが使えます。
カードへ1バイトを送信する場合は、1ビットずつシリアルに送信します。
SD/MMCはクロックの立ち上がりでデータを扱うため、1を送るときはData INをHighにしたあと、クロックを送ります。
下記はカードに 0x95 を送るときの例です。
カードからのデータ受信についても、クロックの立ち上がりでData OUTからデータが出力されます。
下記はカードから 0xFE を受信したときの例です。
これらを覚えてしまえば、あとはどうにでもなります。
カードとのプロトコルをデータシートから読んで実装します。
カードのプロトコルについては、ルネサスのMMC関連PDFに書いてありますので省略します。
ただし、読み込みはFATテーブルのポインタを読んでいけば目当てのデータクラスタが特定できます。
その反面、書き込みの場合はディレクトリエントリや空きクラスタの検索を行わなければならないため、多少複雑になって実行時間もかかります。
色々と考えた結果、今回は下記のような手順で書くことにしました。
■記録開始(ファイルの新規作成)
1.FATテーブルの空きクラスタを検索し、0xFFFF書き込み(予約する)
2.ディレクトリエントリの空き検索
3.空きエントリにクラスタNo、ファイル名、属性などを書き込み
■データ書き込みループ
1.1クラスタ分のデータ書き込み
2.FATテーブルの空きクラスタを検索し、0xFFFF書き込み(次のクラスタを予約)
3.前回のFATテーブルに今回のクラスタNoを書き込み
4.ディレクトリエントリのファイルサイズ(暫定)を更新
■終了時
1.ディレクトリエントリのファイルサイズを正しいものに更新
終了指示が来るまでデータ書き込みループを続け、FATチェーンを繋いでいきます。
こんな感じになります。
この例ではFATの5番目でデータが終了しています。
ディスクが断片化していると、空きクラスタの検索に時間がかかり、書き込み効率が悪くなります。
特に、次の空き相対クラスタがずっと先のセクタにあると最悪です(;´Д`)
できればログ取りに使うカードは、フォーマットした後にファイルの削除は行わないほうがいいと思います。
Card R/W Buffer:
カードのアクセス用に、R/Wバッファとして使用します。
NMEA Data Buffer:
NMEAのデータを1セクタ分保存するために使用します。
DirectoryEntry Cache:
ディレクトリエントリのキャッシュとして使用し、ファイル属性をアップデートするときの効率化を狙います。
SRAMへの書き込みは、アドレスバスへ書き込みたいアドレス、データバスへ書き込むデータを出力します。その後にWEをLowにするとメモリに書き込まれます。
読み込みは、アドレスバスへ読み込みたいアドレスを出力し、OEをLowにします。
するとデータバスに指定したアドレスのデータが出力されます。
今回は日立のHM62256LP(256KBitのSRAM)を使用しましたが、もう出回ってないと思います。よって代替品でOKです。
10年くらい前にスーファミのRAMを増設するために買ったものですので‥
似非NMEAフォーマットから、完全なNMEAの$GPRMCセンテンスに変換します。
また、日時の世界標準時と日本の標準時との変換を行うため、チェックサムの再計算を行います。
変換元のファイルは必ずバックアップを取っておいてください。
万が一バグなどによって貴重なトラックログが壊れたりしても当方は責任を負いません。
また、read_VFAT_info()の中身は空ですので、後述のゆきさんのAVR向けソースから移植してください。
(2005.07.24)BSDライセンスとのことで、公開させていただきます。
(改変したものを勝手に再配布できないので)
常に使うカードが同じなら、決めうちの値をグローバル変数にセットするだけでOKです。
#デバッグ用のコードが大量に残っているので見づらいと思います(w
また、SDのプルアップ抵抗値やパスコンの容量は適当なため、ちゃんと調べて規格内の値にしてください。
とりあえず自分の環境では動いていますが、カードのメーカが違うと動かない可能性があります。
ちなみにRS-232Cのレベルコンバータはライブラリが無かったため手抜きです(w
#実際はISP端子のVccは接続せず、ターゲットに直接給電して書き込みを行っています。
FAT情報の読み方は ゆきさん のAVRによるMP3プレイヤー製作記事が参考になります。
BPBの情報判別モジュールは、ほとんどそのままPICに移植させていただきました。
有用なソースを公開していただきありがとうございます。
ルネサス からMMCカードの仕様やマニュアル類などをダウンロードできます。
これらのPDFは必携です。
私は穴があくほど何度も読み返しました。‥‥‥って、電子媒体に穴が空くかは別にして(w
例によって PCカード/メモリカードの徹底研究 を買いましたが、私にとってはあまり役に立ちませんでした(;´Д`)
実際のカードアクセスやFATの実装はググって資料を探したほうがいいかもしれません。
まあ、初期にググるキーワードの抽出や、とっかかりとして持っていて損はないと思います。
処理が冗長なところがあるので直したい。
同じようなことをやってる関数があるので共通化を‥
SRAMの接続に、アドレスとデータバスだけで19本もポートを占有されているので、どうにかしたい。
もうポートがいっぱいいっぱいなので拡張できません(w
ラッチのロジックICを使えば大幅に削減できますが、ラッチを行う手順が増えるため処理が遅くなる欠点が‥