Arduino環境でSDカードモジュールを使う

コンピュータ、組み込み

Arduino環境上でRaspberry Pi Picoを使ってSDカードモジュールを使います。
ファイルの保存/読み取り、ファイルの存在確認や削除などの使い方について記載します。

今回紹介するもの

SDカードモジュール

特徴

SPIを使った通信でMicroSDカードのファイルの保存や読み取りができます。

製品情報
対応MicroSDカード容量マイクロSDカード ≦ 2GByte
マイクロSDHDカード ≦ 32GByte
動作電圧4.5~5.5V※
通信方式SPI
※Raspberry Pi Pico から 3.3Vを供給しても動作しなかったので、当方は5Vを使用しました。
外観

前面

背面

使用感

普通にデータの保存ができたり読み取りができるので助かります。

SPI配線のわずらわしさはあります。
スケッチについてはライブラリが用意されているので、簡単な記録の保存や読み出しには困りません。

特定のフォーマット(画像ファイルなど)は専用のライブラリが必要になります。
機会があれば都度紹介していこうと思います。

マイコン基板にカードリーダの搭載されているモデルもいくつかあります。
配線不要で使用できることが魅力です。

準備

配線

YD-RP2040配線SDカードモジュール
VoutVCC
GNDGND
GP19MOSI
GP18SCK
GP17CS
GP16MISO
GP18とSCKのワイヤは白と書いていますが、絵は灰色で表現しています。

ライブラリ

SDカードモジュールを使用するためのライブラリは ArduinoIDEをインストールすることで含まれています。
拡張した使用をするときに必要なライブラリがあれば一緒に掲載します。

使い方

ファイルへ保存(追記モード)

説明

SDカードに “sample.txt”ファイルを作ります。
すでに存在する場合は、ファイルの最後に追記します。

COMからの入力データをファイルに書き込みます。
COMからの入力データが”CTRL + z”(0x1a)だった場合、ファイルを閉じてポーリングします。

スケッチ

/**********************************************************************
【ライセンスについて】
Copyright(c) 2022 by tamanegi
Released under the MIT license
'http://tamanegi.digick.jp/about-licence/

【スケッチの説明】
SDカードにsample.txtに追記保存します。

ファイルにCOMから入力の有った文字列を書き込みます。

【ライブラリ】
不要

【準備】
YD RP2040     SD Card Module
GND       <-> GND
Vout      <-> VCC
GP16      <-> MISO
GP19      <-> MOSI
GP18      <-> SCK
GP17      <-> CS

【参考】
'http://www.musashinodenpa.com/arduino/ref/index.php

【バージョン情報】
2022/9/21 : 新規
**********************************************************************/

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

//SPI0 を使用するためのピン番号定義
#define SD_MOSI 19
#define SD_SCK  18
#define SD_CS   17
#define SD_MISO 16

#define FILENAME "sample.txt" //保存ファイル名
File myFile;                  //ファイル操作オブジェクト

void setup()
{

  Serial.begin(115200);       //COMオープン。今回ここから入力の有った文字をファイルに保存します。

  SPI.setTX(SD_MOSI);         //RP2040系 SPI0 ピン設定
  SPI.setSCK(SD_SCK);
  SPI.setRX(SD_MISO);
  SPI.setCS(SD_CS);

  //SPIを指定ピンにするために、CSとSPIオブジェクトを使用するオーバーライド関数を使用する。
  if (SD.begin(SD_CS, SPI) == false)
  {
    Serial.println("initialization failed.");   //SDカードモジュールの初期化に失敗したらポーリング
    while (1);
  }

  myFile = SD.open(FILENAME, FILE_WRITE);       //追記モードでオープン
}

void loop()
{
  char buf = 0;

  //COMに入力があったか : 0 = なし / else = 入力あり
  if(Serial.available() != 0)
  {
    buf = Serial.read();                   
  
    if(buf == 0x1a)                             //入力コードが 0x1a(CTRL + z)の場合
    {
        myFile.close();                         //終了コードの場合ファイルを閉じてポーリングする。
        Serial.printf("Closed file.");
        while(1);
    }

    //終了コードではない場合、ファイルへ保存する。
    myFile.printf("%c", buf);
  }
}

結果

Teratermを使ってCOM接続しました。
今回 “COM120″で認識されています。
ローカルエコーはONにして、入力した文字がわかるようにしています。

今回実験として、”tamanegi” + enter, “たまねぎ” + enter を入力し、CTRL + zを入力しています。
enterはCR(キャリッジリターン)なので、改行しないで行の先頭に移動するので、Teraterm上の文字は上書きされていきます。

最後のCTRL + z を入力したところで、”Closed file.”が表示されました。

この状態でSDカードを取り出して、パソコンのSDカードリーダに挿入すると”sample.txt”ができていました。
開くと “tamanegi”と”たまねぎ”の記載がありました。

このSDカードを再びSDカードモジュールに戻してYD RP2040をリセットすることで、この続きに入力した文字が追記されていきます。

ファイルから読み出し

SDカードカードから指定したファイルを読み取りモードで開きます。

読み取ったデータをCOMに送信します。
すべて読み取りが終わったら “–EOF–“をCOMに送信します。

スケッチ

/**********************************************************************
【ライセンスについて】
Copyright(c) 2022 by tamanegi
Released under the MIT license
'http://tamanegi.digick.jp/about-licence/

【スケッチの説明】
SDカードのsample.txtがあれば読み取りを開始します。
読み取ったデータをCOMに送信します。
すべて読み取った後に、"--EOF--"をCOMに送信します。

【ライブラリ】
不要

【準備】
YD RP2040     SD Card Module
GND       <-> GND
Vout      <-> VCC
GP16      <-> MISO
GP19      <-> MOSI
GP18      <-> SCK
GP17      <-> CS

【参考】
'http://www.musashinodenpa.com/arduino/ref/index.php

【バージョン情報】
2022/9/21 : 新規
**********************************************************************/

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

//SPI0 を使用するためのピン番号定義
#define SD_MOSI 19
#define SD_SCK  18
#define SD_CS   17
#define SD_MISO 16

#define FILENAME "sample.txt" //保存ファイル名
File myFile;                  //ファイル操作オブジェクト

void setup()
{
  delay(500);                 //ウエイトを入れてから起動しないとシリアルが出力されない。

  Serial.begin(115200);       //COMオープン。今回ここから入力の有った文字をファイルに保存します。

  SPI.setTX(SD_MOSI);         //RP2040系 SPI0 ピン設定
  SPI.setSCK(SD_SCK);
  SPI.setRX(SD_MISO);
  SPI.setCS(SD_CS);

  //SPIを指定ピンにするために、CSとSPIオブジェクトを使用するオーバーライド関数を使用する。
  if (SD.begin(SD_CS, SPI) == false)
  {
    Serial.println("initialization failed.");   //SDカードモジュールの初期化に失敗したらポーリング
    while (1);
  }

  //読み取りモードでファイルを開く
  myFile = SD.open(FILENAME, FILE_READ);
  if (myFile == false) 
  {
    Serial.println("open file failed.");
    while(1);
  }

  char buf = 0;

  //ファイルにデータがなくなるまで繰り返す
  while (myFile.available() != 0)
  {
    buf = myFile.read();
    
    //読みだしたテキストファイルの改行コード(0x0d)では、Teraterm上では先頭移動になるだけで
    //以前の読み出した文字が上書きされてしまうため、次の行へ移動させる処理
    if(buf == 0x0d)Serial.println("");        
    
    Serial.write(buf);              //読み取ったデータをCOMに出力
  }
  myFile.close();                             //ファイルを閉じる
  Serial.println("");
  Serial.println("--EOF--\n");

}

void loop()
{
}

結果

読み取られたファイルの内容をTeratermで確認できました。

ファイルの存在確認と削除

SDカードカードから指定したファイルを削除します。

スケッチ

/**********************************************************************
【ライセンスについて】
Copyright(c) 2022 by tamanegi
Released under the MIT license
'http://tamanegi.digick.jp/about-licence/

【スケッチの説明】
SDカードにsample.txtの存在を確認します。
存在すれば削除します。

【ライブラリ】
不要

【準備】
YD RP2040     SD Card Module
GND       <-> GND
Vout      <-> VCC
GP16      <-> MISO
GP19      <-> MOSI
GP18      <-> SCK
GP17      <-> CS

【参考】
'http://www.musashinodenpa.com/arduino/ref/index.php

【バージョン情報】
2022/9/23 : 新規
**********************************************************************/
// ライブラリのインクルード
#include <SD.h>     // SD関連
#include <SPI.h>    // SPI関連
 
//SPI0 を使用するためのピン番号定義
#define SD_MOSI 19
#define SD_SCK  18
#define SD_CS   17
#define SD_MISO 16

#define FILENAME "sample.txt" //保存ファイル名
 
void setup()
{
  bool bSDResult = false;

  delay(500);
  Serial.begin(115200);
  Serial.print("");
 
  SPI.setTX(SD_MOSI);         //RP2040系 SPI0 ピン設定
  SPI.setSCK(SD_SCK);
  SPI.setRX(SD_MISO);
  SPI.setCS(SD_CS);
 
  bSDResult = SD.begin(SD_CS, SPI);
  if(bSDResult == true)
  {
    //ファイルの存在確認 : false = 無い / true = 有る
    if(SD.exists(FILENAME) == true)
    {
      SD.remove(FILENAME);      //ファイルの削除
Serial.println("削除成功");
    }
    else                        //ファイルが見つからなかった場合
    {
Serial.println("ファイルが見つかりません");
    }
  }
}
 
void loop()
{
 
}

結果

結果の出力はTeratermに表示させます。

SDカードにはsample.txt を作成します。(内容は空です。)
SDカードはSDカードモジュールに挿入してマイコンの電源を入れます。

Teraterm上には”削除成功”のメッセージが表示されました。
SDカードをパソコンで読み取らせるとsample.txtが削除されていました。

再びSDカードをSDカードモジュールに挿入して、マイコンからRESETにより再起動させます。
(SDカードにはsample.txtは削除されていて存在しません)
Teraterm上には”ファイルが見つかりません”と表示されました。

ファイルとフォルダのサイズとリストの作成

SDカードカードの指定したフォルダからファイルとフォルダのサイズとリストを作成します。
フォルダ名は ‘/’で区切ります。

今回SDカードのルートフォルダを検索してリストを作成します。

スケッチ

/**********************************************************************
【ライセンスについて】
Copyright(c) 2022 by tamanegi
Released under the MIT license
'http://tamanegi.digick.jp/about-licence/

【スケッチの説明】
SDカードの指定したフォルダからファイルとフォルダのサイズとリストを作成します。
ファイルの場合は F, フォルダ(ディレクトリ)の場合は Dを先頭につけます。
続いて見つかった番号、ファイル名、ファイルサイズの順で表示します。

【ライブラリ】
不要

【準備】
YD RP2040     SD Card Module
GND       <-> GND
Vout      <-> VCC
GP16      <-> MISO
GP19      <-> MOSI
GP18      <-> SCK
GP17      <-> CS

【参考】
'http://www.musashinodenpa.com/arduino/ref/index.php

【バージョン情報】
2022/9/21 : 新規
**********************************************************************/


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

//SPI0 を使用するためのピン番号定義
#define SD_MOSI 19
#define SD_SCK  18
#define SD_CS   17
#define SD_MISO 16

File tFiles;      //Fileオブジェクト

void setup()
{

  delay(500);
  Serial.begin(115200);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  SPI.setTX(SD_MOSI);         //RP2040系 SPI0 ピン設定
  SPI.setSCK(SD_SCK);
  SPI.setRX(SD_MISO);
  SPI.setCS(SD_CS);

  //SPIを指定ピンにするために、CSとSPIオブジェクトを使用するオーバーライド関数を使用する。
  if (SD.begin(SD_CS, SPI) == false)
  {
    Serial.println("initialization failed.");   //SDカードモジュールの初期化に失敗したらポーリング
    while (1);
  }
  tFiles = SD.open("/");        //ルートフォルダ(/)のファイルをすべて読み取る。

  File tNewFile;
  int iFileIndex = 1;

  while(1)
  {
    tNewFile = tFiles.openNextFile();      //ルートフォルダの見つかったリストがまだあるか?
    if(tNewFile == 0)break;

    //見つかったリストがファイルなら F, ディレクトリ(フォルダ)ならF を表示
    if(tNewFile.isDirectory() == true)
    {
      Serial.printf("D ");
    }
    else
    {
      Serial.printf("F ");
    }

    //見つかったインデックス、ファイル名、ファイルサイズを表示する
    Serial.printf("%02d : %s : %d\n", iFileIndex, tNewFile.name(), tNewFile.size());        //見つかった番号とファイル名をシリアル出力
    iFileIndex ++;
  }

  tNewFile.close();
  tFiles.close();

}

void loop()
{
}

結果

結果の出力はシリアルモニタに出力させます。

Windows上では、ファイルサイズをKB(キロバイト)で表示していますが、
ArduinoではByte(バイト)単位で読みだしています。

一番先頭に表示された System Volume Information ファイルのシステムに関するフォルダで、非常に重要なフォルダであるが気にしてはいけないフォルダなので無いものとして考えてください。

Raspberry Pi Pico関連リンク

コメント

タイトルとURLをコピーしました