基于Arduino的SD卡数据记录全攻略
1. 准备工作
在开始使用SD卡与Arduino进行交互之前,需要确保SD卡已正确格式化。格式化完成后,就可以通过SD卡扩展板开始与SD卡进行交互了。
2. Arduino与SD卡的连接
SD卡是3.3V设备,因此需要通过能正确处理逻辑电平转换和电压供应的扩展板来连接SD卡。Arduino与SD卡通过SPI(Serial Peripheral Interface)总线进行通信,Arduino语言提供了SD库,它抽象了底层的SPI通信,让我们可以轻松读写SD卡上存储的文件。
3. SD卡扩展板介绍
有多种扩展板可用于为Arduino添加数据记录功能,下面是一些常见扩展板的介绍:
| 扩展板名称 | 特点 | CS引脚 | 其他特点 |
| — | — | — | — |
| Cooking Hacks Micro SD shield | 体积小,可连接到Uno的8 - 13引脚或ICSP 6引脚头,自带2GB SD卡 | 连接8 - 13引脚时为10;连接ISP头时可自定义 | 适合与其他需要使用引脚10的扩展板配合使用 |
| Official Arduino Wireless SD shield | 支持XBee无线电和SD卡,便于结合无线通信和数据记录功能 | 4 | 需将引脚10设为输出 |
| Official Arduino Ethernet SD shield | 可让Arduino连接有线网络,同时具备SD卡接口 | 4(SD卡),10(以太网控制器) | 主要用于通过网络访问存储的文件 |
| Official Arduino Wi - Fi SD shield | 利用Wi - Fi无线电实现网络连接,具备SD卡接口 | 4(SD卡),10(Wi - Fi控制器) | 同一时间只能激活一个CS线 |
| adafruit data logging shield | 包含实时时钟(RTC)芯片和SD卡接口 | 默认CS引脚 | 适合后续实验,RTC芯片连接到I2C总线 |
| SparkFun MicroSD shield | 简约设计,只有SD卡插槽,有原型制作区域 | 8 | 可焊接额外组件 |
所有扩展板的共同点如下:
- 通过6引脚编程头或复用数字引脚连接到SPI引脚。Uno的SPI引脚是11、12和13,Mega板是50、51和52,Leonardo的SPI引脚仅位于在线串行编程(ICSP)头。
- 指定一个芯片选择(CS)引脚,可能是默认的CS引脚(非Mega板为10,Mega板为53)。
- 为SD卡提供3.3V电压并进行逻辑电平转换。
4. SD卡SPI接口
Arduino通过SPI接口与SD卡通信,需要使用MOSI(主输出,从输入)、MISO(主输入,从输出)、SCLK(串行时钟)和CS(芯片选择)引脚。使用Arduino的SD卡库时,假设使用Arduino的硬件SPI引脚和默认或自定义的CS引脚。即使使用不同的CS引脚,SD卡库也必须将默认CS引脚设置为输出才能正常工作。对于Uno,默认CS引脚是10;对于Mega,是53。
5. 向SD卡写入数据
首先,使用SD卡库向SD卡写入一些示例数据。数据将存储在名为log.csv的文件中,后续可以在计算机上打开。如果SD卡格式化为FAT16,文件名必须遵循8.3格式,即扩展名必须为三个字符,文件名必须为八个字符或更少。
以下是写入数据的具体步骤和代码示例:
1. 确保SD扩展板正确安装在Arduino上,并插入SD卡。
2. 初始化SD卡通信:
if (!SD.begin(CS_pin))
{
Serial.println("Card Failure");
return;
}
Serial.println("Card Ready");
- 写入新数据行:
File dataFile = SD.open("log.csv", FILE_WRITE);
if (dataFile)
{
dataFile.println("hello");
dataFile.close(); // 关闭连接后数据才会写入!
}
else
{
Serial.println("Couldn't open log file");
}
- 完整的写入测试代码如下:
//Write to SD card
#include <SD.h>
//Set by default for the SD card library
//MOSI = pin 11
//MISO = pin 12
//SCLK = pin 13
//We always need to set the CS Pin
const int CS_PIN = 10;
//We set this high to provide power
const int POW_PIN = 8;
void setup()
{
Serial.begin(9600);
Serial.println("Initializing Card");
//CS pin is an output
pinMode(CS_PIN, OUTPUT);
//Card will draw power from pin 8, so set it high
pinMode(POW_PIN, OUTPUT);
digitalWrite(POW_PIN, HIGH);
if (!SD.begin(CS_PIN))
{
Serial.println("Card Failure");
return;
}
Serial.println("Card Ready");
}
void loop()
{
long timeStamp = millis();
String dataString = "Hello There!";
//Open a file and write to it.
File dataFile = SD.open("log.csv", FILE_WRITE);
if (dataFile)
{
dataFile.print(timeStamp);
dataFile.print(",");
dataFile.println(dataString);
dataFile.close(); //Data isn't actually written until we
//close the connection!
//Print same thing to the screen for debugging
Serial.print(timeStamp);
Serial.print(",");
Serial.println(dataString);
}
else
{
Serial.println("Couldn't open log file");
}
delay(5000);
}
需要注意的是:
- CS_PIN应设置为SD卡CS引脚连接的实际引脚。如果不是10,还需要在
setup()
函数中添加
pinMode(10, OUTPUT)
,否则SD库将无法工作。
- 该扩展板从引脚8获取电源,因此需要在
setup
函数中将POW_PIN设置为输出并置为高电平。
- 每次循环时,
timestamp
变量会更新为当前经过的毫秒数,由于其值可能超过16位,因此必须为
long
类型。
6. 从SD卡读取数据
虽然读取SD卡数据在数据记录中使用频率不如写入高,但在设置程序参数时很有用。例如,可以指定数据记录的频率。
以下是读取数据的步骤和代码示例:
1. 将SD卡插入计算机,创建一个名为
speed.txt
的新TXT文件,在文件中输入所需的刷新时间(毫秒)。
2. 将文件保存到SD卡,然后将SD卡放回Arduino扩展板。
3. 修改程序以读取该文件并设置数据记录的刷新速度:
File commandFile = SD.open("speed.txt");
if (commandFile)
{
Serial.println("Reading Command File");
while(commandFile.available())
{
refresh_rate = commandFile.parseInt();
}
Serial.print("Refresh Rate = ");
Serial.print(refresh_rate);
Serial.println("ms");
}
else
{
Serial.println("Could not read command file.");
return;
}
- 整合读写功能的完整代码如下:
//SD read and write
#include <SD.h>
//Set by default for the SD card library
//MOSI = pin 11
//MISO = pin 12
//SCLK = pin 13
//We always need to set the CS pin
const int CS_PIN =10;
const int POW_PIN =8;
//Default rate of 5 seconds
int refresh_rate = 5000;
void setup()
{
Serial.begin(9600);
Serial.println("Initializing Card");
//CS pin is an output
pinMode(CS_PIN, OUTPUT);
//Card will draw power from pin 8, so set it high
pinMode(POW_PIN, OUTPUT);
digitalWrite(POW_PIN, HIGH);
if (!SD.begin(CS_PIN))
{
Serial.println("Card Failure");
return;
}
Serial.println("Card Ready");
//Read the configuration information (speed.txt)
File commandFile = SD.open("speed.txt");
if (commandFile)
{
Serial.println("Reading Command File");
while(commandFile.available())
{
refresh_rate = commandFile.parseInt();
}
Serial.print("Refresh Rate = ");
Serial.print(refresh_rate);
Serial.println("ms");
commandFile.close(); //Close the file when finished
}
else
{
Serial.println("Could not read command file.");
return;
}
}
void loop()
{
long timeStamp = millis();
String dataString = "Hello There!";
//Open a file and write to it.
File dataFile = SD.open("log.csv", FILE_WRITE);
if (dataFile)
{
dataFile.print(timeStamp);
dataFile.print(",");
dataFile.println(dataString);
dataFile.close(); //Data isn't actually written until we
//close the connection!
//Print same thing to the screen for debugging
Serial.print(timeStamp);
Serial.print(",");
Serial.println(dataString);
}
else
{
Serial.println("Couldn't open log file");
}
delay(refresh_rate);
}
7. 使用实时时钟
几乎所有数据记录应用都能从使用实时时钟中受益。使用实时时钟可以为测量数据添加时间戳,方便跟踪事件发生的时间。
7.1 实时时钟原理
实时时钟能精确计时,设置一次时间后,它能准确计时,甚至能处理闰年等情况。这里使用流行的DS1307实时时钟集成电路。
7.2 使用DS1307实时时钟
实时时钟通过I2C连接与Arduino通信,并连接到硬币电池,可保持数年计时。连接到实时时钟的晶体振荡器可实现精确计时。建议使用adafruit DS1307 breakout板,它将IC、振荡器、硬币电池、去耦电容和I2C上拉电阻集成在一起,方便安装在Arduino上。
如果选择自己组装,需要的组件有:32.768kHz的晶体、2.2千欧的I2C上拉电阻和标准3.0V硬币电池,可将这些组件放在面包板上并直接连接到Arduino。
以下是整个操作流程的mermaid流程图:
graph TD;
A[准备SD卡] --> B[选择扩展板并连接到Arduino];
B --> C[写入数据到SD卡];
C --> D[从SD卡读取数据];
D --> E[使用实时时钟添加时间戳];
通过以上步骤,我们可以利用Arduino和SD卡实现数据的记录、读取以及精确的时间记录,为各种数据采集和处理应用提供了强大的支持。
基于Arduino的SD卡数据记录全攻略
8. 常见问题及解决方法
在使用Arduino与SD卡进行数据记录的过程中,可能会遇到一些常见问题,以下是这些问题及相应的解决方法:
| 问题描述 | 可能原因 | 解决方法 |
| — | — | — |
| SD卡初始化失败 | SD卡未正确插入、SD卡损坏、CS引脚设置错误 | 检查SD卡是否正确插入,尝试更换SD卡,确认CS引脚设置是否正确 |
| 无法打开日志文件 | 文件权限问题、SD卡文件系统损坏 | 检查SD卡文件系统,尝试格式化SD卡,确保文件权限正确 |
| 数据写入不完整 | 写入数据时SD卡异常、未正确关闭文件 | 检查SD卡状态,确保在写入数据后正确关闭文件 |
| 实时时钟时间不准确 | 时钟芯片未正确初始化、电池电量不足 | 重新初始化时钟芯片,更换硬币电池 |
9. 高级应用场景
除了基本的数据记录和读取功能,结合Arduino、SD卡和实时时钟,还可以实现一些高级应用场景。
9.1 传感器数据记录
可以连接各种传感器,如温度传感器、湿度传感器、光照传感器等,将传感器采集的数据实时记录到SD卡中。以下是一个简单的温度传感器数据记录示例代码:
#include <SD.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_DHT.h>
#define DHTPIN 2
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
const int CS_PIN = 10;
const int POW_PIN = 8;
void setup() {
Serial.begin(9600);
Serial.println("Initializing Card");
pinMode(CS_PIN, OUTPUT);
pinMode(POW_PIN, OUTPUT);
digitalWrite(POW_PIN, HIGH);
if (!SD.begin(CS_PIN)) {
Serial.println("Card Failure");
return;
}
Serial.println("Card Ready");
dht.begin();
}
void loop() {
float h = dht.readHumidity();
float t = dht.readTemperature();
if (isnan(h) || isnan(t)) {
Serial.println("Failed to read from DHT sensor!");
return;
}
File dataFile = SD.open("sensor_log.csv", FILE_WRITE);
if (dataFile) {
dataFile.print(millis());
dataFile.print(",");
dataFile.print(t);
dataFile.print(",");
dataFile.println(h);
dataFile.close();
Serial.print(millis());
Serial.print(",");
Serial.print(t);
Serial.print(",");
Serial.println(h);
} else {
Serial.println("Couldn't open sensor log file");
}
delay(5000);
}
9.2 远程数据传输
结合无线模块(如XBee、Wi - Fi模块),可以将SD卡中记录的数据远程传输到服务器或其他设备。以下是一个简单的Wi - Fi数据传输示例流程:
1. 连接Wi - Fi模块到Arduino。
2. 读取SD卡中的数据。
3. 通过Wi - Fi模块将数据发送到指定的服务器。
#include <SD.h>
#include <WiFi.h>
const char* ssid = "your_SSID";
const char* password = "your_PASSWORD";
const char* serverName = "your_server_address";
const int CS_PIN = 10;
const int POW_PIN = 8;
WiFiClient client;
void setup() {
Serial.begin(9600);
Serial.println("Initializing Card");
pinMode(CS_PIN, OUTPUT);
pinMode(POW_PIN, OUTPUT);
digitalWrite(POW_PIN, HIGH);
if (!SD.begin(CS_PIN)) {
Serial.println("Card Failure");
return;
}
Serial.println("Card Ready");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("Connected to WiFi");
}
void loop() {
File dataFile = SD.open("log.csv", FILE_READ);
if (dataFile) {
while (dataFile.available()) {
String line = dataFile.readStringUntil('\n');
if (client.connect(serverName, 80)) {
client.println("POST /upload.php HTTP/1.1");
client.println("Host: " + String(serverName));
client.println("Content-Type: text/plain");
client.print("Content-Length: ");
client.println(line.length());
client.println();
client.print(line);
client.stop();
}
}
dataFile.close();
}
delay(60000);
}
10. 总结与展望
通过上述内容,我们详细介绍了如何使用Arduino与SD卡进行数据记录、读取,以及如何结合实时时钟为数据添加精确的时间戳。同时,还探讨了常见问题的解决方法和一些高级应用场景。
在未来,随着技术的不断发展,我们可以进一步扩展这些功能。例如,结合机器学习算法对记录的数据进行分析,实现智能决策;利用物联网技术将多个Arduino设备连接起来,构建大规模的数据采集网络。相信在不久的将来,基于Arduino和SD卡的数据记录系统将在更多领域发挥重要作用。
以下是高级应用场景的mermaid流程图:
graph TD;
A[传感器数据记录] --> B[读取传感器数据];
B --> C[将数据写入SD卡];
D[远程数据传输] --> E[读取SD卡数据];
E --> F[通过无线模块发送数据到服务器];
通过不断探索和实践,我们可以充分发挥Arduino和SD卡的潜力,为各种数据处理和应用需求提供有效的解决方案。
超级会员免费看
1449

被折叠的 条评论
为什么被折叠?



