• How can I write data in a mifare card, increment this data and after read this incremented data?

  • Thr 2019.05.16

    Is the inquiry for designing the circuit, coding the solution, or both?

    Do you have a re-writeable type card to start with?

    https://www.mifare.net/support/forum/top­ic/how-to-write-and-read-data-blocks/

    Which model writer?

    https://mifarecards.blogspot.com/2010/09­/product.html

    Code snippet for reading cards

    http://www.espruino.com/MFRC522

    Arduino sketch to model after

    https://github.com/miguelbalboa/rfid/blo­b/master/examples/rfid_write_personal_da­ta/rfid_write_personal_data.ino

  • Both, but mainly coding the solution. Yes, I have a re-writeable card. I gonna check it out these links.

  • I've already tried this http://www.espruino.com/MFRC522. I received the card ID but I couldn't write.

  • I'm afraid there's no code in that module to handle reading/writing of data on the cards yet - just getting the ID.

    I'm out of the office today but I'll see what I can do on Monday. If you can't wait until then or want do do it yourself you'll need to extend http://www.espruino.com/modules/MFRC522.­js using the information in the MFRC522's datasheet.

  • Ok. I’ll wait for your help. Thanks a lot

  • Well, that took a long time - I'd been hoping to use the Arduino code as a base but something just seemed a bit 'off' with it. Ended up using https://github.com/pimylifeup/MFRC522-py­thon as the datasheet itself doesn't really seem to provide enough info by itself.

    Ok, this is a bit hacky at the moment - I need to turn it into a proper module that works the same way as the old one, but:

    var exports = {};
    
    /* Copyright (c) 2019 Gordon Williams, Pur3 Ltd. See the file LICENSE for copying permission. */
    // based on https://github.com/pimylifeup/MFRC522-py­thon
    exports.connect = function(spi, cs) {
      var m = new MFRC522(spi, cs);
      m.init();
      return m;
    };
    
    MI_OK = "ok";
    MI_ERR = "err";
    
    var PCD = {
        IDLE : 0x00,
        AUTHENT : 0x0E,
        RECEIVE : 0x08,
        TRANSMIT : 0x04,
        TRANSCEIVE : 0x0C,
        RESETPHASE : 0x0F,
        CALCCRC : 0x03
    };
    
    var PICC = {
        REQIDL : 0x26,
        REQALL : 0x52,
        ANTICOLL : 0x93,
        SElECTTAG : 0x93,
        AUTHENT1A : 0x60,
        AUTHENT1B : 0x61,
        READ : 0x30,
        WRITE : 0xA0,
        DECREMENT : 0xC0,
        INCREMENT : 0xC1,
        RESTORE : 0xC2,
        TRANSFER : 0xB0,
        HALT : 0x50
    };
    
    var R = {
      Command:2,
      CommIEn:4,
      DivlEn:6,
      CommIrq:8,
      DivIrq:10,
      Error:12,
      Status1:14,
      Status2:16,
      FIFOData:18,
      FIFOLevel:20,
      WaterLevel:22,
      Control:24,
      BitFraming:26,
      Coll:28,
      Mode:34,
      TxMode:36,
      RxMode:38,
      TxControl:40,
      TxAuto:42,
      TxSel:44,
      RxSel:46,
      RxThreshold:48,
      Demod:50,
      Mifare:56,
      SerialSpeed:62,
      CRCResultH:66,
      CRCResultL:68,
      ModWidth:72,
      RFCfg:76,
      GsN:78,
      CWGsP:80,
      ModGsP:82,
      TMode:84,
      TPrescaler:86,
      TReloadH:88,
      TReloadL:90,
      TCounterValueH:92,
      TCounterValueL:94
    };
    
    function MFRC522(spi, cs) {
      this.spi = spi;
      this.cs = cs;
    }
    
    /// The access key to use - this is set to the default for mifare tags 
    MFRC522.prototype.KEY = [0xFF,0xFF,0xFF,0xFF,0xFF,0xFF];
    
    /// read from a register
    MFRC522.prototype.r = function(addr) {
      if (!addr) throw new Error("invalid register");
      return this.spi.send([addr|0x80,0], this.cs)[1];
    };
    /// multiple read from a register
    MFRC522.prototype.ra = function(addr, c) {
      if (!addr) throw new Error("invalid register");
      var a = new Uint8Array(c+1);
      a.fill(addr|0x80);
      a[c]=0;
      return this.spi.send(a, this.cs).slice(1);
    };
    /// write to a register
    MFRC522.prototype.w = function(addr,data) {
      if (!addr) throw new Error("invalid register");
      if (data===undefined) throw new Error("invalid data");
      this.spi.write(addr, data, this.cs);
    };
    /// turn antenna on/off
    MFRC522.prototype.antenna = function(on) {
      if (on) this.w(R.TxControl, this.r(R.TxControl) | 0x03);
      else this.w(R.TxControl, this.r(R.TxControl) & ~0x03);
    };
    /// reset and initialise the MFRC522 - this is done automatically when `connect` is called
    MFRC522.prototype.init = function() {
      // soft reset
      this.w(R.Command, PCD.RESETPHASE);
      var timeout=50;
      while (--timeout && (this.r(R.Command) & 16));
      if (!timeout) throw new Error("SW Timeout");
      // setup
      this.w(R.TMode, 0x8D);
      this.w(R.TPrescaler, 0x3E);
      this.w(R.TReloadH, 0);
      this.w(R.TReloadL, 30);
      this.w(R.TxAuto, 0x40);
      this.w(R.Mode, 0x3D);
      this.antenna(1);
    };
    
    
    
    /// returns {status, data, bitCount}
    MFRC522.prototype.MFRC522_ToCard = function(command, sendData) {
      //console.log("MFRC522_ToCard ",arguments);
      var backData = [];
      var backLen = 0;
      var status = MI_ERR;
      var irqEn = 0x00;
      var waitIRq = 0x00;
      var lastBits;
    
      if (command == PCD.AUTHENT) {
          irqEn = 0x12;
          waitIRq = 0x10;
      }
      if (command == PCD.TRANSCEIVE) {
          irqEn = 0x77;
          waitIRq = 0x30;
      }
      
      this.w(R.Command, PCD.IDLE);//g
      this.w(R.CommIEn, irqEn | 0x80);
      //this.w(R.CommIrq, 0x7F); // g clear IRQs
      this.w(R.CommIrq, this.r(R.CommIrq)&~0x80);
      this.w(R.FIFOLevel, 0x80); // g clear fifo
      //this.w(R.FIFOLevel, this.r(R.FIFOLevel)|0x80);
    
      //this.w(R.Command, PCD.IDLE);
      this.w(R.FIFOData, sendData);
    
      this.w(R.Command, command);
    
      if (command == PCD.TRANSCEIVE)
        this.w(R.BitFraming, this.r(R.BitFraming)|0x80);
    
      var timeout = 500;
      var n;
      while (--timeout) {
        n = this.r(R.CommIrq);
        if (n&waitIRq) break;
        if (n&1) throw new Error("HW Timeout");
      }
      if (!timeout) throw new Error("SW Timeout "+n);
      this.w(R.BitFraming, this.r(R.BitFraming)&~0x80);
      if ((this.r(R.Error) & 0x1B) == 0x00) {
        status = MI_OK;
        if (command == PCD.TRANSCEIVE) {
          n = this.r(R.FIFOLevel);
          lastBits = this.r(R.Control) & 0x07;
          if (lastBits)
              backLen = (n - 1) * 8 + lastBits;
          else
              backLen = n * 8;
          if (n == 0) n = 1;
          if (n > 16) n = 16;
          backData = this.ra(R.FIFOData, n);
        } 
      } else status = MI_ERR;
    
      var r = {status:status, data:backData, bitCount:backLen};
    
      //console.log("MFRC522_ToCard > ",r);
      return r;
    }
    
    
    // returns {status,tagType}
    MFRC522.prototype.MFRC522_Request = function(reqMode) {
      var TagType = [];
    
      this.w(R.BitFraming, 0x07);
    
      TagType.push(reqMode);
      var r = this.MFRC522_ToCard(PCD.TRANSCEIVE, TagType);
      if ((r.status != MI_OK) | (r.bitCount != 0x10))
          r.status = MI_ERR;
    
      //console.log("MFRC522_Request > "+r.status);
      return { status : r.status, tagType : r.bitCount };
    };
    
    
    MFRC522.prototype.MFRC522_Anticoll = function() {
      
      this.w(R.BitFraming, 0x00);
      var r = this.MFRC522_ToCard(PCD.TRANSCEIVE, [PICC.ANTICOLL,0x20]);
    
      if (r.status == MI_OK) { 
        if (r.data.length == 5) {
          var serNumCheck = 0;
          for (var i=0;i<4;i++)
            serNumCheck = serNumCheck ^ r.data[i];
          if (serNumCheck != r.data[4])
            r.status = MI_ERR;
        }
      } else
        r.status = MI_ERR;
      var r = {status:r.status, uid:r.data};
      //console.log("MFRC522_Anticoll > ",r);
      return r;
    };
    
    /// Given data returns a 2 byte array of the CRC
    MFRC522.prototype.CalulateCRC = function(pIndata) {
      this.w(R.DivIrq, this.r(R.DivIrq)&~0x04);
      this.w(R.FIFOLevel, this.r(R.FIFOLevel)|0x80);
      this.w(R.FIFOData, pIndata);
    
      this.w(R.Command, PCD.CALCCRC);
      var timeout = 200;
      var n;
      while (--timeout) {
        n = this.r(R.DivIrq);
        if (n&4) break;
        if (n&1) throw new Error("HW Timeout");
      }
      if (!timeout) throw new Error("SW Timeout "+n);  
      return [this.r(R.CRCResultL), this.r(R.CRCResultH)];
    };
    
    /// Select the tag - returns the size?
    MFRC522.prototype.MFRC522_SelectTag = function(serNum) {
        var backData = [];
        var buf = [PICC.SElECTTAG, 0x70];
        for (var i=0;i<5;i++)
          buf.push(serNum[i]);
        var pOut = this.CalulateCRC(buf);
        buf.push(pOut[0]);
        buf.push(pOut[1]);
        var r = this.MFRC522_ToCard(PCD.TRANSCEIVE, buf);
        if ((r.status == MI_OK) && (r.bitCount == 0x18)) {
            return r.data[0];
        }
    };
    
    MFRC522.prototype.MFRC522_Auth = function(authMode, BlockAddr, Sectorkey, serNum) {
      var buff = [];
    
      // First byte should be the authMode (A or B)
      buff.push(authMode);
    
      // Second byte is the trailerBlock (usually 7)
      buff.push(BlockAddr);
    
      // Now we need to.push the authKey which usually is 6 bytes of 0xFF
      for (var i=0;i<Sectorkey.length;i++)
          buff.push(Sectorkey[i]);
    
      // Next we.push the first 4 bytes of the UID
      for (var i=0;i<4;i++)
          buff.push(serNum[i]);
    
      // Now we start the authentication itself
      var r = this.MFRC522_ToCard(PCD.AUTHENT, buff);
    
      // Check if an error occurred
      if (r.status != MI_OK)
          throw new Error("AUTH ERROR!!");
      if ((this.r(R.Status2) & 0x08) == 0)
          throw new Error("AUTH ERROR(status2reg & 0x08) != 0");
    
      // Return the status
      return {status:r.status};
    };
    MFRC522.prototype.MFRC522_StopCrypto1 = function() {
      this.w(R.Status2, this.r(R.Status2)&~0x08);
    };
    
    /// Read the given block address, return the data
    MFRC522.prototype.MFRC522_Read = function(blockAddr) {
      var recvData = [];
      recvData.push(PICC.READ);
      recvData.push(blockAddr);
      pOut = this.CalulateCRC(recvData);
      recvData.push(pOut[0]);
      recvData.push(pOut[1]);
      var r = this.MFRC522_ToCard(PCD.TRANSCEIVE, recvData);
      if (r.status != MI_OK)
          throw new Error("Error while reading!");
      if (r.data.length == 16) {
          return r.data;
      }
    };
    
    /// Write the given block address
    MFRC522.prototype.MFRC522_Write = function(blockAddr, writeData) {
      var buf = [PICC.WRITE,blockAddr];
      crc = this.CalulateCRC(buf);
      buf = buf.concat(crc);
      var r = this.MFRC522_ToCard(PCD.TRANSCEIVE, buf);
      if ((r.status != MI_OK) || (r.bitCount != 4) || ((r.data[0] & 0x0F) != 0x0A))
        r.status = MI_ERR;
      //console.log(r.bitCount,"backdata &0x0F == 0x0A ",r.data[0] & 0x0F);
      if (r.status == MI_OK) {
        buf = [];
        // pad with 0s
        for (var i=0;i<16;i++)
          buf.push(0|writeData[i]);
        crc = this.CalulateCRC(buf);
        buf = buf.concat(crc);
        r = this.MFRC522_ToCard(PCD.TRANSCEIVE, buf);
        if ((r.status != MI_OK) || (r.bitCount != 4) || ((r.data[0] & 0x0F) != 0x0A))
          throw new Error("Error while writing");
      }
      return {status:r.status};
    };
    
    
    MFRC522.prototype.read = function(blockAddr) {
      var r = this.MFRC522_Request(PICC.REQIDL);
      if (r.status != MI_OK)
          return;
      r = this.MFRC522_Anticoll();
      if (r.status != MI_OK)
          throw new Error("Anticoll failed");
      this.MFRC522_SelectTag(r.uid);
      r = this.MFRC522_Auth(PICC.AUTHENT1A, 11, this.KEY, r.uid);
      if (r.status != MI_OK)
          throw new Error("Auth failed");
      var data = this.MFRC522_Read(blockAddr);
      nfc.MFRC522_StopCrypto1();
      return data;
    };
    
    MFRC522.prototype.write = function(blockAddr, data) {
      var r = this.MFRC522_Request(PICC.REQIDL);
      if (r.status != MI_OK)
          return;
      r = this.MFRC522_Anticoll();
      if (r.status != MI_OK)
          throw new Error("Anticoll failed");
      this.MFRC522_SelectTag(r.uid);
      r = this.MFRC522_Auth(PICC.AUTHENT1A, 11, this.KEY, r.uid);
      if (r.status != MI_OK)
          throw new Error("Auth failed");
      
      data = E.toUint8Array(data);
      blockAddr = 0|blockAddr;
      var blocks = (data.length+15)>>4;
      for (var b=0;b<blocks;b++) {
        r = nfc.MFRC522_Write(blockAddr+b, new Uint8Array(data.buffer, b*16, 16));
        if (r.status != MI_OK)
          throw new Error("Write to block "+(blockAddr+b)+" failed");
      }  
      nfc.MFRC522_StopCrypto1();
      return r.status;
    };
    
    var spi = new SPI();
    spi.setup({sck:A6, miso:B1, mosi:A7 });
    var nfc = exports.connect(spi, A5/*CS*/);
    nfc.write(8,"This is a test")
    //="ok"
    print(JSON.stringify(E.toString(nfc.read­(8))));
    //="This is a test\0\0"
    

    So using the standard reader and tags, it seems you can only really do stuff with pages 8 and over, which are 16 bytes each?

    Be careful - I think I 'bricked' a tag by writing lots to it and maybe overwriting the 'auth key' with something else. Definitely stick to pages 8/9/0 and 16 bytes each and you're fine though.

    Also, there will be exceptions thrown every so often - sometimes a read will fail and you'll get a "HW Timeout" - but it's easy enough to catch it.

  • Hi Gordon,

    I tried this solution, but I got some problems. I gonna attach these problems here. Could you please try again to help me? I'm using the STM32F4 Cortex M4. Thank you!

    Uncaught Error: SW Timeout 0
    at line 157 col 48
    if (!timeout) throw new Error("SW Timeout "+n);

    in function "MFRC522_ToCard" called from line 183 col 54
    var r = this.MFRC522_ToCard(PCD.TRANSCEIVE, TagType);

    in function "MFRC522_Request" called from line 315 col 41
    var r = this.MFRC522_Request(PICC.REQIDL);

    in function "write" called from line 340 col 29
    nfc.write(8,"This is a test");

    Uncaught Error: SW Timeout 0
    at line 157 col 48
    if (!timeout) throw new Error("SW Timeout "+n);

    in function "MFRC522_ToCard" called from line 183 col 54
    var r = this.MFRC522_ToCard(PCD.TRANSCEIVE, TagType);

    in function "MFRC522_Request" called from line 300 col 41
    var r = this.MFRC522_Request(PICC.REQIDL);

    in function "read" called from line 342 col 43
    print(JSON.stringify(E.toString(nfc.read­(8))));

  • Thr 2019.05.23

    Is the writer the type as requested in #2 above?

    http://www.espruino.com/MFRC522

    or another type?

    re: 'STM32F4 Cortex M4'

    Is the Espruino device the Pico?

  • Yes, this is the writer I'm using. What do you mean with Pico?

  • Hi @user100204, I'll be more succinct then. Which Espruino board?

    Would you mind posting the results of entering process.env from the left-hand console side of the IDE please. (for s/w ver, modules, chk sum, etc)

    With the amount of effort @Gordon has put into this so far, and so that we may provide a speedier response, not having him ask the for the same trivial detail, my inquiry was to better isolate whether we are dealing with a hardware issue or a software one.

  • Hi Robin, sorry for the late, these are the results of entering process.env

    VERSION: "2v01",
    GIT_COMMIT: "748a4d3",
    BOARD: "STM32F4DISCOVERY",
    FLASH: 1048576, RAM: 196608,
    SERIAL: "26003a00-03473235-31383130",
    CONSOLE: "USB",
    MODULES: "Flash,Storage,hea" ... "etworkJS,neopixel",
    EXPTR: 536871060 }

  • Sat 2019.06.08

    Good morning @user100204 and thank you for posting that result set. Confirming that a recent flash of Espruino is being used should remove the notion that Espruino is the culprit and isolate the solution to the module or the calling code.


    re: ' BOARD: "STM32F4DISCOVERY" '

    http://www.espruino.com/Other+Boards

    re: 'STM32F4 Cortex M4'
    re: 'What do you mean with Pico?'

    This thread was originally started under heading:

    Home >> Official Espruino Boards >> General

    As the Discovery is a third-party board, the sub-title 'Questions about Espruino on non-official boards' is for 'Other Boards' that are not official Espruino supported boards. For future posts, the more appropriate place to request assistance on this third-party board would be under either 'General', 'Interfacing' or 'Other Boards' beneath:

    Home >> Other Boards >> Other Boards


    re: 'Could you please try again to help me?'

    Now back to the coding issue. As two weeks have elapsed since the last post, Is there still the issue with the timeout errors as shown in #8 above? It seems that there are several types of errors in either a read or a write operation, would you agree? As the sections shown in #7 will throw exceptions, It is quite possible that the method used to call each type, is not correctly structured within try/catch blocks and the errors are just bubbling up, giving the effect the coding cause is actually somewhere else.

    Let's take each error one at a time, and would you please post some code sections so that we may see how the call to either the read or write and/or the try/catch blocks are structured.

    Hint: Using the '</>Code' button just to the left of the 'Preview' button above this edit window will allow the block and error responses to have additional highlighting, making reading a bit easier as shown in #7


    I am an end user like yourself @user100204 and have a bit of time today that I may be able to assist here. From #4 above it is indicated that a successful read was obtained. As there are many complex areas to comprehend such as callbacks and extending an existing module for instance, in order for me to provide the level of detail that may be necessary, may I ask about how much Javascript experience, JS with microcontrollers and applying that to this instance using the RC522 you possess? No need to spend time needlessly, explaining areas that may already be understood.

  • At @Robin has mentioned, this section of the forum is for official boards (not Discovery boards). There's what I hoped was a very clear message at the top of it when you go to post a new thread.

    I split the forum in two so I can properly support users who paid for official boards (eg by doing work like this on the NFC library) - however if I spent all my time doing work like this for people who have not and presumably have no intention of supporting my work on Espruino then I'd go out of business and none of these tools would exist for anyone.

    So @Robin may be able to help you get this working - but I'm no longer going to be helping you out.

  • Mon 2019.06.10

    First word correction needed above

    I can appreciate @Gordon, that it must have taken several days to crank out that write solution for @user100204 and that effort took away from the need to stay focused on Espruino itself.

    May I inquire as to your setup, e.g. Espruino board and RC522 board mfg?

    I have the original module MFRC522 read code example working, but on a KeyeStudio board controlled by a Pico. I've noticed there seem to be two variants to the Green'ish-Blue one shown on the module web page, being more of a Cobalt Blue in addition to the Green-Yellow KeyeStudio board I possess.

    The Arduino source references I've found, differ slightly and although your solution is quite similar, my KeyeStudio board is struggling around L168 and I'll need to compare the datasheet along with the KeyeStudio Arduino code to then fiddle with that section.

    It's quite possible the subtle hardware differences may cause an issue, and if that is the case, I'll need to pick up the same mfg board as the one you have. I also want to verify with user100204 as that may be an area to resolve.

    Through the use of the debugger and console.log statements, I'm willing to assist user100204 the best I'm able.

    Thank you for all your efforts in keeping the core Espruino functional for the community.

  • It was a Pico and the exact reader you see here: http://www.espruino.com/MFRC522

    The cards used to read/write were the cards that you get given with the reader - the type of card you use definitely matters as they can use different protocols.

    The code itself was mostly based on https://github.com/pimylifeup/MFRC522-py­thon so you could try connecting to a Raspberry Pi and using the Python code to see if that works

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Write/Read data in a mifare card or tag using MFRC522.

Posted by Avatar for user100204 @user100204

Actions