🗂️

SDカードの読み書き方法 (挫折)

2023/05/14に公開

部品

名前 価格
マイクロSDカードスロットDIP化キット 300円
microSD 32GB 680円

配線

Mod モジュール側名称 Arduino 側 GPIO
1 DAT2
2 CD/DAT3 SS 10
3 CMD MOSI 11
4 VDD 3.3V
5 CLK SCK 13
6 VSS GND
7 DAT0 MISO 12
8 DAT1
9 カード検出スイッチA
10 カード検出スイッチB

参考:

https://ht-deko.com/arduino/micro_sdcard.html

ライブラリのサンプルは 2 を 4 に繋ぐようになっているが Arduino の規定する 10 に繋いだ。

差したか判定するには?

カードを差すと「カード検出スイッチ」のAとBが繋がるので、

  • 5V → A → B → 220Ω → LED → GND

としておけばカードを差したときだけ LED が点灯する。

マイクロSDカードはどこにある?

マトリョーシカのごとくSDカードのお尻にマイクロSDカードが差さっている。初見でこれは気づかない。

フォーマットするには?

  • 普通は必要がないがファイルシステムが壊れたときにフォーマットが必要になる
  • アプリケーション > ユーティリティ > ディスクユーティリティ を使う
  • 選択
    • マウント名ではなくルートの「Apple SDXC Reader Media」を選択する
  • 設定
    • 名前: MICROSD32G とした
      • ここは8文字以上でもいいらしい
      • 必ず大文字になる
    • フォーマット: MS-DOS (FAT)
      • FAT にすると FAT32 になる
    • 方式: マスターブートレコード
      • Windows との互換性を重視する方式らしい
  • セキュリティオプションは「最も速い」にする
    • そうしないと恐しく時間がかかる

Mac でフォーマットすると邪魔な隠しファイルができる

Mac でフォーマットするとSDカードに .fseventsd .Spotlight-V100 が作成され、この中に最初から大量のファイルを入れられるため検証の邪魔になる。でも取り除く方法がわからない。Windows でフォーマットすればこのようなファイルは作られないのかもしれない。

スケッチ例の chipSelect は SS (10) に変更する

-  const int chipSelect = 4;
+  const int chipSelect = SS;

スケッチ例はSDカードシールドを利用した場合を想定した 4 になっているので Arduino が定数化している SS (10) に変更する。

情報を確認する

ファイル > スケッチ例 > SD > CardInfo.ino を実行する

実行結果
Initializing SD card...Wiring is correct and a card is present.

Card type:         SDHC
Clusters:          946840
Blocks x Cluster:  64
Total Blocks:      60597760

Volume type is:    FAT32
Volume size (Kb):  30298880
Volume size (Mb):  29588
Volume size (Gb):  28.89

Files found on the card (name, date and size in bytes):
(snip)
TMPFILE1.TXT  2023-05-14 14:07:50 12

書き込みを確認する (失敗)

ファイル > スケッチ例 > SD > Datalogger.ino を実行する。アナログ入力値をCSV風にして DATALOG.TXT に書き出している。しかし正しく書き込めなかった。Mac にマウントして確認するも謎の2文字が書き込まれているだけだった。

初期化処理 (不安定)

#include <DebugLog.h>
#include <SD.h>

void setup() {
  Serial.begin(9600);
  boolean value = SD.begin();
  ASSERT(value);
}

void loop() {
}

動いたり動かなかったりする。

一行ずつ読み込む例

File file1 = SD.open("tmpfile1.txt");
ASSERT(file1);
while (file1.available()) {
  String line = file1.readStringUntil('\n');
  PRINTLN(line.length());
  PRINTLN(line);
}
file1.close();

これは動いた。

一行ずつ書き込む例 (失敗)

File file1 = SD.open("tmpfile1.txt", FILE_WRITE);
ASSERT(file1);
file1.println("123");
file1.println("456");
file1.close();

これを実行するとファイルシステムがぶっこわれる。ファイルがではない。ファイルシステムがである。

まとめ

  • 非常に不安定
    • SD.begin() が成功したり失敗したりする
    • SDカードを抜き差ししたら直ることもあるが根本的な原因はわからない
  • 読み込みはできる
  • 書き込むとファイルシステムが壊れる
  • こういう場合、初心者は詰む

続き

https://zenn.dev/megeton/articles/0be31655d6cf46

Discussion