Magnetic card reader - reading Track 1 & 2 at the same time?

I've got a Magtek with a 9 pin IO which has pin outs for Track 1,2 & 3

I'm following this post to read track 1 which works great.

If I change the data and strobe pins to read track 2 is also works fine. What I would like to do now is read Track 1&2 at the same time. I've tried to combine it in the code but then it looks like the arduino does not read the inputs fast enough and I end of losing information.

What I"ve done is just replicate the code in the read routine but it can't read the data in fast enough.

if (digitalRead(STROBE_T1) == LOW && check_T1 == 1) {
      if (digitalRead(DATA_T1) == HIGH) {
        dataStr_T1[dataNum_T1] = '0';
        dataNum_T1++;
      }
      else {
        dataStr_T1[dataNum_T1] = '1';
        dataNum_T1++;
      }
      check_T1 = 0;
    }
    else if (check_T1 == 0 && digitalRead(STROBE_T1) == HIGH) {
      check_T1 = 1;
    }
    if (digitalRead(CARDPRESENT) == HIGH) {
      break;
    }
}

if (digitalRead(STROBE_T2) == LOW && check_T2 == 1) {
      if (digitalRead(DATA_T2) == HIGH) {
        dataStr_T2[dataNum_T2] = '0';
        dataNum_T2++;
      }
      else {
        dataStr_T2[dataNum_T2] = '1';
        dataNum_T2++;
      }
      check_T2 = 0;
    }
    else if (check_T2 == 0 && digitalRead(STROBE_T2) == HIGH) {
      check_T2 = 1;
    }
    if (digitalRead(CARDPRESENT) == HIGH) {
      break;
    }
}

Clearly my approach is faulty - any tips on how I would accomplish this? What other approach should I use?

Hi GregM,
You don't show all your code but looking at original thread you have removed the while(true) so each routine would need continual calling to read each bit. Maybe the code below is more like what your looking for. If the strobe is synchronized on all tracks then it could be simplified.

while (true) {
    if (digitalRead(STROBE_T1) == LOW && check_T1 == 1) {
        if (digitalRead(DATA_T1) == HIGH) {
            dataStr_T1[dataNum_T1] = '0';
        }
        else {
            dataStr_T1[dataNum_T1] = '1';
        }
        check_T1 = 0;
        dataNum_T1++;
    }
    else if (check_T1 == 0 && digitalRead(STROBE_T1) == HIGH) {
        check_T1 = 1;
    }

    if (digitalRead(STROBE_T2) == LOW && check_T2 == 1) {
        if (digitalRead(DATA_T2) == HIGH) {
            dataStr_T2[dataNum_T2] = '0';
        }
        else {
            dataStr_T2[dataNum_T2] = '1';
        }
        check_T2 = 0;
        dataNum_T2++;
    }
    else if (check_T2 == 0 && digitalRead(STROBE_T2) == HIGH) {
        check_T2 = 1;
    }

    if (digitalRead(CARDPRESENT) == HIGH) {
    break;
    }
}

Thanks - I didnt include all the code.

I’ve taken what you said above and included it into my code.

//Track 1
#define DATA_T1  12  //Ribbon Pin 3
#define STROBE_T1 8

//Track 2
#define DATA_T2 11
#define STROBE_T2 9

#define CARDPRESENT 10
#define SERIALRATE 9600


boolean dataStr_T2[600];

boolean dataStr_T1[600];


boolean check_T2;
boolean check_T1;


int dataNum_T2;
int dataNum_T1;


//boolean SSfound;
//boolean ESfound;
//char currentByte[6];
int i;


void setup() {
  Serial.begin(SERIALRATE);
  Serial.println("Begin");
  pinMode(DATA_T2, INPUT);
  pinMode(DATA_T1, INPUT);
  
  pinMode(STROBE_T2, INPUT);
  pinMode(STROBE_T1, INPUT);
  
  pinMode(CARDPRESENT, INPUT);
}

void loop() {
  resetVals();
  
  waitForCard();
  Serial.println("Read");
  readData();

  Serial.print("T2:");  
  Serial.println(dataNum_T2);



//   while (i < dataNum_T2) {
//    Serial.print(dataStr_T2[i]);
//     ++i;
//    }
  Serial.print("T1:");
  Serial.println(dataNum_T1);

//
//   while (i < dataNum_T1) {
//    Serial.print(dataStr_T1[i]);
//     ++i;
//    }
// 
Serial.println("");
}

//*******************************************************

void resetVals() {
  dataNum_T2 = 0;
  dataNum_T1 = 0;
  
  check_T1 = 0;
  check_T2 = 0;
}

//*******************************************************
 
void waitForCard() {
  while (true) {
    if (digitalRead(CARDPRESENT) == LOW) {
      break;
    }
  }
}

//*******************************************************

void readData() {
  
  Serial.println("Read Routine");
  
while (true) {
    if (digitalRead(STROBE_T1) == LOW && check_T1 == 1) {
        if (digitalRead(DATA_T1) == HIGH) {
            dataStr_T1[dataNum_T1] = '0';
        }
        else {
            dataStr_T1[dataNum_T1] = '1';
        }
        check_T1 = 0;
        dataNum_T1++;
    }
    else if (check_T1 == 0 && digitalRead(STROBE_T1) == HIGH) {
        check_T1 = 1;
    }

    if (digitalRead(STROBE_T2) == LOW && check_T2 == 1) {
        if (digitalRead(DATA_T2) == HIGH) {
            dataStr_T2[dataNum_T2] = '0';
        }
        else {
            dataStr_T2[dataNum_T2] = '1';
        }
        check_T2 = 0;
        dataNum_T2++;
    }
    else if (check_T2 == 0 && digitalRead(STROBE_T2) == HIGH) {
        check_T2 = 1;
    }

    if (digitalRead(CARDPRESENT) == HIGH) {
    break;
    }
} 


}

Still not working properly. The track 1 reading looks ok, but now track 2 is way off. The count for T1 is 600, but the count for T2 is 12336 which is way off. Its reading in too much info. I’ll double check my code maybe its something silly now.

Not sure what the problem is without having the hardware to test with but the code has no checks to ensure dataNum_T does not get incremented beyond the dataStr_T buffer length so if it reads too many bits (currently >600) then memory will become corrupt.

You should also use the code tag for program code and not the quote tag.

It looks like the extra code from the Track 1 checks adds too much of a delay in that the Track 2 checks now are not fast enough to catch all the data out.

Now sure where to start but will maybe have a look at interrupts or try and optimize the code further (Not sure how much more it can be optimized)

From the datasheet on the card reader it says the strobe width is approx 25-50% of the bit width? I don't see any reference to the actual timing of the strobe clock? Do you think the extra code could cause reading problems?

Here's the data sheet.

Ok - looks like its sorted. Nothing as complicated as timing :blush:

As you said I dont check the size of buffer - its reading in more data than the buffer size causing all sorts of problems. I’ve made it a lot bigger with a few more checks and now it seems to behaving :slight_smile:

I think I would use a pin change interrupt:

http://arduino.cc/playground/Code/Interrupts

When the interrupt occurs, quickly read the pins in the interrupt handler (don't do -anything- else though!); if you wanted to do this right, you would use direct port access (instead of digitalRead):

Thanks - I think I might try that - sounds like a better way to do it.

Hey there, GregM. Were you ever able to get this to work? I'm trying to accomplish the same thing...

I have been having the same problem
http://forum.arduino.cc/index.php?topic=224449.0

Any advice would be appreciated...

Hello there,

For all of you trying to read Tracks 1 and 2 in parallel, here is the code I recently wrote.
The approach for reading Tracks is adopted from this great instructable. I slightly changed this code in order to read two tracks in parallel.
The code is tested on Panasonic’s dual head Magnetic Card Reader ZU-1870MA8T.

Take a test with your readers and let me know the results.

Sincerely,
Bojan.

common.h (1.45 KB)

MagCardReader.ino (6.64 KB)