Inhaltsverzeichnis:

Verwandeln Sie Ihr Arduino in einen Magnetkartenleser! - Gunook
Verwandeln Sie Ihr Arduino in einen Magnetkartenleser! - Gunook

Video: Verwandeln Sie Ihr Arduino in einen Magnetkartenleser! - Gunook

Video: Verwandeln Sie Ihr Arduino in einen Magnetkartenleser! - Gunook
Video: 🔴 Lerne Arduino in 12 Minuten, ….…JEDER KANN DAS! | #EdisTechlab 2024, Juli
Anonim
Verwandeln Sie Ihr Arduino in einen Magnetkartenleser!
Verwandeln Sie Ihr Arduino in einen Magnetkartenleser!
Verwandeln Sie Ihr Arduino in einen Magnetkartenleser!
Verwandeln Sie Ihr Arduino in einen Magnetkartenleser!
Verwandeln Sie Ihr Arduino in einen Magnetkartenleser!
Verwandeln Sie Ihr Arduino in einen Magnetkartenleser!

Jeder hat einen Magnetkartenleser benutzt, glaube ich. Ich meine, wer trägt heutzutage Bargeld? Es ist auch nicht schwer, sie in die Finger zu bekommen, und während eines Ausflugs zu meinem lokalen Lieblings-Elektronikladen fand ich einen Mülleimer voller dieser Typen. Also….. natürlich habe ich mir einen geholt und ihn mit nach Hause genommen, um zu sehen, was ich damit und einem AVR machen könnte.

Diese Anleitung zeigt Ihnen, wie Sie einen Magtek-Magnetkartenleser an einen AVR oder Arduino / Klon anschließen und Daten von der ersten Kartenspur lesen. Schnallen Sie Ihre Sitze an; Magnetkartenleser haben eine hohe Bitrate!

Schritt 1: Die Ausrüstungsliste

Die Ausrüstungsliste
Die Ausrüstungsliste
Die Ausrüstungsliste
Die Ausrüstungsliste

Hier sind ein paar Dinge, die Sie benötigen, um loszulegen.

  • Magnetkartenleser (Mine ist ein Magetk 90-mm-Dual-Head-Leser. 5,00 $)
  • AVR, Arduino oder Klon (ATmega328p ~ 4,30 $ von Mouser.com
  • lötfreies Steckbrett
  • etwas Draht
  • vielleicht ein Header, wenn Sie so etwas mögen.
  • etwas, um Ihre serielle Schnittstelle zu lesen. Ich verwende AVR Terminal von BattleDroids.net

Das ist alles, was Sie brauchen, um loszulegen. Je nachdem, welchen Kartenleser Sie erhalten, müssen Sie möglicherweise diese Anweisungen und ganz sicher den Code ändern, damit er mit Ihrem speziellen Leser funktioniert. Der Code, den ich geschrieben habe, sollte Sie jedoch ziemlich weit bringen, hoffe ich.

Schritt 2: Selbsttaktende Magnetkartenleser

Selbsttaktende Magnetkartenleser
Selbsttaktende Magnetkartenleser
Selbsttaktende Magnetkartenleser
Selbsttaktende Magnetkartenleser
Selbsttaktende Magnetkartenleser
Selbsttaktende Magnetkartenleser
Selbsttaktende Magnetkartenleser
Selbsttaktende Magnetkartenleser

Magnetkartenleser sind „selbsttaktend“, d. h. sie bieten einen Takt, der als Strobe bezeichnet wird, gegen den sich der angeschlossene Mikrocontroller synchronisieren kann. Dies ist ein Segen. Das bedeutet, dass Sie sich keine Gedanken über die Suche nach einem Taktsignal und das Timing des Signals machen müssen, um direkt auf dem Taktimpuls zu zentrieren, und kein lästiges Oszillieren in den Sweetspot des Taktsignals. Das macht Sinn, wenn man an Kartenwischer denkt: Jeder wischt in einem anderen Tempo, manche langsamer, manche schneller als andere. Selbst-Clocking ermöglicht es sogar meiner süßen Oma, ihre Karte zu verwenden, ohne sich das Handgelenk zu brechen. Erinnert mich daran, die Einstellung für sie ändern zu müssen, die bestimmt, wie viel Zeit zwischen Klicks gültig ist, um einen Doppelklick zu registrieren….

Die Daten dieses Kartenlesers sind 1,0 us gültig, bevor das Stroboskop auf die Leitung gelegt wird. Für einen Dual-Head-Reader wie den, den ich verwende, stehen zwei Datenspuren zum Lesen zur Verfügung. In diesem ible zeige ich das Lesen des ersten ersten Titels, um Ihnen den Einstieg zu erleichtern. Es gibt fünf Verbindungen, die Sie herstellen müssen (vier, wenn es Ihnen nichts ausmacht, auf mehr fein abgestimmte Steuerung zu verzichten, weil weniger I/O-Ports verwendet werden). Schauen Sie sich das Bild unten an. Der rote Draht geht auf +5V, während der schwarze Draht auf Masse geht. Der grüne Draht ist /CARD_PRESENT; das gelbe Kabel ist /STROBE und das weiße Kabel ist /DATA1. Der Schrägstrich (/) bedeutet, dass die Daten invertiert sind. Ein niedriges Signal (dh 0) wird als Eins oder hoch gelesen. Die anderen Anschlüsse sind braun für /STROBE2 und orange für /DATA2. Wir werden diese nicht verwenden. Wenn Sie möchten, können Sie /CARD_PRESENT vergessen. Diese Datenleitung geht nach etwa 17 Umdrehungen des Kopfflusses auf Low, um anzuzeigen, dass eine Karte vorhanden ist (anstelle von zufälligem Rauschen, das Ihr Lesegerät zum Senden gefälschter Daten veranlasst) und wird verwendet, um zu bestätigen, dass die Daten, die Sie erhalten, Kartendaten sind und kein Müll. Sie können diese Verbindung überspringen, wenn Sie im Datenstrom nach dem Start-Sentinel suchen. Dazu später mehr. Wie Sie unten sehen können, habe ich einen rechtwinkligen Stecker mit einem Steckbrett verwendet und meinen Leser damit verbunden. Ich habe /STROBE mit PIND2 (digitaler Pin 2 auf einem Arduino), /CARD_PRESENT mit PIND3 (zur Veranschaulichung) und /DATA1 mit PIND4 verbunden. Stellen Sie sicher, dass Sie Klimmzüge an diesen Pins aktivieren, damit Ihre Pins nicht schweben. Ich habe auch meinen Arduino gegen einen Bare Bones AVR eingetauscht, weil ich mag, wie er in das Steckbrett passt.

Schritt 3: Grundlagen der Magnetkarte

Grundlagen der Magnetkarten
Grundlagen der Magnetkarten

Die wichtigsten Funktionen, die Sie ausführen müssen, um eine Magnetkarte zu lesen, sind: 1. Erkennen, wenn die Karte durchgezogen wurde 2. Lesen Sie den Datenstrom 3. Erkennen Sie, wenn die Karte weg ist 4. Verarbeiten Sie die Daten 5. Anzeigen der data Zuerst werde ich Ihnen einige Grundlagen von Magnetkarten vorstellen, die Sie wissen müssen, wenn Sie anfangen, Ihren eigenen Code zu schreiben.

Normen für Magnetkarten

Magnetkarten sind von der ISO in den folgenden Dokumenten standardisiert: 7810 Physische Eigenschaften von Dokumenten in Kreditkartengröße 7811-1 Prägung 7811-2 Magnetstreifen – niedrige Koerzitivfeldstärke 7811-3 Position der geprägten Zeichen 7811-4 Position der Spuren 1 und 2 7811- 5 Position der Schiene 3 7811-6 Magnetstreifen - hohe Koerzitivfeldstärke 7813 Finanztransaktionskarten Wie Sie sehen, werden Finanzkarten in einem separaten Dokument angegeben und haben oft andere Formate als beispielsweise Ihre Lebensmittelkarte oder internationale Visitenkarte. Sie müssen für diese Unterschiede programmieren. Ich hatte gerade eine Kreditkarte und eine Versicherungskarte zur Hand, also habe ich für diese Typen programmiert (die beide zufällig das Format B haben).

Kartenformate

Es gibt verschiedene Formate für Magnetkarten. Format A und B sind üblich, wobei B das häufigste ist, das ich gesehen habe und das in diesem Code unterstützt wird. Die Formate C bis M sind meiner Meinung nach von der ISO reserviert, während N bis ?? sind für institutionelle kundenspezifische Zwecke reserviert. Spur 1 Bei Finanzkarten wird die erste Spur mit 210 Bit pro Zoll aufgezeichnet und ist die erste 0,110" der Karte von oben. Die Daten werden als "Kartendaten" mit 7 Bit pro Zeichen codiert. Das sind 6 Bit für das Zeichen und ein Bit für die Parität. Es gibt ~ 79 alphanumerische Zeichen auf Spur 1. Die physische Reihenfolge ist rückwärts, dh die Daten werden rückwärts auf die Karte geschrieben (und daher von Ihrer Firmware gelesen) als Parität ist ungerade Das Kartendatenformat sieht wie folgt aus:

[SS] [FC] [Primäre Kontonummer] [FS] [Name] [FS] [Zusätzliche Daten] [FS][ES][LRC]wobei:

SS Start Sentinel FC Formatcode FS Feldtrennzeichen ES End Sentinel LRC Längsredundanz Prüfzeichen Track one SS = '%', FC = eines der Formate (wird oft B sein), FS ist oft '', ES ist '?' und das LRC-Zeichen ist normalerweise '<', obwohl es in den Standards nicht angegeben ist. Abgesehen davon, dass sie rückwärts auf die Karte geschrieben werden, haben die Daten ein ungerades Paritätsbit und sind 0x20 von ASCII. Wir behandeln dies, wenn wir die Daten verarbeiten. Spur 2 Spur zwei ist 0,110" breit und beginnt 0,110 von der Oberseite der Karte. Die Aufzeichnungsdichte beträgt 75 Bits pro Zoll. Die Daten sind 5 Bits pro Zeichen und bestehen nur aus etwa 40 numerischen Symbolen. Sie sollten auf keine stoßen Buchstaben auf dieser Spur. Das Kartendatenformat sollte dieser Struktur folgen

[SS] [primäre Kontonummer] [FS] [zusätzliche Daten | diskretionäre Daten] [ES] [LRC]

Das SS für Track zwei ist das Semikolon: ';' und der FS ist '=' Mit diesem heiligen Wissen im Gepäck fahren Sie mit den nächsten Schritten fort, um den Code zu sehen, der das oben beschriebene Verfahren implementiert.

Schritt 4: Erkennen, wenn eine Karte durchgezogen wird

Erkennen, wenn eine Karte durchgezogen wird
Erkennen, wenn eine Karte durchgezogen wird

1. Erkennen, wenn eine Karte durchgezogen wurde Formal würde man den /CARD_PRESENT-Pin überprüfen, um zu sehen, ob er niedrig ist. Glücklicherweise ist dies nicht wirklich notwendig. Wir prüfen später, ob die Karte gültig ist. Alternativ können Sie Ihren Stroboskop-Pin ablesen, um zu sehen, wann Stroboskope auf den Pin gesetzt wurden, aber dies wird Ihnen viele Taktnullen einbringen. Das Lesegerät sendet ungefähr 60-70 führende Nullen, um Sie darüber zu informieren, dass die Daten präsentiert werden. Wir werden jedoch die Natur binärer Daten verwenden, um zu bestimmen, wann mit der Aufzeichnung von Bits begonnen werden soll. Der Startwächter (SS) für Track eins ist das Prozentzeichen (%). Sein Binärwert ist 0010 0101, was bedeutet, dass er als 1010 001 gespeichert (und gelesen) wird (es sind 7 Bits, also wird das 8. Bit nicht übertragen). Jetzt wird der kluge Leser feststellen, dass die Daten zwar rückwärts sind, aber nicht mit dem binären ASCII-Wert übereinstimmen. Das liegt daran, dass es 0x20 außerhalb von Hex ist. Das %-Symbol ist 0x25 und 0100 0101 ist 0x05. Kartendaten haben 0x20 vom Wert abgezogen. Dass da draußen im hohen Knabbergebäck hängt, ist das ungerade Paritätsbit. Es wird dort so abgelegt, dass der Wert eine ungerade Anzahl von "1"en enthält. Da wir also wissen, dass eine gültige Karte immer mit diesem Start-Sentinel beginnt, und weil das Paritätsbit eine 1 ist, wissen wir, wenn wir den ersten Übergang von HIGH zu LOW am Daten-Pin erkennen, dann wissen wir, dass wir gerade damit begonnen haben, die zu empfangen Starten Sie Sentinel von einer Karte. Nun, dies wird nicht immer wahr sein, und ein narrensicherer Plan wäre, die /CARD_PRESENT-Karte zusätzlich zu überprüfen, um zu sehen, ob sie auf LOW gegangen ist. Der einfachste Weg, den Start des SS zu erkennen, besteht darin, einen externen Interrupt zu erzeugen, der an der fallenden Flanke von /STROBE ausgelöst wird. Die Daten sind 1,0 us vor der fallenden Flanke gültig. Wenn Sie also die fallende Flanke abgetastet haben, wissen Sie, dass Sie den /DATA1-Pin lesen und einen gültigen Wert erhalten können. Hier ist der Code zum Erstellen Ihres externen Interrupts, der bei einer fallenden Flanke ausgelöst wird.

voidInitInterrupt (void) {// Setup-Interrupt BSET (EIMSK, INT0); // externe Interruptmaske BSET (EICRA, ISC01); // fallende Flanke BCLR (EICRA, ISC00); // fallende Flanke BSET (SREG, 7); // I-Bit im SREG}

In meiner common.h, die ich in alle meine Programme einbaue, sind die Definitionen von BSET und BCLR zu finden. Schlagen Sie in dieser Datei nach, wenn Sie Fragen zum Setzen von Bits haben. Wenn nun der Interrupt ausgelöst wird, möchten wir /DATA1 (in meinem Code als CARD_DATA definiert) abtasten und ein Bit in einem Allzweck-E/A-Register setzen. Wenn wir beim 7. Bit sind, speichern Sie das Register als Zeichen in unserem globalen Puffer. Ich verwende ein GPIOR0-Register, weil es ein schicker schneller Zugriff ist. Der Pseudocode ist ungefähr so:

16-Bit-Timer stoppen Timer löschen Wenn DATA LOW ist BIT=1 in REGISTER setzen BIT dekrementieren Flag setzen, damit keine Nullen mehr übersprungen werden sonst DATA HIGH BIT=0 in REGISTER setzen BIT dekrementieren Wenn BIT 0 ist Byte zum Puffer hinzufügen Index inkrementieren BIT zurücksetzen

Wenn Sie sich fragen, warum dekrementieren statt inkrementieren, denken Sie daran, dass die Daten rückwärts sind. Anstatt die Bits aufzuzeichnen, wenn wir sie von LSB zu MSB bekommen, speichern wir sie von MSB zu LSB, damit wir die Bits nicht umkehren müssen später bei der Verarbeitung der Daten. Wenn Sie wirklich wollten, könnten Sie hier auch 0x20 hex hinzufügen, aber da es bei diesen Strobes etwa 5us sind, halte ich die Verarbeitung in dieser Interrupt-Service-Routine auf ein Minimum.

ISR (INT0_vect) { StopTimer (); ClearTimer(); if (!BCHK(PIND, CARD_DATA1)) // inverse low = 1 { BSET(GPIOR0, bit); --Bit; bDataPresent = 1; aufrechtzuerhalten. Sonst if (bDataPresent) { BCLR (GPIOR0, Bit); --Bit; aufrechtzuerhalten. Wenn (Bit < 0) { buff [idx] = (char) GPIOR0; ++idx; Bit = 6; } StartTimer();} Wenn Sie sich fragen, worum es bei der Zeitmessung geht, wird dies im Schritt zur Feststellung, wann die Karte das Lesegerät verlassen hat, behandelt.

Schritt 5: Lesen Sie den Datenstrom

Lesen Sie den Datenstrom

Nun, ich habe Ihnen bereits gezeigt, wie Sie die Daten lesen, da sie Teil der Interrupt-Service-Routine für unseren externen Interrupt mit fallender Flanke sind. Eine alternative Methode wäre, ein Flag im ISR zu setzen und in der Hauptschleife das Flag abzurufen und die Daten auf diese Weise zu lesen, aber ich glaube, die Art und Weise, wie ich es präsentiert habe, ist sauberer. Seien Sie Ihr eigener Richter und schreiben Sie Ihren, wie auch immer Ihre MCU es zulässt. Lassen Sie uns jedoch herausfinden, wie Sie erkennen können, wann die Karte einen Elvis zieht und das Gebäude verlassen hat.

Schritt 6: Erkennen der Karte, die das Lesegerät verlässt

Erkennen der Karte, die das Lesegerät verlässt
Erkennen der Karte, die das Lesegerät verlässt

Erkennen, wenn eine Karte weg ist

Formal würde man den /CARD_PRESENT-Pin abtasten, um zu sehen, ob er wieder HIGH ist, aber wir brauchen nicht, dass /CARD_PRESENT einen anderen I/O-Port belegt. Hier kommen diese Timer ins Spiel. Jedes Mal, wenn der Interrupt aufgerufen wird, weil wir eine fallende Flanke an /STROBE festgestellt haben, stoppen wir einen Timer, löschen den Timerwert und beginnen mit dem Lesen. Wenn wir mit dem Lesen fertig sind, starten wir den Timer erneut. Wiederholen Sie dies bis zum Erbrechen oder bis der Timer einen bestimmten Wert erreicht. Das bedeutet, dass der letzte Interrupt aufgerufen wurde und keine Daten mehr eingegangen sind, also gehen wir davon aus und beginnen mit der Verarbeitung der gesammelten Daten. Für Timer verwenden wir TIMER1, also den 16-Bit-Timer. Ich verwende einen 16 Mhz Resonator extern zu meinem AVR. Wenn Sie ein Arduino verwenden, sind Sie es wahrscheinlich auch. Ich habe also einen Prescaler-Wert von 1024 gewählt, was bedeutet, dass der Timer alle (16.000.000 / 1024) Mal inkrementiert wird. Das heißt, es „tickt“15.625 Mal pro Sekunde. /CARD_PRESENT geht auf HIGH und zeigt an, dass die Karte das Lesegerät etwa 150 ms nach dem letzten Datenbit verlassen hat. Da ich dies wusste, beschloss ich einfach, ungefähr jede 1/4 Sekunde zu überprüfen. Das würde ungefähr so aussehen:

(((F_CPU) / PRESCALER) / 4) was sich als ungefähr 3900 herausstellt. Wenn also der Timer-Zähler TCNT1 3900 erreicht, weiß ich, dass es ungefähr 300 ms waren und ich kann ziemlich sicher schlussfolgern, dass die Karte den Leser verlassen hat. Einfach

#define PRESCALER 1024#define CHECK_TIME ((F_CPU / PRESCALER) / 4) // 250 ms#define StartTimer() BSET(TCCR1B, CS10), BSET(TCCR1B, CS12) // 1024 Prescaler#define StopTimer() BCLR(TCCR1B, CS10), BCLR(TCCR1B, CS12)#define ClearTimer() (TCNT1 = 0) Sie haben in der ISR gesehen, wo der Timer bei jedem Interrupt gestartet, gestoppt und gelöscht wird. Jetzt prüfen wir in der Hauptschleife nur, ob der Timerzähler unseren Zielwert erreicht hat und starten in diesem Fall die Datenverarbeitung

for (;;){ if(TCNT1 >= CHECK_TIME) {

StoppTimer(); ClearTimer(); Prozessdaten(); ReadData(); idx = 0; Bit = 6; bDataPresent = 0; memset(&buff, 0, MAX_BUFF_SZ1); } } Jetzt können die Daten sicher verarbeitet werden

Code formatiert von

Schritt 7: Verarbeiten Sie die Daten

Daten verarbeiten
Daten verarbeiten

Daten verarbeiten

Die Verarbeitungsphase besteht aus:

  • Überprüfung auf eine gültige SS
  • Parität prüfen
  • in ASCII umwandeln
  • Prüfung auf gültiges ES
  • LRC prüfen

Hier kümmere ich mich nicht um die Überprüfung der Parität, da ich dieses Bit einfach auf Null gesetzt habe. Ich berechne den LRC auch nicht für dieses kleine Tutorial. Das wäre etwas, was eine vollständiger realisierte Firmware vielleicht tun möchte. Hier ist der Code, um die Daten zu verarbeiten, die die obigen Schritte ausführen (ohne das zuvor erwähnte). Finden Sie es im Bild unten. Es ist kommentiert und ziemlich selbsterklärend. Ein besonderer Hinweis zu Parität und ASCII: Ich lösche einfach das Paritätsbit (7. Bit…also eine 1 mit 6 Nullen dahinter) und um von "Kartendaten" umzurechnen, musst du 0x20 zum Wert addieren. Das ist alles.

Schritt 8: Zeigen Sie die Daten an

Daten anzeigen
Daten anzeigen
Daten anzeigen
Daten anzeigen

Daten anzeigen

Die Anzeige geht zu einem Terminalprogramm, das ich speziell für den Anschluss an einen AVR über RS232 oder USB geschrieben habe. Das Programm heißt AVR-Terminal. Die Methode ReadData() ist ziemlich hässlich und Sie sollten eine sauberere Lösung finden als die, die ich mir ausgedacht habe. Es gibt auch eine Ausgabe der Funktion im AVR-Terminal. Die Ausgabe ist zum einen eine Krankenversicherungskarte und zum anderen eine VISA-Karte. Klicken Sie auf in der oberen linken Ecke des Bildes und wählen Sie Original oder großes Bild, um es besser zu sehen.

Schritt 9: Code-Download und Wrapup

In diesem anweisbaren habe ich einige Grundlagen von Magnetkartenlesern besprochen und Ihnen einen Code gezeigt, um Sie in die richtige Richtung beim Lesen von Daten von Magnetkarten zu bringen. Es gibt noch viel mehr Arbeit, die getan werden könnte, wie das Lesen und Decodieren des zweiten Tracks, das Berechnen des LRC und das Berechnen der ungeraden Parität für jedes Byte. Der vollständige Quellcode steht unten zum Download bereit. Es wurde in AVR Studio 4.17 geschrieben. Ich hoffe, Sie haben dieses instructable genossen und freue mich wie immer auf alle Kommentare oder Vorschläge, die Sie haben können. Glückliches Codieren und AVR'ing!

Empfohlen: