0

I have connected an Arduino Micro (not Pro Micro) to an Magtek swipe reader.

  • Data is connected to pin 3,
  • Clock to pin 2
  • And swipe_detect to pin 4.

Then I use this lib to read data from the magstripe reader

However, the magstripe reader reads very poorly. Half of the times, the card doesn't even register, because its skipping bits and then the card sentinel and checksums fail.

I suspect, this is because the Arduino Micro isn't processing the interrupts fast enough.

Is it possible to increase the interrupt resolution in some way? Meaning, having it process interrupts faster? Or does the library process too many things in handle_clock() subroutine and this needs to be fixed?

The datasheet of the reader chip is: https://stripesnoop.sourceforge.net/devel/magtek6516.pdf

Code is:


#include <HID-Project.h>
#include <MagStripe.h>

int buttonpress;
int haspressed;
int tamper;

String code;

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

MagStripe card;

void setup() {
    sei();
    pinMode(A0, INPUT_PULLUP); // ANALOG INPUT FOR BUTTONS (resistor network)
    pinMode(12, OUTPUT);       // ACCESS DENIED LED
    pinMode(11, OUTPUT);       // BUTTON PRESS LED
    pinMode(10, OUTPUT);       // DOOR UNLOCKED LED
    pinMode( 9, OUTPUT);       // SOUNDER/BEEPER
    pinMode( 8, OUTPUT);       // ALARM LED (Default low)
    pinMode(13, INPUT_PULLUP); // TAMPER SWITCH, DETECTS IF READER IS BROKEN OFF THE WALL

    digitalWrite(12, HIGH); 
    digitalWrite(11, HIGH);
    digitalWrite(10, HIGH);
    digitalWrite( 9, HIGH);

    BootKeyboard.begin();

    card.begin(2);
}

void loop() {
    if (card.available()) {
        short chars = card.read(data, DATA_BUFFER_LEN);
        if (chars > 0) {
            digitalWrite(11, LOW);
            delay(100);
            digitalWrite(11, HIGH);
            BootKeyboard.print("CD/" + String(data) + " ");
        }
        memset(data, 0, DATA_BUFFER_LEN);
    }

    digitalWrite(11, HIGH);
    buttonpress = int(12 - int(int( analogRead(A0) / 62 ) - 3));
    delay(50); // BUTTON DEBOUNCE
    if (buttonpress != int(12 - int(int( analogRead(A0) / 62 ) - 3))) {
        buttonpress = -2;
    }
    if (buttonpress < 0) {
        haspressed = 0;
    } else {
        if (haspressed == 0) {
            digitalWrite(11, LOW);
            delay(100);
            digitalWrite(11, HIGH);
            if (buttonpress == 10) {
                code = "/";
            }
            if ((buttonpress == 11) && (code.length() > 0)) {
                BootKeyboard.print("KP" + String(code) + " ");
                if (code == "/<**SNIP** TAMPER RESET CODE>") {
                    tamper = 0;
                    BootKeyboard.print("TMPRST ");
                }
                code = "";
            }
            if ((buttonpress < 10) && (code.length() > 0)) {
                code = code + String(buttonpress);
            }
        }
        haspressed = 1;
    }
    digitalWrite(11, HIGH);

    if (digitalRead(13) == 0) {
        if (tamper == 0) {
            BootKeyboard.print("TMPCLS ");
            tamper = 1;
        }
        if (tamper == 2) {
            digitalWrite(8, HIGH);
            digitalWrite(9, LOW);
            delay(100);
            digitalWrite(8, LOW);
            digitalWrite(9, HIGH);
        }
    } else {
        if (tamper > 0) {
            digitalWrite(8, HIGH);
            digitalWrite(9, LOW);
            delay(100);
            digitalWrite(8, LOW);
            digitalWrite(9, HIGH);
            if (tamper == 1) {
                BootKeyboard.print("TMPTRP ");
                tamper = 2;
            }
        }
    }

    if (BootKeyboard.getLeds() & 1) {
        digitalWrite(12, LOW);
    } else {
        digitalWrite(12, HIGH);
    }

    if (BootKeyboard.getLeds() & 2) {
        digitalWrite(10, LOW);
    } else {
        digitalWrite(10, HIGH);
    }

    if (BootKeyboard.getLeds() & 4) {
        delay(100);
        digitalWrite(8, HIGH);
        digitalWrite(9, LOW);
        delay(100);
        digitalWrite(8, LOW);
        digitalWrite(9, HIGH);
    }
}

Only thing deleted/censored from code is the Tamper reset code, which is written as '/' and then a 6 digit code.

8
  • 1
    Care to share your code with us, or is it top secret? Commented Dec 1 at 6:57
  • 4
    this is an XY question ... you assume that the solution to your problem is to increase the interrupt resolution, so you ask about that, instead of asking about the actual problem Commented Dec 1 at 6:58
  • 1
    Do you have an oscilloscope at hand? Otherwise you will have a hard time to analyze the issue. Additionally, would you mind to edit your question to add a link to the data sheet of your reader, please? Commented Dec 1 at 7:33
  • 1
    What does the library's example do when minimally modified (pin numbers, I would guess) with everything else (wiring etc) being unchanged from how you currently have it? Commented Dec 2 at 2:36
  • 1
    Well, the question is up for reopen. So you're going to have to figure out what you consider to constitute an answer to your actual question. And whether or not what you found is of potential value to anyone else. The one thing you should not do is attempt to edit that as a solution into your question. If you add it in, it gets added in as diagnostic information as part of question that is still unanswered. Commented Dec 2 at 6:39

1 Answer 1

0

I resolved it.

It was the delay(50); line that was used as button debouncing that caused the issue.

I resolved it in two ways:

  1. I added logic to test that the first tested button input (buttonpress from A0) was valid, BEFORE waiting 50 milliseconds and tested the second buttonpress.

    So instead of testing the 2 button presses with 50 ms inbetween in one go, I skipped debouncing if there was no valid button press to start with.

  2. I added logic to disable the keypad completely except for * if * has not been pressed. In this way, I save even more execution time.

  3. A third solution, is also to rewrite the button debounce function, so instead of reading button, waiting a specific time, and then reading button again, I simply read the button every loop() and increase a counter everytime the button press is equal to the last button press previous loop(). When the counter is at a sensible value (lets say 25 button presses in a row that is equal) I decide the button press stable enough to act on it. If the button press is different from last, I know the button have bounced around too much and reset the counter to 0.

9
  • Commonly you avoid delay() completely in non-trivial sketches. Instead use millis() (or similar) and a finite state machine, see the blinky example without delay. Commented Dec 3 at 15:49
  • 1
    You should be able to mark your answer as "accepted". Being a self-answer, it may take a few days before the system lets you do that. Commented Dec 3 at 17:53
  • 1
    Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center. Commented Dec 3 at 17:55
  • instead of using delay (), check the value of millis () at the beginning of loop (), then every millisecond decrement a counter (stop decrement at zero) ... if the counter is zero then check the state of the button ... if the button is pressed, then set the counter to 50 and raise a buttonClick flag ... clear the buttonClick flag at end of loop () Commented Dec 3 at 19:33
  • 1
    There are a few debouncing libraries that let you manage buttons in an easy, non-blocking fashion. I suggest you try Bounce2. Commented Dec 4 at 7:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.