最新案例教程点击下方链接跳转,CSDN已停止更新
点
击
跳
转
简介
使用MFRC522 RFID传感器与舵机制作的刷卡门禁系统。使用阿里云平台场景联动功能,只识别设定的卡号,简单实现多卡识别。满足小区使用场景。
准备
本案例需要的硬件
器材 | 数量 |
---|---|
HaaS506开发板 | 1 |
MFRC522 RFID传感器 | 1 |
SG90舵机 | 1 |
喇叭 | 1 |
SIM卡 | 1 |
RFID卡片 | 若干 |
杜邦线 | 若干 |
硬件连接图
代码流程
1、连接阿里云平台
2、上报门禁状态
3、读RFID卡号,上传阿里云平台
4、云平台判断卡号,控制门禁
5,开门后等待时间,关闭门禁,上传门禁状态
功能实现
1、物联网平台开发
第一次使用物联网平台的读者,需要开通实例后使用物联网平台功能。也可以使用免费的公共实例进行开发,在阿里云物联网平台中,左上角选择‘华东2-上海’,点击‘公共实例’,即可开通。
1、平台产品创建可参考haas506 2.0开发教程-aliyunIoT
2、创建产品属性(添加物模型)
选择产品功能定义–编辑草稿
1、添加自定义功能
2、按照图2显示添加标识符与数据类型(标识符要与代码一致)
3、点击发布上线
- 点击确定
2、设备端开发
-
第一次使用开发板的读者可以按照haas5062.0开发教程-导学篇搭建开发环境。
-
搭建完后复制以下代码到Visual Studio Code,复制产品证书到代码相应位置。
-
舵机使用案例参考
-
2.2版本获取IMEI号接口有更新,需要更改以下内容(Ctrl+F 查找modem)
由
# 获取设备的IMEI 作为deviceName 进行动态注册
deviceName = modem.getDevImei()
...
改为
# 获取设备的IMEI 作为deviceName 进行动态注册
deviceName = modem.info.getDevImei()
...
注意:代码中mp3文件需要自行添加
main.py
# coding=utf-8
from driver import PWM
import network
import ujson
import utime as time
import modem
from aliyunIoT import Device
import kv
import mfrc522
import audio
#当iot设备连接到物联网平台的时候触发'connect' 事件
def on_connect(data):
global module_name,default_ver,productKey,deviceName,deviceSecret,on_trigger,on_download,on_verify,on_upgrade
print('***** connect lp succeed****')
data_handle = {}
data_handle['device_handle'] = device.getDeviceHandle()
#当连接断开时,触发'disconnect'事件
def on_disconnect():
print('linkkit is disconnected')
#当iot云端下发属性设置时,触发'props'事件
def on_props(request):
global servo_data
params=request['params']
params=eval(params)
servo=params["open_door"]
servo_data={}
if servo ==1:
param2 = {'freq':50, 'duty': 12 }
pwm_lpg.setOption(param2)
print('open zhe door')
servo_data["open_door"]= 1
servo_data_str=ujson.dumps(servo_data)
data={
'params':servo_data_str
}
device.postProps(data)
aud.play('/data/pyamp/welcome.mp3')
time.sleep(3)
param2 = {'freq':50, 'duty': 5 }
pwm_lpg.setOption(param2)
time.sleep(1)
servo_data["open_door"]= 0
servo_data_str=ujson.dumps(servo_data)
data={
'params':servo_data_str
}
device.postProps(data)
else:
pass
#当iot云端调用设备service时,触发'service'事件
def on_service(id,request):
print('clound req id is {} , req is {}'.format(id,request))
#当设备跟iot平台通信过程中遇到错误时,触发'error'事件
def on_error(err):
print('err msg is {} '.format(err))
#网络连接的回调函数
def on_4g_cb(args):
global g_connect_status
pdp = args[0]
netwk_sta = args[1]
if netwk_sta == 1:
g_connect_status = True
else:
g_connect_status = False
#网络连接
def connect_network():
global net,on_4g_cb,g_connect_status
#NetWorkClient该类是一个单例类,实现网络管理相关的功能,包括初始化,联网,状态信息等.
net = network.NetWorkClient()
g_register_network = False
if net._stagecode is not None and net._stagecode == 3 and net._subcode == 1:
g_register_network = True
else:
g_register_network = False
if g_register_network:
#注册网络连接的回调函数on(self,id,func); 1代表连接,func 回调函数 ;return 0 成功
net.on(1,on_4g_cb)
net.connect(None)
else:
print('网络注册失败')
while True:
if g_connect_status:
print('网络连接成功')
break
time.sleep_ms(20)
#动态注册回调函数
def on_dynreg_cb(data):
global deviceSecret,device_dyn_resigter_succed
deviceSecret = data
device_dyn_resigter_succed = True
# 连接物联网平台
def dyn_register_device(productKey,productSecret,deviceName):
global on_dynreg_cb,device,deviceSecret,device_dyn_resigter_succed
key = '_amp_customer_devicesecret'
deviceSecretdict = kv.get(key)
if isinstance(deviceSecretdict,str):
deviceSecret = deviceSecretdict
if deviceSecretdict is None or deviceSecret is None:
key_info = {
'productKey': productKey ,
'productSecret': productSecret ,
'deviceName': deviceName
}
# 动态注册一个设备,获取设备的deviceSecret
#下面的if防止多次注册,当前若是注册过一次了,重启设备再次注册就会卡住,
if not device_dyn_resigter_succed:
device.register(key_info,on_dynreg_cb)
def upload_uid():
global uid_data
uid_data["rfid"]= uid
uid_data_str=ujson.dumps(uid_data)
data={
'params':uid_data_str
}
device.postProps(data)
def do_read():
global uid,uid_data
rdr=mfrc522.MFRC522()
uid = ''
try:
while True:
(stat, tag_type) = rdr.request(rdr.REQIDL)
if stat == rdr.OK:
(stat, raw_uid) = rdr.anticoll()
if stat == rdr.OK:
uid=hex(raw_uid[0])[2:]+hex(raw_uid[1])[2:]+hex(raw_uid[2])[2:]+hex(raw_uid[3])[2:]
print(' - uid : ',uid)
aud.play('/data/pyamp/ding.mp3')
time.sleep(1)
upload_uid()
else:
print('read error')
time.sleep(1)
except KeyboardInterrupt:
print("Bye")
if __name__ == '__main__':
ICCID=None
g_connect_status = False
net = None
device = None
deviceSecret = None
deviceName = None
productKey = "your productKey "
productSecret = "your productSecret "
device_dyn_resigter_succed = False
# 连接网络
connect_network()
# 获取设备的IMEI 作为deviceName 进行动态注册
deviceName = modem.info.getDevImei()
#获取设备的ICCID
ICCID=modem.sim.getIccid()
#初始化物联网平台Device类,获取device实例
device = Device()
if deviceName is not None and len(deviceName) > 0 :
#动态注册一个设备
dyn_register_device(productKey,productSecret,deviceName)
else:
print("获取设备IMEI失败,无法进行动态注册")
while deviceSecret is None:
time.sleep(0.2)
print('动态注册成功:' + deviceSecret)
key_info = {
'region' : 'cn-shanghai' ,
'productKey': productKey ,
'deviceName': deviceName ,
'deviceSecret': deviceSecret ,
'keepaliveSec': 60,
}
#打印设备信息
print(key_info)
#device.ON_CONNECT 是事件,on_connect是事件处理函数/回调函数
device.on(device.ON_CONNECT,on_connect)
device.on(device.ON_DISCONNECT,on_disconnect)
device.on(device.ON_PROPS,on_props)
device.on(device.ON_SERVICE,on_service)
device.on(device.ON_ERROR,on_error)
device.connect(key_info)
#上报信息
servo_data={}
pwm_lpg = PWM()
pwm_lpg.open("pwm_lpg")
param2 = {'freq':50, 'duty': 5 }
pwm_lpg.setOption(param2)
time.sleep(1)
servo_data["open_door"]= 0
servo_data_str=ujson.dumps(servo_data)
data={
'params':servo_data_str
}
device.postProps(data)
#音频实例化
aud=audio.Audio()
aud.set_pa() #开启使能
aud.setVolume(10) #设置音量
print('witing read ------ ')
uid_data={}
do_read()
mfrc522.py
from driver import SPI
from driver import GPIO
class MFRC522:
OK = 0
NOTAGERR = 1
ERR = 2
REQIDL = 0x26
REQALL = 0x52
AUTHENT1A = 0x60 #验证A密钥
AUTHENT1B = 0x61 #验证B密钥
def __init__(self):
self.spi=SPI()
self.spi.open('SPI0')
self.rst=GPIO()
self.rst.open('rst')
self.rst.write(0)
self.rst.write(1)
self.init()
def _wreg(self, reg, val):
writeBuf=bytearray([int(0xff & ((reg << 1) & 0x7e)),int(0xff & val)])
self.spi.write(writeBuf,2)
def _rreg(self, reg):
readBuf=bytearray(1)
writeBuf=bytearray([int(0xff & (((reg << 1) & 0x7e) | 0x80))])
self.spi.write(writeBuf,1)
self.spi.read(readBuf,1)
return readBuf[0]
def _sflags(self, reg, mask):
self._wreg(reg, self._rreg(reg) | mask)
def _cflags(self, reg, mask):
self._wreg(reg, self._rreg(reg) & (~mask))
def _tocard(self, cmd, send):
recv = []
bits = irq_en = wait_irq = n = 0
stat = self.ERR
if cmd == 0x0E:
irq_en = 0x12
wait_irq = 0x10
elif cmd == 0x0C:
irq_en = 0x77
wait_irq = 0x30
self._wreg(0x02, irq_en | 0x80)
self._cflags(0x04, 0x80)
self._sflags(0x0A, 0x80)
self._wreg(0x01, 0x00)
for c in send:
self._wreg(0x09, c)
self._wreg(0x01, cmd)
if cmd == 0x0C:
self._sflags(0x0D, 0x80)
i = 2000
while True:
n = self._rreg(0x04)
i -= 1
if ~((i != 0) and ~(n & 0x01) and ~(n & wait_irq)):
break
self._cflags(0x0D, 0x80)
if i:
if (self._rreg(0x06) & 0x1B) == 0x00:
stat = self.OK
if n & irq_en & 0x01:
stat = self.NOTAGERR
elif cmd == 0x0C:
n = self._rreg(0x0A)
lbits = self._rreg(0x0C) & 0x07
if lbits != 0:
bits = (n - 1) * 8 + lbits
else:
bits = n * 8
if n == 0:
n = 1
elif n > 16:
n = 16
for _ in range(n):
recv.append(self._rreg(0x09))
else:
stat = self.ERR
return stat, recv, bits
def _crc(self, data):
self._cflags(0x05, 0x04)
self._sflags(0x0A, 0x80)
for c in data:
self._wreg(0x09, c)
self._wreg(0x01, 0x03)
i = 0xFF
while True:
n = self._rreg(0x05)
i -= 1
if not ((i != 0) and not (n & 0x04)):
break
return [self._rreg(0x22), self._rreg(0x21)]
def init(self):
self.reset()
self._wreg(0x2A, 0x8D)
self._wreg(0x2B, 0x3E)
self._wreg(0x2D, 30)
self._wreg(0x2C, 0)
self._wreg(0x15, 0x40)
self._wreg(0x11, 0x3D)
self.antenna_on()
def reset(self):
self._wreg(0x01, 0x0F)
def antenna_on(self, on=True):
if on and ~(self._rreg(0x14) & 0x03):
self._sflags(0x14, 0x03)
else:
self._cflags(0x14, 0x03)
def request(self, mode):
self._wreg(0x0D, 0x07)
(stat, recv, bits) = self._tocard(0x0C, [mode])
if (stat != self.OK) | (bits != 0x10):
stat = self.ERR
return stat, bits
def anticoll(self):
ser_chk = 0
ser = [0x93, 0x20]
self._wreg(0x0D, 0x00)
(stat, recv, bits) = self._tocard(0x0C, ser)
if stat == self.OK:
if len(recv) == 5:
for i in range(4):
ser_chk = ser_chk ^ recv[i]
if ser_chk != recv[4]:
stat = self.ERR
else:
stat = self.ERR
return stat, recv
def select_tag(self, ser):
buf = [0x93, 0x70] + ser[:5]
buf += self._crc(buf)
(stat, recv, bits) = self._tocard(0x0C, buf)
return self.OK if (stat == self.OK) and (bits == 0x18) else self.ERR
def auth(self, mode, addr, sect, ser):
return self._tocard(0x0E, [mode, addr] + sect + ser[:4])[0]
def stop_crypto1(self):
self._cflags(0x08, 0x08)
def read(self, addr): #读块数据
data = [0x30, addr]
data += self._crc(data)
(stat, recv, _) = self._tocard(0x0C, data)
return recv if stat == self.OK else None
def write(self, addr, data):
buf = [0xA0, addr]
buf += self._crc(buf)
(stat, recv, bits) = self._tocard(0x0C, buf)
if not (stat == self.OK) or not (bits == 4) or not ((recv[0] & 0x0F) == 0x0A):
stat = self.ERR
else:
buf = []
for i in range(16):
buf.append(data[i])
buf += self._crc(buf)
(stat, recv, bits) = self._tocard(0x0C, buf)
if not (stat == self.OK) or not (bits == 4) or not ((recv[0] & 0x0F) == 0x0A):
stat = self.ERR
return stat
board.json
{
"name": "haas506",
"version": "2.0.0",
"io": {
"pwm_lpg": {
"type": "PWM",
"port": 3
},
"KEY1": {
"type": "GPIO",
"port": 44,
"dir": "irq",
"pull": "pullup",
"intMode": "rising"
},
"led1": {
"type": "GPIO",
"port": 7,
"dir": "output",
"pull": "pulldown"
},
"led_g": {
"type": "GPIO",
"port": 32,
"dir": "output",
"pull": "pulldown"
},
"cs": {
"type": "GPIO",
"port": 15,
"dir": "output",
"pull": "pullup"
},
"rst":{
"type":"GPIO",
"port": 31,
"dir": "output",
"pull":"pullup"
},
"SPI0": {
"type": "SPI",
"port": 0,
"mode": "master",
"freq": 2000000
},
"serial1": {
"type": "UART",
"port": 0,
"dataWidth": 8,
"baudRate": 115200,
"stopBits": 1,
"flowControl": "disable",
"parity": "none",
"timeout": 1000
},
"serial2": {
"type": "UART",
"port": 1,
"dataWidth": 8,
"baudRate": 9600,
"stopBits": 1,
"flowControl": "disable",
"parity": "none",
"timeout": 1000
},
"serial3": {
"type": "UART",
"port": 2,
"dataWidth": 8,
"baudRate": 115200,
"stopBits": 1,
"flowControl": "disable",
"parity": "none",
"timeout": 1000
}
},
"debugLevel": "ERROR",
"repl": "enable",
"replPort": 0
}
调试
1、阿里云平台,打开实时刷新,刷卡后卡片号码会即时上报
3、场景联动设定
点击规则引擎–场景联动,点击创建规则
进行规则设定,如下图所示,云端识别到卡号,就发送一条开门命令。
点击保存
启动场景联动
刷卡测试
使用预设卡片刷卡时,舵机会转动,将门打开,其他卡片不行