MagStripe card.available pauses and no other code can run

Hi

I am using the MagStrip library (https://github.com/carlosefr/magstripelib). In my main loop I call the function which runs the code:

void magcardFunc()
{
static const byte DATA_BUFFER_LEN = 108;
static char magcard[DATA_BUFFER_LEN];
  
// Don't do anything if there isn't a card present

  if (!card.available()) {
    return;
  }

    // Read the card into the buffer "magcard" (as a null-terminated string)
  short chars = card.read(magcard, DATA_BUFFER_LEN);

  if (chars < 0) {
    Serial.print("bad read");
    return;
  }
  
  // Send the data to the computer if data was read
  if (chars != 0) {
    Serial.print(magcardstr);
  }
}

The code successfully reads a magnetic card when inserted.

The problem is, I have other functions which are called from the main loop but they do not get called as the code pauses at:

if (!card.available()) {
    return;
  }

    // Read the card into the buffer "magcard" (as a null-terminated string)
  short chars = card.read(magcard, DATA_BUFFER_LEN);

If I insert a card into my mag reader (and leave it there), the program continues and the other functions are called. I want the main loop to continue and the other functions be called without having to leave a card inserted.

I have tried removing the IF statement:

if (!card.available()) {
    return;
  }

and I have tried reversing it

if (card.available()) {
    return;
  }

If I reverse it as above, the other functions run but when I do swipe a card, it is not read.
I get no compiler errors.

Any help is appreciated.

card.available() just reads the state of 1 pin. I can't see how that would stop your code from functioning...

bool MagStripe::available()
{
    return digitalRead(this->pin_cls) == LOW;
}

and card.read() calls this function before trying to read, so it isn't really necessary. The problem may very well be in part of the code you did not share. Can you create the smallest possible complete sketch that demonstrates this problem?

Thanks @blh64
Here is an example sketch which replicates the problem. otherFunc does not get called.

#include <MagStripe.h>

void magcardFunc();
void otherFunc();

MagStripe card;

static const byte DATA_BUFFER_LEN = 108;
static char data[DATA_BUFFER_LEN];


void setup()
{
  // The card data will be sent over serial...
  Serial.begin(9600);
  
  // Initialize the library for reading track 2...
  card.begin(2);
}


void loop()
{
  magcardFunc();
  otherFunc();
}
 
void magcardFunc()
{
  // Don't do anything if there isn't a card present...
  if (!card.available()) {
    return;
  }
  
  
  // Read the card into the buffer "data" (as a null-terminated string)...
  short chars = card.read(data, DATA_BUFFER_LEN);
  

  if (chars < 0) {
  Serial.println("no chars");

    return;
  }

  // Send the data to the computer...
  Serial.println(data);
}

void otherFunc()
{
  Serial.println("I am another function");
  delay(500); //feel free to remove me
}

I noticed that this sketch actually did call the otherFunc when the mag card reader was unplugged. I am not sure why when it is plugged in it pauses. Maybe an interrupt is always on?

Thank you

#define MAGSTRIPE_CLS 4 /* card present pin (yellow) */
Did you connect the yellow wire to Pin 4?

    // Wait while the data is being read by the interrupt routines...
    while (this->available()) {}

This bit of code in card.read() will hang for as long as Pin 4 is LOW.

Thanks @johnwasser
Yes I connected the yellow CLS wire to pin 4.
Do you think there is a way to get around it hanging while Pin 4 is LOW? I thought maybe removing the interrupt and just do a digitalRead of pin 4 to see if it is low each time the function is called..

I think you have to ask yourself "Why is Pin 4 LOW for so long?" Are you leaving the card in the reader?

I would try a little sketch to show the state of Pin 4 on the built-in LED:

void setup()
{
  pinMode(4, INPUT);
  pinMode(LED_BUILTIN, OUTPUT);
}
void loop()
{
   digitalWrite(LED_BUILTIN, digitalRead(4));
}

What causes the LED to turn off? When does it turn back on?

Thanks @johnwasser

I put your sketch into my sketch above. The LED comes on/off when the card is inserted all the way (triggers the CLS).
I think the problem here is the program is frozen (or hanging) waiting for a card to be inserted but this hinders the ability to do anything else while it is waiting.
While a card is inserted all the way, the program freely continues.

If I swap the

  if (!card.available()) {
    return;
  }

to

  if (card.available()) {
    return;
  }

The program also runs freely but the card never gets read.

I am a bit stuck at what to do, I am not sure if I am over thinking it and there is a simple solution..

Why?!?

Which is it?!? ON or OFF?

So I could see the LED turn on or off and see when that stopped happening.. I thought that was the point?
The LED turns ON when I insert the card and OFF when I remove the card

Perhaps you are misinterpreting the "card available" indicator. It is telling you the card data is available for reading, nothing else.
Also, the mag stripe magnetic tracks have sync bits at the beginning and at the end, so the data can be read both when you insert the card and when you remove the card.
Paul

Thanks @Paul_KD7HB
I think I understand the "card available" method.. I do not know why when a card is not inserted that my magcardFunc(); function doesn't return;.

if (!card.available()) {
    return;
  }

The point was to run the sketch by itself, to do nothing but monitor the state of the input pin.

So Pin 4 is going HIGH when you insert a card and LOW when the card is removed. The library reports "card.available() == true" when the input is LOW:

bool MagStripe::available()
{
    return digitalRead(this->pin_cls) == LOW;
}

That means you are getting a card.available() == true whenever the card is removed?!? That sounds like a hardware problem.