├── README.md └── mfrc522 └── mfrc522.py /README.md: -------------------------------------------------------------------------------- 1 | # micropython-NFC 2 | 3 | This repository contains some experiments with NFC readers. 4 | 5 | First experiment was to have the MFRC522 working on the PYB board. Next thing is to move it over to the ESP8266. 6 | 7 | # MFRC522 8 | One of the more mature readers is the NXP MFRC522 Reader. This is a 3.3V reader with `UART`, `I2C` and `SPI` interfaces. The latest silicon v2.0 is in the `MFRC52202HN1` chip. 9 | 10 | The reader supports: 11 | - MIFARE Mini, 12 | - MIFARE 1K, 13 | - MIFARE 4K, 14 | - MIFARE Ultralight, 15 | - MIFARE DESFire EV1 and 16 | - MIFARE Plus RF identification protocols. 17 | 18 | # mfrc522.py 19 | The code uses the `PYB` module (need to change to `machine`). Using `execfile('mfrc522.py')` to start the reading, `import MFRC522` to add the module to your program. 20 | 21 | -------------------------------------------------------------------------------- /mfrc522/mfrc522.py: -------------------------------------------------------------------------------- 1 | """ NFC MFRC522x Reader 2 | 3 | Author: Roland van Straten, @rlndvnstrtn 4 | Date: 03-08-2016 5 | Version: 1.2 6 | 7 | Original code from github.com/mxgxw and a little of me... 8 | 9 | Adapted for use with micropython / PYB10 board running mpy 1.8.2 10 | Adapted for use with micropython / ESP8266 11 | 12 | The basic reading is working, need to test the other stuff and add the samples of mxgxw to __main__ 13 | - Added the blue LED to show a tag is actually read. 14 | - Added read version of chip 15 | - Added reading of Receiver gain setting 16 | 17 | PYB 1.0 BOARD MFRC522 Reader Wiring 18 | 19 | SIGNAL | PYB10 | CPU | INFO 20 | ============ | ===== | ==== | ======= 21 | NRSTPD | Y9 | PB10 | GPIO 22 | SDA / NSS | X5 | PA4 | NSS 23 | SCK | X6 | PA5 | SPI1 24 | MISO | X7 | PA6 | SPI1 25 | MOSI | X8 | PA7 | SPI1 26 | 27 | ESP-13 MODULE MFRC522 Reader Wiring 28 | 29 | SIGNAL | ESP13 | INFO 30 | ============ | ===== | ======= 31 | NRSTPD | IO2 | GPIO 32 | SDA / NSS | IO0 | GPIO 33 | SCK | IO14 | SPI 34 | MISO | IO12 | SPI 35 | MOSI | IO13 | SPI 36 | 37 | Able to read my collection of NFC cards and tags 38 | UID: 243,236, 67,146 NORTEC KEY TAG 39 | UID: 136, 2,226, 0 ST25TA02K 40 | UID: 136, 4,104, 57 elektor membership ultralight 4400 41 | UID: 136, 4,126,253 rfid ACG PHILIPS ELEKTUUR 42 | UID: 68,131,181, 89 mifare card 43 | UID: 45,136,224,140 OV-chipcard 44 | UID: 136, 4, 48,195 NXP mtag 45 | 46 | 47 | TODO: "port" it to ESP8266 mpy 48 | add a ctrl-break in the main function code 49 | add error checking 50 | 51 | REMARKS: tried uploading it to the ESP-13, however it has to little memory 52 | stripped, resized, etc. but still not loading correctly 53 | 54 | 55 | 56 | """ 57 | 58 | MPY_ESP8266 = True 59 | 60 | if not MPY_ESP8266: 61 | # can be better :-) 62 | from pyb import * 63 | else: 64 | from machine import Pin, SPI 65 | import time 66 | 67 | 68 | 69 | class MFRC522(object): 70 | """ class for interacting with the 'RC522' NFC reader chip """ 71 | 72 | MI_OK = 0 73 | MI_NOTAGERR = 1 74 | MI_ERR = 2 75 | 76 | PCD_IDLE = 0x00 77 | PCD_AUTHENT = 0x0E 78 | PCD_RECEIVE = 0x08 79 | PCD_TRANSMIT = 0x04 80 | PCD_TRANSCEIVE = 0x0C 81 | PCD_RESETPHASE = 0x0F 82 | PCD_CALCCRC = 0x03 83 | 84 | PICC_REQIDL = 0x26 85 | PICC_REQALL = 0x52 86 | PICC_ANTICOLL = 0x93 87 | PICC_SElECTTAG = 0x93 88 | PICC_AUTHENT1A = 0x60 89 | PICC_AUTHENT1B = 0x61 90 | PICC_READ = 0x30 91 | PICC_WRITE = 0xA0 92 | PICC_DECREMENT = 0xC0 93 | PICC_INCREMENT = 0xC1 94 | PICC_RESTORE = 0xC2 95 | PICC_TRANSFER = 0xB0 96 | PICC_HALT = 0x50 97 | 98 | Reserved00 = 0x00 99 | CommandReg = 0x01 100 | CommIEnReg = 0x02 101 | DivlEnReg = 0x03 102 | CommIrqReg = 0x04 103 | DivIrqReg = 0x05 104 | ErrorReg = 0x06 105 | Status1Reg = 0x07 106 | Status2Reg = 0x08 107 | FIFODataReg = 0x09 108 | FIFOLevelReg = 0x0A 109 | WaterLevelReg = 0x0B 110 | ControlReg = 0x0C 111 | BitFramingReg = 0x0D 112 | CollReg = 0x0E 113 | Reserved01 = 0x0F 114 | 115 | Reserved10 = 0x10 116 | ModeReg = 0x11 117 | TxModeReg = 0x12 118 | RxModeReg = 0x13 119 | TxControlReg = 0x14 120 | TxAutoReg = 0x15 121 | TxSelReg = 0x16 122 | RxSelReg = 0x17 123 | RxThresholdReg = 0x18 124 | DemodReg = 0x19 125 | Reserved11 = 0x1A 126 | Reserved12 = 0x1B 127 | MifareReg = 0x1C 128 | Reserved13 = 0x1D 129 | Reserved14 = 0x1E 130 | SerialSpeedReg = 0x1F 131 | 132 | Reserved20 = 0x20 133 | CRCResultRegM = 0x21 134 | CRCResultRegL = 0x22 135 | Reserved21 = 0x23 136 | ModWidthReg = 0x24 137 | Reserved22 = 0x25 138 | RFCfgReg = 0x26 139 | GsNReg = 0x27 140 | CWGsPReg = 0x28 141 | ModGsPReg = 0x29 142 | TModeReg = 0x2A 143 | TPrescalerReg = 0x2B 144 | TReloadRegH = 0x2C 145 | TReloadRegL = 0x2D 146 | TCounterValueRegH = 0x2E 147 | TCounterValueRegL = 0x2F 148 | 149 | Reserved30 = 0x30 150 | TestSel1Reg = 0x31 151 | TestSel2Reg = 0x32 152 | TestPinEnReg = 0x33 153 | TestPinValueReg = 0x34 154 | TestBusReg = 0x35 155 | AutoTestReg = 0x36 156 | VersionReg = 0x37 157 | AnalogTestReg = 0x38 158 | TestDAC1Reg = 0x39 159 | TestDAC2Reg = 0x3A 160 | TestADCReg = 0x3B 161 | Reserved31 = 0x3C 162 | Reserved32 = 0x3D 163 | Reserved33 = 0x3E 164 | Reserved34 = 0x3F 165 | 166 | MAX_LEN = 16 167 | 168 | serNum = [] 169 | 170 | 171 | 172 | def __init__(self): 173 | ''' init the interface ''' 174 | 175 | if not MPY_ESP8266: 176 | # PYB specific use 177 | self.nrstpd = pyb.Pin(pyb.Pin.cpu.B10, pyb.Pin.OUT) # sets the pin to output 178 | self.nenbrc522 = pyb.Pin(pyb.Pin.cpu.A4, pyb.Pin.OUT) # sets the pin to output 179 | 180 | self.nenbrc522.high() # deselect device 181 | self.nrstpd.low() # put it in power down mode 182 | 183 | # reader has stable data on rising edge of signal (phase 0), clock is high active (polarity 0) 184 | self.spi = SPI(1, SPI.MASTER, baudrate=1000000, polarity=0, phase=0, firstbit=SPI.MSB) # default pins for SPI1 are selected 185 | else: 186 | # ESP8266 specific use 187 | self.nrstpd = machine.Pin(0, machine.Pin.OUT) # sets the pin to output 188 | self.nenbrc522 = machine.Pin(2, machine.Pin.OUT) # sets the pin to output 189 | 190 | self.nenbrc522.high() # deselect device 191 | self.nrstpd.low() # put it in power down mode 192 | 193 | # reader has stable data on rising edge of signal (phase 0), clock is high active (polarity 0) 194 | self.spi = SPI(SPI.MASTER, baudrate=1000000, polarity=0, phase=0, firstbit=SPI.MSB) # default pins for SPI are selected 195 | 196 | 197 | # go configure yourself 198 | self.MFRC522_Init() 199 | 200 | 201 | def Write_MFRC522(self, addr, val): 202 | data = bytearray(2) 203 | data[0] = (addr<<1) & 0x7E 204 | data[1] = val 205 | self.nenbrc522.low() # start the transaction 206 | 207 | if not MPY_ESP8266: 208 | self.spi.send(data) # transfer two bytes to the chip 209 | else: 210 | self.spi.write(data) # transfer buffer 211 | 212 | self.nenbrc522.high() # finished it 213 | 214 | 215 | def Read_MFRC522(self, addr): 216 | data = bytearray(2) 217 | buf = bytearray(2) # could reuse data instead of using buf 218 | data[0] = ((addr<<1)&0x7E) | 0x80 219 | data[1] = 0x00 220 | 221 | self.nenbrc522.low() # start transaction 222 | 223 | if not MPY_ESP8266: 224 | self.spi.send_recv(data,buf) # send data and read two bytes back 225 | else: 226 | self.spi.write_readinto(data,buf) # send data and read two bytes back 227 | 228 | self.nenbrc522.high() # transaction ended 229 | 230 | return buf[1] 231 | 232 | 233 | def MFRC522_Reset(self): 234 | self.Write_MFRC522(self.CommandReg, self.PCD_RESETPHASE) 235 | 236 | 237 | def SetBitMask(self, reg, mask): 238 | tmp = self.Read_MFRC522(reg) 239 | self.Write_MFRC522(reg, tmp | mask) 240 | 241 | 242 | def ClearBitMask(self, reg, mask): 243 | tmp = self.Read_MFRC522(reg); 244 | self.Write_MFRC522(reg, tmp & (~mask)) 245 | 246 | 247 | def AntennaOn(self): 248 | temp = self.Read_MFRC522(self.TxControlReg) 249 | if (~(temp & 0x03)): 250 | self.SetBitMask(self.TxControlReg, 0x03) 251 | 252 | 253 | def AntennaOff(self): 254 | self.ClearBitMask(self.TxControlReg, 0x03) 255 | 256 | 257 | def MFRC522_ToCard(self,command,sendData): 258 | backData = [] 259 | backLen = 0 260 | status = self.MI_ERR 261 | irqEn = 0x00 262 | waitIRq = 0x00 263 | lastBits = None 264 | n = 0 265 | i = 0 266 | 267 | if command == self.PCD_AUTHENT: 268 | irqEn = 0x12 269 | waitIRq = 0x10 270 | if command == self.PCD_TRANSCEIVE: 271 | irqEn = 0x77 272 | waitIRq = 0x30 273 | 274 | self.Write_MFRC522(self.CommIEnReg, irqEn|0x80) 275 | self.ClearBitMask(self.CommIrqReg, 0x80) 276 | self.SetBitMask(self.FIFOLevelReg, 0x80) 277 | 278 | self.Write_MFRC522(self.CommandReg, self.PCD_IDLE); 279 | 280 | while(i self.MAX_LEN: 316 | n = self.MAX_LEN 317 | 318 | i = 0 319 | while i> 4 519 | 520 | if (val==0) or (val==2): 521 | val = 18 522 | elif (val==1) or (val==3): 523 | val = 23 524 | elif val==4: 525 | val = 33 526 | elif val==5: 527 | val=38 528 | elif val==6: 529 | val=43 530 | else: 531 | val=48 532 | return val 533 | 534 | 535 | def MFRC522_Init(self): 536 | ''' init the device registers ''' 537 | self.nrstpd.high() # get it out of reset 538 | 539 | self.MFRC522_Reset(); 540 | 541 | if not MPY_ESP8266: 542 | pyb.delay(500) 543 | else: 544 | time.sleep_ms(500) 545 | 546 | print("MFRC522 version is " + str(self.MFRC522_Version() ) ) 547 | print("Receiver gain is " + str(self.MFRC522_ReceiverGain()) + "dB") 548 | 549 | self.Write_MFRC522(self.TModeReg, 0x8D) 550 | self.Write_MFRC522(self.TPrescalerReg, 0x3E) 551 | self.Write_MFRC522(self.TReloadRegL, 30) 552 | self.Write_MFRC522(self.TReloadRegH, 0) 553 | 554 | self.Write_MFRC522(self.TxAutoReg, 0x40) 555 | self.Write_MFRC522(self.ModeReg, 0x3D) 556 | self.AntennaOn() 557 | 558 | 559 | def MFRC522_DeInit(self): 560 | ''' turn it off and sleep ''' 561 | self.AntennaOff() 562 | self.nenbrc522.high() 563 | self.nrstpd.low() # put the chip into power down 564 | self.spi.deinit() # turn off SPI bus 565 | 566 | 567 | 568 | if __name__ == '__main__': 569 | """ some basic test code resides here """ 570 | 571 | if not MPY_ESP8266: 572 | print("PYB1.0 Board configuration") 573 | else 574 | print("ESP-13 Module configuration") 575 | 576 | hell_freezes_over = True 577 | 578 | # let's have a reader 579 | MIFAREReader = MFRC522() 580 | 581 | # loop keeps checking for cards and tags. If one is near it will catch the UID and authenticate it 582 | while hell_freezes_over: 583 | 584 | # Scan for cards 585 | (status,TagType) = MIFAREReader.MFRC522_Request(MIFAREReader.PICC_REQIDL) 586 | # If a card is found 587 | if status == MIFAREReader.MI_OK: 588 | print ("NFC card detected") 589 | 590 | # Get the UID of the card 591 | (status,uid) = MIFAREReader.MFRC522_Anticoll() 592 | 593 | # If we have the UID, continue 594 | if status == MIFAREReader.MI_OK: 595 | if not MPY_ESP8266: 596 | pyb.LED(4).on() 597 | pyb.delay(200) 598 | pyb.LED(4).off() 599 | 600 | # Print UID 601 | print("Card read UID: "+str(hex(uid[0]))+","+str(hex(uid[1]))+","+str(hex(uid[2]))+","+str(hex(uid[3])) ) 602 | 603 | # This is the default key for authentication 604 | key = [0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] 605 | # Select the scanned tag 606 | #MIFAREReader.MFRC522_SelectTag(uid) 607 | # Dump the data 608 | #MIFAREReader.MFRC522_DumpClassic1K(key, uid) 609 | # Stop 610 | #MIFAREReader.MFRC522_StopCrypto1() 611 | 612 | 613 | if not MPY_ESP8266: 614 | pyb.delay(1000) 615 | else: 616 | time.sleep_ms(1000) 617 | 618 | # handle ctrl-c 619 | --------------------------------------------------------------------------------