├── .gitignore ├── .npmignore ├── CODE_OF_CONDUCT.md ├── Changelog.md ├── LICENSE.md ├── README.md ├── commands.js ├── docs ├── demo.md └── demonstration │ ├── 1.jpg │ ├── 2.jpg │ ├── 3.jpg │ ├── 4.jpg │ ├── 5.jpg │ ├── 6.jpg │ ├── 7.jpg │ ├── 8.jpg │ ├── 9.jpg │ ├── demo.gif │ └── demo.mp4 ├── index.js ├── package-lock.json ├── package.json ├── project-diagram ├── mfrc-522-node.fzz └── modules │ ├── AMS1117 │ ├── AMS1117.fzpz │ ├── AMS1117_bb.svg │ ├── AMS1117_pcb.svg │ └── AMS1117_schematic.svg │ └── RFID RC522 SIP - 8 pins.fzpz ├── test ├── dumpCard.js ├── dumpNTAG213.js ├── read.js ├── write.js └── writeAuthenticationKey.js └── wiki ├── GPIO-pins.png ├── RC522.jpg ├── ams1117.png ├── buzzer.jpg ├── diff-passive-active-buzzer.jpg ├── gpio-map.png ├── mfrc522-node.png ├── rpi-mfrc522-wiring2.PNG └── youtube.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Node template 3 | # Logs 4 | logs 5 | *.log 6 | npm-debug.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # node-waf configuration 27 | .lock-wscript 28 | 29 | # Compiled binary addons (http://nodejs.org/api/addons.html) 30 | build/Release 31 | 32 | # Dependency directories 33 | node_modules 34 | jspm_packages 35 | 36 | # Optional npm cache directory 37 | .npm 38 | 39 | # Optional eslint cache 40 | .eslintcache 41 | 42 | # Optional REPL history 43 | .node_repl_history 44 | 45 | # Output of 'npm pack' 46 | *.tgz 47 | 48 | # Yarn Integrity file 49 | .yarn-integrity 50 | 51 | 52 | .idea -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | docs 3 | wiki 4 | project-diagram -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at info@teufel-it.de. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /Changelog.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | ## [2.1.1 - 2019-12-14] 4 | 5 | ### Fixed 6 | 7 | - Add Docs to .npmignore 8 | 9 | ## [2.1.0 - 2019-12-14] 10 | 11 | ### Added 12 | 13 | - Update node-rpio from 1.0.13 to 1.3.0 14 | - Extended Information about card register 15 | - Example how to change authentication key for card register (test\writeAuthenticationKey.js) 16 | - Extended Readme & Documentation 17 | - Buzzer Notifications (optional) 18 | - Circuit Diagram -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Tristan Teufel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mfrc522-rpi 2 | 3 | :key: JavaScript class to control MFRC522 RFID Module with your Raspberry-pi 4 | 5 | MFRC522 is integrated in all types of 13.56MHz RFID passive contactless communication methods and protocols. 6 | 7 | It uses the ISO14443 specification to communicate to MIFARE cards (also known as NTAG, NFC) 8 | [MIFARE wiki](https://en.wikipedia.org/wiki/MIFARE) 9 | [ISO14443 wiki](https://de.wikipedia.org/wiki/ISO/IEC_14443) 10 | 11 | ## Features 12 | 13 | - Read uid & card memory 14 | - Write card memory & card key 15 | - Buzzer notification (Optional) 16 | 17 | ## Demo 18 | 19 | ![Example](https://github.com/firsttris/mfrc522-rpi/raw/master/docs/demonstration/demo.gif) 20 | 21 | [Watch on Youtube (with sound)](https://youtu.be/e5D_fy8IIjY) 22 | 23 | ## Enable SPI 24 | 25 | The SPI master driver is disabled by default on Raspbian. To enable it, use raspi-config, or ensure the line dtparam=spi=on isn't commented out in /boot/config.txt. When it is enabled then reboot your pi. If the SPI driver was loaded, you should see the device /dev/spidev0.0 26 | 27 | [more info about SPI](https://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/README.md) 28 | 29 | ## Install 30 | 31 | [![npm version](https://badge.fury.io/js/mfrc522-rpi.svg)](https://badge.fury.io/js/mfrc522-rpi) 32 | 33 | ``` 34 | npm install mfrc522-rpi 35 | ``` 36 | 37 | ## [node-rpio Compatibility](https://github.com/jperkin/node-rpio/blob/master/README.md#compatibility) 38 | 39 | * Raspberry Pi Models: A, B (revisions 1.0 and 2.0), A+, B+, 2, 3, 3+, 40 | 3 A+, 4, Compute Module 3, Zero. 41 | * Node.js Versions: 0.8, 0.10, 0.12, 4, 5, 6, 7, 8, 9, 10, 11, 12 42 | 43 | ## Usage 44 | 45 | The examples in the `test` folder will help you get things started 46 | 47 | #### read uid 48 | 49 | `node /node_modules/mfrc522-rpi/test/read.js` 50 | 51 | #### dump card 52 | 53 | `node /node_modules/mfrc522-rpi/test/dumpCard.js` 54 | 55 | #### dump NTAG213 (sticker) 56 | 57 | `node /node_modules/mfrc522-rpi/test/dumpNTAG213.js` 58 | 59 | #### write NTAG213 60 | 61 | https://github.com/firsttris/mfrc522-rpi/issues/5 Thanks to [musdom](https://github.com/musdom) 62 | 63 | #### write card 64 | 65 | `node /node_modules/mfrc522-rpi/test/write.js` 66 | 67 | ### Card Register 68 | 69 | Your MiFare NFC chip consists of multiple sectors, each containing 4 blocks. 70 | The first 3 blocks of every sector are used to store data, the last block 71 | contains security features (access keys and bits). 72 | Every block holds 16 bytes of data. A typical MiFare Classic 1K chip 73 | has 16 of these sectors, accounting to 64 blocks with 1024 bytes in total. 74 | 75 | The first sector is reserved for manufacturer data, while the second sector 76 | is supposed to contain card holder data. 77 | So, to be on the safe side, start writing your data on the third sector, starting 78 | with block 8. 79 | 80 | Every last block of a sector is called a trailer block. It contains two access 81 | keys, which are used for protecting the data against unpermitted access, and 82 | access bits controlling what can be done with this sector. 83 | The first 6 bytes of such a block contain access key A, the following 4 bytes 84 | are the access bits, and the last 6 bytes are access key B (optional key). 85 | 86 | Please note that when reading a trailer block with this module, it will always return 87 | the same (incorrect) values regardless of its actual content. This might be a security 88 | feature of the chips. 89 | 90 | For simplicity reasons, this module will always authenticate with and refer to key A only. 91 | The default key A on new cards is always `[0xff, 0xff, 0xff, 0xff, 0xff, 0xff]`. 92 | 93 | The access bits in the middle of a sector trailer block should never be changed without 94 | exactly knowing what you're doing. They control what can be done with the current sector 95 | and which of the access key(s) can be used for authentication. 96 | If they don't make sense, the sector (4 blocks) is irreversively blocked and can never 97 | be used again. 98 | 99 | If you want to safely change the access key for a sector, please use the 100 | `writeAuthenticationKey` method (see the `writeAuthenticationKey.js` example in `test`). 101 | Always store the new access key(s) somewhere safe. 102 | 103 | Physical memory content of the chip/card which was included on the RFID-RC522 Module 104 | 105 | ``` 106 | Block: 0 Data: 89,229,151,26,49,8,4,0,98,99,100,101,102,103,104,105 107 | Block: 1 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 108 | Block: 2 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 109 | Block: 3 Data: 0,0,0,0,0,0,255,7,128,105,255,255,255,255,255,255 110 | Block: 4 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 111 | Block: 5 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 112 | Block: 6 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 113 | Block: 7 Data: 0,0,0,0,0,0,255,7,128,105,255,255,255,255,255,255 114 | Block: 8 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 115 | Block: 9 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 116 | Block: 10 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 117 | Block: 11 Data: 0,0,0,0,0,0,255,7,128,105,255,255,255,255,255,255 118 | Block: 12 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 119 | Block: 13 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 120 | Block: 14 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 121 | Block: 15 Data: 0,0,0,0,0,0,255,7,128,105,255,255,255,255,255,255 122 | Block: 16 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 123 | Block: 17 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 124 | Block: 18 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 125 | Block: 19 Data: 0,0,0,0,0,0,255,7,128,105,255,255,255,255,255,255 126 | Block: 20 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 127 | Block: 21 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 128 | Block: 22 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 129 | Block: 23 Data: 0,0,0,0,0,0,255,7,128,105,255,255,255,255,255,255 130 | Block: 24 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 131 | Block: 25 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 132 | Block: 26 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 133 | Block: 27 Data: 0,0,0,0,0,0,255,7,128,105,255,255,255,255,255,255 134 | Block: 28 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 135 | Block: 29 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 136 | Block: 30 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 137 | Block: 31 Data: 0,0,0,0,0,0,255,7,128,105,255,255,255,255,255,255 138 | Block: 32 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 139 | Block: 33 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 140 | Block: 34 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 141 | Block: 35 Data: 0,0,0,0,0,0,255,7,128,105,255,255,255,255,255,255 142 | Block: 36 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 143 | Block: 37 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 144 | Block: 38 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 145 | Block: 39 Data: 0,0,0,0,0,0,255,7,128,105,255,255,255,255,255,255 146 | Block: 40 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 147 | Block: 41 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 148 | Block: 42 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 149 | Block: 43 Data: 0,0,0,0,0,0,255,7,128,105,255,255,255,255,255,255 150 | Block: 44 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 151 | Block: 45 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 152 | Block: 46 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 153 | Block: 47 Data: 0,0,0,0,0,0,255,7,128,105,255,255,255,255,255,255 154 | Block: 48 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 155 | Block: 49 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 156 | Block: 50 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 157 | Block: 51 Data: 0,0,0,0,0,0,255,7,128,105,255,255,255,255,255,255 158 | Block: 52 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 159 | Block: 53 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 160 | Block: 54 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 161 | Block: 55 Data: 0,0,0,0,0,0,255,7,128,105,255,255,255,255,255,255 162 | Block: 56 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 163 | Block: 57 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 164 | Block: 58 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 165 | Block: 59 Data: 0,0,0,0,0,0,255,7,128,105,255,255,255,255,255,255 166 | Block: 60 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 167 | Block: 61 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 168 | Block: 62 Data: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 169 | Block: 63 Data: 0,0,0,0,0,0,255,7,128,105,255,255,255,255,255,255 170 | ``` 171 | 172 | ### Changing Authentication Keys 173 | 174 | This has so far only been tested with MiFare Classic 1K cards (the ones that come with the reader)! 175 | Please use the `writeAuthenticationKey` method 176 | (see the `writeAuthenticationKey.js` example in `test`). 177 | 178 | ## Documentation 179 | 180 | Manufacturer documentation of MFRC522 181 | 182 | [MFRC522-Doc.pdf](https://www.nxp.com/documents/data_sheet/MFRC522.pdf) 183 | 184 | [NFC-TAG Types](http://www.nfc-tag-shop.de/info/ueber-nfc-tags/nfc-tag-typen.html) 185 | 186 | [NTAG213_215_216.pdf](https://www.nxp.com/documents/data_sheet/NTAG213_215_216.pdf) 187 | 188 | ### Wiring 189 | 190 | Follow the map here to do the interface pins. 191 | 192 | | Name | Pin # | Pin name | 193 | | ------ | ----- | ------------------ | 194 | | SDA | 24 | CE0 | 195 | | SCK | 23 | SCLK1 | 196 | | MOSI | 19 | MOSI1 | 197 | | MISO | 21 | MOSO1 | 198 | | IRQ | None | None | 199 | | GND | Any | Any Ground | 200 | | RST | 22 | GPIO5C3 | 201 | | 3.3V | 1 | 3V3 | 202 | | Buzzer | 18 | GPIO5B3 (Optional) | 203 | 204 | Note that the pins number is different from the BCM number. 205 | 206 | ![Screenshot](wiki/rpi-mfrc522-wiring2.PNG) 207 | 208 | ![Screenshot](wiki/gpio-map.png) 209 | 210 | ### Which hardware is used? 211 | 212 | List of hardware which are used with links to `amazon.de`: 213 | 214 | - [Raspberry Pi 3 B+](https://www.amazon.de/Raspberry-1373331-Pi-Modell-Mainboard/dp/B07BDR5PDW/ref=sr_1_3?crid=78XCCBIEFSD9&keywords=raspberry+pi+3+b%2B&qid=1565892766&s=gateway&sprefix=raspberry%2Caps%2C173&sr=8-3) 215 | - [RFID kit RC522](https://www.amazon.de/AZDelivery-Reader-Arduino-Raspberry-gratis/dp/B01M28JAAZ/ref=sr_1_1?keywords=MFRC522&qid=1565892804&s=gateway&sr=8-1) 216 | 217 | ## Buzzer Notifications (optional) 218 | 219 | It's possible to get buzzer notifications when the module reads a chip, simply connect a piezo speaker to your PI. 220 | 221 | ### Components for Buzzer 222 | 223 | - [DC to DC regulator (5V to 3.3V)](https://www.amazon.de/PEMENOL-AMS1117-Stromversorgungsmodul-Raspberry-Mikrocontroller/dp/B07FSLGPR8/ref=sr_1_1?keywords=AMS1117&qid=1565868927&s=ce-de&sr=1-1) (optional) used only if you want to interface buzzer with the system. 224 | ![ams1117](wiki/ams1117.png) 225 | - [Active buzzer (NOT passive)](https://www.amazon.de/BETAFPV-Terminals-Electronic-Continuous-12X9-5mm/dp/B073RH8TQK/ref=sr_1_2?keywords=Active+buzzer&qid=1565892971&s=ce-de&sr=1-2) (optional) 226 | ![ams1117](wiki/diff-passive-active-buzzer.jpg) 227 | - [NPN transistor](https://www.amazon.de/100pcs-S8050-S8050D-Transistor-40Volts/dp/B00CZ6K2SM/ref=sr_1_1?keywords=s8050&qid=1565894051&s=computers&sr=1-1) (Optional) 228 | 229 | Those three optional component are required to run the buzzer with 5V. The RC522 is running at 3.3V so we need to step down the voltage a bit. 230 | 231 | ### Wiring with Buzzer 232 | 233 | ![Screenshot](wiki/mfrc522-node.png) 234 | 235 | ## Demonstration 236 | 237 | - Some images and video demonstration can be found [here](docs/demo.md) 238 | 239 | ## Circuit Diagram: 240 | 241 | Inside `project-diagram` folder there is a diagram for the system. You can run it with `Fritzing` application and make a printable PCB after aligning components on your wish. 242 | 243 | ### Sources 244 | 245 | https://github.com/miguelbalboa/rfid 246 | 247 | https://github.com/mxgxw/MFRC522-python 248 | 249 | ## Code of Conduct 250 | 251 | See the [CODE](CODE_OF_CONDUCT.md) 252 | 253 | ## License 254 | 255 | See the [LICENSE](LICENSE.md) file for license rights and limitations (MIT). 256 | -------------------------------------------------------------------------------- /commands.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | module.exports = { 3 | PCD_IDLE: 0x00, 4 | PCD_AUTHENT: 0x0E, 5 | PCD_RECEIVE: 0x08, 6 | PCD_TRANSMIT: 0x04, 7 | PCD_TRANSCEIVE: 0x0C, 8 | PCD_RESETPHASE: 0x0F, 9 | PCD_CALCCRC: 0x03, 10 | 11 | PICC_REQIDL: 0x26, 12 | PICC_REQALL: 0x52, 13 | PICC_ANTICOLL: 0x93, 14 | PICC_SELECTTAG: 0x93, 15 | PICC_AUTHENT1A: 0x60, 16 | PICC_AUTHENT1B: 0x61, 17 | PICC_READ: 0x30, 18 | PICC_WRITE: 0xA0, 19 | PICC_DECREMENT: 0xC0, 20 | PICC_INCREMENT: 0xC1, 21 | PICC_RESTORE: 0xC2, 22 | PICC_TRANSFER: 0xB0, 23 | PICC_HALT: 0x50, 24 | 25 | Reserved00: 0x00, 26 | CommandReg: 0x01, 27 | CommIEnReg: 0x02, 28 | DivlEnReg: 0x03, 29 | CommIrqReg: 0x04, 30 | DivIrqReg: 0x05, 31 | ErrorReg: 0x06, 32 | Status1Reg: 0x07, 33 | Status2Reg: 0x08, 34 | FIFODataReg: 0x09, 35 | FIFOLevelReg: 0x0A, 36 | WaterLevelReg: 0x0B, 37 | ControlReg: 0x0C, 38 | BitFramingReg: 0x0D, 39 | CollReg: 0x0E, 40 | Reserved01: 0x0F, 41 | 42 | Reserved10: 0x10, 43 | ModeReg: 0x11, 44 | TxModeReg: 0x12, 45 | RxModeReg: 0x13, 46 | TxControlReg: 0x14, 47 | TxAutoReg: 0x15, 48 | TxSelReg: 0x16, 49 | RxSelReg: 0x17, 50 | RxThresholdReg: 0x18, 51 | DemodReg: 0x19, 52 | Reserved11: 0x1A, 53 | Reserved12: 0x1B, 54 | MifareReg: 0x1C, 55 | Reserved13: 0x1D, 56 | Reserved14: 0x1E, 57 | SerialSpeedReg: 0x1F, 58 | 59 | Reserved20: 0x20, 60 | CRCResultRegM: 0x21, 61 | CRCResultRegL: 0x22, 62 | Reserved21: 0x23, 63 | ModWidthReg: 0x24, 64 | Reserved22: 0x25, 65 | RFCfgReg: 0x26, 66 | GsNReg: 0x27, 67 | CWGsPReg: 0x28, 68 | ModGsPReg: 0x29, 69 | TModeReg: 0x2A, 70 | TPrescalerReg: 0x2B, 71 | TReloadRegH: 0x2C, 72 | TReloadRegL: 0x2D, 73 | TCounterValueRegH: 0x2E, 74 | TCounterValueRegL: 0x2F, 75 | 76 | Reserved30: 0x30, 77 | TestSel1Reg: 0x31, 78 | TestSel2Reg: 0x32, 79 | TestPinEnReg: 0x33, 80 | TestPinValueReg: 0x34, 81 | TestBusReg: 0x35, 82 | AutoTestReg: 0x36, 83 | VersionReg: 0x37, 84 | AnalogTestReg: 0x38, 85 | TestDAC1Reg: 0x39, 86 | TestDAC2Reg: 0x3A, 87 | TestADCReg: 0x3B, 88 | Reserved31: 0x3C, 89 | Reserved32: 0x3D, 90 | Reserved33: 0x3E, 91 | Reserved34: 0x3F 92 | } -------------------------------------------------------------------------------- /docs/demo.md: -------------------------------------------------------------------------------- 1 | # Demonstration 2 | 3 | Those are some images related to a real module build with `mfrc522-rpi` library. 4 | 5 | ![pic_1](demonstration/1.jpg) 6 | ![pic_2](demonstration/2.jpg) 7 | ![pic_3](demonstration/3.jpg) 8 | ![pic_4](demonstration/4.jpg) 9 | ![pic_5](demonstration/5.jpg) 10 | ![pic_6](demonstration/6.jpg) 11 | ![pic_7](demonstration/7.jpg) 12 | ![pic_9](demonstration/9.jpg) 13 | 14 | **Video demo** 15 | 16 | ![Example](https://github.com/firsttris/mfrc522-rpi/raw/master/docs/demonstration/demo.gif) 17 | 18 | [Watch on Youtube (with sound)](https://youtu.be/e5D_fy8IIjY) 19 | -------------------------------------------------------------------------------- /docs/demonstration/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firsttris/mfrc522-rpi/867d273ede5ac27c5a28408d307ffab7b86dcb8a/docs/demonstration/1.jpg -------------------------------------------------------------------------------- /docs/demonstration/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firsttris/mfrc522-rpi/867d273ede5ac27c5a28408d307ffab7b86dcb8a/docs/demonstration/2.jpg -------------------------------------------------------------------------------- /docs/demonstration/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firsttris/mfrc522-rpi/867d273ede5ac27c5a28408d307ffab7b86dcb8a/docs/demonstration/3.jpg -------------------------------------------------------------------------------- /docs/demonstration/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firsttris/mfrc522-rpi/867d273ede5ac27c5a28408d307ffab7b86dcb8a/docs/demonstration/4.jpg -------------------------------------------------------------------------------- /docs/demonstration/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firsttris/mfrc522-rpi/867d273ede5ac27c5a28408d307ffab7b86dcb8a/docs/demonstration/5.jpg -------------------------------------------------------------------------------- /docs/demonstration/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firsttris/mfrc522-rpi/867d273ede5ac27c5a28408d307ffab7b86dcb8a/docs/demonstration/6.jpg -------------------------------------------------------------------------------- /docs/demonstration/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firsttris/mfrc522-rpi/867d273ede5ac27c5a28408d307ffab7b86dcb8a/docs/demonstration/7.jpg -------------------------------------------------------------------------------- /docs/demonstration/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firsttris/mfrc522-rpi/867d273ede5ac27c5a28408d307ffab7b86dcb8a/docs/demonstration/8.jpg -------------------------------------------------------------------------------- /docs/demonstration/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firsttris/mfrc522-rpi/867d273ede5ac27c5a28408d307ffab7b86dcb8a/docs/demonstration/9.jpg -------------------------------------------------------------------------------- /docs/demonstration/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firsttris/mfrc522-rpi/867d273ede5ac27c5a28408d307ffab7b86dcb8a/docs/demonstration/demo.gif -------------------------------------------------------------------------------- /docs/demonstration/demo.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firsttris/mfrc522-rpi/867d273ede5ac27c5a28408d307ffab7b86dcb8a/docs/demonstration/demo.mp4 -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const CMD = require("./commands"); 3 | const rpio = require("rpio"); 4 | const OK = true; 5 | const ERROR = false; 6 | let BUZZERCount = 1; 7 | let isCycleEnded = true; 8 | 9 | class MFRC522 { 10 | /** 11 | * Initialize MFRC522 12 | * 13 | * @param {any} SoftSPI object 14 | * @param {any} reset pin number 15 | * @memberof MFRC522 16 | */ 17 | constructor(spi) { 18 | this.spi = spi; 19 | this.spi.open(); 20 | return this; 21 | } 22 | 23 | setResetPin(pin = 22) { 24 | if (!pin) { 25 | throw new Error( 26 | "Invalid parameter! reset pin parameter is invalid or not provided!" 27 | ); 28 | } 29 | this.reset_pin = pin; 30 | // Hold RESET pin low for 50ms to hard reset the reader 31 | rpio.open(this.reset_pin, rpio.OUTPUT, rpio.LOW); 32 | setTimeout(function() { 33 | rpio.write(this.reset_pin, rpio.HIGH); 34 | }.bind(this), 50); 35 | return this; 36 | } 37 | 38 | setBuzzerPin(pin) { 39 | // Set Alert mode and initial value. 40 | if (!pin) { 41 | throw new Error( 42 | "Invalid parameter! buzzer pin parameter is invalid or not provided!" 43 | ); 44 | } 45 | this.buzzer_pin = pin; 46 | rpio.open(this.buzzer_pin, rpio.OUTPUT); 47 | rpio.write(this.buzzer_pin, rpio.LOW); 48 | return this; 49 | } 50 | 51 | /** 52 | * Initializes the MFRC522 chip. 53 | * 54 | * @memberof MFRC522 55 | */ 56 | reset() { 57 | this.writeRegister(CMD.CommandReg, CMD.PCD_RESETPHASE); // reset chip 58 | this.writeRegister(CMD.TModeReg, 0x8d); // TAuto=1; timer starts automatically at the end of the transmission in all communication modes at all speeds 59 | this.writeRegister(CMD.TPrescalerReg, 0x3e); // TPreScaler = TModeReg[3..0]:TPrescalerReg, ie 0x0A9 = 169 => f_timer=40kHz, ie a timer period of 25μs. 60 | this.writeRegister(CMD.TReloadRegL, 30); // Reload timer with 0x3E8 = 1000, ie 25ms before timeout. 61 | this.writeRegister(CMD.TReloadRegH, 0); 62 | this.writeRegister(CMD.TxAutoReg, 0x40); // Default 0x00. Force a 100 % ASK modulation independent of the ModGsPReg register setting 63 | this.writeRegister(CMD.ModeReg, 0x3d); // Default 0x3F. Set the preset value for the CRC coprocessor for the CalcCRC command to 0x6363 (ISO 14443-3 part 6.2.4) 64 | this.antennaOn(); // Enable the antenna driver pins TX1 and TX2 (they were disabled by the reset) 65 | } 66 | 67 | /** 68 | * Writes a bit to the specified register in the MFRC522 chip. 69 | * The interface is described in the datasheet section 8.1.2. 70 | * 71 | * @param {any} addr 72 | * @param {any} val 73 | * @memberof MFRC522 74 | */ 75 | writeRegister(addr, val) { 76 | const data = [(addr << 1) & 0x7e, val]; 77 | const uint8Data = Uint8Array.from(data); 78 | this.spi.write(uint8Data); 79 | } 80 | 81 | /** 82 | * Alert card holder that the card has been read. 83 | */ 84 | alert() { 85 | if (this.buzzer_pin) { 86 | setTimeout(() => { 87 | rpio.write(this.buzzer_pin, 1); 88 | setTimeout(() => { 89 | rpio.write(this.buzzer_pin, 0); 90 | BUZZERCount++; 91 | if (BUZZERCount == 3) { 92 | BUZZERCount = 1; 93 | isCycleEnded = true; 94 | } else { 95 | isCycleEnded = false; 96 | this.alert(); 97 | } 98 | }, 80); 99 | }, 180); 100 | } 101 | } 102 | 103 | /** 104 | * Reads a bit from the specified register in the MFRC522 chip. 105 | * The interface is described in the datasheet section 8.1.2. 106 | * 107 | * @param {any} addr 108 | * @returns 109 | * @memberof MFRC522 110 | */ 111 | readRegister(addr) { 112 | const data = [((addr << 1) & 0x7e) | 0x80, 0]; 113 | const uint8Data = Uint8Array.from(data); 114 | const uint8DataResponse = this.spi.transfer(uint8Data); 115 | return uint8DataResponse[1]; 116 | } 117 | 118 | /** 119 | * Sets the bits given in mask in register reg. 120 | * 121 | * @param {any} reg 122 | * @param {any} mask 123 | * @memberof MFRC522 124 | */ 125 | setRegisterBitMask(reg, mask) { 126 | let response = this.readRegister(reg); 127 | this.writeRegister(reg, response | mask); 128 | } 129 | 130 | /** 131 | * Clears the bits given in mask from register reg. 132 | * 133 | * @param {any} reg 134 | * @param {any} mask 135 | * @memberof MFRC522 136 | */ 137 | clearRegisterBitMask(reg, mask) { 138 | let response = this.readRegister(reg); 139 | this.writeRegister(reg, response & ~mask); 140 | } 141 | 142 | /** 143 | * 144 | * 145 | * @memberof MFRC522 146 | */ 147 | antennaOn() { 148 | let response = this.readRegister(CMD.TxControlReg); 149 | if (~(response & 0x03) != 0) { 150 | this.setRegisterBitMask(CMD.TxControlReg, 0x03); 151 | } 152 | } 153 | 154 | /** 155 | * 156 | * 157 | * @memberof MFRC522 158 | */ 159 | antennaOff() { 160 | this.clearRegisterBitMask(CMD.TxControlReg, 0x03); 161 | } 162 | 163 | /** 164 | * 165 | * RC522 and ISO14443 card communication 166 | * @param {any} command - command - MF522 command word 167 | * @param {any} bitsToSend - sent to the card through the RC522 data 168 | * @returns {{status: boolean, data: Array, bitSize: number}} 169 | * @memberof MFRC522 170 | */ 171 | toCard(command, bitsToSend) { 172 | let data = []; 173 | let bitSize = 0; 174 | let status = ERROR; 175 | let irqEn = 0x00; 176 | let waitIRq = 0x00; 177 | 178 | if (command == CMD.PCD_AUTHENT) { 179 | irqEn = 0x12; 180 | waitIRq = 0x10; 181 | } 182 | if (command == CMD.PCD_TRANSCEIVE) { 183 | irqEn = 0x77; 184 | waitIRq = 0x30; 185 | } 186 | this.writeRegister(CMD.CommIEnReg, irqEn | 0x80); //Interrupt request is enabled 187 | this.clearRegisterBitMask(CMD.CommIrqReg, 0x80); //Clears all interrupt request bits 188 | this.setRegisterBitMask(CMD.FIFOLevelReg, 0x80); //FlushBuffer=1, FIFO initialization 189 | this.writeRegister(CMD.CommandReg, CMD.PCD_IDLE); // Stop calculating CRC for new content in the FIFO. 190 | //Write data to the FIFO 191 | for (let i = 0; i < bitsToSend.length; i++) { 192 | this.writeRegister(CMD.FIFODataReg, bitsToSend[i]); 193 | } 194 | //Excuting command 195 | this.writeRegister(CMD.CommandReg, command); 196 | if (command == CMD.PCD_TRANSCEIVE) { 197 | this.setRegisterBitMask(CMD.BitFramingReg, 0x80); //StartSend=1,transmission of data starts 198 | } 199 | //Wait for the received data to complete 200 | let i = 2000; //According to the clock frequency adjustment, operation M1 card maximum waiting time 25ms 201 | let n = 0; 202 | do { 203 | n = this.readRegister(CMD.CommIrqReg); 204 | i--; 205 | } while (i != 0 && !(n & 0x01) && !(n & waitIRq)); 206 | 207 | this.clearRegisterBitMask(CMD.BitFramingReg, 0x80); //StartSend=0 208 | if (i != 0) { 209 | if ((this.readRegister(CMD.ErrorReg) & 0x1b) == 0x00) { 210 | //BufferOvfl Collerr CRCErr ProtecolErr 211 | status = OK; 212 | if (n & irqEn & 0x01) { 213 | status = ERROR; 214 | } 215 | if (command == CMD.PCD_TRANSCEIVE) { 216 | n = this.readRegister(CMD.FIFOLevelReg); 217 | let lastBits = this.readRegister(CMD.ControlReg) & 0x07; 218 | if (lastBits) { 219 | bitSize = (n - 1) * 8 + lastBits; 220 | } else { 221 | bitSize = n * 8; 222 | } 223 | if (n == 0) { 224 | n = 1; 225 | } 226 | if (n > 16) { 227 | n = 16; 228 | } 229 | //Reads the data received in the FIFO 230 | for (let i = 0; i < n; i++) { 231 | data.push(this.readRegister(CMD.FIFODataReg)); 232 | } 233 | } 234 | } else { 235 | status = ERROR; 236 | } 237 | } 238 | return { status: status, data: data, bitSize: bitSize }; 239 | } 240 | 241 | /** 242 | * Alert card holder that the card has been read. 243 | */ 244 | static alert() { 245 | setTimeout(() => { 246 | WiringPi.digitalWrite(BUZZER, 1); 247 | setTimeout(() => { 248 | WiringPi.digitalWrite(BUZZER, 0); 249 | BUZZERCount++; 250 | if (BUZZERCount == 3) { 251 | BUZZERCount = 1; 252 | isCycleEnded = true; 253 | } else { 254 | isCycleEnded = false; 255 | this.alert(); 256 | } 257 | }, 80); 258 | }, 180); 259 | } 260 | 261 | /** 262 | * Find card, read card type 263 | * TagType - Returns the card type 264 | * 0x4400 = Mifare_UltraLight 265 | * 0x0400 = Mifare_One (S50) 266 | * 0x0200 = Mifare_One (S70) 267 | * 0x0800 = Mifare_Pro (X) 268 | * 0x4403 = Mifare_DESFire 269 | * 270 | * @returns {{status: *, bitSize: *}} 271 | * @memberof MFRC522 272 | */ 273 | findCard() { 274 | if (isCycleEnded) { 275 | this.writeRegister(CMD.BitFramingReg, 0x07); 276 | const tagType = [CMD.PICC_REQIDL]; 277 | let response = this.toCard(CMD.PCD_TRANSCEIVE, tagType); 278 | if (response.bitSize != 0x10) { 279 | response.status = ERROR; 280 | } 281 | return { status: response.status, bitSize: response.bitSize }; 282 | } 283 | return { status: null, bitSize: null }; 284 | } 285 | 286 | /** 287 | * Anti-collision detection, get uid (serial number) of found card 288 | * 4-bit card to return the serial number, the first five bit for the check bit 289 | * 290 | * @returns {{status: *, data: Array, bitSize: *}} 291 | * @memberof MFRC522 292 | */ 293 | getUid() { 294 | this.alert(); 295 | this.writeRegister(CMD.BitFramingReg, 0x00); 296 | const uid = [CMD.PICC_ANTICOLL, 0x20]; 297 | let response = this.toCard(CMD.PCD_TRANSCEIVE, uid); 298 | if (response.status) { 299 | let uidCheck = 0; 300 | for (let i = 0; i < 4; i++) { 301 | uidCheck = uidCheck ^ response.data[i]; 302 | } 303 | if (uidCheck != response.data[4]) { 304 | response.status = ERROR; 305 | } 306 | } 307 | return { status: response.status, data: response.data }; 308 | } 309 | 310 | /** 311 | * Use the CRC coprocessor in the MFRC522 to calculate a CRC 312 | * 313 | * @param {any} data 314 | * @returns {array} 315 | * @memberof MFRC522 316 | */ 317 | calculateCRC(data) { 318 | this.clearRegisterBitMask(CMD.DivIrqReg, 0x04); // Clear the CRCIRq interrupt request bit 319 | this.setRegisterBitMask(CMD.FIFOLevelReg, 0x80); // FlushBuffer = 1, FIFO initialization 320 | //Write data to the FIFO 321 | for (let i = 0; i < data.length; i++) { 322 | this.writeRegister(CMD.FIFODataReg, data[i]); 323 | } 324 | this.writeRegister(CMD.CommandReg, CMD.PCD_CALCCRC); 325 | //Wait for the CRC calculation to complete 326 | let i = 0xff; 327 | let n; 328 | do { 329 | n = this.readRegister(CMD.DivIrqReg); 330 | i--; 331 | } while (i != 0 && !(n & 0x04)); //CRCIrq = 1 332 | //CRC calculation result 333 | return [ 334 | this.readRegister(CMD.CRCResultRegL), 335 | this.readRegister(CMD.CRCResultRegM) 336 | ]; 337 | } 338 | 339 | /** 340 | * Select card by, returns card memory capacity 341 | * 342 | * @param {any} uid 343 | * @returns 344 | * @memberof MFRC522 345 | */ 346 | selectCard(uid) { 347 | let buffer = [CMD.PICC_SELECTTAG, 0x70]; 348 | for (let i = 0; i < 5; i++) { 349 | buffer.push(uid[i]); 350 | } 351 | buffer = buffer.concat(this.calculateCRC(buffer)); 352 | let response = this.toCard(CMD.PCD_TRANSCEIVE, buffer); 353 | let memoryCapacity = 0; 354 | if (response.status && response.bitSize == 0x18) { 355 | memoryCapacity = response.data[0]; 356 | } 357 | return memoryCapacity; 358 | } 359 | 360 | /** 361 | * Verify the card password 362 | * Auth at Block N+1 with Key from Block N 363 | * Examle: Block 7 has Credentials from Block 8, in Block 7 there are 2 Keys A and B 364 | * @param address - block address 365 | * @param key - password for block 366 | * @param uid - card serial number, 4 bit 367 | * @returns {*} 368 | * @memberof MFRC522 369 | */ 370 | authenticate(address, key, uid) { 371 | /* Password authentication mode (A or B) 372 | * 0x60 = Verify the A key are the first 6 bit 373 | * 0x61 = Verify the B key are the last 6 bit 374 | * Second bit is the block address 375 | */ 376 | let buffer = [CMD.PICC_AUTHENT1A, address]; 377 | // Key default 6 bit of 0xFF 378 | for (let i = 0; i < key.length; i++) { 379 | buffer.push(key[i]); 380 | } 381 | // Next we append the first 4 bit of the UID 382 | for (let j = 0; j < 4; j++) { 383 | buffer.push(uid[j]); 384 | } 385 | // Now we start the authentication itself 386 | let response = this.toCard(CMD.PCD_AUTHENT, buffer); 387 | if (!(this.readRegister(CMD.Status2Reg) & 0x08)) { 388 | response.status = ERROR; 389 | } 390 | return response.status; 391 | } 392 | 393 | /** 394 | * 395 | * 396 | * @memberof MFRC522 397 | */ 398 | stopCrypto() { 399 | this.clearRegisterBitMask(CMD.Status2Reg, 0x08); 400 | } 401 | 402 | /** 403 | * Get Data for Block 404 | * 405 | * @param {any} address 406 | * @returns 407 | * @memberof MFRC522 408 | */ 409 | getDataForBlock(address) { 410 | let request = [CMD.PICC_READ, address]; 411 | request = request.concat(this.calculateCRC(request)); 412 | let response = this.toCard(CMD.PCD_TRANSCEIVE, request); 413 | if (!response.status) { 414 | console.log( 415 | "Error while reading! Status: " + 416 | response.status + 417 | " Data: " + 418 | response.data + 419 | " BitSize: " + 420 | response.bitSize 421 | ); 422 | } 423 | return response.data; 424 | } 425 | 426 | /** 427 | * 428 | * 429 | * @param {any} buffer 430 | * @returns 431 | * @memberof MFRC522 432 | */ 433 | appendCRCtoBufferAndSendToCard(buffer) { 434 | buffer = buffer.concat(this.calculateCRC(buffer)); 435 | let response = this.toCard(CMD.PCD_TRANSCEIVE, buffer); 436 | if ( 437 | !response.status || 438 | response.bitSize != 4 || 439 | (response.data[0] & 0x0f) != 0x0a 440 | ) { 441 | console.log( 442 | "Error while writing! Status: " + 443 | response.status + 444 | " Data: " + 445 | response.data + 446 | " BitSize: " + 447 | response.bitSize 448 | ); 449 | response.status = ERROR; 450 | } 451 | return response; 452 | } 453 | 454 | /** 455 | * Write Data To Block 456 | * 457 | * @param {any} address 458 | * @param {any} sixteenBits 459 | * @memberof MFRC522 460 | */ 461 | writeDataToBlock(address, sixteenBits) { 462 | let buffer = []; 463 | buffer.push(CMD.PICC_WRITE); 464 | buffer.push(address); 465 | let response = this.appendCRCtoBufferAndSendToCard(buffer); 466 | if (response.status) { 467 | buffer = []; 468 | // Write 16 bit of data to the FIFO 469 | for (let i = 0; i < 16; i++) { 470 | buffer.push(sixteenBits[i]); 471 | } 472 | response = this.appendCRCtoBufferAndSendToCard(buffer); 473 | if (response.status) { 474 | console.log("Data written successfully"); 475 | } 476 | } 477 | } 478 | 479 | /** 480 | * Write a new authentication key 481 | * @param {Number} address - block address 482 | * @param {Array} newKey - new key A, 6 bytes 483 | * @returns {Boolean} 484 | * @memberof MFRC522 485 | */ 486 | writeAuthenticationKey(address, newKeyA) { 487 | if (!address || !newKeyA) { 488 | return false; 489 | } 490 | 491 | if (address % 4 !== 3) { 492 | const offset = 3 - (address % 4); 493 | console.log( 494 | "Error: Chosen block is not a sector trailer! " + 495 | "Please write authentication key to block " + 496 | (address + offset) + 497 | "!" 498 | ); 499 | return false; 500 | } 501 | 502 | if (newKeyA.length !== 6) { 503 | console.log("Error: Key length must be 6!"); 504 | return false; 505 | } 506 | 507 | const data = this.getDataForBlock(address); 508 | const newData = newKeyA.concat(data.slice(6)); 509 | return this.writeDataToBlock(address, newData); 510 | } 511 | } 512 | 513 | module.exports = MFRC522; 514 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mfrc522-rpi", 3 | "version": "2.1.4", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "bindings": { 8 | "version": "1.5.0", 9 | "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", 10 | "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", 11 | "requires": { 12 | "file-uri-to-path": "1.0.0" 13 | } 14 | }, 15 | "file-uri-to-path": { 16 | "version": "1.0.0", 17 | "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", 18 | "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" 19 | }, 20 | "nan": { 21 | "version": "2.14.1", 22 | "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", 23 | "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==" 24 | }, 25 | "rpi-softspi": { 26 | "version": "1.0.5", 27 | "resolved": "https://registry.npmjs.org/rpi-softspi/-/rpi-softspi-1.0.5.tgz", 28 | "integrity": "sha512-b9umzQUk7p6HRSmQV3U9+ooboBOaodzJwqvZjX993D88geQePNzLaZDDQkMW2Ny14FwSUB3IvpBP3KFzv2rdaA==", 29 | "requires": { 30 | "rpio": "*" 31 | } 32 | }, 33 | "rpio": { 34 | "version": "1.7.1", 35 | "resolved": "https://registry.npmjs.org/rpio/-/rpio-1.7.1.tgz", 36 | "integrity": "sha512-jjccmmNHDOK4jsKNQVZcXCa1fKPUlO4BOcYZk5pdU8cPWyjcCh6D1/tpNYq5fOjeyGuemE6o9AZSRx6q7ICPcw==", 37 | "requires": { 38 | "bindings": "~1.5.0", 39 | "nan": "~2.14.0" 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mfrc522-rpi", 3 | "version": "2.1.4", 4 | "description": "small JavaScript interface to control RFID reader MFRC522 with Raspberry-pi", 5 | "main": "index.js", 6 | "scripts": { 7 | "read": "node test/read.js", 8 | "write": "node test/write.js", 9 | "dump": "node test/dumpCard.js" 10 | }, 11 | "keywords": [ 12 | "mfrc522", 13 | "rfid", 14 | "nfc", 15 | "rpi", 16 | "internet-of-things", 17 | "iot", 18 | "javascript", 19 | "nodejs" 20 | ], 21 | "author": "Tristan Teufel", 22 | "license": "ISC", 23 | "repository": { 24 | "type": "git", 25 | "url": "https://github.com/firsttris/mfrc522-rpi.git" 26 | }, 27 | "dependencies": { 28 | "rpi-softspi": "^1.0.5", 29 | "rpio": "^1.3.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /project-diagram/mfrc-522-node.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firsttris/mfrc522-rpi/867d273ede5ac27c5a28408d307ffab7b86dcb8a/project-diagram/mfrc-522-node.fzz -------------------------------------------------------------------------------- /project-diagram/modules/AMS1117/AMS1117.fzpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firsttris/mfrc522-rpi/867d273ede5ac27c5a28408d307ffab7b86dcb8a/project-diagram/modules/AMS1117/AMS1117.fzpz -------------------------------------------------------------------------------- /project-diagram/modules/AMS1117/AMS1117_bb.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | SOT223 30 | 31 | 32 | 33 | 34 | 35 | 36 | 1 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 4 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 2 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 3 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /project-diagram/modules/AMS1117/AMS1117_pcb.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 21 | 23 | 24 | 26 | image/svg+xml 27 | 29 | 30 | 31 | 32 | 34 | 54 | 57 | 60 | 72 | 84 | 96 | 108 | 111 | 112 | 113 | 116 | 119 | 129 | 139 | 149 | 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /project-diagram/modules/AMS1117/AMS1117_schematic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 21 | 23 | 24 | 26 | image/svg+xml 27 | 29 | 30 | 31 | 32 | 34 | 54 | 57 | 60 | 67 | 70 | 72 | AMS1117 77 | 78 | 79 | 89 | 99 | 109 | 119 | 127 | 132 | 135 | 137 | 3 141 | 142 | 143 | 146 | 148 | IN 152 | 153 | 154 | 165 | 173 | 176 | 178 | 180 | 183 | 185 | 187 | 190 | 192 | 1 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 208 | 210 | 212 | 215 | 217 | 219 | 222 | 224 | GND 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 245 | 250 | 253 | 255 | 2 259 | 260 | 261 | 264 | 266 | OUT 270 | 271 | 272 | 283 | 288 | 291 | 293 | 4 298 | 299 | 300 | 303 | 305 | OUT 310 | 311 | 312 | 313 | 314 | 315 | -------------------------------------------------------------------------------- /project-diagram/modules/RFID RC522 SIP - 8 pins.fzpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firsttris/mfrc522-rpi/867d273ede5ac27c5a28408d307ffab7b86dcb8a/project-diagram/modules/RFID RC522 SIP - 8 pins.fzpz -------------------------------------------------------------------------------- /test/dumpCard.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const Mfrc522 = require("./../index"); 3 | const SoftSPI = require("rpi-softspi"); 4 | 5 | //# This loop keeps checking for chips. If one is near it will get the UID and authenticate 6 | console.log("scanning..."); 7 | console.log("Please put chip or keycard in the antenna inductive zone!"); 8 | console.log("Press Ctrl-C to stop."); 9 | 10 | const softSPI = new SoftSPI({ 11 | clock: 23, // pin number of SCLK 12 | mosi: 19, // pin number of MOSI 13 | miso: 21, // pin number of MISO 14 | client: 24 // pin number of CS 15 | }); 16 | 17 | // GPIO 24 can be used for buzzer bin (PIN 18), Reset pin is (PIN 22). 18 | // I believe that channing pattern is better for configuring pins which are optional methods to use. 19 | const mfrc522 = new Mfrc522(softSPI).setResetPin(22).setBuzzerPin(18); 20 | 21 | setInterval(function() { 22 | //# reset card 23 | mfrc522.reset(); 24 | 25 | //# Scan for cards 26 | let response = mfrc522.findCard(); 27 | if (!response.status) { 28 | return; 29 | } 30 | console.log("Card detected, CardType: " + response.bitSize); 31 | 32 | //# Get the UID of the card 33 | response = mfrc522.getUid(); 34 | if (!response.status) { 35 | console.log("UID Scan Error"); 36 | return; 37 | } 38 | //# If we have the UID, continue 39 | const uid = response.data; 40 | console.log( 41 | "Card read UID: %s %s %s %s", 42 | uid[0].toString(16), 43 | uid[1].toString(16), 44 | uid[2].toString(16), 45 | uid[3].toString(16) 46 | ); 47 | 48 | //# Select the scanned card 49 | const memoryCapacity = mfrc522.selectCard(uid); 50 | console.log("Card Memory Capacity: " + memoryCapacity); 51 | 52 | //# This is the default key for authentication 53 | const keyA = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff]; 54 | const keyB = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 55 | 56 | //# dump 64 bit fifo buffer 57 | for (let i = 0; i < 64; i++) { 58 | if (mfrc522.authenticate(i, keyA, uid)) { 59 | console.log("Block: " + i + " Data: " + mfrc522.getDataForBlock(i)); 60 | } else { 61 | console.log("Authentication Error"); 62 | break; 63 | } 64 | } 65 | 66 | //# Stop 67 | mfrc522.stopCrypto(); 68 | }, 500); 69 | -------------------------------------------------------------------------------- /test/dumpNTAG213.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const Mfrc522 = require("./../index"); 3 | const SoftSPI = require("rpi-softspi"); 4 | 5 | //# This loop keeps checking for chips. If one is near it will get the UID and authenticate 6 | console.log("scanning..."); 7 | console.log("Please put chip or keycard in the antenna inductive zone!"); 8 | console.log("Press Ctrl-C to stop."); 9 | 10 | const softSPI = new SoftSPI({ 11 | clock: 23, // pin number of SCLK 12 | mosi: 19, // pin number of MOSI 13 | miso: 21, // pin number of MISO 14 | client: 24 // pin number of CS 15 | }); 16 | 17 | // GPIO 24 can be used for buzzer bin (PIN 18), Reset pin is (PIN 22). 18 | // I believe that channing pattern is better for configuring pins which are optional methods to use. 19 | const mfrc522 = new Mfrc522(softSPI).setResetPin(22).setBuzzerPin(18); 20 | 21 | setInterval(function() { 22 | //# reset card 23 | mfrc522.reset(); 24 | 25 | //# Scan for cards 26 | let response = mfrc522.findCard(); 27 | if (!response.status) { 28 | return; 29 | } 30 | console.log("Card detected, CardType: " + response.bitSize); 31 | 32 | //# Get the UID of the card 33 | response = mfrc522.getUid(); 34 | if (!response.status) { 35 | console.log("UID Scan Error"); 36 | return; 37 | } 38 | //# If we have the UID, continue 39 | const uid = response.data; 40 | console.log( 41 | "Card read UID: %s %s %s %s", 42 | uid[0].toString(16), 43 | uid[1].toString(16), 44 | uid[2].toString(16), 45 | uid[3].toString(16) 46 | ); 47 | 48 | //# Select the scanned card 49 | const memoryCapacity = mfrc522.selectCard(uid); 50 | console.log("Card Memory Capacity: " + memoryCapacity); 51 | 52 | //# dump fifo buffer 53 | for (let i = 0; i < 45; i++) { 54 | console.log("Block: " + i + " Data: " + mfrc522.getDataForBlock(i)); 55 | } 56 | }, 500); 57 | -------------------------------------------------------------------------------- /test/read.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const Mfrc522 = require("./../index"); 3 | const SoftSPI = require("rpi-softspi"); 4 | 5 | //# This loop keeps checking for chips. If one is near it will get the UID and authenticate 6 | console.log("scanning..."); 7 | console.log("Please put chip or keycard in the antenna inductive zone!"); 8 | console.log("Press Ctrl-C to stop."); 9 | 10 | const softSPI = new SoftSPI({ 11 | clock: 23, // pin number of SCLK 12 | mosi: 19, // pin number of MOSI 13 | miso: 21, // pin number of MISO 14 | client: 24 // pin number of CS 15 | }); 16 | 17 | // GPIO 24 can be used for buzzer bin (PIN 18), Reset pin is (PIN 22). 18 | // I believe that channing pattern is better for configuring pins which are optional methods to use. 19 | const mfrc522 = new Mfrc522(softSPI).setResetPin(22).setBuzzerPin(18); 20 | 21 | setInterval(function() { 22 | //# reset card 23 | mfrc522.reset(); 24 | 25 | //# Scan for cards 26 | let response = mfrc522.findCard(); 27 | if (!response.status) { 28 | console.log("No Card"); 29 | return; 30 | } 31 | console.log("Card detected, CardType: " + response.bitSize); 32 | 33 | //# Get the UID of the card 34 | response = mfrc522.getUid(); 35 | if (!response.status) { 36 | console.log("UID Scan Error"); 37 | return; 38 | } 39 | //# If we have the UID, continue 40 | const uid = response.data; 41 | console.log( 42 | "Card read UID: %s %s %s %s", 43 | uid[0].toString(16), 44 | uid[1].toString(16), 45 | uid[2].toString(16), 46 | uid[3].toString(16) 47 | ); 48 | 49 | //# Select the scanned card 50 | const memoryCapacity = mfrc522.selectCard(uid); 51 | console.log("Card Memory Capacity: " + memoryCapacity); 52 | 53 | //# This is the default key for authentication 54 | const key = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff]; 55 | 56 | //# Authenticate on Block 8 with key and uid 57 | if (!mfrc522.authenticate(8, key, uid)) { 58 | console.log("Authentication Error"); 59 | return; 60 | } 61 | 62 | //# Dump Block 8 63 | console.log("Block: 8 Data: " + mfrc522.getDataForBlock(8)); 64 | 65 | //# Stop 66 | mfrc522.stopCrypto(); 67 | }, 500); 68 | -------------------------------------------------------------------------------- /test/write.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const Mfrc522 = require("./../index"); 3 | const SoftSPI = require("rpi-softspi"); 4 | 5 | //# This loop keeps checking for chips. If one is near it will get the UID and authenticate 6 | console.log("scanning..."); 7 | console.log("Please put chip or keycard in the antenna inductive zone!"); 8 | console.log("Press Ctrl-C to stop."); 9 | 10 | const softSPI = new SoftSPI({ 11 | clock: 23, // pin number of SCLK 12 | mosi: 19, // pin number of MOSI 13 | miso: 21, // pin number of MISO 14 | client: 24 // pin number of CS 15 | }); 16 | 17 | // GPIO 24 can be used for buzzer bin (PIN 18), Reset pin is (PIN 22). 18 | // I believe that channing pattern is better for configuring pins which are optional methods to use. 19 | const mfrc522 = new Mfrc522(softSPI).setResetPin(22).setBuzzerPin(18); 20 | 21 | setInterval(function() { 22 | //# reset card 23 | mfrc522.reset(); 24 | 25 | //# Scan for cards 26 | let response = mfrc522.findCard(); 27 | if (!response.status) { 28 | console.log("No Card"); 29 | return; 30 | } 31 | console.log("Card detected, CardType: " + response.bitSize); 32 | 33 | //# Get the UID of the card 34 | response = mfrc522.getUid(); 35 | if (!response.status) { 36 | console.log("UID Scan Error"); 37 | return; 38 | } 39 | //# If we have the UID, continue 40 | const uid = response.data; 41 | console.log( 42 | "Card read UID: %s %s %s %s", 43 | uid[0].toString(16), 44 | uid[1].toString(16), 45 | uid[2].toString(16), 46 | uid[3].toString(16) 47 | ); 48 | 49 | //# Select the scanned card 50 | const memoryCapacity = mfrc522.selectCard(uid); 51 | console.log("Card Memory Capacity: " + memoryCapacity); 52 | 53 | //# This is the default key for authentication 54 | const key = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff]; 55 | 56 | //# Authenticate on Block 8 with key and uid 57 | if (!mfrc522.authenticate(8, key, uid)) { 58 | console.log("Authentication Error"); 59 | return; 60 | } 61 | 62 | //# Variable for the data to write 63 | let data = [ 64 | 0xff, 65 | 0xff, 66 | 0xff, 67 | 0xff, 68 | 0xff, 69 | 0xff, 70 | 0xff, 71 | 0xff, 72 | 0xff, 73 | 0xff, 74 | 0xff, 75 | 0xff, 76 | 0xff, 77 | 0xff, 78 | 0xff, 79 | 0xff, 80 | 0xff 81 | ]; 82 | 83 | console.log("Block 8 looked like this:"); 84 | console.log(mfrc522.getDataForBlock(8)); 85 | 86 | console.log("Block 8 will be filled with 0xFF:"); 87 | mfrc522.writeDataToBlock(8, data); 88 | 89 | console.log("Now Block 8 looks like this:"); 90 | console.log(mfrc522.getDataForBlock(8)); 91 | 92 | data = [ 93 | 0x00, 94 | 0x00, 95 | 0x00, 96 | 0x00, 97 | 0x00, 98 | 0x00, 99 | 0x00, 100 | 0x00, 101 | 0x00, 102 | 0x00, 103 | 0x00, 104 | 0x00, 105 | 0x00, 106 | 0x00, 107 | 0x00, 108 | 0x00, 109 | 0x00 110 | ]; 111 | 112 | console.log("Now we fill it with 16 x 0"); 113 | mfrc522.writeDataToBlock(8, data); 114 | 115 | console.log("It is now empty:"); 116 | console.log(mfrc522.getDataForBlock(8)); 117 | 118 | mfrc522.stopCrypto(); 119 | 120 | console.log("finished successfully!"); 121 | }, 500); 122 | -------------------------------------------------------------------------------- /test/writeAuthenticationKey.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const Mfrc522 = require("./../index"); // when using module, change this to: require("mfrc522-rpi") 3 | const SoftSPI = require("rpi-softspi"); 4 | 5 | //# This loop keeps checking for chips. If one is near it will get the UID and authenticate 6 | console.log("scanning..."); 7 | console.log("Please put chip or keycard in the antenna inductive zone!"); 8 | console.log("Press Ctrl-C to stop."); 9 | 10 | const softSPI = new SoftSPI({ 11 | clock: 23, // pin number of SCLK 12 | mosi: 19, // pin number of MOSI 13 | miso: 21, // pin number of MISO 14 | client: 24 // pin number of CS 15 | }); 16 | 17 | // GPIO 24 can be used for buzzer bin (PIN 18), Reset pin is (PIN 22). 18 | // I believe that channing pattern is better for configuring pins which are optional methods to use. 19 | const mfrc522 = new Mfrc522(softSPI).setResetPin(22).setBuzzerPin(18); 20 | 21 | setInterval(function() { 22 | //# reset card 23 | mfrc522.reset(); 24 | 25 | //# Scan for cards 26 | let response = mfrc522.findCard(); 27 | if (!response.status) { 28 | return; 29 | } 30 | 31 | console.log("Card detected, CardType: " + response.bitSize); 32 | 33 | //# Get the UID of the card 34 | response = mfrc522.getUid(); 35 | if (!response.status) { 36 | console.log("UID Scan Error"); 37 | return; 38 | } 39 | //# If we have the UID, continue 40 | const uid = response.data; 41 | console.log( 42 | "Card read UID: %s %s %s %s", 43 | uid[0].toString(16), 44 | uid[1].toString(16), 45 | uid[2].toString(16), 46 | uid[3].toString(16) 47 | ); 48 | 49 | //# Select the scanned card 50 | const memoryCapacity = mfrc522.selectCard(uid); 51 | console.log("Card Memory Capacity: " + memoryCapacity); 52 | 53 | //# oldKey is the default key for authentication 54 | const oldKey = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff]; 55 | const newKey = [0x11, 0x22, 0x33, 0x44, 0x55, 0x66]; 56 | 57 | //# Authenticate on Block 11 with key and uid 58 | if (!mfrc522.authenticate(11, oldKey, uid)) { 59 | console.log("Authentication Error"); 60 | return; 61 | } 62 | 63 | console.log("Changing access key in block 11 for blocks 8-11 to:", newKey); 64 | mfrc522.writeAuthenticationKey(11, newKey); 65 | 66 | console.log("Now we can use the new access key to store data in block 10..."); 67 | 68 | if (!mfrc522.authenticate(10, newKey, uid)) { 69 | console.log("Authentication Error"); 70 | return; 71 | } 72 | 73 | const oldData = mfrc522.getDataForBlock(10); 74 | console.log("Block 10 previous data: ", oldData); 75 | const newData = [ 76 | 0x00, 77 | 0x01, 78 | 0x02, 79 | 0x03, 80 | 0x04, 81 | 0x05, 82 | 0x06, 83 | 0x07, 84 | 0x08, 85 | 0x09, 86 | 0x0a, 87 | 0x0b, 88 | 0x0c, 89 | 0x0d, 90 | 0x0e, 91 | 0x0f 92 | ]; 93 | console.log("Data to write: ", newData); 94 | mfrc522.writeDataToBlock(10, newData); 95 | console.log("Block 10 data is now: ", mfrc522.getDataForBlock(10)); 96 | console.log("Change block 10 back to previous data"); 97 | mfrc522.writeDataToBlock(10, oldData); 98 | 99 | console.log("Now we change the access key back to factory default"); 100 | mfrc522.writeAuthenticationKey(11, oldKey); 101 | 102 | mfrc522.stopCrypto(); 103 | 104 | console.log("finished successfully!"); 105 | process.exit(); 106 | }, 500); 107 | -------------------------------------------------------------------------------- /wiki/GPIO-pins.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firsttris/mfrc522-rpi/867d273ede5ac27c5a28408d307ffab7b86dcb8a/wiki/GPIO-pins.png -------------------------------------------------------------------------------- /wiki/RC522.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firsttris/mfrc522-rpi/867d273ede5ac27c5a28408d307ffab7b86dcb8a/wiki/RC522.jpg -------------------------------------------------------------------------------- /wiki/ams1117.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firsttris/mfrc522-rpi/867d273ede5ac27c5a28408d307ffab7b86dcb8a/wiki/ams1117.png -------------------------------------------------------------------------------- /wiki/buzzer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firsttris/mfrc522-rpi/867d273ede5ac27c5a28408d307ffab7b86dcb8a/wiki/buzzer.jpg -------------------------------------------------------------------------------- /wiki/diff-passive-active-buzzer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firsttris/mfrc522-rpi/867d273ede5ac27c5a28408d307ffab7b86dcb8a/wiki/diff-passive-active-buzzer.jpg -------------------------------------------------------------------------------- /wiki/gpio-map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firsttris/mfrc522-rpi/867d273ede5ac27c5a28408d307ffab7b86dcb8a/wiki/gpio-map.png -------------------------------------------------------------------------------- /wiki/mfrc522-node.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firsttris/mfrc522-rpi/867d273ede5ac27c5a28408d307ffab7b86dcb8a/wiki/mfrc522-node.png -------------------------------------------------------------------------------- /wiki/rpi-mfrc522-wiring2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firsttris/mfrc522-rpi/867d273ede5ac27c5a28408d307ffab7b86dcb8a/wiki/rpi-mfrc522-wiring2.PNG -------------------------------------------------------------------------------- /wiki/youtube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firsttris/mfrc522-rpi/867d273ede5ac27c5a28408d307ffab7b86dcb8a/wiki/youtube.png --------------------------------------------------------------------------------