Adafuit PN532 draining battery

Hey guys, I have a question for everyone. I would like to make my program more efficient in terms of saving battery power. I currently have an adafruit PN532 NFC reader connected to a SparkFun Fio V3 that powers a servo to lock and unlock my front door when the card is detected. It is being powered through the micro USB port by an external 16,000 mAh battery pack (the same ones commonly used for charging phones on the go).
However, it seems that after 3 days of having the unit powered the battery is already halfway gone. Can you all look at my code to see if there are any inefficiencies within it that would cause the battery to be drained so fast. Is the PN532 is constantly being polled and asking (is there a card.... is the a card now??) and draining my battery?

 #include <Wire.h>
 #include<Servo.h>
 #include<SPI.h>
 #include <Adafruit_PN532.h>


#include "Servo.h"
#include "Wire.h"
#include "SPI.h"
#include "Adafruit_PN532.h"

#define PN532_IRQ   (7)
#define PN532_RESET (3)

Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET);

Servo myservo;  // create servo object to control a servo

int servoPin = 9;  // servo pin on Arduino
int lockState = 2;  // IMPORTANT: if state = 1; locked, state = 2; unlocked
int doorLock;


void setup() {
  Serial.begin(115200);
  Serial.println("Hello!");
  // find Adafruit RFID/NFC shield
  nfc.begin();

  
  uint32_t versiondata = nfc.getFirmwareVersion();
  if (! versiondata) {
    Serial.print("Didn't find PN532 board");
    while (1); // halt
  }
  // Got ok data, print it out!
  Serial.print("Found chip PN5"); Serial.println((versiondata >> 24) & 0xFF, HEX);
  Serial.print("Firmware ver. "); Serial.print((versiondata >> 16) & 0xFF, DEC);
  Serial.print('.'); Serial.println((versiondata >> 8) & 0xFF, DEC);

  // configure board to read RFID tags
  nfc.SAMConfig();

}


//***********LOOP************

unsigned digit = 0;

void loop(void) {
  
  uint8_t success;
  uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };  // Buffer to store the returned UID
  uint8_t uidLength;                        // Length of the UID (4 or 7 bytes depending on ISO14443A card type)

  // Wait for an ISO14443A type cards (Mifare, etc.).  When one is found
  // 'uid' will be populated with the UID, and uidLength will indicate
  // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
  success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);

  uint32_t cardidentifier = 0;

  if (success) {
    // Display some basic information about the card
    Serial.println("Found an ISO14443A card");
    Serial.println("Card detected #");
    // turn the four byte UID of a mifare classic into a single variable #
    cardidentifier = uid[3];
    cardidentifier <<= 8; cardidentifier |= uid[2];
    cardidentifier <<= 8; cardidentifier |= uid[1];
    cardidentifier <<= 8; cardidentifier |= uid[0];
    Serial.println(cardidentifier);
    Serial.println("Add this tag # to code");



    // repeat this for loop as many times as you have RFID cards
    switch (cardidentifier) {
          
      case 1303311769:    // these are the tags numbers
        lockUnlock();
        myservo.detach();
        delay(2000);      // do not allow the card to read for x second(s)
        break;
        
      case 1694073287:
        lockUnlock();   
        myservo.detach();
        delay(2000);      // do not allow the card to read for x second(s)
        break;
        
      case 1694526935:
        lockUnlock();
        myservo.detach();
        delay(2000);      // do not allow the card to read for x second(s)
        break;

      case 1304635385:
        lockUnlock();
        myservo.detach();
        delay(2000);      // do not allow the card to read for x second(s)
        break;

      case 1245611012:
        lockUnlock();
        myservo.detach();
        delay(2000);      // do not allow the card to read for x second(s)
        break;

      case 3723402814:
        lockUnlock();
        myservo.detach();
        delay(2000);      // do not allow the card to read for x second(s)
        break;

      
     
    }
  }

}

void lockUnlock() { // locks or unlocks door
  myservo.attach(servoPin);

  if (lockState == 1) {
    myservo.write(180);    // unlock the door
    delay(500);            // move servo for X second(s)
    lockState = 2;

  }
  else if (lockState == 2) {
    myservo.write(0);     // lock the door
    delay(500);           // move servo for X second(s)
    lockState = 1;
  }

  myservo.detach();
}

Yes the code is polling continually. Have you tried to see how much it draws and if that matches with your battery’s drop ?

If I remember correctly there's an IRQ pin on the PN532 breakout shield - you could use that to wake up your arduino system instead of polling but The PN532 still needs to be powered (and configured) as your tags are passive and this is what blasts energy onto the cards.

Which version of the board you have? Adaftuit’s v1.0 and v1.3 of the breakout boards have a problem where SVDD is connected directly to VDD instead of being left floating. This has no effect on the functionality of the boards, but does cause some extra current to be drawn.

I have the V1.3, in the code i have set the IRQ to pin 7 on the Fio V3, am i not setting it up per what you're talking about? (waking it up). Also, should i (or do I) have to cut the trace between pin 2 and the IRQ on the NFC shield?

I would start by measuring current draw. What you’ll save sleeping your arduino might be relatively small compared to what is drawn by the PN532 shield (you can expect the chip to draw 100mA when looking for a card)

You say you went thru 8000 mAh in 3 days that’s a draw of ~110mA for the system... not that bad when running all the time...

would the below code added not stop the polling continuously?

  // Got ok data, print it out!
  Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 
  Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 
  Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
  
// Set the max number of retry attempts to read from a card
  // This prevents us from waiting forever for a card, which is
  // the default behaviour of the PN532.
  nfc.setPassiveActivationRetries(0xFF);

except i would want to change 0xFF to say 0x01 for just one poll right? then wouldnt it stop asking "wheres the card..."

What would you gain? The loop would still loop...

What is the point of the below?

  nfc.setPassiveActivationRetries(0xFF);

I thought 0xFF meant it is continuously polling for a card

Then wouldn't this look one time, and then give up until a card presents itself?

  nfc.setPassiveActivationRetries(1);

And then the loop loops and you ask again... so it’s similar

So they have added that to the NFC library and it's pointless? Per adafruit, this should be initiated in the setup and before the

// configure board to read RFID tags
  nfc.SAMConfig();

So why would they say that this would solve the polling problem. I understand why it would continuously keep looping (its a loop), but i cant understand then why adafruit would say this would simply be the solution to the problem..

They explain the issue in their FAQ

Ah, I just re-read it, now it makes sense as to what that line of code is allowing to happen. For my case it is essentially pointless.

:slight_smile: yes

Sometimes it just helps to have someone tell you you're wrong haha