7687浏览
查看: 7687|回复: 4

[求助] Arduino Uno板 SD模块 与RFID模块不能共用

[复制链接]
就是用RFID模块 读卡号 然后存到SD卡上
基本上就是整合两个库函数 自带的例子
也就是MISO MOSI SCK 共用11 12 13号引脚
SD卡的片选引脚CS 接4
RFID的片选引脚CS 接10
但是现在是两个模块一旦一起接上  都不工作了,就算我只上传了RFID的例子 RFID是不工作的。只上传SD的例子,SD是可以正常工作的
把SD的正极 或者MISO线 拿掉 RFID就可以正常工作了
后来 我又在SD的MISO线上 接个电阻。但是呢RFID工作,SD的例子 又不工作了
又查了各种资料 什么SPI通讯 片选什么的 都试过了

如果有创客 同时用过这两个模块 请给下帮助 真滴谢谢了

Angelo  初级技匠

发表于 2017-8-21 14:25:13

本帖最后由 Angelo 于 2017-8-21 14:27 编辑

请问用的是哪一款 RFID 模块? 能否把型号发过来看看.

似乎是电压不匹配造成的.
还是推荐用其他的接口, 比如串口之类的.
回复

使用道具 举报

qq576193486  中级技师
 楼主|

发表于 2017-8-21 20:29:25

Angelo 发表于 2017-8-21 14:25
请问用的是哪一款 RFID 模块? 能否把型号发过来看看.

似乎是电压不匹配造成的.

型号是RC522
回复

使用道具 举报

Angelo  初级技匠

发表于 2017-8-24 14:26:02

这个型号的RFID我这边没有, 实在没办法帮你做测试啊.
实在不行的话, 可以考虑搞一个串口的RFID, 会简单很多.
回复

使用道具 举报

qq576193486  中级技师
 楼主|

发表于 2017-8-27 19:35:25

本帖最后由 qq576193486 于 2017-8-27 19:43 编辑

这几天算是解决了。(我在其他的论坛也发过相关的帖子,这个解决方案也会发在那些论坛里,如果各位在其他论坛看到,或者转载都没问题)一开始也想过,既然共用有问题,那么就不让它们共用。那么把两个模块的电源引脚单独用一个引脚去控制。
这个解决方案,应该说很不好。因为两个模块都说是用SPI通讯的,跟电源没关系。
在Google上,倒是看到过类似的情况,
有的说是要在SD模块的MISO(即主机输入,从机输出,模块向板子发送)之间加一个330R的电阻(这个方案我试过,没成功)
有的说是要在SD模块的MISO之间加个二极管,阳极接SD卡模块,阴极接板子(这个还没试过)

那么 我只把我的实现方法介绍给那些,在搞这两个模块一起用的。在弄这两个模块也发现了以前没注意到的

首先是 RFID模块:
我用的是RFID库, 整理者:极客工坊bg1lsy (lsy@sogou.com) 整理时间:2013.05.25
(这个应该蛮多人都在用的,官方有个MRC522的库,应该是基于这个库整理的)
RFID rfid(10,5) (rfid 是个名称 可以改 例 myrfid)
第一个参数 是片选引脚 也就是SDA引脚, (对于SD卡模块 片选引脚是CS引脚 ChipSelect)
然后呢有个初始化函数 rfid.init()
当RFID给电以后 只能运行一次:也就是说
RFID给电后 执行了两次rfid.init() RFID 不工作
RFID断电,重新给电后 没有执行rfid.init() RFID不工作(重新给电后 要延时一小会 再执行初始化函数)


接着是SD卡模块:
这个SD卡官方有库的
SD可以不用声明对象的
初始化函数SD.begin(4) (4就是CS引脚)成功返回true 失败返回false
这个不同于RFID的初始化
如果SD卡模块没问题,第一次执行会返回true 再次执行会返回false,但是SD卡还是能用的,比如读写文件
(我们都可以把SD卡拿下来,再插上去,都不用重启)

还有一点就是,SD卡打开的文件名字不能过长,8+3(文件名别超过8个字母,扩展名别超过3个)
当打开一个不存在的文件时,它会自动以大写字母创建一个文件
----------------------------------------------------------------
我用到了RFID模块,SD模块,舵机(也就是门禁,人比较多,板子存不下了,就加个SD卡)
功能就是RFID读卡号(这里卡号我用的是10进制),去SD卡里的记事本里面一行一行比对,如果有,就舵机动,没有就存到SD卡的一个记事本里面(把没有的存起来,这样添加更简单)
在发一大堆长代码之前,我先把一些函数功能写出来,免得看起来头疼
先写官方的:
File dataFile;//文件类型的,用来准备下一步 SD卡打开的文件
不能同时打开两个文件,也就是说,如果要打开另一个文件之前 要先关闭当前打开的文件 函数是dataFile.close()
dataFile = SD.open("people.txt");//打开文件



dataFile.available();//这个是判断文件是否读取完 常用形式就是while(dataFile.available()) 如果文件没读完 就执行这个循环


dataFile.readStringUntil('\n');//这个就是说读取到指定的字符 我这里就是说读取到换行符结束,返回的是字符串String
我用的形式 就是 String str=dataFile.readStringUntil('\n'); 这样的话 str 就是一行的字符串了
这里还有个文件指针,大概理解就是,记事本里光标的位置
当我执行完一次readStringUntil('\n')后,再次执行的时候,它是从下一行 开始读取的
这个位置向文件写东西的时候 有关 在打开文件的时候 有关


dataFile.println();//这个函数是向文件里写东西的,参数可以是字符串String 整形int 自动加换行符
那么从哪开始写的呢,这就涉及到位置了。那么对于我来说,我是希望向文件写东西的时候 是写到最后面的
这里就涉及到打开文件的方式了


SD卡打开文件:
dataFile = SD.open("people.txt");//这个打开方式 它的位置 是在最开始的(读取的时候 通常采用这种方式)
dataFile = SD.open("people.txt", FILE_WRITE);//这个打开方式 它的位置是在最末尾(写文件的时候 常采用这种)



Servo舵机:
myservo.detach();//使得舵机不加力


String的函数:
str.indexOf('/');//这个函数是在字符串中 找到第一个匹配的字符,返回字符所在位置 即整形
str.substring(0,n);//这个函数是截取字符串,第一个参数0是起始位置,第二个参数n是结束位置,返回一个新的字符串
这两个函数 结合起来用 就是
str = str.substring(0, str.indexOf('/'));
这样的话str就是/前面的字符了。我的意图就是记事本里 /前面保存卡号 /后面保存注释
例如 111111111111/XXX 修改时间:xxxx年xx月xx日


然后是我自己写的函数
void judge() 用来比较卡号的
void openTheDoor() 开门的
void readCard() 读卡号的
void turnOnSD() 这个函数先关闭RFID的电源 再给SD电源
void turnOnRFID() 这个函数先关闭SD的电源 再给RFID电源

[mw_shl_code=cpp,true]//整理者:仰望
//整理时间:2017年8月20日
#include <Servo.h>
#include <SD.h>
#include <SPI.h>
#include <RFID.h>
//---------宏定义 各个引脚------------
//---------RFID-----------------------
#define RFID_SS_PIN 10
#define RFID_RST_PIN 5
#define RFID_POWER_PIN 7//RFID的电源用引脚来控制

//---------SD-------------------------
#define SD_SS_PIN 4
#define SD_POWER_PIN 8

//---------Servo----------------------
#define Servo_PIN 9

//---------两个模块切换的时间间隔 毫秒
#define CHANGE_TIME 10


String num = "";//用字符串 存储当前读到的卡号
int pos = 0;//舵机的角度
bool flag = false;//是否开门


Servo myservo;  //声明舵机对象
RFID rfid(RFID_SS_PIN, RFID_RST_PIN);   //D10--读卡器MOSI引脚、D5--读卡器RST引脚

void turnOnRFID() {
        //关掉SD
        digitalWrite(SD_POWER_PIN, LOW);
        delay(CHANGE_TIME);
        //打开RFID
        digitalWrite(RFID_POWER_PIN, HIGH);//RFID的电源给电
        delay(CHANGE_TIME);//延时一小会 再初始化
        rfid.init();//每次重新上电 都要重新初始化
}
void turnOnSD() {
        //关掉RFID
        digitalWrite(RFID_POWER_PIN, LOW);
        delay(CHANGE_TIME);
        //打开SD
        digitalWrite(SD_POWER_PIN, HIGH);//SD的电源给电
        delay(CHANGE_TIME);
        SD.begin(SD_SS_PIN);
}
void readCard()
{
        //Serial.println("Find the card!");
        //读取卡序列号
        if (rfid.readCardSerial()) {
                num.concat(rfid.serNum[0]);//拼接字符串
                num.concat(rfid.serNum[1]);
                num.concat(rfid.serNum[2]);
                num.concat(rfid.serNum[3]);
                num.concat(rfid.serNum[4]);
                //Serial.println(num);
        }
        //选卡,可返回卡容量(锁定卡片,防止多数读取),去掉本行将连续读卡
        rfid.selectTag(rfid.serNum);
}
void openTheDoor()
{
        myservo.attach(Servo_PIN);
        for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
                                                                                          // in steps of 1 degree
                myservo.write(180);              // tell servo to go to position in variable 'pos'
                delay(5);                       // waits 15ms for the servo to reach the position
        }
        delay(3500);
        for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
                myservo.write(0);              // tell servo to go to position in variable 'pos'
                delay(5);                       // waits 15ms for the servo to reach the position
        }
        num = "";
        Serial.println(num);
        flag = false;
}
void judge()
{
        String s;//用来保存从文件读取的一行字符串(截止符'/'前面的字符串)
        Serial.println();
        int n;//用来计数的
        File dataFile;
        dataFile = SD.open("teachers.txt");//打开文件
        if (dataFile) {//判断文件是否打开成功
                n = 1;
                while (dataFile.available())//判断是否读完了整个文件
                {
                        s = dataFile.readStringUntil('\n');//读取到换行符 结束(也就是读取一行的字符串)
                                                                                           //substring 截取字符串 第一个参数是起始位置 第二个参数是结束位置
                                                                                           //indexOf 查找一个字符的位置 返回位置
                        s = s.substring(0, s.indexOf('/'));
                        if (s == num) {//判断是否找到了人
                                flag = true;//找到了人 令flag为真
                                Serial.print("Welcom Teacher ");
                                Serial.print("No.");
                                Serial.print(n);
                                Serial.print("  CARD:");
                                Serial.println(s);
                                return;
                        }
                        n++;//没找到就自增1
                }
        }
        else {
                Serial.println("error opening file teachers.txt");
        }
dataFile.close();
delay(10);
        dataFile = SD.open("students.txt");//打开文件
        if (dataFile) {//判断文件是否打开成功
                n = 1;
                while (dataFile.available())//判断是否读完了整个文件
                {
                        s = dataFile.readStringUntil('\n');//读取到换行符 结束(也就是读取一行的字符串)
                                                                                           //substring 截取字符串 第一个参数是起始位置 第二个参数是结束位置
                                                                                           //indexOf 查找一个字符的位置 返回位置
                        s = s.substring(0, s.indexOf('/'));
                        if (s == num) {//判断是否找到了人
                                flag = true;//找到了人 令flag为真
                                Serial.print("Welcom Student ");
                                Serial.print("No.");
                                Serial.print(n);
                                Serial.print("  CARD:");
                                Serial.println(s);
                                return;
                        }
                        n++;//没找到就自增1
                }
        }
        else {
                Serial.println("error opening file students.txt");
        }
        if (!flag)
        {//如果是未注册的 就写到unexist.txt文件里 方便社员自己加入卡
    dataFile.close();
    delay(10);
                Serial.print("Unregistered CARD: ");
                Serial.println(num);
                dataFile = SD.open("unexist.txt", FILE_WRITE);
                if (dataFile) {
                        dataFile.println(num + "/");
                }
                //没打开文件
                else {
                        Serial.println("error opening file unexist.txt");
                }
        }
dataFile.close();
delay(10);
}
void setup()
{
        pinMode(RFID_POWER_PIN, OUTPUT);
        pinMode(SD_POWER_PIN, OUTPUT);
        Serial.begin(9600);
        SPI.begin();
        myservo.attach(Servo_PIN);//舵机的初始化
        myservo.write(0);
        delay(100);
        //   member=sizeof(password);
        Serial.println("START!");
digitalWrite(SD_POWER_PIN,HIGH);
if (!SD.begin(SD_SS_PIN)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");
  delay(CHANGE_TIME);
        turnOnRFID();//初始化的时候 先初始化RFID 因为RFID的初始化 必须只执行一次
}

void loop()
{
        //turnOnRFID();//打开RFID
        //找卡
        if (rfid.isCard())
        {
                readCard();//读卡
                                   //读完卡后 把卡号存到了 String变量num里面 然后在判断之前 打开SD模块
                turnOnSD();
                judge();//判断刷入卡号是否登记
                                //判断完后 SD关电 RFID重新上电 执行一次RFID的初始化函数
                turnOnRFID();
        }


        if (flag)
        {
                openTheDoor();//开门
        }
        myservo.detach();//使得舵机不加力
        pinMode(Servo_PIN, OUTPUT);
        digitalWrite(Servo_PIN, LOW);
        delay(90);
        num = "";//清空
}
[/mw_shl_code]

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail