Arduino
IoT
Grove

ArduinoでSDカードにデータを保存する

はじめに

sakura.io を使って電子工作初心者がIoTなGPSロガーを作るメモの[その3]にてデータをデバイス内に保存する必要が出てきました。

Arduinoにも内蔵の「EEPROM」がありますがUNOの場合には保存容量が1024bytesで書き込み寿命が100,000回、非常に容量が小さいので起動時のデバイス設定などの情報を記録するのに適しているようです。

Arduino用のSDカードシールドという商品があったので試してみました。

SDカードシールド

「Seeed Studio SDカードシールド 1,944 円」
1292_101-s.jpg

「Arduino Uno」+「GROVEベースシールド」+「SDカードシールド」+「sakura.io」
4段重ねになってしまいましたが今のところ普通に使えています。

「D4」コネクタがSDカード用となります。

サンプルコード

コメント多めですが以下のスケッチを実行してみてください。

#include <SD.h>

//---SDCard D4 pin
const int sd_chip_select = 4;

//---テスト用
int test_count = 0;
String test_str = "";


////===========================================================================================
//   + setup()
////===========================================================================================

void setup() {

    //---Serialポートを開く
    Serial.begin(9600);

    //---------------------------------------------
    //   +SDカード読み込み
    //---------------------------------------------

    //---SSピンは出力にする必要がある(SD)
    pinMode(SS, OUTPUT);

    Serial.print(F("SDCard:"));

    //---SDライブラリの初期化エラー
    if(!SD.begin(sd_chip_select)) {

        Serial.println(F(" error..."));

    }else{

        Serial.println(F(" OK"));

        //---ファイル一覧を表示
        Serial.println(F("----------------------------"));
        SdFileList();
        Serial.println(F("----------------------------"));
    }
}

////===========================================================================================
//   + loop()
////===========================================================================================

void loop() {


    //---カウンタを読み込み
    test_count = SdFileRead("COUNT.TXT").toInt();

    //---カウントアップ
    test_count++;

    //---カウンタを書き込み
    SdFileWrite("COUNT.TXT", String(test_count));


    //---文字列を読み込み
    test_str = SdFileRead("STR.TXT");

    //---文字列に追記
    test_str += "SD";

    //---文字列を書き込み
    SdFileWrite("STR.TXT", test_str);


    Serial.println(F("----------------------------"));

    delay(3000);
}

////===========================================================================================
//   + SDファイル一覧
////===========================================================================================

void SdFileList() {

    File dir = SD.open("/");

    while(1){

        File entry =  dir.openNextFile();

        if(!entry){ break;}

        //---ファイルのみを表示(ファイル名は8文字+3文字)
        if (!entry.isDirectory()) {

            Serial.print('\t'); Serial.print(entry.name());
            Serial.print("\t"); Serial.println(entry.size(), DEC);
        }

        entry.close();
    }
}

////===========================================================================================
//   + SDファイル読み込み
////===========================================================================================

String SdFileRead(String p_file_name) {

    String str;

    //---読み込みモードでファイルを開く
    File file = SD.open(p_file_name);

    Serial.print(F("SD FileRead: ")); Serial.print(p_file_name);

    if(file){

        //---1byteずつ読み込んだ文字を結合
        while (file.available()) {

            str += char(file.read());
        }

        Serial.print(F(" > ")); Serial.println(str);

    } else{

        Serial.println(F(" error..."));
    }

    //---ファイルを閉じる
    file.close();

    //---------------------
    //   +返り値
    //---------------------

    return str;
}

////===========================================================================================
//   + SDファイル書き込み
////===========================================================================================

void SdFileWrite(String p_file_name, String p_str) {

    //---上書きモードでファイルを開く
    File file = SD.open(p_file_name , FILE_WRITE | O_TRUNC);

    Serial.print(F("SD FileWrite: ")); Serial.print(p_file_name);

    if(file){

        //---書き込み
        file.print(p_str); Serial.print(F(" << ")); Serial.println(p_str);

    } else{

        Serial.println(F(" error..."));
    }

    //---ファイルを閉じる
    file.close();
}

SDカードを入れて実行するとシリアルモニタにSDカード内のファイル一覧が表示された後に以下の内容が表示されます。

20170808_222202.png

数値のカウントアップと文字列の結合をテストしたデータがSDカード内に保存されます。

Arduiono本体のメモリが小さいので大容量のファイルを読み書きするよりは、小さいサイズのファイルに1つの数値を書き込んだ方が効率が良いと判断しました。

またArduinoからSDカードを取り出してWindowsPCに繋げると内容が読み込めます。
(PC側でSDカードをフォーマットすれば大量のファイルを一気に消せるのでファイルを消す処理は省略している…)

まとめ

  • ファイル名は8文字+3文字までしか使えないので注意
  • SDカードに書き込む際にはすべて文字列(String)として書き込む
  • SDカードから読み込む際に(String)→(Int) (String)→(Float)と型を変換
  • WindowsPCでデータが読み込める