{"id":331,"date":"2009-03-07T00:26:30","date_gmt":"2009-03-07T05:26:30","guid":{"rendered":"http:\/\/www.tigoe.net\/pcomp\/code\/?p=331"},"modified":"2009-03-07T11:50:03","modified_gmt":"2009-03-07T16:50:03","slug":"writing-to-mifare-rfid-tags","status":"publish","type":"post","link":"https:\/\/www.tigoe.com\/pcomp\/code\/Processing\/331\/","title":{"rendered":"Writing to Mifare RFID tags"},"content":{"rendered":"<p>Mifare RFID tags, like other RFID tags, contain a serial number that can be read using an RFID reader, but they also have a limited amount of memory space that you can write data to, and read back from.\u00a0 This can be handy if you want to do something like keep a user&#8217;s account balance or name directly on the RFID tag.<\/p>\n<p>This tutorial shows a number of the functions of my <a href=\"https:\/\/tigoe.com\/pcomp\/code\/category\/\/314\">sonMicroReader\u00a0 library<\/a> for <a href=\"http:\/\/www.processing.org\">Processing<\/a>, including how to write to the memory on tags.\u00a0 It uses the same circuit as the <a href=\"http:\/\/www.sonmicro.com\/1356\/sm130.php\">SM130<\/a> <em><a href=\"https:\/\/tigoe.com\/pcomp\/code\/category\/Processing\/309\">reader example<\/a><\/em>. The entire sketch can be downloaded here:<\/p>\n<p><a href=\"https:\/\/tigoe.com\/pcomp\/code\/wp-content\/uploads\/2009\/03\/sonmicro_writer_0001.zip\">sonmicro_writer_0001<\/a><\/p>\n<p><!--more-->The interface screen of this sketch is shown in Figure 1. It contains buttons that trigger the major functions of the SM130 module, including\u00a0 setting the antenna power, selecting tags, authenticating for reading from or writing to tags, reading a block of memory, seeking tags, writing to a block of memory,\u00a0 writng to a 4-byte block, and getting the firmware version.<\/p>\n<figure id=\"attachment_334\" aria-describedby=\"caption-attachment-334\" style=\"width: 411px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/tigoe.com\/pcomp\/code\/wp-content\/uploads\/2009\/03\/picture-2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-334\" style=\"border: 0pt none;\" title=\"rfid_screenshot_2\" src=\"https:\/\/tigoe.com\/pcomp\/code\/wp-content\/uploads\/2009\/03\/picture-2.png\" alt=\"Figure 1. Screenshot of the reader\/writer sketch\" width=\"411\" height=\"298\" srcset=\"https:\/\/www.tigoe.com\/pcomp\/code\/wp-content\/uploads\/2009\/03\/picture-2.png 685w, https:\/\/www.tigoe.com\/pcomp\/code\/wp-content\/uploads\/2009\/03\/picture-2-300x217.png 300w\" sizes=\"auto, (max-width: 411px) 100vw, 411px\" \/><\/a><figcaption id=\"caption-attachment-334\" class=\"wp-caption-text\">Figure 1. Screenshot of the reader\/writer sketch<\/figcaption><\/figure>\n<p><strong>How do I read a tag&#8217;s ID number?<\/strong><\/p>\n<p>There are two ways to read a tag&#8217;s ID number: you can <strong>select tag<\/strong>, or you can <strong>seek tag<\/strong>. Select tag assumes that there&#8217;s a tag in the field of the antenna. Seek tag, on the other hand, puts the reader in a continuous loop where it waits for a tag to come into range, then automatically gives you the results when it has a tag.\u00a0 This sketch doesn&#8217;t read continuously. It issues each command once when you click the appropriate button.\u00a0 For more on reading continuously, see the <a href=\"https:\/\/tigoe.com\/pcomp\/code\/category\/Processing\/309\"><em>Reading Mifare Tags<\/em><\/a> example.<\/p>\n<p>To see reading in action, run the sketch and click the &#8220;Select Tag&#8221; button.\u00a0 With no tag in range, nothing will happen. By contrast, try clicking &#8220;Seek Tag&#8221; with no tag in range, then bring a tag into range.\u00a0 You&#8217;ll see that when the tag comes into range, the reader reads automatically.<\/p>\n<p><strong>How do I write to a tag&#8217;s memory?<\/strong><\/p>\n<p>To write to a tag, you first have to select the tag, then authenticate the block of memory using an authentication key. There are three basic authentication key types, called A, B, and FF. The latter uses a special transport key to authenticate, which you can set.\u00a0 The sequence goes like this:<\/p>\n<ul>\n<li>select tag<\/li>\n<li>authenticate block of memory you want to write to<\/li>\n<li>write data<\/li>\n<\/ul>\n<p>You can write up to 16 bytes for every block of memory.\u00a0 Beyond that, you have to break your message up across multiple blocks.<\/p>\n<p>The mifare ultralight tags have smaller blocks of memory, so there is also a writeFourByteBlock() command.\u00a0 This command writes only four-byte strings.<\/p>\n<p><strong>How do I read from a tag&#8217;s memory?<\/strong><\/p>\n<p>Reading works much like writing.\u00a0 First you select, then you authenticate, then you read.\u00a0 If a block of memory was authenticated with key type A for writing, then it has to be read with the same key type. Just like with writing, the operation goes like so:<\/p>\n<ul>\n<li>select tag<\/li>\n<li>authenticate block of memory you want to write to<\/li>\n<li>read data<\/li>\n<\/ul>\n<p><strong>To see reading and writing in action, do the following:<\/strong><\/p>\n<ul>\n<li>Hit delete, then type a short message (16 characters or less).<\/li>\n<li>Bring a tag in range<\/li>\n<li>Click Select<\/li>\n<li>When you get a good result, click Authenticate<\/li>\n<li>When you get a good result, click Write Block<\/li>\n<\/ul>\n<p>To read the same tag&#8217;s memory, here&#8217;s the sequence:<\/p>\n<ul>\n<li>Bring the tag in range<\/li>\n<li>Click Select<\/li>\n<li>When you get a good result, click Authenticate<\/li>\n<li>When you get a good result, click Read Block<\/li>\n<li>You should see your message in the response field<\/li>\n<\/ul>\n<p>Now that you&#8217;ve got the basic functionality down, it&#8217;s time to look at the code in depth.<\/p>\n<h2>The Code<\/h2>\n<p>This sketch uses the serial and sonMicro libraries. The global variables are mostly used to keep track of the last received messages from the reader:<\/p>\n<pre>\/\/ import libraries:\r\nimport processing.serial.*;\r\nimport sonMicroReader.*;\r\n\r\nString tagID = \"\";        \/\/ the string for the tag ID\r\nSerial myPort;            \/\/ serial port instance\r\nSonMicroReader myReader;  \/\/ sonMicroReader instance\r\n\r\nint  lastCommand = 0;        \/\/ last command sent\r\nint lastTagType = 0;         \/\/ last tag type received\r\nint lastPacketLength = 0;    \/\/ last packet length received\r\nString lastTag = null;       \/\/ last tag ID received\r\nint lastErrorCode = 0;       \/\/ last error code received\r\nint[] lastResponse = null;   \/\/ last response from the reader (raw data)\r\nint lastAntennaPower = 0;    \/\/ last antenna power received\r\nint lastChecksum = 0;        \/\/ last checksum received\r\n\r\nint fontHeight = 14;         \/\/ font height for the text onscreen\r\nString message = null;       \/\/ message read from tag\r\nString outputString = \"Hello world!\";    \/\/ string to write to tag<\/pre>\n<p>The setup() method initializes the libraries, the screen size, and the fonts. It also calls a method called makeButtons() that initializes a list of the button objects:<\/p>\n<pre>void setup() {\r\n  \/\/ set window size:\r\n  size(600,400);\r\n  \/\/ list all the serial ports:\r\n  println(Serial.list());\r\n\r\n  \/\/ based on the list of serial ports printed from the\r\n  \/\/ previous command, change the 0 to your port's number:\r\n  String portnum = Serial.list()[0];\r\n  \/\/ initialize the serial port. default data rate for\r\n  \/\/ the SM130 reader is 19200:\r\n  myPort = new Serial(this, portnum, 19200);\r\n  \/\/ initialize the reader instance:\r\n  myReader = new SonMicroReader(this,myPort);\r\n  myReader.start();\r\n\r\n  \/\/ create a font with the second font available to the system:\r\n  PFont myFont = createFont(PFont.list()[2], fontHeight);\r\n  textFont(myFont);\r\n  \/\/ create the command buttons:\r\n  makeButtons();\r\n}<\/pre>\n<p>The draw() method draws all the stuff on the screen.\u00a0 It calls drawButtons(), which iterates over the buttons and redraws them. Then it prints the status messages for the command, packet length, tag type, and so forth.\u00a0 If there&#8217;s a new response string, it draws that. Finally, it draws whatever you type in the output field.<\/p>\n<pre>void draw() {\r\n  \/\/ clear the screen:\r\n  background(0);\r\n  \/\/ draw the command buttons:\r\n  drawButtons();\r\n  \/\/ draw the output fields:\r\n  textAlign(LEFT);\r\n  text(\"Command: \" + hex(lastCommand, 2), 10, 30);\r\n  text(\"Packet length: \" +lastPacketLength, 10, 50);\r\n  text(\"Antenna power: \" + lastAntennaPower, 10, 70);\r\n  text(\"Tag type: \" + lastTagType, 10, 90);\r\n  text(\"Tag string: \" + lastTag, 10, 110);\r\n  text(\"Error code: \" + hex(lastErrorCode, 2), 10, 130);\r\n\r\n  \/\/ print the hex values for all the bytes in the response:\r\n  String responseString = \"\";\r\n  if (lastResponse != null) {\r\n    for (int b = 0; b &lt; lastResponse.length; b++) {\r\n      responseString += hex(lastResponse[b], 2) + \" \";\r\n    }\r\n    \/\/ wrap the full text so it doesn't overflow the buttons\r\n    \/\/ and make the screen all messy:\r\n    text(\"Full response:\\n\" + responseString, 10, 150, 300, 200);\r\n  }\r\n  \/\/ print any error messages from the reader:\r\n  text(myReader.getErrorMessage(), 10, 210);\r\n  \/\/ if there's a message from the tag's memory,\r\n  \/\/ print it:\r\n  if (message != null) {\r\n    text(\"message read from tag:\\n\" + message, 10, 230);\r\n  }\r\n\r\n  \/\/ print the output message:\r\n  text(\"type your message to write to tag:\\n\",10, 300);\r\n  fill(0,0,150);\r\n  text(outputString, 10, 320);\r\n\r\n  \/\/ show the firmware version:\r\n  fill(0);\r\n  text(\"SonMicroReader version: \" + myReader.version(), width - 300, height - 30);\r\n}<\/pre>\n<p>The sonMicroEvent() is called automatically whenever a new packet of data comes in from the reader. It parses all the messages out from the packet, and if the command sent was a Read Block, it prints out the message received from the tag&#8217;s memory.<\/p>\n<pre>void sonMicroEvent(SonMicroReader myReader) {\r\n  \/\/ get all the relevant data from the last data packet:\r\n  lastCommand = myReader.getCommand();\r\n  lastTagType = myReader.getTagType();\r\n  lastPacketLength =  myReader.getPacketLength();\r\n  lastTag = myReader.getTagString();\r\n  println(lastTag);\r\n  lastErrorCode = myReader.getErrorCode();\r\n  lastAntennaPower = myReader.getAntennaPower();\r\n  lastResponse = myReader.getSonMicroReading();\r\n  lastChecksum = myReader.getCheckSum();\r\n\r\n  \/\/ if the last command sent was a read block command:\r\n  if (lastCommand == 0x86) {\r\n    int[] inputString = myReader.getPayload();\r\n    message = \"\";\r\n    for (int c = 0; c &lt; inputString.length; c++) {\r\n      message += char(inputString);\r\n    }\r\n    println(message);\r\n  }\r\n  else {\r\n    message = null;\r\n  }\r\n}<\/pre>\n<p>The buttonPressed() method scans the list of buttons to see which matches the one clicked.\u00a0 Then it chooses the appropriate command to execute for that button:<\/p>\n<pre>void buttonPressed(RectButton thisButton) {\r\n  \/\/ figure out which button this is in the ArrayList:\r\n  int buttonNumber = buttons.indexOf(thisButton);\r\n\r\n\/\/ do the right thing:\r\n  switch (buttonNumber) {\r\n  case 0: \/\/  set antenna power\r\n    if (myReader.getAntennaPower() &lt; 1) {\r\n      myReader.setAntennaPower(0x01);\r\n    }\r\n    else {\r\n      myReader.setAntennaPower(0x00);\r\n    }\r\n    break;\r\n  case 1: \/\/ select tag\r\n    myReader.selectTag();\r\n    break;\r\n  case 2:  \/\/ authenticate\r\n    myReader.authenticate(0x10, 0xFF);\r\n    break;\r\n  case 3:   \/\/ readblock\r\n    myReader.readBlock(0x10);\r\n    break;\r\n  case 4:  \/\/ seek tag\r\n    myReader.seekTag();\r\n    break;\r\n  case 5:  \/\/ write tag - must be 16 bytes or less\r\n    myReader.writeBlock(0x10, outputString);\r\n    outputString = \"\";\r\n    break;\r\n  case 6:  \/\/ write 4-byte block - must be 4 bytes or less\r\n    String shortString = outputString.substring(0,4);\r\n    println(shortString);\r\n    myReader.writeFourByteBlock(0x10, shortString);\r\n    break;\r\n  case 7:  \/\/ get reader firmware version\r\n    myReader.getFirmwareVersion();\r\n    break;\r\n  }\r\n}<\/pre>\n<p>the keyTyped() method takes in whatever you typed and adds it to the output string. If you type DELETE, it clears the output string.\u00a0 If you type more than 16 characters, it warns you that you can&#8217;t fit that in one block.<\/p>\n<pre>void keyTyped() {\r\n  switch (key) {\r\n  case ENTER:\r\n    outputString = \"\\0\";\r\n    break;\r\n  case BACKSPACE:  \/\/ delete\r\n    outputString = \"\\0\";\r\n    break;\r\n  default:\r\n\r\n    if (outputString.length() &lt; 16) {\r\n      outputString += key;\r\n    }\r\n    else {\r\n      outputString = \"output string can't be more than 16 characters\";\r\n    }\r\n  }\r\n}<\/pre>\n<p>That&#8217;s the main code for the sketch.\u00a0 There is a second tab in the sketch that generates the buttons. It&#8217;s based on <a href=\"http:\/\/www.processing.org\">Processing<\/a>&#8216;s buttons example (in the File menu &#8211;&gt; Examples &#8211;&gt; Topics &#8211;&gt; GUI &#8211;&gt; Buttons). For more details, see that example.<\/p>\n<p>Here&#8217;s the code in its entirety:<\/p>\n<p><a href=\"https:\/\/tigoe.com\/pcomp\/code\/wp-content\/uploads\/2009\/03\/sonmicro_writer_0001.zip\">sonmicro_writer_0001<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Mifare RFID tags, like other RFID tags, contain a serial number that can be read using an RFID reader, but they also have a limited amount of memory space that you can write data to, and read back from.\u00a0 This can be handy if you want to do something like keep a user&#8217;s account balance &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.tigoe.com\/pcomp\/code\/Processing\/331\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Writing to Mifare RFID tags&#8221;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[50,111,47,48,49],"class_list":["post-331","post","type-post","status-publish","format-standard","hentry","category-Processing","tag-mifare","tag-Processing","tag-rfid","tag-sm130","tag-sonmicro"],"_links":{"self":[{"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/posts\/331","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/comments?post=331"}],"version-history":[{"count":10,"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/posts\/331\/revisions"}],"predecessor-version":[{"id":346,"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/posts\/331\/revisions\/346"}],"wp:attachment":[{"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/media?parent=331"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/categories?post=331"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/tags?post=331"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}