Skip to content

Instantly share code, notes, and snippets.

@noahcoad
Last active August 3, 2022 19:42
Show Gist options
  • Save noahcoad/85e2bbeb6463367598eb326d9776111c to your computer and use it in GitHub Desktop.
Save noahcoad/85e2bbeb6463367598eb326d9776111c to your computer and use it in GitHub Desktop.
//
// Magnetic Card Reader with ESP32 Arduino
// Created on 2020-06-13 by Noah Coad
//
// Connect card reader cable to ESP32 pins:
// DATA (yellow) = 15, PRESENT (orange) = 14, STROBE (green) = 32
//
// I'm using Adafruit HUZZAH32 ESP32 Feather Board, but any ESP32 should work
// And the Magtek 21050071 card reader, which reads the 2nd card track only (encoded in 5 bits)
// Double check your card reader, which track(s) it reads, because track #1 is encoded differently
//
// Much thanks to nevdull's tutorial which this is based off of:
// https://www.instructables.com/id/Turn-your-Arduino-into-a-Magnetic-Card-Reader/
//
// variables
const int PIN_LED = 13;
// card data struct
struct CardReader {
const uint8_t PIN_CARD_DATA;
const uint8_t PIN_CARD_PRESENT;
const uint8_t PIN_CARD_STROBE;
bool bDataPresent;
char buff[40];
int64_t stamp;
uint8_t data, bitpos, idx;
};
// init card info
CardReader reader = {15, 14, 32, false, "", 0, 0, 0, 0};
// interrupt
void IRAM_ATTR isr() {
// reset our timer
reader.stamp = 0;
// a digital 1 is read as a low pin
if (digitalRead(reader.PIN_CARD_DATA) == LOW) { // low=1
bitSet(reader.data, reader.bitpos++);
reader.bDataPresent = true;
} else if (reader.bDataPresent) {
bitClear(reader.data, reader.bitpos++);
}
// if we've ready five bits already
// save off this byte worth of data
if (reader.bitpos == 5) {
reader.buff[reader.idx++] = reader.data;
reader.bitpos = 0;
}
// remember when last bit was
reader.stamp = millis();
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
// setup the pin modes
pinMode(reader.PIN_CARD_DATA, INPUT_PULLUP);
pinMode(reader.PIN_CARD_PRESENT, INPUT_PULLUP);
pinMode(reader.PIN_CARD_STROBE, INPUT_PULLUP);
pinMode(PIN_LED, OUTPUT);
digitalWrite(PIN_LED, LOW);
// attach interrupt
attachInterrupt(reader.PIN_CARD_STROBE, isr, FALLING);
// reset card data
initCardData();
}
void loop() {
// put your main code here, to run repeatedly:
// if data is ready
if (reader.bDataPresent) {
if (reader.stamp > 0 && ((millis() - reader.stamp) > 10)) {
printf("Card slide: ");
for (int x = 0; x < reader.idx - 1; x++) {
bitClear(reader.buff[x], 4);
printf("%1X", reader.buff[x]);
}
printf("\n");
digitalWrite(PIN_LED, LOW);
// check validity
int pos = 0;
for (int x = 14; x < reader.idx; x++)
if (reader.buff[x] == 0x0D) { pos = x; break; }
bool valid = pos > 13 && pos < 21 && reader.buff[0] == 0x0B && reader.idx > pos + 4;
// show card info if valid
if (valid) {
for (int x = 1; x < pos + 5; x++) reader.buff[x] += 48;
printf(" valid, card # %.*s, exp %.*s/%.*s\n", pos - 1, &(reader.buff[1]),
2, &(reader.buff[pos + 3]), 2, &(reader.buff[pos + 1]));
}
else printf(" invalid\n");
initCardData();
} else {
digitalWrite(PIN_LED, HIGH);
}
}
}
void initCardData() {
reader.idx = 0;
reader.bDataPresent = false;
reader.bitpos = 0;
}
@braysonjohn148
Copy link

Works like a charm. I had another use with pin 32 so i connected to pin 13. ESP-32. i could not find a library for this reader, and i came across this. You have a wonderful day

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment