SDカードからデータ読み出し(Arduino詳解)

Arduino詳解その29です。前回の記事はこちらです。
hirocom777.hatenadiary.org

ファイルに書き込む

 前回はSDカードにファイルを作って書き込んでみました。

f:id:HiroCom777:20210130174447j:plain
今回は、ファイルからデータを読み出してみたいと思います。以下のスケッチを用意しました。

#include <SPI.h>
#include <SD.h>

File myFile;
const int chipSelect = 4;

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

  myFile = SD.open("test.txt", FILE_READ);
  Serial.println("test.txt:");
  while (myFile.available()) {
    Serial.write(myFile.read());
  }
  myFile.close();
}

void loop() {
}

動かしてみる

 それでは動かしてみましょう。SDカードにファイルtext.txtを作って、何かテキストを入力してください。PCでもいいですし、前回のスケッチで作っ手もいいです。SDカードをSDカードシールドに実装した状態で上記のスケッチを書き込み、実行してみてください。シリアルモニターを開いてみると・・・。シリアルモニターには、ファイルの内容が表示されていると思います。

f:id:HiroCom777:20210130174652j:plain

スケッチの解説

 それではスケッチの解説です。今回も使用するライブラリも、前回と一緒です。今回はsetupだけ。以下が新しくでてきましたね。

FileObject.available()
 ファイルから読み取り可能なバイトがあるかどうかを確認します。読み取り可能なデータのバイト数を返します。

FileObject.read()
 ファイルからデータを1バイト読み込んで返します。データを読み込めない場合は-1を返します。

 つまり、今回ご紹介したスケッチは開いたファイルを確認ながら最後までデータを読み込んでシリアルモニターに表示するものです。簡単ですね!!

1行ずつ読みたい

 さて、上に紹介した例では1バイトずつデータを読み込んでいます。でも、前回ご紹介したデータの書込みでは文字データを1行ずつ書き込んでいました。1行ずつ読み込むにはどうしたらいいのでしょうか?以下のスケッチ例をご紹介します。

#include <SPI.h>
#include <SD.h>

File myFile;
const int chipSelect = 4;

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

  myFile = SD.open("test.txt", FILE_READ);
  myFile.setTimeout(100);

  Serial.println("test.txt:");
  while (myFile.available()) {
    for (int i = 1; myFile.available(); i++) {
      Serial.print(String(i) + ": ");
      Serial.println(myFile.readStringUntil('\n'));
    }
  }
  myFile.close();
}

void loop() {
}

 動かしてみると・・・、今度は先頭に番号がついて表示されましたね。1行ずつ読み込んでいる証拠です。(余談ですが、こんな感じのfor文はじめて書きました)

f:id:HiroCom777:20210130174937j:plain
 新しく出てきたものは以下になります。

FileObject.setTimeout()
 データ読込みの待ち時間を設定します。待ち時間はカッコ内の引数としてミリ秒単位で設定します(デフォルトでは1000ミリ秒=1秒)。

FileObject.readStringUntil()
 ファイルからデータを連続して読み込みます。引数として終了文字が指定できます。終了文字が検出されるかタイムアウトになると読込を終了します。今回は改行コード('/n’)を指定したため1行ごとに読込を終了しています。

 今回の場合タイムアウトを設定しなくても問題ないのですが、ファイルの最後が終了文字で終わらない場合に終了まで1秒時間がかかってしまいます。0.1秒程度に設定しておくのが無難でしょう。

数値を読み出したいときは?

 SDカードに数値を書き込むと、文字列に変換されて書き込みます。したがって、読み出すときには文字として読み出して数値に変換するってなるのが普通なのですが、数値として読めると便利ですよね。以下のスケッチを作ってみました。

#include <SPI.h>
#include <SD.h>

File myFile;
const int chipSelect = 4;

int dataInt;
float dataFloat;

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

  myFile = SD.open("test2.txt", FILE_WRITE); 
  myFile.println(7);
  myFile.println(1.23);
  myFile.close();

  myFile = SD.open("test2.txt", FILE_READ);
  myFile.setTimeout(100);
  dataInt = myFile.parseInt();
  dataFloat = myFile.parseFloat();
  Serial.println(dataInt + 1);
  Serial.println(dataFloat * 2);
  myFile.close();

  SD.remove("test2.txt"); 
}

void loop() {
}

 実行してシリアルモニターを見てみると・・・整数値8と浮動小数点値2.46が表示されます。このスケッチの動きは以下の様になります。
 

f:id:HiroCom777:20210130175155j:plain
 -新しく作成したファイルtext2.txtに整数値7と浮動小数点値1.23を書き込む
 -text2txtをクローズする
 -text2.txtを読み込みモードで開く
 -整数型の変数dataIntと、 浮動小数点型の変数dataFloatに読み込んだ値をセットする
 -変数dataIntに1を足した値(7 + 1 = 8)をシリアルモニターに返す
 -変数dataFloatに2を掛けた値(1.23 * 2 = 2.46)をシリアルモニターに返す
 -text2txtをクローズして削除する

計算して正しい値を表示できているので、数値として読み込めていることがわかると思います。新しく出てきたものはこちらです。

FileObject.parseInt()
 ファイルの読込み位置から最初の有効な整数値を返します。それ以前にある数値やマイナス記号でないデータは読み飛ばしてしまいます。数値が読み込めない場合やタイムアウトの場合は0を返して終了します。

FileObject.parseFloat()
 ファイルの読込み位置から最初の有効な浮動小数点値を返します。それ以前にある数値やマイナス記号などは読み飛ばしてしまいます。数値が読み込めない場合やタイムアウトの場合は0を返して終了します。

最後のSD.remove()はファイルを削除するのですが、こちらは次回説明したいと思います。

お次はファイルとフォルダーの取り扱い

 いかがでしたでしょうか?これでデータ読み書きの基本が出来たと思います。次回は、ファイルとフォルダーの取り扱いについてご紹介しようと思います。お楽しみに!!
hirocom777.hatenadiary.org



Arduino UNO入門の連載記事はコチラからどうぞ!!