#include<Servo.h>
#include<SoftwareSerial.h>
#include <SPI.h>
#include <MFRC522.h>
#define RST_PIN 9 // Configurable, see typical pin layout above
#define SS_PIN 10 // Configurable, see typical pin layout above
#include <Wire.h>
#include <LiquidCrystal_I2C.h> //1602LCD 驱动 引用I2C库
LiquidCrystal_I2C lcd(0x27, 16, 2);
SoftwareSerial duiduino(2, 3); //用于和小二arduino通信
SoftwareSerial mySerial(7, 8);
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
int sum=0;
//以上为刷卡模块的声明
//重力传感器的参数
extern unsigned long HX711Read(void);
extern long getWeight();
///变量定义
float weight = 0;
int HX711_SCK = 4 ; /// 作为输出口
int HX711_DT = 5 ; /// 作为输入口
long HX711Buffer = 0;
long grossWeight = 0;
long netWeight = 0;
int gapValue = 405; ///该值需校准 每个传感器都有所不同
int MEASURE_INTERVAL = 2000; // 测量时间间隔
int CALIBRATION_INTERVAL = 2000; // 校准时间间隔
///状态定义
#define STATE_CALIBRATE 1 // 校准状态
#define STATE_MEASURE 2 // 测量状态
int state = 1; // 当前状态
char sc[100];
void setup()
{
Serial.begin(9600);
duiduino.begin(4800);
mySerial.begin(115200);//与esp8266通信波特率,固定
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init();
lcd.init(); // 初始化LCD
lcd.backlight(); //设置LCD背景等亮
pinMode(HX711_SCK, OUTPUT); ///SCK 为输出口 ---输出脉冲
pinMode(HX711_DT, INPUT); /// DT为输入口 ---读取数据
Serial.println("Pressure Sensor Operating Terminal");
Serial.println("calibrate mode");
delay(3000); ///延时3秒
//获取毛皮重量
grossWeight = HX711Read();
//Serial.begin(9600);
//AT指令用于arduino与esp8266通信
mySerial.write("AT\r\n");//如果能连接上,esp8266会回复ok。
delay(3000);
Serial.println(mySerial.readString());//在这里,readString()函数返回软串口从esp8266设备中接收到的数据,以字符串格式返回。
mySerial.write("AT+CWMODE=3\r\n");//设置esp8266工作模式。模式1 : 接收模式 2 : 发送模式 3 : 混合模式
delay(3000);
Serial.print(mySerial.readString());
mySerial.write("AT+CWJAP=\"Mate 60\",\"Lm19710623\"\r\n");//加入当前无线网络,两个字段分别为无线网络的用户名和密码
delay(3000);
Serial.print(mySerial.readString());
mySerial.write("AT+CIFSR\r\n");
delay(3000);
Serial.print(mySerial.readString());
mySerial.write("AT+CIPMUX=0\r\n"); //开启连接模式。0为单连接状态 1为多连接状态。
delay(3000);
Serial.print(mySerial.readString());
mySerial.write("AT+CIPMODE=1\r\n"); //设置透传模式。0:非透传模式 1:透传模式
delay(3000);
Serial.print(mySerial.readString());
//mySerial.write("AT+CIPSTART=\"TCP\",\"183.230.40.40\",1811\r\n");
mySerial.write("AT+CIPSTART=\"TCP\",\"183.230.40.33\",80\r\n");//连接到Onenet服务器,IP地址为:183.230.40.33,端口为80。
delay(3000);
Serial.print(mySerial.readString());
mySerial.write("AT+CIPSEND\r\n"); //开始传输数据。
delay(3000);
Serial.print(mySerial.readString());
}
//char c="";
void loop()
{
float a1;
int a=0;
int f=1;//第一次读卡是否完成冲突检测
int b=1;//第一次读卡是否完成读卡
int f1=1;
int b1=1;
String com="";
String name_first="";//用于存储从卡中读取到的完整姓氏
String name_family="";//用于存储从卡中读取到的完整名
String name_full="";
/*
if(b==1)
{
Serial.print("您好,请输入您的姓名:");
b=0;
while(Serial.available()<=0)
{}
while(Serial.available()>0)
{
com1+= char(Serial.read());
f=0;
a=1;
delay(100);
}
if(a==1)
{
Serial.println(com1);
Serial.print("欢迎您,您的积分是:");
Serial.println(sc);
Serial.println("请开始捐赠");
f=1;
}
}
*/
int ok=0;//确定第一次是否刷卡成功的变量
int ok1=0;
int kechengzhong=0;//确定是否可称重的变量,初始为0
int score=0;
// Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
MFRC522::MIFARE_Key key;//验证密钥
//String com="";//用于存储原始的积分数据(字符串)
byte buffer[34];
byte block;
byte block1;
byte block2;
MFRC522::StatusCode status;
byte len;
char aaaaat;
lcd.clear();
Serial.println(F("请刷卡:"));
lcd.setCursor(0,0); //设置显示字符的位置
lcd.print("Please Scipe!"); //输出字符到LCD1602上
//lcd.setCursor(0,1);
//lcd.print("");
//定义密钥为初始密钥,默认为FFFFFFFFFFFF
for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;
//delay(4000);
// Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
//若一直未寻到新卡,就持续while循环(防冲突机制)
while(f || b) {
if (! mfrc522.PICC_IsNewCardPresent() || ! mfrc522.PICC_ReadCardSerial()) {
f = 1;
b = 1;
} else {
f = 0;
b = 0;
// 执行刷卡成功的代码
}
}
delay(500);
//第一次刷卡成功
if(ok1==0)
{
//液晶屏显示“welcome!"
lcd.clear();
lcd.setCursor(0,0); //设置显示指针
lcd.print("Welcome you!!");
Serial.println("Welcome!");
kechengzhong=1;//设置可称重变量为1(此时后即可开始称重)
byte buffer11[18];
block1 = 8;
len = 18;
//------------------------------------------- GET FIRST NAME
status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 8, &key, &(mfrc522.uid)); //验证刚刚读取到的卡,它绝对地址为8的块密钥
if (status != MFRC522::STATUS_OK) {
Serial.print(F("Authentication failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
status = mfrc522.MIFARE_Read(block1, buffer11, &len);//将绝对地址为8的那块的数据读取到buffer11这个字节数组中
if (status != MFRC522::STATUS_OK) {
Serial.print(F("Reading failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
//PRINT FIRST NAME
for (uint8_t i = 0; i < 16; i++)
{
if (buffer11[i] != 32)
{
Serial.write(buffer11[i]);
name_first+=char(buffer11[i]);//将字节数据buffer[i]转换为字符格式后,依次连接为一个完整的姓氏
}
}
Serial.print("");
//---------------------------------------- GET LAST NAME
byte buffer22[18];
block2 = 1;
status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 1, &key, &(mfrc522.uid)); //验证刚刚读取到的卡,它绝对地址为1的块密钥
if (status != MFRC522::STATUS_OK) {
Serial.print(F("Authentication failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
status = mfrc522.MIFARE_Read(block2, buffer22, &len);//将绝对地址为1的那块的数据读取到buffer22这个字节数组中
if (status != MFRC522::STATUS_OK) {
Serial.print(F("Reading failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
//PRINT LAST NAME
for (uint8_t i = 0; i < 16; i++) {
Serial.write(buffer22[i] );
name_family+=char(buffer22[i]);//将字节数据buffer22[i]转换为字符格式后,依次连接为一个完整的名
}
Serial.println("");
char first_name[20]="";
char family_name[20]="";
name_first.toCharArray(first_name,name_first.length()+1);//将字符串name_first转换为字符数组first_name
name_family.toCharArray(family_name,name_family.length()+1);//将字符串name_family转换为字符数组family_name
strcat(first_name,family_name);//将family_name字符数组连接到first_name字符数组后,新的first_name数组为完整姓名
lcd.setCursor(0,1); //设置显示在第二行
lcd.print(first_name);
mfrc522.PICC_HaltA(); // 使放置在读卡区的IC卡进入休眠状态,不再重复读卡
mfrc522.PCD_StopCrypto1();
}
//第一次刷卡成功后(即身份认证后)即可开始称重
if(kechengzhong==1)
{
delay(2000);
runStateMachine(state);
delay(200);
duiduino.write("9");//向小二发送指令:可以回收垃圾了。
delay(1000);
duiduino.listen();//切换监听duiduino这个软串口
//监听duiduino,若没有信息,就一直等待
if(duiduino.isListening())
{while(duiduino.available()<=0)
{}
//从duiduino串口接收到来自小二的信息,接收信息
aaaaat = duiduino.read();}
//若接收到字符‘f’,代表旧物回收完成
if (aaaaat=='f')
{
Serial.print(aaaaat);
delay(200);
//若一直未寻到新卡,就持续while循环(防冲突机制)
while(f1 || b1) {
if (! mfrc522.PICC_IsNewCardPresent() || ! mfrc522.PICC_ReadCardSerial()) {
f1 = 1;
b1 = 1;
} else {
f1 = 0;
b1 = 0;
// 执行刷卡成功的代码
}
}
delay(500);
//delay(100);
// Select one of the cards
if(ok==0)
{
Serial.println(F("刷卡成功!!"));
//输出卡的UID
String uuid=""; //用于存储读取到的uid
Serial.print(F("Card UID:")); //Dump UID
for (byte i = 0; i < mfrc522.uid.size; i++) {
//Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
//Serial.print(mfrc522.uid.uidByte[i], HEX);
uuid+=mfrc522.uid.uidByte[i];//将获取到的UID连接在一起
}
if(uuid.length()==9)
{uuid+="00";}
char uuid_onenet[20];//存储上传到onenet的卡号
uuid.toCharArray(uuid_onenet,uuid.length()+1);//将字符串uuid转换为字符数组uuid_onenet
Serial.println(uuid);
//将卡号上传至onenet平台,在onenet云平台上传数据时,变量应该为字符数组。
mySerial.write("POST /devices/1170533101/datapoints HTTP/1.1\r\n");//设备号为1170533101
mySerial.write("api-key: 62AMcjNqWgEK5yL7XdHTQ2VvdOg=\r\n");//填写设备的API-key
mySerial.write("Host:api.heclouds.com\r\n");//固定
mySerial.write("Content-Length: 69\r\n");//内容长度,不能长也不能短
mySerial.write("\r\n");
mySerial.write("{\"datastreams\":[{\"id\":\"name\",\"datapoints\":[{\"value\":");//53
//mySerial.write("成功");//5
mySerial.write(uuid_onenet);//9
mySerial.write("}]}]}\r\n");//5
delay(2000);
Serial.println();
/*
//输出卡的类型
Serial.print(F(" PICC type: ")); // Dump PICC type
MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
Serial.println(mfrc522.PICC_GetTypeName(piccType));
*/
byte buffer1[18]={};//存储卡内剩余积分
byte buffer2[18]={};//存储增加积分与原始积分之和
byte buffer3[18]={};//将最后读取的积分存储于本字节数组
block = 10;//针对的是第10扇区(非控制块)
len = 18;
//读取用户姓名
//Serial.print(F("Name: "));
Serial.print(F("Score: "));
//读取卡内剩余积分
status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 10, &key, &(mfrc522.uid)); //验证刚刚读取到的卡,它绝对地址为10的块密钥
if (status != MFRC522::STATUS_OK) {
Serial.print(F("Authentication failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
status = mfrc522.MIFARE_Read(block, buffer1, &len);//将绝对地址为10的那块的数据读取到buffer1这个字节数组中
if (status != MFRC522::STATUS_OK) {
Serial.print(F("Reading failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
for (uint8_t i = 0; i < 16; i++)
{
if (buffer1[i] != 32)
{
Serial.write(buffer1[i]);
com+=char(buffer1[i]);//将字节数据buffer1[i]转换为字符格式后,依次连接为一个完整的原积分数值
}
}
char neww[20];
com.toCharArray(neww,com.length()+1);//将新积分数值存储于字符数组neww中,用于在LCD1602模块中显示
lcd.clear(); //清空原屏幕中的内容
lcd.setCursor(0,0); //设置显示位置为第一行
lcd.print("Old Score:");
lcd.print(neww);
Serial.println("");
Serial.setTimeout(20000L) ; // wait until 20 seconds for input from serial
Serial.print(F(" New Score: "));
//byte buffer1[18];
block = 10;
len = 18;
String score_aad=String(sc);//增加的积分
//Serial.print(score_aad);
//int add=30;
//新增积分
//Serial.println(com);
score=com.toInt();//字符串转整型
score=score_aad.toInt()+score;
String sum_score=String(score);//整型变量score转字符串
char sscore[20];//用于存储总积分
sum_score.toCharArray(sscore,sum_score.length()+1);//字符串转字符数组,用于在Onenet上传输
lcd.setCursor(0,1); //设置显示指针
lcd.print("Sum Score:");
lcd.print(sscore);
duiduino.write("c");
String new_score=String(score);//整型转字符串型
new_score.getBytes(buffer2,16);//字符串转字节数组
//将新增积分和旧积分之和存入卡中
status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 10, &key, &(mfrc522.uid));
if (status != MFRC522::STATUS_OK) {
Serial.print(F("PCD_Authenticate() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
// Write block
status = mfrc522.MIFARE_Write(block, buffer2, 16);
if (status != MFRC522::STATUS_OK) {
Serial.print(F("MIFARE_Write() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
/*
//读取现在的卡内剩余积分
status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 10, &key, &(mfrc522.uid)); //line 834 of MFRC522.cpp file
if (status != MFRC522::STATUS_OK) {
Serial.print(F("Authentication failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
status = mfrc522.MIFARE_Read(block, buffer3, &len);
if (status != MFRC522::STATUS_OK) {
Serial.print(F("Reading failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
for (uint8_t i = 0; i < 16; i++)
{
//if (buffer3[i] != 32)
//{
Serial.write(buffer3[i]);
//com+=char(buffer1[i]);
//}
}*/
mfrc522.PICC_HaltA(); // 使放置在读卡区的IC卡进入休眠状态,不再重复读卡
mfrc522.PCD_StopCrypto1();
Serial.println("");
mySerial.write("POST /devices/1170533101/datapoints HTTP/1.1\r\n");//设备号为1170533101
mySerial.write("api-key: 62AMcjNqWgEK5yL7XdHTQ2VvdOg=\r\n");//填写设备的API-key
mySerial.write("Host:api.heclouds.com\r\n");//固定
mySerial.write("Content-Length: 62\r\n");//内容长度,不能长也不能短
mySerial.write("\r\n");
mySerial.write("{\"datastreams\":[{\"id\":\"score\",\"datapoints\":[{\"value\":");//53
//mySerial.write("成功");//5
mySerial.write(sscore);//5
mySerial.write("}]}]}\r\n");//5
delay(2000);
Serial.println(" ");
}
}
}
delay(2000);
}
// 压力传感器状态机
void runStateMachine(int state) {
if (state == STATE_CALIBRATE) {
printMessage(CALIBRATION_INTERVAL);
} else if (state == STATE_MEASURE) {
printMessage(MEASURE_INTERVAL);
}
}
// 称重函数
// 返回值:测得重量(去皮)
long getWeight() {
HX711Buffer = HX711Read(); /// 读取此时的传感器输出值
netWeight = HX711Buffer; /// 将传感器的输出值储存
netWeight = netWeight - grossWeight; // 获取实物的AD采样数值。
netWeight = (long)((float)netWeight/gapValue); // AD值转换为重量(g)
return netWeight;
}
// 把称重打到串口
// 参数:interval 输出时间间隔,单位ms
void printMessage(int interval) {
while(1)
{weight = getWeight();
if(weight<=0)
{
continue;
}
break;}
String wweight=String(float(weight));
char lcd_weight[20];
wweight.toCharArray(lcd_weight,wweight.length()+1);
String strn=String(float(weight)*0.08);
strcpy(sc,strn.c_str()); // 计算放在传感器上的重物重量
//以下操作为不保留两位小数
String score_latest=String(sc);//字符数组转字符串
int latest_int=score_latest.toInt();//字符串转整型
String nc=String(latest_int);//整型转字符串型
char latest_onenet[20];
nc.toCharArray(latest_onenet,nc.length()+1);//字符串转字符数组,用于在Onenet上传输
//Serial.println(sc);
//while(weight<=0)
//{
//Serial.println("emtpy");
//delay(100);
//}
if(weight != 0)
{ //asr.write("1");
//Serial.print("oooo");
lcd.clear();
lcd.setCursor(0,0); //设置显示指针
lcd.print("Weight:");
lcd.print(lcd_weight);
lcd.print("g");
lcd.setCursor(0,1); //设置显示指针
lcd.print("Score:");
lcd.print(latest_onenet);
Serial.print("捐赠物品的重量为:");
Serial.print(weight); // 串口显示重量,3意为保留三位小数
Serial.print(" g\n"); // 显示单位
Serial.print("\n"); // 显示单位
Serial.print("所兑换积分为:");
Serial.print(sc);// 显示单位
Serial.print("\n");
mySerial.write("POST /devices/1170533101/datapoints HTTP/1.1\r\n");//设备号为1170533101
mySerial.write("api-key: 62AMcjNqWgEK5yL7XdHTQ2VvdOg=\r\n");//填写设备的API-key
mySerial.write("Host:api.heclouds.com\r\n");//固定
mySerial.write("Content-Length: 62\r\n");//内容长度,不能长也不能短
mySerial.write("\r\n");
mySerial.write("{\"datastreams\":[{\"id\":\"latest\",\"datapoints\":[{\"value\":");//54
//mySerial.write("123");//5
mySerial.write(latest_onenet);//3
mySerial.write("}]}]}\r\n");//5
delay(MEASURE_INTERVAL); }
delay(200);
}
// HX711驱动程序
// 返回值:模拟电压值
unsigned long HX711Read(void) { // 选择芯片工作方式并进行数据读取
unsigned long count; /// 储存输出值
unsigned char i;
//high--高电平 1 low--低电平 0
digitalWrite(HX711_DT, HIGH); //digitalWrite作用: DT=1;
delayMicroseconds(1); //延时 1微秒
digitalWrite(HX711_SCK, LOW); //digitalWrite作用: SCK=0;
delayMicroseconds(1); //延时 1微秒
count = 0;
while(digitalRead(HX711_DT)); // 当DT的值为1时,开始ad转换
for(i = 0; i < 24; i++) { /// 24个脉冲,对应读取24位数值
digitalWrite(HX711_SCK, HIGH); //digitalWrite作用: SCK=0;
/// 利用 SCK从0--1 ,发送一次脉冲,读取数值
delayMicroseconds(1); //延时 1微秒
count = count<<1; /// 用于移位存储24位二进制数值
digitalWrite(HX711_SCK, LOW); //digitalWrite作用: SCK=0;为下次脉冲做准备
delayMicroseconds(1);
if (digitalRead(HX711_DT)) { /// 若DT值为1,对应count输出值也为1
count++;
}
}
digitalWrite(HX711_SCK, HIGH); /// 再来一次上升沿 选择工作方式 128增益
count ^= 0x800000; // 按位异或 不同则为1 0^0=0; 1^0=1;
///对应二进制 1000 0000 0000 0000 0000 0000 作用为将最高位取反,其他位保留原值
delayMicroseconds(1);
digitalWrite(HX711_SCK, LOW); /// SCK=0;
delayMicroseconds(1); //延时 1微秒
return(count); /// 返回传感器读取值
}
以上程序为我在用RC522做arduino开发时的部分代码,其中主要功能是分两次使用刷卡,第一次仅读取,第二次写入。但是在实际操作的过程中我发现刷卡有时会失效,具体体现在第二次刷卡一闪而过,或刷卡没有任何反应,请大家帮帮忙。