如果要在 Arduino 紀錄感測元件接收的數值,除了透過網路模組送出以外,開發板本身並不像 Raspberry Pi有外接 SD 或 Micro SD卡的介面,可以儲存在記憶卡上,要寫入資料到 SD卡上,就必須透過 SPI 的介面,才能將感測的資料寫入 SD卡。
[材料]
• Arduino Uno x 1
• SD 卡模組 x1
• 連接線 x 6條
• SD 卡模組連接線路
SPI匯流排規定了4個保留邏輯訊號介面:(維基百科)
• SCLK (Serial Clock):串行時鐘,由主機發出
• MOSI (Master Output,Slave Input):主機輸出從機輸入訊號,由主機發出
• MISO (Master Input,Slave Output):主機輸入從機輸出訊號,由從機發出
• SS (Slave Selected) 或 Chip Select (CS):由主機發出,低電位有效
有關SPI的說明,可參考這篇:「Raspberry Pi 筆記(二):GPIO接腳與 I2C 及 SPI 安裝」。
• 初始設定 SD卡及函式庫:SD.begin(cspin)
cspin (選項): Arduino 連接SD卡模組 SS 或 CS的 Pin腳
• 檢查括號內的檔案名稱是否存在:exists()
• 建立目錄:SD.mkdir(filename)
• 開啟檔案:SD.open(filepath, mode)
mode : FILE_READ 開啟唯讀檔案,從檔案開始處讀取.
FILE_WRITE 開啟讀寫檔案,從檔案最後處開始寫入
• 移除檔案:SD.remove(filename)
• 移除目錄:SD.rmdir(filename)
File Class
• 關閉檔案:file.close()
• 將data 字串寫到檔案中,不跳行:file.print(data)
• 將data 字串寫到檔案中,不跳行:file.println(data)
• 將 data 字串寫入檔案中:file.write(data)
• SD 卡模組 x1
• 連接線 x 6條
[接線圖]
• 註:上圖 DI 代表 SD卡模組 MOSI,DO代表 SD卡模組 MISO• SD 卡模組連接線路
SD
卡模組
|
Arduino
|
GND
|
GND
|
+5V
|
5V
|
CS
|
Pin 4
|
MOSI
|
Pin 11
|
SCK (CLK)
|
Pin 13
|
MISO
|
Pin 12
|
• SCLK (Serial Clock):串行時鐘,由主機發出
• MOSI (Master Output,Slave Input):主機輸出從機輸入訊號,由主機發出
• MISO (Master Input,Slave Output):主機輸入從機輸出訊號,由從機發出
• SS (Slave Selected) 或 Chip Select (CS):由主機發出,低電位有效
有關SPI的說明,可參考這篇:「Raspberry Pi 筆記(二):GPIO接腳與 I2C 及 SPI 安裝」。
[SD Library]
SD Class• 初始設定 SD卡及函式庫:SD.begin(cspin)
cspin (選項): Arduino 連接SD卡模組 SS 或 CS的 Pin腳
• 檢查括號內的檔案名稱是否存在:exists()
• 建立目錄:SD.mkdir(filename)
• 開啟檔案:SD.open(filepath, mode)
mode : FILE_READ 開啟唯讀檔案,從檔案開始處讀取.
FILE_WRITE 開啟讀寫檔案,從檔案最後處開始寫入
• 移除檔案:SD.remove(filename)
• 移除目錄:SD.rmdir(filename)
File Class
• 關閉檔案:file.close()
• 將data 字串寫到檔案中,不跳行:file.print(data)
• 將data 字串寫到檔案中,不跳行:file.println(data)
• 將 data 字串寫入檔案中:file.write(data)
[程式]
我參考Arduino IDE的兩個範例 cardinfo 跟 files,試著在 SD卡上,顯示 SD 卡的相關資訊,再建立一個檔案,寫入測試文字後,關閉檔案。以下是執行的測試程式:#include <SPI.h>
#include <SD.h>
File myFile;
// 設定 SD library 功能變數:
Sd2Card card;
SdVolume volume;
SdFile root;
const int chipSelect = 4;
void setup() {
Serial.begin(9600); // 開啟通訊串列埠開啟
while (!Serial) { // 等待串列埠連線
}
//----------- 寫入檔案
Serial.print("\nWaiting for SD card ready...");
if (!SD.begin(4)) {
Serial.println("Fail!");
return;
}
Serial.println("Success!");
myFile = SD.open("card.txt", FILE_WRITE); // 開啟檔案,一次僅能開啟一個檔案
if (myFile) { // 假使檔案開啟正常
Serial.print("Write to card.txt...");
myFile.println("Test to write data to SD card..."); // 繼續寫在檔案後面
myFile.close(); // 關閉檔案
Serial.println("Completed!");
} else {
Serial.println("\n open file error "); // 無法開啟時顯示錯誤
}
//----------- 顯示SD 卡資訊
if (!card.init(SPI_HALF_SPEED, chipSelect)) {
Serial.println("initialization failed. Check: SD Card");
return;
} else {
Serial.println("============= Card Information ==================");
}
// 顯示SD卡類型
Serial.print("Card type: ");
switch (card.type()) {
case SD_CARD_TYPE_SD1:
Serial.println("SD1");
break;
case SD_CARD_TYPE_SD2:
Serial.println("SD2");
break;
case SD_CARD_TYPE_SDHC:
Serial.println("SDHC");
break;
default:
Serial.println("Unknow");
}
// Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
if (!volume.init(card)) {
Serial.println("Could not find FAT16/FAT32 partition.");
return;
}
// 顯示類型和 FAT 空間大小
uint32_t volumesize;
Serial.print("Volume type is FAT");
Serial.println(volume.fatType(), DEC);
Serial.println();
volumesize = volume.blocksPerCluster(); // clusters are collections of blocks
volumesize *= volume.clusterCount(); // we'll have a lot of clusters
volumesize *= 512; // SD card blocks are always 512 bytes
Serial.print("Volume size (bytes): ");
Serial.println(volumesize);
Serial.print("Volume size (Kbytes): ");
volumesize /= 1024;
Serial.println(volumesize);
Serial.print("Volume size (Mbytes): ");
volumesize /= 1024;
Serial.println(volumesize);
Serial.println("\nFiles found on the card (name, date and size in bytes): ");
root.openRoot(volume);
// list all files in the card with date and size
root.ls(LS_R | LS_DATE | LS_SIZE);
Serial.println("================= Finished =====================");
}
void loop() { // 在Setup()執行完成後,就等結束
}
[執行結果]
換上W5100網路擴展板,程式一個字元都不需要更改,可以讀取擴展板上的 SD卡資料。我的 SD卡上有中文名稱,就會顯示部分中文沒問題,但大多數變成亂碼。檔案列表第一個 card.txt 就是測試時寫入的檔案。[參考資料]
• Arduino.cc :SD Library


你好:我是arduino的初學者,想請問你SD 卡模組的型號是??在哪裡購買的??謝謝
回覆刪除你好;我看一下SD卡上沒有標示型號,我有一個SD卡模組,另一個是Micro SD卡模組。前者是在台北光華商場買的,後者是在拍賣網路買的,只要是SPI介面,應該都可以用。
刪除感謝分享
回覆刪除您好:想請問一下 因為我有另外接一個RTC的時鐘模組,因此我有時間的數據
回覆刪除那麼是否可以讓檔案名稱變為日期
EX:今天是2018.01.23,那麼檔案名稱便為"2018.01.23.txt"這樣
不好意思麻煩您了,謝謝您!
您好,在網路擴展板,連接網路的時候,需要做SSID跟password的設定。
回覆刪除是否有辦法讓網路擴展板去讀取SSID跟password、讓控制板直接連網呢?
我想請問一下 怎麼寫入Flash memory
回覆刪除你好:
回覆刪除我剛開始學
想請問文章中的SD Library那邊的設定要從哪邊開始操作?
你好,
刪除要載入SD Library,可以從Arduino的IDE選單,選擇「草稿碼」-> 「匯入程式庫」->「管理程式庫」,輸入 SD Library, 再安裝即可。有關Library安裝,可參考這裡的說明https://atceiling.blogspot.com/2019/09/arduino-arduino-ide-library.html
張貼留言