PIC24F GPS Handy Data Logger
概要
ハードウェア
ソフトウェア
ソフトウェアソースコード
参考文献
変更履歴
2010年1月1日 新規作成
1月4日更新 「ソフトウェア」部分中心
1月5日更新 「ソフトウェア」部分中心
1月7日更新 「ソフトウェア」部分中心
PIC24USB( オプティマイズ)利用のデータロガー
ソフトウェア開発環境
Data Logger ----- 概要
<自作>
インターネットで電子工作関連の情報を集めると、2006年頃からGPSを用いたデータロガーの製作記事が多数見つかります。
例えば、
Fenrir's Blog: http://fenrir.naruoka.org/archives/000569.html
GPSデータの小部屋
ZZO分室 http://minkara.carview.co.jp/userid/339813/blog/12813686/
後閑さんの電子工作の実験室 http://www.picfun.com/app24Fframe.html GPS携帯型ロガー
しかし、昨今では市販のシステムも多く出ており、コンパクトで使いやすい点から買ってしまったほうが安くて便利な時代になっています。
例えば、
GPSDGPS.COM http://www.gpsdgps.com/index.htm
HOLUX http://www.holux.com/JCore/en/products/products_content.jsp?pno=341
などで、部品代だけでもこれから紹介するバラックセットより安いでしょう。
しかし、どんなに性能が良くて形が綺麗でも自作の喜びを満足させることは出来ません。
・・・・ということで、自己満足の世界に入り込んでいます。
<目標>
元々の目標は車に積んで、走行状態(エンジン回転、加速度、横G、アクセル、操舵角、位置情報など)を記録することを目標に始めたのですが、車に触れられる環境から一時的(?)に遠のいたために、目標を変更して先ずはハンディタイプで検討しました。
しかし、車載用データロガー製作は是非やりたいことで、CAN通信の勉強も始めています。これはもう少し時間がかかりそうです。
<CPU選定とその開発環境>
などの条件より、PIC24Fを選びました。過去に様々なCPUとお付き合いしましたが、PIC16F84以来遠ざかっていたPICに再度挑戦することを2009年春に決めました。
上記条件を厳密に判定した訳ではありませんが半年以上経った時点で、それほど間違った判断ではなかったと思います。
Data Logger ----- ハードウェア
PIC24USBのボードを中心に回路構成しています。回路図は、オプティマイズのPIC24USBの★回路図・製作に公開されています。
私の場合には、
としています。ボードへ供給する電源はUSBからでなく、別置きのDC-DCコンバータによって電池から昇圧(もしくは降圧)しています。
各部品への結線は、下記を参照ください。
PICkit2 | |||||
..... | PIC24USB | ..... | PICkit2 | ||
1 | MCLR | 1 | Vpp/MCLR | ||
2 | +3V3 | 2 | Vdd Target | ||
3 | GND | 3 | Vss(Ground) | ||
4 | PGD | 4 | ICSPDAT/PGD | ||
5 | PGC | 5 | ICSPCLK/PGC | ||
6 | Auxiliary |
SD Memory | SD Card ソケット経由 |
||||||||
PIC24USB | CARD | ||||||||
CN2 | 13 | RD4/RP25 | CS | 1 | SD_CS | ||||
CN2 | 14 | RD3/RP22 | SD0 | 2 | SD_D1 | ||||
CN2 | 1 | GND | GND | 3 | Vss | ||||
CN1 | 3 | +3.3V | Vdd | 4 | Vdd | ||||
CN2 | 15 | RD2/RP23 | SCK | 5 | SD_SCLK | ||||
CN2 | 1 | GND | GND | 6 | Vss | ||||
CN2 | 12 | RD5/RP20 | SDI | 7 | SD_D0 | ||||
N/A | 8 | SD_RES1 | |||||||
N/A | 9 | SD_RES2 | |||||||
CN2 | 10 | RD7 | CD | 10 | SD_CD | ||||
CN2 | 11 | RD6 | WE | 11 | SD_WP |
I2C LCD | |||||||
PIC24USB | LCD | ||||||
CN2 | 7 | RE0 | 1 | -RST | |||
CN2 | 25 | RF5/RP17/SCL2 | 2 | SCL | |||
CN2 | 26 | RF4/RP10/SDA2 | 3 | SDA | |||
CN1 | 1 | GND | 4 | Vss | |||
CN1 | 3 | +3.3V | 5 | Vdd | |||
N/A | 6 | CAP+ | |||||
N/A | 7 | CAP- | |||||
N/A | 8 | VOUT | |||||
N/A | 9 | A | |||||
N/A | 10 | K |
GPS | |||||||
PIC24USB | GPS-52D | ||||||
CN1 | 18 | RB7/RP7/AN7/TX1 | 1 | RX1 | |||
CN1 | 1 | GND | 2 | GND | |||
CN1 | 17 | RB6/RP6/AN6/RX1 | 3 | TX1 | |||
+3.3V Battery | 4 | BATT | |||||
CN1 | 3 | +3.3V | 5 | +3.3V | |||
N/A | 6 | N.C. | |||||
N/A | 7 | N.C. | |||||
N/A | 8 | N.C. |
G-Sensor | ||||||
...... | PIC24USB | KXM52-1050 | ||||
CN1 | 3 | +3.3V | 1 | VCC | ||
CN1 | 3 | +3.3V | 2 | PSD | ||
CN1 | 1 | GND | 3 | GND | ||
N/A | 4 | Parity | ||||
CN1 | 1 | GND | 5 | Selftest | ||
CN1 | 22 | RB11/AN11 | 6 | X | ||
CN1 | 23 | RB12/AN12 | 7 | Y | ||
CN1 | 24 | RB13/AN13 | 8 | Z |
I2C G-Sensor | ||||||
PIC24USB | MMA7455L Module | |||||
CN1 | 1 | GND | 1 | GND | ||
CN1 | 3 | +3.3V | 2 | DVDD | ||
CN1 | 1 | GND | 3 | GND | ||
CN1 | 1 | GND | 4 | IADDR0 | ||
CN1 | 1 | GND | 5 | GND | ||
CN1 | 3 | +3.3V | 6 | AVDD | ||
CN1 | 1 | GND | 7 | GND | ||
CN1 | 3 | +3.3V | 8 | CS | ||
9 | INT1/DRDY | |||||
10 | INT2 | |||||
CN1 | 1 | GND | 11 | GND | ||
12 | SDO | |||||
CN2 | 22 | RD9/RP4/SDA1 | 13 | SDA/SDI/SDO | ||
CN2 | 21 | RD10/RP3/SCL1 | 14 | SCL/SPC |
この他に、ADC基準電圧入力としてシャントレギュレータTL431、温度センサとしてLM60を接続しています。
また、写真には写っていませんが、素人のソフトウェア開発に頼もしい味方になるLEDを2個取り付けて、タスク周期測定や事象の有無などの観測をしています。
PIC24USBから見た結線は下記のようになります。
消費電流はかなり大きな値となっています。GPSの電流が60mA(@3.3V)以上あり、システム全体でも5.2V電源(DC-DCコン上流測定)で消費電流が130mA近く流れています。
5.2Vx130mA=676mW
GPSは、携帯用としては低消費電力タイプのものが素人にも手に入るようになって来ました。例えば、
GPS-GM318 電流:約40mA(@3.3V) ←カタログからの読取値
GPS-GM316 電流:衛星補足時35mA,通常動作時27mA ←Webからの読取値
既に、GM318は入手していますので交換予定です。このシリーズは、SiRF社製のワンチップGPSレシーバにより低消費電力が達成されているようです。
後閑さんの「電子工作の実験室」では、GPSの電源を制御して消費電力を下げる工夫が紹介されています。将来的には取り組みたい技術です。
システム機能が一様出来あがってきていますので、次の課題は「少電力化」でしょうか?
Data Logger ----- ソフトウェア
ソフトウェアに関する記述が多くなりました。興味のある部分に下記リンクから直接アクセスしてください。
<全体構成>
全体構成は下記のようになります。
ファイル合計=19(c)+34(h)
こちらがC Source Codeファイル こちらがIncludeファイル
ソフトウェアは、大別すると
で構成されます。
FreeRTOSは、ソースコードが入手可能なリアルタイムOSです。詳しくは、<FreeRTOS>を参照ください。
2及び3のソフトウェアは、Microchip社が提供しているSoftware Libraryで、これもソースコードが入手可能です。
リンク先はいつ切れるかわかりませんが、下記のMicrochipのサイトからソースコード一式が入手可能です。
リンク切れを想定して、画面の一部を貼り付けて置きます。
http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2680&dDocName=en537044
へのリンク
USB Framework とあるが、2009年11月17日付けでUSBだけでなくMDD、TCPIP、Graficなどを すべて一つのZipファイルとして、それぞれのライブラリ提供を開始した模様 →感謝! |
左画面の下まで行くと、”Microchip Application Libraries"のZipファイルがある |
私は2009年に3つの異なるLibraryをこのMicrochipのサイトから入手しています。
私が実作業を進めたVersionはv2009-07-24で、03-24との違いはほとんどなかった(私のほしいソースコードに関係する部分)のですが、本日(2009年12月31日)v2009-11-18が出て来たことを初めて知ったばかりで、何が変更追加になったのかを把握していません。少し調べてから情報を流します。
その他の部分は、私が作成した部分ですが、FreeRTOS上に上記2,3,4のそれぞれがタスクとして動作する仕組みになっています。
下記はmain()ルーチンの一部です。USBモードと通常モードの分岐を電源ON時のENTRキーのOn/Offfで判断してタスクを起動しています。
タスクは、全部で7つありますが起動される数は最大7つです。
if (running_mode == MODE_USB){ //////// USB MODE →ENTRキーが押されたまま電源投入されるとこのモードに入る
//********** Initialize USB Function ***************************************
mLCD_Strings("JH1PJL FreeRTOS"); // Display Start Message
mLCD_2L1P();
mLCD_Strings("--- USB MODE ---"); // Display Start Message
#if defined(USE_USB_BUS_SENSE_IO)
tris_usb_bus_sense = INPUT_PIN; // See HardwareProfile.h
#endif
#if defined(USE_SELF_POWER_SENSE_IO)
tris_self_power = INPUT_PIN; // See HardwareProfile.h
#endif
usb_initializeSystem();
USBDeviceInit();
// USB Control // USBとLCDタスクのみ起動
xTaskCreate( vTask5, (signed portCHAR *)"T5", 300, NULL, 1, NULL );
// LCD & LED Control
xTaskCreate( vTask6, (signed portCHAR *)"T6", 300, NULL, 1, NULL );
} else { //// NORMAL MODE /////////////
// Creat Queue buffer and Semaphore
lcdQueue = xQueueCreate(4, 8);
// 8Byte x 4
sdcardQueue = xQueueCreate(4, 8); // 8Byte x 4
/// Task creates
// General and other functions
xTaskCreate( vTask1, (signed portCHAR *)"T1", 300, NULL, 1, NULL );
// ADC Data Control
xTaskCreate( vTask2, (signed portCHAR *)"T2", 300, NULL, 1, NULL );
// SD File System
xTaskCreate( vTask3, (signed portCHAR *)"T3", 500, NULL, 1, NULL );
// GPS Data Control
xTaskCreate( vTask4, (signed portCHAR *)"T4", 500, NULL, 1, NULL );
// USB Control // USBタスクは起動させない
/* xTaskCreate( vTask5, (signed portCHAR *)"T5", 300, NULL, 1, NULL ); */
// LCD & LED Control
xTaskCreate( vTask6, (signed portCHAR *)"T6", 300, NULL, 1, NULL );
// Mode definition based on Switch condition
xTaskCreate( vTask7, (signed portCHAR *)"T7", 300, NULL, 1, NULL );
}
/// Task scheduling starts
rtos_start_flg = 1;
// RTOS started
vTaskStartScheduler();
/// Main loop forever
while (1){
;
}
}
各タスクがどのように協調して動作するのかは下記を参照ください。
各タスクに処理内容を分散する方針も大切ですが、もう一つ大切なのは状態遷移図で今何を制御しているのかを明確に定義することです。状態が明確に定義出来れば、やるべき処理も定義出来ます。
今回のロガーは下記のような状態遷移が存在します。
それぞれの状態間を遷移させる要因は、主にキー入力ですが、他に下記のような要因があります。
<ADC>
//不具合//
ADCでもっとも大事な情報は、これだと思います。
Module: A/D Converter When using PGEC1 and PGED1 to debug an application on any 64-pin devices in this family, all voltage references will be disabled. This includes VREF+, VREF-, AVDD and AVSS. Any A/D conversion will always equal 0x3FF. |
これは、Microchipが提供しているSilicon Errota情報で、原典はここにあります(Item#20, page7 doc. rev.F (07/2009))。実は、私はこの問題ではまってしまい1カ月以上解決出来ないまま悶々としていました。
他にやるべき課題があったので、そちらの作業を優先していたので大きな遅れはなかったのですが、Forumでこの問題が取り上げられて初めて問題がチップ自体にあることを知りました。ここを参照ください。
但し、問題があるのはRevision A3(ID=01h)のみで、その後のRevision(2009年末ではA3とA5のみか?)は不具合が無くなっていると書かれています。使用しているチップのRevisionはPICkit2では、IDE画面で下記のように表示されます。
下記例では、チップが不具合を持つA3(Rev 0x1)であることがわかります。
何が起こるかと言えば、PICkit2のようなPGEC/PGED利用のDebuggerを64Pinデバイス(PIC24USBは、64PinのPIC24F256GA106使用)で使用しながらADCを動作させると変換値が最大値に張付いて意味のない値を示すことになります。
オプティマイズのWebページで紹介しているように(★開発例及び★フラッシュツール参照)、PICkit2などを使用しないでUSB経由でプログラムをFLASHに書いて走らせる場合には問題が起きません!
勿論、PICkit2をDebuggerでなくProgrammerとして使えば、問題ありません。私は下記のように、PICkit2を常時接続しておいて必要に応じて、Debugger/ProgrammerをSWとMPLABの両方で切り替えています。
この不具合対策として、Silicon Errota内にはPGEC2とPGED2を使うように書かれていますが、私が実験したところ症状としての改善はありませんでした。勿論、PICkit2をPGEC2/PGED2に接続してもDebugger/Programmerの機能は動作しました。
//動作説明//
ADCは、TASK2として起動され、
等の処理をしている。
//正規化処理//
各ADCデータは、電圧の絶対値で物理量と関連付けられている。
入力信号 | 接続先 | 信号単位 | 補足 | |
Gセンサ | KXM52-1050 | 660mV/g | offset = 1.65V @3.3V | |
温度センサ | LM60 | 6.25mV/degC | 424mV@ 0degC | |
Vref | TL431 | 2.495V typ. | @Ika = 10mA | |
電源電圧 | 電池 | - | - |
従って、先ずは絶対値が判明しているVrefとVrefのADCデータとで補正値を算出し、その補正値をもとに各変換値を補正してから、物理量に変換します。
この作業を電源電圧と温度センサに対して実施したのが、下記の表です。Excelを使って8/16/32ビット各数値範囲内で正規化できるか検証しています。
//Gセンサ処理//
Gセンサの出力処理に関して、まだ方針が定まっていません。2つのGセンサ(KXM52-1050、MMA7455L)を付けたのも両者の相関を把握したいと思ったからです。
Gセンサの応用として携帯用GPSであれば、万歩計を思いつくでしょう。
3軸の加速度の測定値を二乗して足した値の平方根が静止している場合には重力(1G=9.8m/s2)となるはずで、これは取付角度によらず一定のはずです。
自然落下時はこれが0となります。ハードディスクを落下時の事故から防ぐためにG計算して、落下直後には磁気ヘッドをディスクから離し落下時の衝撃でヘッドがディスクを傷つけないようにしていることはよく知られています。
歩行に伴うG変化を下記計算式で算出して、歩数計算に応用するつもりです。
<I2C Interface>
今回は、I2Cインターフェイスを、
に使用しました。
I2Cは1ラインでも2つのデバイスのアドレスが違うので制御出来ると思いますが、RTOS内で違う周期で動作しているので別ラインに割付けました。
PIC24USBの入出力もまだ空きがありますので、無理に一緒にして制御を複雑にする必要はないでしょう。
//LCD//
LCDに関しては、Write Onlyで唯一ACK/NACKが返されるだけですので制御としては簡単で、Strwberry Linuxが用意してくれているAVR用サンプルプログラムを書き換えるだけで比較的簡単に制御出来ました。
LCDに流し込むデータは、16x2のキャラクタ表示ではたいしたことはありませんが、その上に位置するアイコン制御には思ったより多くの情報を流し込まなければなりません。頻繁に更新するとI2C制御に係る時間が思ったよりかかりますので注意してください。アイコンは下記のようなデータとなります。
//MMA7455L//
画面の一部をご紹介しましょう。クリックすれば、拡大画面で見えます。
I2Cの制御プロトコルをソフトウェアとして実装する秘訣は、ひとつひとつの各ステップ(シーケンス)をCPUとデバイスの間で必ず確認していくプログラムを作ることが重要です。
Microchipのドキュメントには、下記のように書かれており各ステップ(下記ではイベント)をキューイング出来ないと書かれています。
Note: The I2C module does not allow queueing of events. For instance, the software is not allowed to initiate a Start condition and immediately write the I2CxTRN register to initiate transmission before the Start condition is complete. In this case, the I2CxTRN will not be written to and the IWCOL bit will be set, indicating that this write to the I2CxTRN did not occur. |
これを実践するのは、例えば上記アナライザ表示の中にあるPIC24がMMA7455からXYZ各軸の加速度データを読み込むステップの流れは下記のようになります。
スタート | // バスがアイドル状態か否かをチェック while(I2C1CONbits.RSEN || I2C1CONbits.SEN || I2C1CONbits.PEN || I2C1CONbits.RCEN || I2C1CONbits.ACKEN || I2C1STATbits.TRSTAT); // スタート条件を設定 (SCLがHの時に、SDAをHからLに変化させることで始まる)→SENビットを1にすると動作が始まる I2C1CONbits.SEN = 1; // SENが1から0になると動作完了。動作完了待ち while(I2C1CONbits.SEN); // MMA7455のアドレス(0x1D)を1ビットシフトして、bit0=0とすることで書込みモードとする I2C1TRN = (0x1D<<1) | 0x00; // 書込んだ後にバスが衝突していないかをチェックする。IWCOLが1の場合には衝突発生なので終了 if(I2C1STATbits.IWCOL) return -1; // 書き込んだデータ(8bit)すべてが、バスに送出されるまで待つ。TBF=0になれば、送出完了 while(I2C1STATbits.TBF); // 送信完了後にMMA7455からのACK確認 while(I2C1STATbits.TRSTAT); // MMA7455のレジスタ(8bitX軸加速度データレジスタ=0x06)を指定して送出 I2C1TRN = 0x06; // 書込んだ後にバスが衝突していないかをチェックする。IWCOLが1の場合には衝突発生なので終了 if(I2C1STATbits.IWCOL) return -1; // 書き込んだデータ(8bit)すべてが、バスに送出されるまで待つ。TBF=0になれば、送出完了 while(I2C1STATbits.TBF); // 送信完了後にMMA7455からのACK確認 while(I2C1STATbits.TRSTAT); // リスタート条件を設定→RSENビットを1にすると動作が始まる I2C1CONbits.RSEN = 1; // RSENが1から0になると動作完了。動作完了待ち while(I2C1CONbits.RSEN ); // MMA7455のアドレス(0x1D)を1ビットシフトして、bit0=1とすることで読込みモードとする I2C1TRN = (0x1D<<1) | 0x01; // 書込んだ後にバスが衝突していないかをチェックする。IWCOLが1の場合には衝突発生なので終了 if(I2C1STATbits.IWCOL) return -1; // 書き込んだデータ(8bit)すべてが、バスに送出されるまで待つ。TBF=0になれば、送出完了 while(I2C1STATbits.TBF); // 送信完了後にMMA7455からのACK確認 while(I2C1STATbits.TRSTAT); // MMA7455からの受信モードに設定。RCEN=1で動作開始 I2C1CONbits.RCEN = 1; // RCENが1から0になると動作完了。動作完了待ち while(I2C1CONbits.RCEN); // I2COV=0とし、オーバーフローフラグをクリア(なぜこれをここで行う?→MicrochipのLibraryでは実施) I2C1STATbits.I2COV = 0; // データを受信。Reg=0x06としたので、先ずは8bitX軸加速度データ 1st_data = I2C1RCV; // MMA7455にACKを送出。これで、データが受信出来たことをMMA7455に伝えるとともに次のデータを要求(Reg=0x06が1つとなりの0x07となる) I2C1CONbits.ACKDT = 0; I2C1CONbits.ACKEN = 1; // ACKENが1から0になると動作完了。動作完了待ち while(I2C1CONbits.ACKEN); // 次の8bitY軸加速度データ I2C1CONbits.RCEN = 1; while(I2C1CONbits.RCEN); I2C1STATbits.I2COV = 0; 2nd_data = I2C1RCV; // まだZを呼込むのでACKを送出 I2C1CONbits.ACKDT = 0; I2C1CONbits.ACKEN = 1; while(I2C1CONbits.ACKEN); // 次の8bitZ軸加速度データ I2C1CONbits.RCEN = 1; while(I2C1CONbits.RCEN); I2C1STATbits.I2COV = 0; 3rd_data = I2C1RCV; // データが全て受信出来たので、NACKを返してMMA7455のデータ送信を終了させる I2C1CONbits.ACKDT = 1; I2C1CONbits.ACKEN = 1; while(I2C1CONbits.ACKEN); // ストップ条件を設定→PENビットを1にすると動作が始まる I2C1CONbits.PEN = 1; // PENが1から0になると動作完了。動作完了待ち while(I2C1CONbits.PEN); |
|||
MMA7455 選択 |
||||
レジスタ 指定 |
||||
リスタート (読込 モード 設定) |
||||
データ 読込 |
||||
次の データ 読込 |
||||
次の データ 読込 (NACK で 読込 停止) |
||||
ストップ |
バスに信号を乗せて、それが完了したら次のステップへ。まさに、”The I2C module does not allow queueing of
events”の実践です。
PICのハード設計時にキューイングを許すように設計すれば出来ないことでもないような気がしますが・・・・・?
<File System>
//動作説明 SDカードへの記録//
SDカードへのデータ記録の流れは、下記のようになります。
//記録例//
2010年1月2日、実験を兼ねて神奈川県秦野市の弘法山公園・吾妻山ハイキングコースに家内と二人で出かけてきました。晴天で富士山が綺麗でした。
その時のSDカード記録内容の一部を紹介します。
SDカード: 実際にはMicro SD Card 2GB (秋葉原で980円で入手(2009/11))をFAT32フォーマットで初期化して、SDカードアダプタに装着して使用
記録内容: 下記が記録したカードから吸い上げたファイルです
ファイル名は時分秒を組合わせて構成しています(gps.c ->define_file_namen())が、UTC(Universal Time,
Cordinated)でGPSからの生データがベースです。
従って、例えば、L235834.txt 2010/01/02 9:56の場合には、JST(Japan Standard Time)では、8時58分34秒に記録開始したことになります(+9時間)。
1月2日の9時56分のタイムスタンプがあるのは、RTCCに記録されたJST基準の時計を基にファイルシステムがFile Close時にタイムスタンプを押した結果です。
この設定には、ファイルFSconfig.h内の#define USEREALTIMECLOCKを有効にする必要があります。
ほぼ1時間毎(正確な時間計測でなく、FreeRTOSのvTaskDela関数の一分カウンタを更に60回計測しているため。ここは修正可能だが・・・)にファイルが作られています。
ちなみに11時40分から午後1時38分までは、弘法の湯で温泉に入っていたため電源OFFとしていました。
ハイキング中のデータは、L005651.TXTの記録内容で紹介します。
$GPRMC,013913.287,A,3522.8256,N,13915.8410,E,0000.00,040.01,020110,,*3D $ADC, 153, 0411, 0411, 791, 0021, -051, -114,0172, 0801, 0720,*00 $GPVTG,040.01,T,,M,0000.00,N,0000.00,K*55 $GPZDA,013914.287,02,01,2010,,*55 $ADC, 124, 0355, 0483, 712, 0029, -034, -052,0172, 0801, 0720,*00 $ADC, 66, 0460, 0508, 637, -004, -023, -056,0172, 0801, 0720,*00 $ADC, 70, 0445, 0528, 640, 0011, -030, -058,0172, 0801, 0720,*00 $ADC, 103, 0451, 0521, 714, 0009, -044, -094,0172, 0801, 0720,*00 $ADC, 150, 0424, 0469, 804, 0020, -054, -114,0172, 0801, 0720,*00 $ADC, 124, 0444, 0468, 753, -013, -046, -102,0172, 0801, 0720,*00 $ADC, 80, 0509, 0488, 676, -019, -040, -053,0172, 0801, 0720,*00 $GPGGA,013914.287,3522.8256,N,13915.8410,E,1,06,01.7,00195.3,M,0039.4,M,000.0,0000*4C $GPGSA,A,3,28,11,20,19,17,32,,,,,,,02.5,01.7,01.9*0C $ADC, 68, 0482, 0505, 648, -024, -032, -069,0172, 0801, 0720,*00 $GPGSV,2,1,07,11,64,033,38,28,58,292,33,32,55,100,37,20,54,159,39*7A $ADC, 68, 0485, 0503, 649, -013, -034, -064,0172, 0801, 0720,*00 $GPGSV,2,2,07,19,23,095,31,17,21,302,30,08,14,234,28*4C $GPRMC,013914.287,A,3522.8256,N,13915.8410,E,0000.00,040.01,020110,,*3A $ADC, 124, 0425, 0447, 743, 0017, -065, -101,0172, 0801, 0720,*00 $GPVTG,040.01,T,,M,0000.00,N,0000.00,K*55 $GPZDA,013915.287,02,01,2010,,*54 $ADC, 159, 0387, 0447, 807, 0037, -049, -096,0172, 0801, 0720,*00 $ADC, 92, 0402, 0501, 665, 0006, -031, -064,0172, 0801, 0720,*00 $ADC, 75, 0460, 0513, 657, 0014, -029, -067,0172, 0801, 0720,*00 $ADC, 79, 0443, 0513, 659, 0000, -023, -098,0172, 0801, 0720,*00 $ADC, 101, 0466, 0513, 714, 0008, -019, -085,0172, 0801, 0720,*00 $ADC, 145, 0388, 0457, 778, 0024, -044, -080,0172, 0801, 0720,*00 $ADC, 118, 0491, 0467, 750, -015, -039, -099,0172, 0801, 0720,*00 $GPGGA,013915.287,3522.8256,N,13915.8410,E,1,06,01.7,00195.3,M,0039.4,M,000.0,0000*4D $GPGSA,A,3,28,11,20,19,17,32,,,,,,,02.5,01.7,01.9*0C $ADC, 69, 0493, 0494, 652, 0003, -036, -062,0172, 0801, 0720,*00 $GPGSV,2,1,07,11,64,033,40,28,58,292,30,32,55,100,35,20,54,159,38*75 $ADC, 67, 0492, 0504, 649, -006, -038, -046,0172, 0801, 0720,*00 $GPGSV,2,2,07,19,23,095,32,17,21,302,35,08,14,234,21*43 $ADC, 61, 0497, 0514, 638, -011, -021, -071,0172, 0801, 0720,*00 $GPRMC,013915.287,A,3522.8256,N,13915.8410,E,0000.00,040.01,020110,,*3B |
先頭のRMCデータから下記の情報が得られます。
$GPRMC,013913.287,A,3522.8256,N,13915.8410,E,0000.00,040.01,020110,,*3D
013913.287 | A | 3522.8256,N | 13915.8410,E | 0000.00 | 356.89 | 020110 | *39 | |
01:39:13.287 UTC | 緯度35度22.8256分 | 経度139度15.8410分 | 対地速度0.0ノット | 進行方向 | 2010年1月2日(UTC) | チェックサム | ||
午前10時39分13秒287 | 有効 | 緯度35度22分49.54秒 | 経度139度15分50.46秒 | 2010年1月2日(JST) |
上記データを基に、Google Earthで場所をチェックしたところずれがあることが確認出来ました。どうも、測地系の初期化が行われていないようです。
ここで、測地系変換をしてみるとWGS84系では、下記の値になりました。
緯度 35度23分01.30秒
経度 139度15分39.00秒
$GPGSA,A,3,28,11,20,19,17,32,,,,,,,02.5,01.7,01.9*0C
A | 3 | 28,11,20,19,17,32,,,,,,, | 2.5 | 1.7 | 1.9 | *0C | |
即位モード | 3D | 衛星番号 | PDOP | HDOP | VDOP | チェックサム |
ADCに関しては下記の情報が入っています。上記青字の部分(100mS毎データ)。
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ヘッダー | G(Total) | G(X) | G(Y) | G(Z) | DG(X) | DG(Y) | DG(Z) | 温度 | 電源電圧 | Vref | チェックサム | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
3軸合成G | KXM52生データ | MMA7455生データ |
3軸合成Gは、1/100で実Gとなります。静止時は100(1G)を示していますので、上記は歩行中と思われます。
チェックサムは、ダミーデータです。形式を整える意味でGPSフォーマットをまねています。
//ソースファイル構成//
MD File Systemのファイルとして、6つのソースファイルを使います。
Microchipから新しいLibraryがリリースされたので、私の使ったファイルとの差を見極めておくことが重要です。
対象ファイルは、新しいDirectoryがCドライブの直下に作られることを仮定すると
を用います。FSconfig.hはいろいろな場所に存在しますので注意してください。
赤字のファイルには、修正を加える必要がありますがSD-SPI.c以外はIncludeファイルのパスの変更で本質的な変更ではありません。
SD-SPI.cは、下記のように変更しています。Milliseconds単位での遅延発生をvTaskDelay()で置き換えています。
///-> by jh1pjl
// FreeRTOS /Delay by vTaskDelay function
extern char rtos_start_flg;
void Delayms(BYTE milliseconds)
{
BYTE ms;
DWORD count;
ms = milliseconds;
if ( rtos_start_flg == 0 ){
while (ms--) {
count = MILLISECDELAY;
while (count--);
}
Nop();
return;
} else {
ms = milliseconds / portTICK_RATE_MS;
vTaskDelay( ms ); // Wait
}
}
私も2010年1月3日に新バージョンv2009-11-18に移行して、上記変更点を反映して修正しました。結果としてうまく動作しているように見えます。
<USB Interface>
//概要//
当初は、計測中でもUSB制御のTASKを走らせていたのですが、データ収集時(Logging)とデータ解析時とは別作業にしたほうが効率が良いと思い、電源ON時のENTRキーにより動作を分離しました。
FreeRTOS上で他のTASKと一緒に走らせるためにソースファイルの一部を修正して使っています。
大きな問題もなく動いていますが、PC側の検出が遅い(PCとUSBで接続して、エクスプローラが自動的に立ち上がるまでの時間)点が気になります。
多分、USB通信だけでなく、SDファイルシステムのスピードが遅いことに起因していると思いますが、まだ分析していません。
下記はファイル転送にかかる時間ですが、改善の余地がありそうです。
ファイル転送時間(93MBのPDFファイル1個) | |||||
接続先 | 書込み時間 | 相対速度比 | 読出し時間 | 相対速度比 | |
GPS Data Logger (今回の試作機) |
12分30秒 | 1 | 10分0秒 | 1 | |
バッファロー製USB接続640MBHDD (HD-ES640U2) |
5秒 | 1/150 | 5秒 | 1/120 | |
BUFFALO製USB接続タイプSDカードリーダ (同じMicro SD Card使用) |
15秒 | 1/50 | 8秒 | 1/75 |
//ソースファイル構成//
使用するファイルは下記のものです。Cソースファイルが4つとヘッダーファイルが7つの合計11ファイルが必要です。
変更しなけらばいけないファイルは、7つです。
File System同様、2010年1月4日にUSB修正を新バージョンv2009-11-18に対して実施しました。こちらもまだ充分検証は出来ませんが動作しているように見えます。
//PCとのUSB接続//
プログラムが正常に動作するとPC側で、Storage Deviceとして認識されます。私の環境では下記のようになりました。
<GPS>
//動作説明//
GPSの処理は、概ね下記のようになります。
//GPS情報の処理 NMEA-0183フォーマットの場合//
私のGPS関連の情報は、ほとんど「GPSの森」によって得ています。
NMEA-0183フォーマット情報は、ここにあります。
ファイルネームの作成
ファイルネームをタイムスタンプから作っています。
UTCからJSTへの変換
思ったほど簡単でない、UTCからJSTへの時間変換。
自信がありませんが、実装しています。
gps.c->usc2jst()
RTCCの初期化
現在、RTCC(REAL-TIME CLOCK AND CALENDAR)は、電源OFFに伴い停止しています。その為、常に電源ON後に初期化する必要があります。
現時点では、2つのステップで初期化しています。
チェックサム計算
GPSデータは、チェックサムによりパケットの信頼性を確保しています。
チェックサムは、パケットの最初の文字'$'を含まずチェックサムの2桁の前にある'*'直前までの文字列を8ビットデータとしてExclushive
OR(XOR)で計算したHEX値を2桁のASCII文字で表しています。
この計算を、受取ったパケットに対して実施し、パケットに付いてきた2桁の値と比較しチェックサムの正当性を検証しています。
gps.c->judge_check_sum()
この結果は、LCD画面のアイコンとして表示されます。
//測地系初期化失敗について//
現在調査中
<FreeRTOS>
//リアルタイムOSの有効性//
今回、RTOSを使おうと思ったのは拡張性を考慮したからです。どんなシステムを作成するのかあらかじめ厳密に決まっている場合には、必ずしも必要とは言えません。
ここで紹介しているシステムでは、GPSからのデータは割込みを使用し、他のLCD表示やSDメモリ書込み、そしてスイッチ入力は1つのタスクとして表現が出来るでしょう。
しかし、少しづつ機能を拡張していく場合には、RTOS上でソフトウェアを構築していくことのメリットは絶大です。
勿論、最初にRTOSを使うまでに費やす労力は、少ないとは言えません。しかし、そんなに多くを期待しなければ私が行っているようにほんの少しの機能だけ使えばよいと思います。
私が使っている機能は下記だけです。
この中で、青字の3つの機能は初期化などで使わされているもので、意図的に使っているのは赤字の3つの機能だけです。
しかし、プログラムとしてはこれだけでリアルタイムでマルチタスクの制御が可能になります。
FreeRTOSは、ファイル数から言ってもコンパクトなRTOSです。是非一度挑戦することをお勧めします。
後閑さんの「電子工作の実験室」でも、ここで紹介されています。詳しい説明がありますので、参考にしてください。
//FreeRTOSのVer//
私が使用しているFreeRTOSは、Ver5.2.0ですが現時点では、V.6.0.1が現時点(2010年1月4日)での最新です。
両者を比較した結果、色々と差はありますが、下記の変更でV6.0.1でも動作することを確認出来ました。
違いを下記に示します。
ここも、2010年1月4日に新バージョンV.6.0.12に移行しました。こちらも動作に問題は起きていません。
<Switch I/F>
スイッチ入力は、いろいろな方法で検出が可能です。例えば、
どれが良いとか悪いとかではなく、制御目的から最適な方法を選べば良いわけですが、今回は3番目の方法でスイッチ状態を検出しています。
3番目の方法は、先に説明した状態遷移を意識したプログラム作成に相性が良いことも採用した理由です。
下記がスイッチ状態検出の方法です。
少し判りずらいので、説明します。
Status: スイッチの状態を検出ソフトウェアが判断した結果です
Direction: スイッチのStatusを基に次に検出すべき状態を示します。今OFFであれば、次に検出すべきはON状態ということになります
Counter: 状態が変化している場合にカウントダウンして、ゼロになると状態が変化したと見なします。状態が戻った場合には初期値に戻ります
横軸は時間の推移ですが、CPUは一定時間毎にスイッチの状態を見に行き、Directionと同じ状態が起こっていたらカウントダウンを行い、ゼロとなった時にDirectionが目指していた状態になったと判断して、StatusをDirectionの値とし、Direction自体は逆の状態にします。
このようにすることで、スイッチが持つチャタリング現象での誤検出を防ぎながら、スイッチの状態を正確に読み込めます。
ポーリング(一定間隔毎の読込)の周期を、適切に設定し、スイッチの特性(チャタリングはスイッチの種類により多様な振る舞い)に合わせてCount値の初期値を最適化してください。
もう一つの機能は、Modifyのステータスです。これは、スイッチの状態を呼び出して使う際に一度でも押されたか否かを保持する機能があり、読出しによりその値をリセットする機能を持ちます。
Data Logger ----- ソフトウェアソースコード
ソースファイル一式を用意出来ます。
必要な方はお手数ですが、メールにてお知らせください。
kenjia の後に@sannet.ne.jp
です。
下記をベースとしています。
FreeRTOS V.6.0.12
Microchip MDD File System, USB v2009-11-18
Data Logger ----- 参考文献
オプティマイズ (PIC24USB)
http://optimize.ath.cx/index.html
http://optimize.ath.cx/pic24usb/index.html
Strawberry Linux (LCD, G-sensor, DC-DC Converter)
http://strawberry-linux.com/
LCD
http://strawberry-linux.com/catalog/items?code=27001
G-sensor (MMA7455L)
http://strawberry-linux.com/catalog/items?code=12102
DC-DC
http://strawberry-linux.com/catalog/items?code=12010
秋月電子通商 (GPS, G-sensor)
http://akizukidenshi.com/catalog/default.aspx
LCD
http://akizukidenshi.com/catalog/g/gK-02294/
G-sensor (KXM52-1050)
http://akizukidenshi.com/catalog/g/gI-01425/
電子工作の実験室 (PIC24F関連情報、データロガー情報、FreeRTOS情報)
http://www.picfun.com/
PIC24F関連情報
http://www.picfun.com/PIC24Fframe.html
データロガー関連情報 (GPS携帯型ロガー)
http://www.picfun.com/app24Fframe.html
FreeRTOS情報
http://www.picfun.com/RTOS24/FreeRTOS24frame.html
FreeRTOS
http://www.freertos.org/
Microchip
http://www.microchip.com/
PIC24F256GA106
http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en531071