如果要在 Arduino 紀錄感測元件接收的數值,除了透過網路模組送出以外,要寫入資料到 SD卡上,就必須透過 SPI 的介面,才能將感測的資料寫入 SD卡。
[材料]
• Arduino Uno x 1
• SD 卡模組 x1
• 杜邦連接線 x 6條
SPI匯流排規定了4個保留邏輯訊號介面:(維基百科)
• SCLK (Serial Clock):串行時鐘,由主機發出
• MOSI (Master Output,Slave Input):主機輸出從機輸入訊號,由主機發出
• MISO (Master Input,Slave Output):主機輸入從機輸出訊號,由從機發出
• SS (Slave Selected) 或 Chip Select (CS):由主機發出,低電位有效
開啟Arduino IDE檔案->範例->SD的範例程式,執行各範例內容。
注意範例檔中,各接腳的位置務必正確,MOSI及MISO勿接反。VCC接到5V。
可先測試Cardinfo範例,可在串列埠視窗獲得SD卡資訊。
執行listfiles範例,可在串列埠視窗獲得SD卡內檔案資訊。
執行ReadWrite範例,可產生一個test.txt檔,並寫入資料。
以下為ReadWrite範例,可看到在setup()執行了一次寫入及讀取動作。
試著找出setup()的寫入動作程式碼片段,及讀取動作程式碼片段,改放在loop迴圈內,分別製成兩個檔案,可分別執行寫入及讀取。
myFile = SD.open("test.txt", FILE_WRITE); 將test.txt設定為寫入,並設為myFile物件內容。
寫入動作為:
先以SD.open();打開檔案
再以print()或println()寫入字串內容到SD卡。
最後再以close();關閉檔案。
讀取動作為
先以SD.open();打開檔案
再以read()讀取SD卡內檔案字串內容。
最後再以close();關閉檔案。
/*
SD card read/write
This example shows how to read and write data to and from an SD card file
The circuit:
* SD card attached to SPI bus as follows:
** MOSI - pin 11
** MISO - pin 12
** CLK - pin 13
** CS - pin 4 (for MKRZero SD: SDCARD_SS_PIN)
created Nov 2010
by David A. Mellis
modified 9 Apr 2012
by Tom Igoe
This example code is in the public domain.
*/
#include <SPI.h>
#include <SD.h>
File myFile; //宣告物件 myFile
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.print("Initializing SD card...");
if (!SD.begin(4)) {
Serial.println("initialization failed!");
while (1);
}
Serial.println("initialization done.");
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
myFile = SD.open("test.txt", FILE_WRITE);
// if the file opened okay, write to it:
if (myFile) {
Serial.print("Writing to test.txt...");
myFile.println("testing 1, 2, 3."); //將testing 1,2,3寫入記憶卡內的test.txt
// close the file:
myFile.close();
Serial.println("done.");
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
// re-open the file for reading:
myFile = SD.open("test.txt");
if (myFile) {
Serial.println("test.txt:");
// read from the file until there's nothing else in it:
while (myFile.available()) {
Serial.write(myFile.read());
}
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
}
void loop() {
// nothing happens after setup
}
SD.begin() //初始化SD函示庫及SD卡 SD.begin(cspin)
cspin (選項): Arduino 連接SD卡模組 SS 或 CS的 Pin腳,此例為4號腳
SD.exists() //檢查括號內名稱的資料夾或檔案是否存在 SD.exists(filename)
SD.mkdir() //建立括號內名稱的資料夾 SD.mkdir(dir_name)
SD.open() //開啟括號內名稱的資料夾或檔案 SD.open(filepath) (若檔案不存在會自動建立)
SD.remove() //刪除括號內名稱的檔案 SD.remove(filename)
SD.rmdir() //刪除括號內名稱的資料夾 SD.rmdir(dir_name)
file.name() // 回傳檔案名稱 file.name()
file.available() // 檢查檔案是否有可讀取的有效資料
file.flush() // 檔案關閉時會自動確實寫入修改的資料存到 SD 卡
file.close()//關閉檔案。
file.position() // 取得文件正在寫入的位置
file.print() // 將data 字串寫到檔案中,不跳行 。file為檔案名稱。( )若有" "則寫入" "內的文字,若要寫入變數,則刮號內直接寫變數名稱。
例如:filr.print("i"),寫入i。若為filr.print(i)則寫入變數i的內容。
Print data to the file, which must have been opened for writing. Prints numbers as a sequence of digits, each an ASCII character
file.print(data) file.print(data, BASE)
BASE (optional): the base in which to print numbers: BIN for binary (base 2), DEC for decimal (base 10), OCT for octal (base 8), HEX for hexadecimal (base 16).
file.println() // 字串寫到檔案中,且跳行 Print data, followed by a carriage return and newline, to the File, which must have been opened for writing.
file.println() file.println(data) file.print(data, BASE)
data (optional): the data to print (char, byte, int, long, or string)
BASE (optional): the base in which to print numbers: BIN for binary (base 2), DEC for decimal (base 10), OCT for octal (base 8), HEX for hexadecimal (base 16)
file.seek() // Print data, followed by a carriage return and newline, to the File, which must have been opened for writing.
file.seek(pos)
file.size() // 取得檔案大小 file.size()
file.read() // 讀取檔案資料 file.read() file.read(buf, len)
file.write() // 寫入資料到檔案 file.write(data) file.write(buf, len)
file.isDirectory() // 判斷開啟的檔案是否為資料夾 file.isDirectory()
file.openNextFile() //
file.rewindDirectory() //
/*
SD card read/write
This example shows how to read and write data to and from an SD card file
The circuit:
* SD card attached to SPI bus as follows:
** MOSI - pin 11
** MISO - pin 12
** CLK - pin 13
** CS - pin 4 (for MKRZero SD: SDCARD_SS_PIN)
created Nov 2010
by David A. Mellis
modified 9 Apr 2012
by Tom Igoe
This example code is in the public domain.
*/
#include <SPI.h>
#include <SD.h>
File myFile;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.print("Initializing SD card...");
if (!SD.begin(4)) {
Serial.println("initialization failed!");
while (1);
}
Serial.println("initialization done.");
}
void loop() {
// re-open the file for reading:
myFile = SD.open("test.txt");
if (myFile) {
Serial.println("test.txt:");
// read from the file until there's nothing else in it:
while (myFile.available()) {
Serial.write(myFile.read());
}
delay(10000);
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
}
/*
SD card read/write
This example shows how to read and write data to and from an SD card file
The circuit:
* SD card attached to SPI bus as follows:
** MOSI - pin 11
** MISO - pin 12
** CLK - pin 13
** CS - pin 4 (for MKRZero SD: SDCARD_SS_PIN)
created Nov 2010
by David A. Mellis
modified 9 Apr 2012
by Tom Igoe
This example code is in the public domain.
*/
#include <SPI.h>
#include <SD.h>
#include "DHT.h" // 匯入DHT函式庫
#define DHTPIN 2 // 定義DHT函式庫中,所使用的訊號來源
#define DHTTYPE DHT22 // 定義DHT函式庫中,所使用的感測器
DHT dht(DHTPIN, DHTTYPE);
File myF;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.print("Initializing SD card...");
dht.begin();
}
void loop() {
int dhtT = dht.readTemperature(); //設定浮點變數dhtT,讀取溫度
int dhtH = dht.readHumidity(); //設定浮點變數dhtH,讀取濕度
if (!SD.begin(4)) {
Serial.println("initialization failed!");
while (1);
}
Serial.println("initialization done.");
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
myF = SD.open("clock.txt", FILE_WRITE);
// if the file opened okay, write to it:
if (myF) {
Serial.print("Writing to clock.txt...");
myF.print(dhtT);
myF.print(",");
myF.println(dhtH);
delay(10000);
// close the file:
myF.flush();
myF.close();
Serial.println("done.");
} else {
// if the file didn't open, print an error:
Serial.println("error opening clock.txt");
}
}
修改範例的Datalogger檔案
#include <SPI.h>
#include <SD.h>
#include "DHT.h" // 匯入DHT函式庫
#define DHTPIN 2 // 定義DHT函式庫中,所使用的訊號來源
#define DHTTYPE DHT22 // 定義DHT函式庫中,所使用的感測器
DHT dht(DHTPIN, DHTTYPE);
const int chipSelect = 4;
String dataString = "T,H";
unsigned long Interval=3600000;
unsigned long previoustime=millis();
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.print("Initializing SD card...");
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
// don't do anything more:
while (1);
}
Serial.println("card initialized.");
dht.begin(); //啟動dht
File dataFile = SD.open("datalog.txt", FILE_WRITE);
// if the file is available, write to it:
if (dataFile) {
dataFile.println(dataString);
dataFile.close();
}
}
void loop() {
// make a string for assembling the data to log:
if(millis()-previoustime>=Interval){
previoustime=millis();
float dhtT = dht.readTemperature(); //設定浮點變數dhtT,讀取溫度
float dhtH = dht.readHumidity(); //設定浮點變數dhtH,讀取濕度
// read three sensors and append to the string:
dataString = (String(dhtT,2));
dataString += ",";
dataString += (String(dhtH,2));
//dataString +="\r\n";
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
File dataFile = SD.open("datalog.txt", FILE_WRITE);
// if the file is available, write to it:
if (dataFile) {
dataFile.println(dataString);
dataFile.close();
// print to the serial port too:
Serial.println(dataString);
}
// if the file isn't open, pop up an error:
else {
Serial.println("error opening datalog.txt");
}
}
}
讀取寫入的溫度內容
/*
SD card read/write
This example shows how to read and write data to and from an SD card file
The circuit:
SD card attached to SPI bus as follows:
** MOSI - pin 11
** MISO - pin 12
** CLK - pin 13
** CS - pin 4 (for MKRZero SD: SDCARD_SS_PIN)
created Nov 2010
by David A. Mellis
modified 9 Apr 2012
by Tom Igoe
This example code is in the public domain.
*/
#include <SPI.h>
#include <SD.h>
File myF;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.print("Initializing SD card...");
if (!SD.begin(4)) {
Serial.println("initialization failed!");
while (1);
}
Serial.println("initialization done.");
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
myF = SD.open("clock.txt", FILE_WRITE);
// if the file opened okay, write to it:
// re-open the file for reading:
myF = SD.open("clock.txt");
if (myF) {
Serial.println("clock.txt");
// read from the file until there's nothing else in it:
while (myF.available()) {
Serial.write(myF.read());
}
// close the file:
myF.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
}
void loop() {
// nothing happens after setup
}