Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changing the MFRC522 Receiver Gain #43

Closed
mdxs opened this issue Nov 8, 2014 · 8 comments
Closed

Changing the MFRC522 Receiver Gain #43

mdxs opened this issue Nov 8, 2014 · 8 comments

Comments

@mdxs
Copy link
Contributor

mdxs commented Nov 8, 2014

Inspired by the "Extend range for MFRC522 RFID Reader" discussion at http://forum.arduino.cc/index.php?topic=199983.0 I've played around a bit.

Initially, I followed the approach "omersiar" described in that discussion: to alter the PCD_Init() implementation within the .cpp of the library. But somehow it didn't feel right... and the approach didn't seem to respect reserved/future bits either.

So, I reverted the library changes and found that the following works to set the Rx Gain to it's maximum value (which is documented to be some 48 dB; see 9.3.3.6 / table 98):

    mfrc522.PCD_Init();  // NOTE: unmodified initialization...
    // Enhance the MFRC522 Receiver Gain to maximum value of some 48 dB
    mfrc522.PCD_SetRegisterBitMask(mfrc522.RFCfgReg, (0x07<<4));

Note that this is done inside the sketch, within the regular setup. Perhaps one can also change it from within the main loop. Possibly cycling through the options by some button being pressed?

While above code works to maximize the Rx Gain, in order to minimize it... we need:

    mfrc522.PCD_Init();  // NOTE: unmodified initialization...
    // Reduce the MFRC522 Receiver Gain to minimum value of some 18 dB
    mfrc522.PCD_ClearRegisterBitMask(mfrc522.RFCfgReg, (0x07<<4));
    mfrc522.PCD_SetRegisterBitMask(mfrc522.RFCfgReg, (0x00<<4));

Note the bit mask clearing call, which (as the set register call) should avoid altering reserved/future bits. It seemed to be the cleanest way to do this.

Between minimum and maximum settings, you will notice a big difference (in centimetres: cm) in the distance at which the PICC is read. Now beware, newbie at play... and I've NOT tried all the bit patterns, but think this is on the right track and better than what the mentioned discussion described.

@omersiar
Copy link
Contributor

omersiar commented Nov 8, 2014

Once I tried Setting Register but obviously failed because of bit shifting. I was really confused as a Newbie, Now it is clear to me, thank you.

What do you suggest where to use Gain Control ? at Library level or Sketch level? Maybe a simple define help others to know there is a Gain Control with Dump Example or Calling PCD_Init(VariableGain); ? other MFRC522 Library for another platform comes with Maximum Gain by default.

byte gain = 0x07 ; // defines Receiver's gain dafault 48db max

/*RxGain [2:0]
  defines the receiver's signal voltage gain factor:
  000 18 dB HEX = 0x00
  001 23 dB HEX = 0x01
  010 18 dB HEX = 0x02  
  011 23 dB HEX = 0x03
  100 33 dB HEX = 0x04
  101 38 dB HEX = 0x05
  110 43 dB HEX = 0x06
  111 48 dB HEX = 0x07
  3 to 0 reserved - reserved for future use
*/



void MFRC522::PCD_Init(byte gain[]) {
  if (digitalRead(_resetPowerDownPin) == LOW) { //The MFRC522 chip is in power down mode.
    digitalWrite(_resetPowerDownPin, HIGH); // Exit power down mode. This triggers a hard reset.

    // Section 8.8.2 in the datasheet says the oscillator start-up time is the start up time of the crystal + 37,74ms. Let us be generous: 50ms.
    delay(50);
  }
  else { // Perform a soft reset
    PCD_Reset();
  }

  // When communicating with a PICC we need a timeout if something goes wrong.
  // f_timer = 13.56 MHz / (2*TPreScaler+1) where TPreScaler = [TPrescaler_Hi:TPrescaler_Lo].
  // TPrescaler_Hi are the four low bits in TModeReg. TPrescaler_Lo is TPrescalerReg.

  PCD_WriteRegister(TModeReg, 0x80);        // TAuto=1; timer starts automatically at the end of the transmission in all communication modes at all speeds
  PCD_WriteRegister(TPrescalerReg, 0xA9);   // TPreScaler = TModeReg[3..0]:TPrescalerReg, ie 0x0A9 = 169 => f_timer=40kHz, ie a timer period of 25�s.
  PCD_WriteRegister(TReloadRegH, 0x03);     // Reload timer with 0x3E8 = 1000, ie 25ms before timeout.
  PCD_WriteRegister(TReloadRegL, 0xE8);

  PCD_WriteRegister(TxASKReg, 0x40);        // Default 0x00. Force a 100 % ASK modulation independent of the ModGsPReg register setting
  PCD_WriteRegister(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)
  PCD_WriteRegister(RFCfgReg, (gain<<4));       // Set Rx Gain to max
  PCD_AntennaOn();              // Enable the antenna driver pins TX1 and TX2 (they were disabled by the reset)
} // End PCD_Init()

@mdxs
Copy link
Contributor Author

mdxs commented Nov 9, 2014

Well, I think the PCD_WriteRegister approach for RFCfgReg shown in above modified PCD_Init might be incorrect; as that is setting more bits than what the specification says are to be used... this is why that bit shifting is needed.

I would recommend to change:

  PCD_WriteRegister(RFCfgReg, (gain<<4));       // Set Rx Gain to max

Into:

  PCD_ClearRegisterBitMask(RFCfgReg, (0x07<<4));
  PCD_SetRegisterBitMask(RFCfgReg, (gain<<4));       // Set Rx Gain

In that customization of PCD_Init; and also consider why byte gain[] is used as parameter... shouldn't that be simply byte gain (and check the prototype declaration in the .h file)?

Now that may help you customization of the library, but I wonder if it should be done this way in the miguelbalboa/rfid version of the library. As the gain can be changed in the Sketch after calling PCD_Init, it doesn't make sense to me to force everybody to consider the extra parameter.

And it might not be correct to assume a proper default in the library... I guess the hardware/chip provides a default if it is not specifically set via the library. So perhaps manufacturers have a specific reason to use their setting as default.

So, what to do? I guess the best would be to provide some #define entries to describe the RxGain table you provided in a comment block. Together with a helper function to set it to one of those values, using the Clear- and SetRegisterBitMask combo approach. Perhaps adding an if-then guard to help preventing accidental out-of-bounds.

@miguelbalboa would you like a PR for that; and if so, can you suggest some function name to use?

@mdxs
Copy link
Contributor Author

mdxs commented Nov 9, 2014

Perhaps something like this:

void MFRC522::PCD_SetAntennaGain(byte mask) {
    if ((mask >= (0x00<<4)) && (mask <= (0x07<<4))) {
        PCD_ClearRegisterBitMask(RFCfgReg, (0x07<<4));
        PCD_SetRegisterBitMask(RFCfgReg, mask);
    }
}

where the if should actually check for some defined values (not using #define as I said before, but rather some enum in the .h part).

@mdxs
Copy link
Contributor Author

mdxs commented Nov 10, 2014

Closed with #47 being merged into the library.

@albapa
Copy link

albapa commented Jul 21, 2015

Hi, should there be a difference whether PCD_SetAntennaGain() is called before or after PCD_Init()? Thanks in advance.

@omersiar
Copy link
Contributor

Should be, because when you call gain control it modify pcd's specific
register you should init before any other register change.
21 Tem 2015 16:25 tarihinde "albapa" notifications@github.com yazdı:

Hi, should there be a difference whether PCD_SetAntennaGain() is called
before or after PCD_Init()? Thanks in advance.


Reply to this email directly or view it on GitHub
#43 (comment).

@albapa
Copy link

albapa commented Jul 21, 2015

Thanks for your reply.

I was asking because in the original version the antenna gain was set in PCD_Init() before calling PCD_AntennaOn(). In the update, if you call PCD_SetAntennaGain() after PCD_Init(), this will naturally happen also after switching on the antenna.

I suppose my question really is whether setting the appropriate register corresponding to maximum gain should happen before or after switching on the antenna or it doesn't matter. Thanks!

@YIGITER-CLOAK-AND-DAGGER

When I use the function in my code mfrc522.PCD_SetRegisterBitMask(mfrc522.RFCfgReg, (0x07<<4)) after initializing the reader The RFID reader will misread the codes for the RFID. It doesn't matter the level of gain. 20% of the time it reads it wrong. When I remove it there is no error. I have tested it with multiple types and the error persists.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants