« 2015年9月 | メイン | 2015年11月 »

2015年10月18日 (日)

PICマイコンでSDカードのファイルを読み込む

<カテゴリー:PICマイコン

マイクロチップのMLAの中にあるデモソフトは簡易データロガーともいえるもので、何らかの手段で定期的に入手したデータをデモファイルにAPPENDしながら書き込んでいくものです。 従い、MS-DOSのDIRコマンドに相当したファイル検索や、特定のファイル名をオープンして、中身を読みだすという動作は行いません。 ただし、これらの機能の、コマンドの使い方は例で示してあります。 

今回、SDカードにセーブしたCSVファイルを検索して、LCD上にファイル名を表示させる機能、及び、表示したファイル名を指定して、そのCSVファイルを読み込み、LCD上にSWRカーブを再表示させる事にトライしました。 FILEIOのHELPドキュメントを読んだだけでは理解できず、構造体の勉強を3週間くらいやって、やっと、思ったようにソフトが動くようになりました。

Aa50_find

Aa_50_40m

ソースコードを下記しますが、そのままコピペしても動作しません。 これをデモ用として提供されているソースコードの中に埋め込んでやると期待したような動作が得られます。

MS-DOSのDIRに相当する関数は「FILEIO_Find」という関数を使います。

searchnameは16bitの文字で "*.CSV" と初期設定し、FILEIO_Findの関数を実行させるとsearchRecordの中にファイル名がひとつだけストアされます。 これをset_dir_fname()の関数に送り、そこで2次元の文字列にストアします。この動作を20回繰り返します。 ファイルの数が20以下の場合、i=20で強制的にループを抜けます。

unsigned int  find_SD_card(void) {

     DEMO_STATE demoState = DEMO_STATE_NO_MEDIA;

   FILEIO_OBJECT file;

    FILEIO_SEARCH_RECORD searchRecord;

    init_SDcard();

    unsigned char i;

   uint16_t SD_ER = 0;

      while(SD_ER == 0) {

        switch (demoState) {

            case DEMO_STATE_NO_MEDIA:

                 if (FILEIO_MediaDetect(&gSdDrive, &sdCardMediaParameters) == true) {

                    demoState = DEMO_STATE_MEDIA_DETECTED;  

                    }

                 break;

            case DEMO_STATE_MEDIA_DETECTED:

                  SD_ER=(FILEIO_DriveMount(drive_A, &gSdDrive, &sdCardMediaParameters));

                if (SD_ER ==0){

                    demoState = DEMO_STATE_DRIVE_MOUNTED;

                     } else {

                    demoState = DEMO_STATE_NO_MEDIA;

                    }

                     break;

            case DEMO_STATE_DRIVE_MOUNTED:

                if (FILEIO_Find (searchname, FILEIO_ATTRIBUTE_MASK, &searchRecord, true) == FILEIO_RESULT_SUCCESS) {

                    i=0;

                    set_dir_fname(&searchRecord,i);

                    i++;

                    } //サーチの最初はこのようにtrueを指定して検索

                    while (i < 20) {

                        if (FILEIO_Find (searchname, FILEIO_ATTRIBUTE_MASK, &searchRecord, false) == FILEIO_RESULT_SUCCESS) {

                           set_dir_fname(&searchRecord,i);

                            i++;

                            } else {i=20;} //whileループから抜ける為

                        }  //2回目以降はfalseを指定して検索

・・・・・・

・・・・・・

このfind_SD_cardの関数は、ファイル名を検索して最大で20個表示したら一旦ドライブをアンマウントさせます。

.

.

ファイルの読み出しは「FILEIO_GetChar」という関数を使います。

void get_SDdata(unsigned int *sptr) { //テキストデータを1行(LFまで)読み込む
     uint8_t C=0;
     uint8_t i=0;
     while (C != 0x0A) {
        C=FILEIO_GetChar(sptr);
        if (C == 0x1A) {break;} //EOFでもループを抜ける
        SWR_SDdata[i]=C;
        i++;

     if (i>40) {break;} //1行の文字数が40を超えたら抜ける
        }
     SWR_SDdata[i-2]=0;
  }

セーブされたテキストデータは必ず「CR+LF」で1行完了としていますので、上の関数で、CR+LFが削除された文字列として、SWR_SDdata[]の中にストアされます。

正規のSWRカーブファイル以外の場合、暴走しないように、EOFを見つけたり、1行の文字数が40を超えたら、ループから抜けます。 

.

以下はASCIIからUTF-16への変換関数です。

void Uint8toUint16(uint8_t *fname8) { //ASCIIをUTF-16に変換します。
        unsigned char i ;
        for (i=0;i<13;i++) {
            fname16[i]=fname8[i];
        }
    }   

以下が特定の16bitファイル名「fname16[]」をオープンして読みだす処理になります。

unsigned int  open_SD_card(unsigned char *fptr) {
   DEMO_STATE demoState = DEMO_STATE_NO_MEDIA;
   FILEIO_OBJECT file;
   unsigned char i;
    uint16_t SD_ER = 0;
    Uint8toUint16(fptr);

・・・・・

・・・・・

 if (FILEIO_Open (&file, (uint16_t *)fname16, FILEIO_OPEN_READ) == FILEIO_RESULT_FAILURE) {
 
                    demoState = DEMO_STATE_FAILED;
 
                    SD_ER=2;
                    break;
                    }
                    SD_ER=50;
 
        get_SDdata(&file);
        set_FREQ_data(&SWR_SDdata,1);

読み込みは全部で225行に渡りくりかえされますが、それが終わるとファイルクローズします。 

 if (FILEIO_Close (&file) != FILEIO_RESULT_SUCCESS) { //ファイルクローズ                     demoState = DEMO_STATE_FAILED;

                  SD_ER=3;

                    return SD_ER;

                  }          

クローズが失敗したらメインルーチン側で強制的にドライブアンマウントを実行させます。

クローズが成功してもドライブをアンマウントします。

FILEIO_DriveUnmount ('A'); //ドライブアンマウント

SD_ER=20;

return SD_ER;

・・・・・・・

・・・・・・・

ファイルを削除する時は以下のコマンドとなります。

 if (FILEIO_Remove ((uint16_t *)fname16) != FILEIO_RESULT_SUCCESS) {
                        SD_ER=10;
                        }
                    break;

エディター上ではTABを使い、行の整列がきれいに出来ているのですが、このブログに貼り付けるとメチャクチャになって、大変読みにくくなってしまいました。

このデモプログラムのなかでは、かなり詳しいエラーメッセージが定義され、それが番号で返されますが、そのままでは、かえって混乱しますので、新たにSD_ERという変数で、勝手にエラー番号を定義し、ループからの抜けや、メインルーチン側でのエラー処理に使っています。

出来てしまえば、簡単な記述で完成するのですが、ここまでやるのに優に1か月かかりました。

実際にアンテナアナライザーに組み込んだ状態はここで紹介しています。

INDEXに戻る

2015年10月17日 (土)

過去のデータを再表示

<カテゴリ:アンテナアナライザー>

周波数対SWRの変化特性をグラフにし、このデータをSDカードに保存し、PCでエクセルデータとして取り込む状態まで完了していましたが、せっかくSDカードにセーブできましたので、このデータを、再度アナライザーのLCD画面に表示する事にトライしました。

この機能を追加するのは、純然たるソフトウェアだけの世界となりますので、ハードの変更は一切なく、ただひたすらにC言語に苦しみながらPCと向き合う事になってしまいました。

 

Aa50_faile_select

Aa50_re_display

左上の画像がSDカード内のSWRカーブファイル名を表示させた状態で、画像ではSWR00044.CSVを選択している状態です。 この状態でワイドキーを押すと右上の画像のように、グラフデータをLCD上に表示します。 表示したデータは、前回セーブした14MHzのスカイドアアンテナの特性です。

Aa50_21m_mtu

左の画像は私の21MHz用アンテナを3つのMTUでそれぞれチューニングした時のSWR特性をグラフで表示させたものです。 SDカードにセーブして有りましたので、それを呼び出してLCD上に再表示させました。 この画像では、3本のSWRカーブが3色で描画されていますが、マイコンの仕様としては最大で7本のカーブを7色で描画できます。 また、読み込んだファイル名も表示させる事にしました。

ここまでの機能を入れ込んだ状態で、ROMエリアは91%、RAMエリアは85%となりました。まだ、バグや使い勝手の悪いところもありますので、それらの対策をして、ギリギリの容量かも知れません。

このアナライザーの場合、SDカードにセーブ出来るファイル数はSDカードの容量が上限を決めます。 しかし、検索出来るファイル数は、現在は20個までです。デバッグの進行状況を見ながら、RAMエリアに余裕があれば増やす事はできますが、それでもLCDの画面サイズの関係から最大50個くらいと思われます。 また、読み込み順序もFAT32のファイルシステムで記録された物理的なアドレス順になります。 通常は古いファイルから先に検索されますので、仮に50個以上のファイルをセーブしていても、新しいファイルは表示できなくなります。

Aa50_delete

このような条件から、SDカードのファイルをオープンしてLCDに表示した後、そのファイルを手動で削除する機能を追加しました。 グラフが表示された状態で左の画像のごとく、確認メッセージを出した上で、DOWNキーで削除できます。 この機能を追加した事により、削除する為にSDカードをいちいち抜いてPCに接続する必要も無くなります。

ファイル名が連番ですので、古い番号のファイルの中身が、どのアンテナのどのような条件でのSWRカーブであったかは、多分覚えていないでしょうから、必要なファイルはせっせとPCにコピーして置けば良く、その必要がないなら、古いファイルはせっせと削除すれば良い事になります。 RAM容量が限られているマイコンではやむを得ない処理でしょう。

10月31日追記

Aa50_max50

その後、2週間くらいデバッグを繰り返して、バグも収束してきましたので、表示可能なファイル名数を最大50まで増やす事にしました。 左の画像のごとく、LCD上でのディスプレーの都合でファイル名は連番の部分のみとしましたが、不便はないでしょう。  ファイル数が50を超えている場合、この画面上でなんらかの警告を出す事にしています。 常に50個以下にしておかないと、最新のファイルが検索できなくなります。  この状態で、ROMエリアは91%、RAMエリアは88%の使用となりました。

マイクロチップのMLAを使ったFILEIOアプリでファイル表示や、特定のファイルの読み込み方法は PICマイコンでSDカードのファイルを読み込む で紹介しています。

ここまでの基板の状況は以下のようになりました。 一番左の基板表側はスルーホールの部品だけが目立ちますが、真ん中のこの基板の裏側はチップ部品よりジャンパーワイヤーだけが目立ちます。 一応、高周波回路は最短で構成し、単純なDC電源やDC信号ラインはジャンパー線でまかなったので、発振回路としての動作は安定しております。 RF回路を横断しているいくつものジャンパ-線は、RF的にはすべてGNDレベルの線なので、写真では無造作に結線されているように見えますが、一応、元プロフェッショナルな作業は行っています。

Aa50_osc_f

Aa50_main_f

Aa50_mic_f

ソフトのバグも収束ぎみですので、これからケースに収納する為の検討をする事にします。

アンテナアナライザーの製作(ケース入れ) へ続く。

INDEXに戻る