در پروژه RFID میکروپایتون با استفاده از ماژول RC522 و به کمک میکروپایتون قصد خواندن و نوشتن مقادیر در تگ های RFID را داریم، در این پروژه از برد ESP32 و میکروپایتون برای راهاندازی و کد نویسی ماژول RC522 استفاده خواهیم کرد. در این پروژه هردو سناریو برای خواندن و همچنین نوشتن مقادیر مربوط در تگ های RFID بر پایه میکروپایتون را بررسی خواهیم کرد. در این پروژه برای کدنویسی از نرمافزار upycraft استفاده خواهیم کرد. در ادامه این آموزش با مرجع تخصصی آردوینو به زبان فارسی، دیجی اسپارک همراه باشید.
ماژول RC522
به لطف تکنولوژی Radio Frequency IDentification یا RFID در طول روز تنها با حمل یک کارت کوچک، قادر به پرداخت هزینه حمل نقل عمومی و تایید هویت در مکان های محتلف هستیم و این تنها دو نمونه از کاربرد های این تکنولوژی جذاب است، ماژول RC522 یک انتخاب خوب برای پروژه های این چنینی به حساب می آید. کم مصرف، کم هزینه، رابط کاربری آسان و بسیار محبوب بین علاقه مندان است. ماژول RC522 مبتنی بر MFRC522 IC از NXP یکی از ارزان ترین گزینه ها برای پروژه های بر پایه RFID است، که معمولاً با تگ RFID با حافظه ۱KB ارائه می شود. و از همه مهم تر، می تواند بر روی این تگ ها بنویسد، بنابراین می توانید نوعی پیام مخفی خود را در آن ذخیره کنید.
ماژول RC522 برای خواندن تگ های RFID اقدم به ایجاد یک میدان الکترومغناطیسی ۱۳٫۵۶MHz می کند که از آن برای برقراری ارتباط با تگ های RFID استفاده می کند. این تگ دارای استاندارد ISO 14443A هستند. RC522 می تواند با یک میکروکنترلر از طریق رابط سریال ۴ پین سریال (SPI) با حداکثر سرعت داده ۱۰Mbps اقدام به برقراری ارتباط کند. همچنین این ارتباطات از طریق پروتکل های I2C و UART نیز امکان پذیر می باشد. ولتاژ کاری ماژول از ۲٫۵ تا ۳٫۳ ولت است، اما خبر خوب این است که پایه های منطقی، ۵ ولت را تحمل می کنند، بنابراین ما می توانیم بدون استفاده از مبدل سطح منطقی، آن را به راحتی به یک Arduino یا هر میکروکنترلر با ولتاژ ۵ ولت متصل کنیم.
تراشه ESP32
ESP32 می تواند به عنوان یک سیستم کامل مستقل یا به عنوان یک دستگاه MCU عمل کند و بار اضافی ارتباطات را در پردازنده اصلی برنامه کاهش دهد. ESP32 می تواند با سیستم های دیگر ارتباط برقرار کند تا از طریق SPI عملکرد Wi-Fi و بلوتوث را ارائه دهد. ESP32 با سوئیچ های آنتن داخلی، RF balun، تقویت کننده قدرت، تقویت کننده دریافت، فیلترها و ماژول های مدیریت توان یکپارچه شده است. ESP32 با حداقل الزامات برد مدار چاپی (PCB) ، عملکرد و تطبیق پذیری بی نظیری را به برنامه های شما اضافه می کند. برد ESP32 نسل پیشرفته ESP8266 است. یکی از تفاوتهای آن بلوتوث داخلیاش میباشد. همچنین دارای هسته وایفای ۲,۴ گیگا هرتزی و بلوتوث داخلی تولید شده با تکنولوژی ۴۰ نانومتری شرکت TSMC میباشد. این ماژول دارای بهترین پرفورمنس در مصرف انرژی میباشد یعنی با کمترین مصرف انرژی بهترین نتیجه را برای ما به همراه دارد. اگر بخواهیم دقیقتر به این برد نگاه کنیم باید بگوییم که این یک chip است که پلتفرم NodeMCU در اون پیاده سازی شده که به این نوع چیپ ها System on a chip microcontrollers هم گفته میشود.
شرح پروژه RC522
در پروژه RFID میکروپایتون با استفاده از دو فایل کد یعنی کتابخانه ماژول RC522 و کدی برای سناریو اصلی اقدام به راهاندازی این سنسور به منظور خواندن مقادیر تگ های RFID خواهیم کرد، در ادامه این آموزش نحوه کار با ماژول RC522 را با استفاده از برنامه نویسی میکروپایتون یاد خواهید گرفت و قادر خواهید بود با تغییر کد های این پروژه و افزودن موارد دلخواه به عنوان ویژگی های اضافه پروژه خود را پیش ببرید.
شماتیک پروژه RFID میکروپایتون

کد های پروژه RFID میکروپایتون
کد های پروژه RFID میکروپایتون از دوبخش تشکیل شدهاند، مانند پروژه های قبلی میکروپایتون بیس با ESP32 ابتدا کتابخانه مورد نظر برای راهاندازی سنسور یا ماژول مورد استفاده را اضافه میکنیم که در این پروژه مورد مدنظر ما ماژول RC522 است. کد زیر را با نام mfrc522.py در نرمافزار upycraft ایجاد و ذخیره کنید، و در ادامه کد را در برد ESP32 آپلود کنید.
from machine import Pin, SPI
from os import uname
emptyRecv = b""
class MFRC522:
GAIN_REG = 0x26
MAX_GAIN = 0x07
OK = 0
NOTAGERR = 1
ERR = 2
REQIDL = 0x26
REQALL = 0x52
AUTHENT1A = 0x60
AUTHENT1B = 0x61
def __init__(self, spi=None, gpioRst=None, gpioCs=None):
if gpioRst is not None:
self.rst = Pin(gpioRst, Pin.OUT)
else:
self.rst = None
assert(gpioCs is not None, "Needs gpioCs") # TODO fails without cableSelect
if gpioCs is not None:
self.cs = Pin(gpioCs, Pin.OUT)
else:
self.cs = None
# TODO CH rationalise which of these are referenced, which can be identical
self.regBuf = bytearray(4)
self.blockWriteBuf = bytearray(18)
self.authBuf = bytearray(12)
self.wregBuf = bytearray(2)
self.rregBuf = bytearray(1)
self.recvBuf = bytearray(16)
self.recvMv = memoryview(self.recvBuf)
if self.rst is not None:
self.rst.value(0)
if self.cs is not None:
self.cs.value(1)
if spi is not None:
self.spi = spi
else:
sck = Pin(14, Pin.OUT)
mosi = Pin(13, Pin.OUT)
miso = Pin(12, Pin.IN)
if uname()[0] == 'WiPy':
self.spi = SPI(0)
self.spi.init(SPI.MASTER, baudrate=1000000, pins=(sck, mosi, miso))
elif uname()[0] == 'esp8266': # TODO update to match https://github.com/cefn/avatap/blob/master/python/host/cockle.py #prepareHost()
self.spi = SPI(baudrate=100000, polarity=0, phase=0, sck=sck, mosi=mosi, miso=miso)
self.spi.init()
else:
raise RuntimeError("Unsupported platform")
if self.rst is not None:
self.rst.value(1)
self.init()
def _wreg(self, reg, val):
if self.cs is not None:
self.cs.value(0)
buf = self.wregBuf
buf[0]=0xff & ((reg << 1) & 0x7e)
buf[1]=0xff & val
self.spi.write(buf)
if self.cs is not None:
self.cs.value(1)
def _rreg(self, reg):
if self.cs is not None:
self.cs.value(0)
buf = self.rregBuf
buf[0]=0xff & (((reg << 1) & 0x7e) | 0x80)
self.spi.write(buf)
val = self.spi.read(1)
if self.cs is not None:
self.cs.value(1)
return val[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, into=None):
recv = emptyRecv
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
if into is None:
recv = self.recvBuf
else:
recv = into
pos = 0
while pos < n:
recv[pos] = self._rreg(0x09)
pos += 1
if into is None:
recv = self.recvMv[:n]
else:
recv = into
else:
stat = self.ERR
return stat, recv, bits
def _assign_crc(self, data, count):
self._cflags(0x05, 0x04)
self._sflags(0x0A, 0x80)
dataPos = 0
while dataPos < count:
self._wreg(0x09, data[dataPos])
dataPos += 1
self._wreg(0x01, 0x03)
i = 0xFF
while True:
n = self._rreg(0x05)
i -= 1
if not ((i != 0) and not (n & 0x04)):
break
data[count] = self._rreg(0x22)
data[count + 1] = 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.set_gain(self.MAX_GAIN)
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
# CH Note bytearray allocation here
return stat, bytearray(recv)
def select_tag(self, ser):
# TODO CH normalise all list manipulation to bytearray, avoid below allocation
buf = bytearray(9)
buf[0] = 0x93
buf[1] = 0x70
buf[2:7] = ser
self._assign_crc(buf, 7)
(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):
# TODO CH void ser[:4] implicit list allocation
buf = self.authBuf
buf[0]=mode # A or B
buf[1]=addr # block
buf[2:8]=sect # key bytes
buf[8:12]=ser[:4] # 4 bytes of id
return self._tocard(0x0E, buf)[0]
# TODO this may well need to be implemented for vault to properly back out from a card session
# TODO how, why, when is 'HaltA' needed? see https://github.com/cefn/micropython-mfrc522/issues/1
def halt_a(self):
pass
def stop_crypto1(self):
self._cflags(0x08, 0x08)
def set_gain(self, gain):
assert gain <= self.MAX_GAIN
# clear bits
self._cflags(self.GAIN_REG, 0x07<< 4)
# set bits according to gain
self._sflags(self.GAIN_REG, gain << 4)
def read(self, addr, into = None):
buf = self.regBuf
buf[0]=0x30
buf[1]=addr
self._assign_crc(buf, 2)
(stat, recv, _) = self._tocard(0x0C, buf, into=into)
# TODO this logic probably wrong (should be 'into is None'?)
if into is None: # superstitiously avoid returning read buffer memoryview
# CH Note bytearray allocation here
recv = bytearray(recv)
return recv if stat == self.OK else None
def write(self, addr, data):
buf = self.regBuf
buf[0] = 0xA0
buf[1] = addr
self._assign_crc(buf, 2)
(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 = self.blockWriteBuf
i = 0
while i < 16:
buf[i] = data[i] # TODO CH eliminate this, accelerate it?
i += 1
self._assign_crc(buf, 16)
(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
در ادامه نوبت به کد اصلی پروژه RFID میکروپایتون میرسد، کد بالا به تنهایی برای ما کار مفیدی انجام نمیدهد و نیاز به یک برنامه جداگانه برای استفاده از قابلیت هایی دارد که در اختیار ما قرار میدهد، کد پایین را با نام rc522.py در نرمافزار upycraft ذخیره کنید و سپس هردو کد را در برد ESP32 خود آپلود کنید. نکته: در نرمافزار upycraft به منظور آپلود هر کد در صفحه های جداگانه نیاز دارید تا هر کد را بصورت جداگانه آپلود کنید.
from mfrc522 import MFRC522
from machine import Pin
from machine import SPI
spi = SPI(2, baudrate=2500000, polarity=0, phase=0)
spi.init()
rdr = MFRC522(spi=spi, gpioRst=4, gpioCs=5)
print("Place card")
while True:
(stat, tag_type) = rdr.request(rdr.REQIDL)
if stat == rdr.OK:
(stat, raw_uid) = rdr.anticoll()
if stat == rdr.OK:
card_id = "uid: 0x%02x%02x%02x%02x" % (raw_uid[0], raw_uid[1], raw_uid[2], raw_uid[3])
print(card_id)
نتیجه نهایی
در نهایت پس از آپلود کد های این پروژه RFID میکروپایتون و برقراری اتصالات، در صورتی که تمام مراحل به درستی امجام شده باشد. قادر خواهید بود در نرمافزار upycraft در ترمینال این نرمافزار خواهید دید پس از هربار نزدیک کردن تگ rfid نزدیک ماژول rc522 شناسه uid تگ برای شما نمایش داده میشود، با استفاده از این شناسه و افزودن به کد های این پروژه قادر خواهید بود تا سییستم تایید هویت مبتنی بر ماژول rc522 و تگ های rfid بسازید.
کلام آخر با سایفر
چنانچه در مراحل راه اندازی و انجام این پروژه با مشکل مواجه شدید، بدون هیچ نگرانی در انتهای همین پست، به صورت ثبت نظر سوالتان را مطرح کنید. من در سریعترین زمان ممکن پاسخ رفع مشکل شما را خواهم داد. همچنین اگر ایرادی در کدها و یا مراحل اجرایی وجود دارند میتوانید از همین طریق اطلاع رسانی کنید.
در پایان نظرات و پیشنهادات خود را با ما درمیان بگذارید و با اشتراک گذاری این آموزش در شبکه های اجتماعی , از وبسایت دیجی اسپارک حمایت کنید.







سلام خسته نباشید کدوم پایه هارو متصل کردید؟ زیاد واضح نیست عکس ، اگه میشه یک راهنمایی بکنید که کدوم پایه هارو به RFID متصل کنیم برای این کدی که نوشتید
ممنون
با سلام
در بخش شماتیک پروژه RFID میکروپایتون به صورت متنی توضیح داده شده است. طبق توضیحات اقدام کنید.