Project stops working when USB is unpluged

markmonkey:
When i scan the both LED's light which tells me the reader has picked up a card, this does not happen when powered with batteries but works flawlessly when plugged into the USB.

How do you tell if the scan is failing if BOTH success and failure flash BOTH LED's at same rate?

What is your USB PC port power limit?
Program your USB PC port to supply 50 mA ( or less) and see if the relay will operate reliably.
Or remove ANY calls for relay operation and see if the program will run on external power.
Or you could just tell us the relay spec. ( Did I missed it?)

Quick update, i have stripped the code right back to just 1 led that lights up when it reads a card, this program works for exactly 30 seconds then it wont read any more cards - this is really bursting my head, any help would be appreciated.

This is my code below.

#include <LEEPROM.h> // Needed to write to EEPROM storage

boolean programMode = false; // Initialize program mode to false
boolean match = false; // initialize card match to false
byte storedCard[6]; // Stores an ID read from EEPROM
byte readCard[6]; // Sotres an ID read from the RFID reader
byte checksum = 10; // Stores the checksum to verify the ID
#define passPin 4 // Grenn LED

void setup()
{
//  Serial.begin(115200);

  Serial1.begin(9600); // RFID
  pinMode(passPin, OUTPUT); // Connected to Green on tri-color LED to indicate user is valid
  delay(3000);
}

void loop()
{


  byte val = 0; // Temp variable to hold the current byte
  if (Serial1.available() > 0) // If the serial port is available and sending data...
  {
    if ((val = Serial1.read()) == 2) // First Byte should be 2, STX byte
    {
      getID(); // Get the ID, sets readCard = to the read ID
      byte bytesread = 0;

      if ( findID(readCard) ) // If not, see if the card is in the EEPROM
      {
        digitalWrite(passPin, HIGH);
        delay(500);              // wait for a second
        digitalWrite(passPin, LOW);
      }
      else
      {
        digitalWrite(passPin, HIGH);   // turn the LED on (HIGH is the voltage level)
        delay(500);              // wait for a second
        digitalWrite(passPin, LOW);    // turn the LED off by making the voltage LOW 
      }

    }
  }
  delay(200);

}

void getID()
{
  byte bytesread = 0;
  byte i = 0;
  byte val = 0;
  byte tempbyte = 0;
  // 5 HEX Byte code is actually 10 ASCII Bytes.
  while ( bytesread < 12 ) // Read 10 digit code + 2 digit checksum
  {
    if ( Serial1.available() > 0) // Check to make sure data is coming on the serial line
    {
      val = Serial1.read(); // Store the current ASCII byte in val
      if ((val == 0x0D) || (val == 0x0A) || (val == 0x03) || (val == 0x02))
      { // If header or stop bytes before the 10 digit reading
        break; // Stop reading
      }
      if ( (val >= '0' ) && ( val <= '9' ) ) // Do Ascii/Hex conversion
      {
        val = val - '0';
      }
      else if ( ( val >= 'A' ) && ( val <= 'F' ) )
      {
        val = 10 + val - 'A';
      }
      if ( bytesread & 1 == 1 ) // Every two ASCII charactors = 1 BYTE in HEX format
      {
        // Make some space for this hex-digit by
        // shifting the previous hex-digit with 4 bits to the left:
        readCard[bytesread >> 1] = (val | (tempbyte << 4));
        if ( bytesread >> 1 != 5 ) // If we're at the checksum byte,
        {
          checksum ^= readCard[bytesread >> 1]; // Calculate the checksum using XOR
        };
      }
      else // If it is the first HEX charactor
      {
        tempbyte = val; // Store the HEX in a temp variable
      };
      bytesread++; // Increment the counter to keep track
    }
  }
  bytesread = 0;
}

int findIDSLOT( byte find[] )
{
  int count = EEPROM.read(0); // Read the first Byte of EEPROM that
  // Serial.print("Count: "); // stores the number of ID's in EEPROM
  // Serial.print(count);
  //Serial.print("n");
  for ( int i = 1; i <= count; i++ ) // Loop once for each EEPROM entry
  {
    readID(i); // Read an ID from EEPROM, it is stored in storedCard[6]
    if ( checkTwo( find, storedCard ) ) // Check to see if the storedCard read from EEPROM
    { // is the same as the find[] ID card passed
      //Serial.print("We have a matched card!!! n");
      return i; // The slot number of the card
      break; // Stop looking we found it
    }
  }
}

boolean checkTwo ( byte a[], byte b[] )
{
  if ( a[0] != NULL ) // Make sure there is something in the array first
    match = true; // Assume they match at first
  for ( int k = 0; k < 5; k++ ) // Loop 5 times
  {
    if ( a[k] != b[k] ) // IF a != b then set match = false, one fails, all fail
      match = false;
  }
  if ( match ) // Check to see if if match is still true
  {
    //Serial.print("Strings Match! n");
    return true; // Return true
  }
  else {
    //Serial.print("Strings do not match n");
    return false; // Return false
  }
}

boolean findID( byte find[] )
{
  int count = EEPROM.read(0); // Read the first Byte of EEPROM that
  // Serial.print("Count: "); // stores the number of ID's in EEPROM
  // Serial.print(count);
  //Serial.print("n");
  for ( int i = 1; i <= count; i++ ) // Loop once for each EEPROM entry
  {
    readID(i); // Read an ID from EEPROM, it is stored in storedCard[6]
    if ( checkTwo( find, storedCard ) ) // Check to see if the storedCard read from EEPROM
    { // is the same as the find[] ID card passed
      //Serial.print("We have a matched card!!! n");
      return true;
      break; // Stop looking we found it
    }
    else // If not, return false
    {
      //Serial.print("No Match here.... n");
    }
  }
  return false;
}

void readID( int number ) // Number = position in EEPROM to get the 5 Bytes from
{
  int start = (number * 5 ) - 4; // Figure out starting position
  for ( int i = 0; i < 5; i++ ) // Loop 5 times to get the 5 Bytes
  {
    storedCard[i] = EEPROM.read(start + i); // Assign values read from EEPROM to array
  }
}

Since you are not responding to suggestions , here is my last one.
Change findID to immediately return false and add some Serial prints to your code evaluating this function plus some delay and counter to see how long you actually run the code, assuming you ARE receiving data on Serial1.

It is generally better to have MORE Serial prints when trying to find code problems.
You are flying blindfolded and have no good reason for it.

Also be more selective when reusing / using variable names, see above.

Hi Vaclav, sorry i actually did not see the second part of your first post, i will try anything that gets put forward to me.

But what i have just done to the code really simplified things so that the help i get can be narrowed down.

I have stripped the code back to what you see below, when i plug into the USB in my laptop the project will work with no issues, but as soon as i power with a battery it only lasts for 30 seconds then stops responding to RFID cards being scanned.

Now for the power i have tried just regular batteries in the DC input (this lasts for about 10 seconds), i have also tried to power via the USB port (this lasts for 30 seconds)

When you say above try and add some serial prints - if i add serial prints i need to plug the USB into my laptop to see them, but when i do this the program runs fine.

#define passPin 13
#define failPin 12

void setup()
{
//  Serial.begin(115200);

  Serial1.begin(9600); // RFID
  pinMode(passPin, OUTPUT); // Connected to Green on tri-color LED to indicate user is valid
  pinMode(failPin, OUTPUT);
  digitalWrite(failPin, LOW);
  digitalWrite(passPin, LOW);
  delay(3000);
}

void loop()
{

  byte val = 0; // Temp variable to hold the current byte
  if (Serial1.available() > 0) // If the serial port is available and sending data...
  {
    if ((val = Serial1.read()) == 2) // First Byte should be 2, STX byte
    {
        digitalWrite(passPin, HIGH);
        delay(500);              // wait for a second
        digitalWrite(passPin, LOW);
    }
    
  }
 
        delay(100);
}

Can you run this?

#define passPin 13
#define failPin 12

void setup()
{
// Serial.begin(115200);

Serial1.begin(9600); // RFID
pinMode(passPin, OUTPUT); // Connected to Green on tri-color LED to indicate user is valid
//pinMode(failPin, OUTPUT);
//digitalWrite(failPin, LOW);
//digitalWrite(passPin, LOW);
delay(3000);
}

void loop()
{

//byte val = 0; // Temp variable to hold the current byte
//if(Serial1.available() > 0) // If the serial port is available and sending data...
{
// if ((val = Serial1.read()) == 2) // First Byte should be 2, STX byte
{
digitalWrite(passPin, HIGH);
delay(500); // wait for a second
digitalWrite(passPin, LOW);
delay(500); // wait for a second}
}
// delay(100);
}

Here is part of your problem

#define passPin 13
#define failPin 12

void setup()
{
Serial.begin(115200);

//Serial1.begin(9600); // RFID
pinMode(passPin, OUTPUT); // Connected to Green on tri-color LED to indicate user is valid
//pinMode(failPin, OUTPUT);
//digitalWrite(failPin, LOW);
//digitalWrite(passPin, LOW);
delay(3000);
}

void loop()
{

//byte val = 0; // Temp variable to hold the current byte
//if(Serial1.available() > 0) // If the serial port is available and sending data...
if ((random(0, 2)))
{
// if ((val = Serial1.read()) == 2) // First Byte should be 2, STX byte

There should be no delay AFTER you start getting data
You are missing data

Serial.println("Data"); // test only
digitalWrite(passPin, HIGH); // OK as indicator

//delay(500); // wait for a second
//digitalWrite(passPin, LOW); does not do much anyway if not followed by delay
//delay(500); // wait for a second}

}
else
{
Serial.println("No data");
digitalWrite(passPin, HIGH);
delay(100); // wait for a second
digitalWrite(passPin, LOW);
delay(100); // wait for a second
}
// delay(100);

}

}
}
}

Vaclav:
Here is part of your problem

#define passPin 13
#define failPin 12

void setup()
{
Serial.begin(115200);

//Serial1.begin(9600); // RFID
pinMode(passPin, OUTPUT); // Connected to Green on tri-color LED to indicate user is valid
//pinMode(failPin, OUTPUT);
//digitalWrite(failPin, LOW);
//digitalWrite(passPin, LOW);
delay(3000);
}

void loop()
{

//byte val = 0; // Temp variable to hold the current byte
//if(Serial1.available() > 0) // If the serial port is available and sending data...
if ((random(0, 2)))
{
// if ((val = Serial1.read()) == 2) // First Byte should be 2, STX byte

There should be no delay AFTER you start getting data
You are missing data

Serial.println("Data"); // test only
digitalWrite(passPin, HIGH); // OK as indicator

//delay(500); // wait for a second
//digitalWrite(passPin, LOW); does not do much anyway if not followed by delay
//delay(500); // wait for a second}

}
else
{
Serial.println("No data");
digitalWrite(passPin, HIGH);
delay(100); // wait for a second
digitalWrite(passPin, LOW);
delay(100); // wait for a second
}
// delay(100);

}

}
}
}

Your a legend :slight_smile:

Hi,

Have you tried the LowPass filter on page 12 of the data sheet?

The RFID unit you are using is quoted supply current of 45mA
BUT,the antenna current voltage, 45mA at 80Vpk.
SO .045 x 80 = 4Watts of RF, when it transmits its pulse.
SO the current is spiked with 4/5= 800mA spikes minimum, inefficiency has not been added.

Tom.... :slight_smile:
(Shoot me down if I'm wrong)