Inhoudsopgave:

Verander uw Arduino in een magnetische kaartlezer! 9 stappen (met afbeeldingen) Antwoorden op al uw "Hoe?"
Verander uw Arduino in een magnetische kaartlezer! 9 stappen (met afbeeldingen) Antwoorden op al uw "Hoe?"

Video: Verander uw Arduino in een magnetische kaartlezer! 9 stappen (met afbeeldingen) Antwoorden op al uw "Hoe?"

Video: Verander uw Arduino in een magnetische kaartlezer! 9 stappen (met afbeeldingen) Antwoorden op al uw
Video: Использование Melexis MLX90614 Инфракрасный термометр с Arduino 2024, Juli-
Anonim
Verander uw Arduino in een magnetische kaartlezer!
Verander uw Arduino in een magnetische kaartlezer!
Verander uw Arduino in een magnetische kaartlezer!
Verander uw Arduino in een magnetische kaartlezer!
Verander uw Arduino in een magnetische kaartlezer!
Verander uw Arduino in een magnetische kaartlezer!

Iedereen heeft wel eens een magnetische kaartlezer gebruikt, geloof ik. Ik bedoel, wie heeft tegenwoordig contant geld bij zich? Ze zijn ook niet moeilijk te bemachtigen, en tijdens een reis naar mijn favoriete plaatselijke elektronicawinkel vond ik een bak vol met deze jongens. Dus… natuurlijk pakte ik er een en nam hem mee naar huis om te zien wat voor dingen ik ermee kon doen en een AVR.

Deze instructable laat je zien hoe je een Magtek magnetische kaartlezer aansluit op een AVR of Arduino/kloon en gegevens leest van het eerste spoor van de kaart. Zet je stoelen vast; magnetische kaartlezers hebben een hoge bitrate!

Stap 1: De apparatuurlijst

De uitrustingslijst
De uitrustingslijst
De uitrustingslijst
De uitrustingslijst

Hier zijn een paar dingen die je nodig hebt om te beginnen.

  • Magnetische kaartlezer (de mijne is een Magetk 90 mm dual-head-lezer. $ 5,00)
  • AVR, Arduino of kloon (ATmega328p ~ $ 4,30 van Mouser.com
  • soldeerloze breadboard
  • wat draad
  • misschien een header als je dat soort dingen leuk vindt.
  • iets om uw seriële poort te lezen. Ik gebruik AVR Terminal van BattleDroids.net

Dat is alles wat je nodig hebt om te beginnen. Afhankelijk van de magcard-lezer die u uiteindelijk krijgt, moet u mogelijk deze instructies, en zeker de code, aanpassen om met uw specifieke lezer te werken. De code die ik heb geschreven, zou je echter behoorlijk ver moeten brengen, hoop ik.

Stap 2: zelfklokkende magnetische kaartlezers

Zelfklokkende magnetische kaartlezers
Zelfklokkende magnetische kaartlezers
Zelfklokkende magnetische kaartlezers
Zelfklokkende magnetische kaartlezers
Zelfklokkende magnetische kaartlezers
Zelfklokkende magnetische kaartlezers
Zelfklokkende magnetische kaartlezers
Zelfklokkende magnetische kaartlezers

Magnetische kaartlezers zijn "zelfklokkend", wat betekent dat ze een klok bieden, een stroboscoop genaamd, waartegen de aangesloten microcontroller kan synchroniseren. Dit is een zegen. Het betekent dat u zich geen zorgen hoeft te maken over het zoeken naar een kloksignaal en het timen van het signaal om direct op de klokpuls te centreren, en geen hinderlijk oscilleren in de goede plek van het kloksignaal. Dit is logisch als je denkt aan kaartveegacties: iedereen veegt in een ander tempo, sommige langzamer, sommige sneller dan andere. Door zelfklokken kan zelfs mijn lieve oma haar kaart gebruiken zonder haar pols te breken. Doet me denken aan de instelling voor haar die bepaalt hoeveel tijd geldig is tussen klikken om een dubbelklik te registreren….

De gegevens van deze kaartlezer zijn 1,0 us geldig voordat de flitser op de lijn wordt gezet, dus u hoeft zich geen zorgen te maken over vertragingen om uzelf in de "bit-tijd" te krijgen. Voor een dual head-lezer zoals degene die ik gebruik, zijn er twee datatracks beschikbaar om te lezen. In deze 'ible' ga ik het lezen van het primaire eerste nummer laten zien om je op weg te helpen. Er zijn vijf verbindingen die je moet maken (vier als je het niet erg vindt om meer fijnafgestelde controle op te geven voor minder I/O-poorten die worden gebruikt). Bekijk de afbeelding hieronder. De rode draad gaat naar +5V terwijl de zwarte draad naar aarde gaat. De groene draad is /CARD_PRESENT; de gele draad is /STROBE en de witte draad is /DATA1. De schuine streep (/) betekent dat de gegevens worden geïnverteerd. Een laag signaal (dwz 0) wordt gelezen als een één of hoog. De andere connectoren zijn bruin voor /STROBE2 en oranje voor /DATA2. Deze gaan we niet gebruiken. Als je wilt, kun je /CARD_PRESENT vergeten. Deze datalijn wordt laag na ongeveer 17 kopfluxrotaties om aan te geven dat een kaart aanwezig is (in plaats van bijvoorbeeld willekeurige ruis waardoor uw lezer nepgegevens verzendt) en wordt gebruikt om te valideren dat de gegevens die u krijgt kaartgegevens zijn en geen afval. U kunt deze verbinding overslaan als u controleert op de startschildwacht in de datastroom. Daarover later meer. Zoals je hieronder kunt zien, heb ik een mannelijke header met een rechte hoek gebruikt die is aangesloten op een breadboard en heb ik mijn lezer daarop aangesloten. Ik heb /STROBE aangesloten op PIND2 (digitale pin 2 op een Arduino), /CARD_PRESENT op PIND3 (ter illustratie) en /DATA1 op PIND4. Zorg ervoor dat je pullups op deze pinnen inschakelt, zodat je pinnen niet zweven. Ik heb ook mijn Arduino ingeruild voor een Bare Bones AVR omdat ik het leuk vind hoe het in het breadboard past.

Stap 3: Basisprincipes van magnetische kaarten

Basisprincipes van magnetische kaarten
Basisprincipes van magnetische kaarten

De belangrijkste functies die u moet doen om een magnetische kaart te lezen, zijn: 1. Detecteren wanneer de kaart is doorgehaald 2. De gegevensstroom lezen 3. Detecteren wanneer de kaart verdwenen is 4. De gegevens verwerken 5. De data Eerst zal ik je kennis laten maken met enkele basisprincipes van magnetische kaarten die je moet weten als je begint met het schrijven van je eigen code.

Normen voor magnetische kaarten

Magnetische kaarten zijn gestandaardiseerd door de ISO in de volgende documenten: 7810 Fysieke kenmerken van creditcardformaat document 7811-1 Embossing 7811-2 Magneetstrip - lage coërciviteit 7811-3 Locatie van reliëfkarakters 7811-4 Locatie van sporen 1 & 2 7811- 5 Locatie spoor 3 7811-6 Magneetstrip - hoge coërciviteit 7813 Financiële transactiekaarten Zoals u kunt zien, worden financiële kaarten gespecificeerd in een apart document en hebben ze vaak een ander formaat dan bijvoorbeeld uw boodschappenkaart of internationale telefoonkaart. U zult voor deze verschillen moeten programmeren. Ik had net een creditcard en een verzekeringskaart bij de hand, dus ik heb voor deze typen geprogrammeerd (die beide formaat B zijn).

Kaartformaten

Er zijn verschillende formaten voor magneetkaarten. Formaat A en B zijn gebruikelijk, waarbij B de meest voorkomende is die ik heb gezien en die in deze code wordt ondersteund. Formaten C tot en met M zijn volgens mij gereserveerd door de ISO, terwijl N tot en met ?? zijn gereserveerd voor institutioneel gebruik op maat. Track 1 Voor financiële kaarten wordt de eerste track opgenomen met 210 bits per inch en is de eerste 0,110" van de kaart vanaf de bovenkant. De gegevens worden gecodeerd als "kaartgegevens" met 7 bits per teken. Dat is 6 bits voor het teken en een bit voor pariteit. Er zijn ~ 79 alfanumerieke tekens op spoor 1. De fysieke volgorde is omgekeerd. Dat wil zeggen, gegevens zijn maar achteruit op de kaart geschreven (en worden daarom door uw firmware gelezen) als. pariteit is vreemd. Het formaat van de kaartgegevens ziet er als volgt uit:

[SS] [FC] [Primair account #] [FS] [Naam] [FS] [Aanvullende gegevens] [FS][ES][LRC]waar:

SS Start sentinel FC Formaatcode FS Veldscheidingsteken ES End sentinel LRC Longitudinal Redundancy Check-teken Spoor één SS = '%', FC = een van de formaten (zal vaak B zijn), FS is vaak '', ES is '?' en het LRC-teken is gewoonlijk '<', hoewel het niet in de normen is gespecificeerd. Behalve dat ze achterstevoren op de kaart worden geschreven, hebben de gegevens een oneven pariteitsbit en zijn ze 0x20 van ASCII. We zullen dit afhandelen wanneer we de gegevens verwerken. Spoor 2 Spoor twee is 0,110" breed en begint 0,110 vanaf de bovenkant van de kaart. De opnamedichtheid is 75 bits per inch. De gegevens zijn 5 bits per teken en bestaan alleen uit ongeveer 40 numerieke symbolen. letters op dit spoor. Het kaartgegevensformaat moet deze structuur volgen

[SS] [primaire account #] [FS] [aanvullende gegevens | discretionaire gegevens] [ES] [LRC]

De SS voor spoor twee is de puntkomma: ';' en de FS is '=' Met deze heilige kennis onder uw riem, gaat u verder met de volgende stappen om de code te zien die de hierboven beschreven procedure implementeert.

Stap 4: Detecteren wanneer een kaart wordt geveegd

Detecteren wanneer een kaart wordt geveegd
Detecteren wanneer een kaart wordt geveegd

1. Detecteren wanneer een kaart is weggevaagd Formeel zou men de /CARD_PRESENT-pin controleren om te zien of deze laag is gevallen. Gelukkig is dit niet echt nodig. We controleren later op een geldige kaart. Als alternatief kunt u uw stroboscooppin lezen om te zien wanneer flitsers op de pin zijn geplaatst, maar dit zal u veel kloknullen opleveren. De lezer stuurt ongeveer 60-70 voorloopnullen om u te laten weten dat de gegevens op het punt staan gepresenteerd te worden. We gaan echter de aard van binaire gegevens gebruiken om te bepalen wanneer we moeten beginnen met het opnemen van bits. De startschildwacht (SS) voor spoor één is het percentageteken (%). De binaire waarde is 0010 0101, wat betekent dat het wordt opgeslagen (en gelezen) als 1010 001 (het is 7-bits, dus de 8e bit wordt niet verzonden). Nu zal de scherpzinnige lezer opmerken dat hoewel de gegevens achterwaarts zijn, deze niet overeenkomen met de binaire ASCII-waarde. Dat komt omdat het 0x20 van hex af is. Het %-symbool is 0x25 en 0100 0101 is 0x05. Kaartgegevens hebben 0x20 afgetrokken van de waarde. Diegene die daar in de hoge knabbel hangt, is het vreemde pariteitsbit. Het is daar zo geplaatst dat er een oneven aantal "1"-en in de waarde zit. Dus omdat we weten dat een geldige kaart altijd begint met deze startschildwacht, en omdat de pariteitsbit een 1 is, weten we dat wanneer we de eerste overgang van HOOG naar LAAG op de datapin detecteren, we net zijn begonnen met het ontvangen van de start schildwacht vanaf een kaart. Dit zal niet altijd waar zijn, en een onfeilbaar plan zou zijn om de /CARD_PRESENT-kaart te controleren om te zien of deze bovendien LAAG is geworden. De eenvoudigste manier om het begin van de SS te detecteren, is door een externe interrupt te creëren die wordt geactiveerd op de dalende flank van de /STROBE. De gegevens zijn geldig 1.0 us vóór de dalende flank, dus als je de dalende flank hebt gesampled, dan weet je dat je de /DATA1-pin kunt lezen en een geldige waarde kunt krijgen. Hier is de code om uw externe interrupt te maken die wordt geactiveerd op een dalende flank.

voidInitInterrupt (void) {// Setup-onderbreking BSET (EIMSK, INT0); // extern interruptmasker BSET (EICRA, ISC01); // dalende flank BCLR (EICRA, ISC00); // dalende flank BSET (SREG, 7); // I-bit in SREG}

In mijn common.h die ik in al mijn programma's opneem, staan de definities van BSET en BCLR. Raadpleeg dat bestand als u vragen heeft over het instellen van bits. Nu, wanneer de interrupt wordt geactiveerd, willen we de /DATA1 samplen (in mijn code gedefinieerd als CARD_DATA) en een bit instellen in een IO-register voor algemene doeleinden. Als we op de 7e bit zitten, sla het register dan op als een teken in onze globale buffer. Ik gebruik een GPIOR0-register omdat het een snelle toegang is. De pseudo-code ziet er ongeveer zo uit:

Stop 16-bit timer Wis timer Als DATA LAAG is Stel BIT=1 in bij REGISTER BIT verlagen Stel vlag in zodat we geen nullen meer overslaan DATA is HOOG Stel BIT=0 in REGISTER BIT verlagen Als BIT 0 is Voeg byte toe aan buffer Verhogingsindex Reset BIT

Als je jezelf afvraagt waarom decrementeren in plaats van verhogen, onthoud dan dat de gegevens achterwaarts zijn, dus in plaats van de bits op te nemen zoals we ze van LSB naar MSB krijgen, slaan we ze op van MSB naar LSB, zodat we de bits niet hoeven om te keren later bij het verwerken van de gegevens. Als je echt zou willen, zou je hier ook 0x20 hex kunnen toevoegen, maar aangezien het ongeveer 5us is op deze flitsers, beperk ik de verwerking in deze interruptservice-routine tot een minimum.

ISR(INT0_vect){ StopTimer(); ClearTimer(); if (!BCHK(PIND, CARD_DATA1)) // inverse laag = 1 {BSET(GPIOR0, bit); --beetje; bDataPresent = 1; } else if (bDataPresent) { BCLR(GPIOR0, bit); --beetje; } if (bit <0) { buff[idx] = (char)GPIOR0; ++idx; beetje = 6; } StartTimer();} Als je je afvraagt waar de timing-business over gaat, wordt dat behandeld in de stap om te bepalen wanneer de kaart de lezer heeft verlaten.

Stap 5: Lees de gegevensstroom

Lees de gegevensstroom

Nou, ik heb je al laten zien hoe je de gegevens moet lezen, omdat het deel uitmaakt van de Interrupt Service Routine voor onze externe interrupt met dalende rand. Een alternatieve methode zou zijn om een vlag in de ISR in te stellen en in de hoofdlus de vlag te pollen en de gegevens op die manier te lezen, maar ik geloof dat de manier waarop ik het heb gepresenteerd schoner is. Wees je eigen rechter en schrijf de jouwe zoals je MCU het toelaat. Dat gezegd hebbende, laten we verder gaan met het ontdekken hoe je kunt detecteren wanneer de kaart een Elvis trekt en het gebouw heeft verlaten.

Stap 6: Detecteren dat de kaart de lezer verlaat

Detecteren dat de kaart de lezer verlaat
Detecteren dat de kaart de lezer verlaat

Detecteren wanneer een kaart is verdwenen

Formeel zou men de /CARD_PRESENT-pin kunnen samplen om te zien of deze weer HOOG is geworden, maar we hebben geen steenkin' /CARD_PRESENT nodig die een andere I/O-poort inneemt. Dit is waar die timers binnenkomen. Elke keer dat de interrupt wordt aangeroepen omdat we een dalende flank op /STROBE hebben gedetecteerd, stoppen we een timer, wissen de timerwaarde en beginnen met lezen. Als we klaar zijn met lezen starten we de timer weer. Herhaal ad misselijk, of totdat de timer een bepaalde waarde bereikt. Dat betekent dat de laatste interrupt is aangeroepen en er geen gegevens meer zijn binnengekomen, dus we gaan ervan uit dat dit het is en beginnen met het verwerken van de gegevens die we hebben verzameld. Voor timers gebruiken we TIMER1, oftewel de 16-bit timer. Ik gebruik een 16 Mhz resonator extern op mijn AVR. Als je een arduino gebruikt, dan ben je dat waarschijnlijk ook. Dus ik heb een prescaler-waarde van 1024 gekozen, wat betekent dat de timer elke (16 000, 000 / 1024) keer zal toenemen. Dat wil zeggen, het zal 15, 625 keer per seconde 'tikken'. De /CARD_PRESENT wordt HOOG, wat aangeeft dat de kaart de lezer ongeveer 150 ms na de laatste databit heeft verlaten. Dit wetende, besloot ik om ongeveer elke 1/4 van een seconde te controleren. Dat zou er ongeveer zo uitzien:

(((F_CPU) / PRESCALER) / 4) wat ongeveer 3900 blijkt te zijn. Dus als de timerteller TCNT1 3900 bereikt, weet ik dat het ongeveer 300 ms is geweest en kan ik redelijk veilig concluderen dat de kaart de lezer heeft verlaten. Eenvoudig

#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) Je hebt in de ISR gezien waar de timer wordt gestart, gestopt en gewist bij elke interrupt. Nu controleren we in de hoofdlus of de timerteller onze doelwaarde heeft bereikt, en zo ja, start de gegevensverwerking

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

StopTimer(); ClearTimer(); Data verwerken(); LeesData(); idx = 0; beetje = 6; bDataPresent = 0; memset(&buff, 0, MAX_BUFF_SZ1); } } Nu is het veilig om de gegevens te verwerken

code geformatteerd door

Stap 7: Verwerk de gegevens

Verwerk de gegevens
Verwerk de gegevens

Verwerk de gegevens

De verwerkingsfase bestaat uit:

  • controleren op een geldige SS
  • pariteit controleren
  • converteren naar ASCII
  • controleren op een geldige ES
  • LRC. controleren

Hier doe ik geen moeite om de pariteit te controleren, omdat ik dat bit gewoon op nul heb gezet. Ik bereken ook niet de LRC voor deze kleine tutorial. Dat zou iets zijn dat een vollediger gerealiseerde firmware zou willen doen. Hier is de code om de gegevens te verwerken door de bovenstaande stappen uit te voeren (zonder de eerder genoemde). Vind het in de afbeelding hieronder. Het is becommentarieerd en spreekt voor zich. Een speciale opmerking over pariteit en ASCII: ik wis eenvoudig het pariteitsbit (7e bit … dwz een 1 met 6 nullen erachter) en om van "kaartgegevens" te converteren, moet u 0x20 aan de waarde toevoegen. Dat is het zo'n beetje.

Stap 8: Geef de gegevens weer

Geef de gegevens weer
Geef de gegevens weer
Geef de gegevens weer
Geef de gegevens weer

Geef de gegevens weer

Het display gaat naar een terminalprogramma dat ik speciaal heb geschreven voor aansluiting op een AVR via RS232 of USB. Het programma heet AVR Terminal. De ReadData()-methode is behoorlijk lelijk en je wordt aangemoedigd om een schonere oplossing te vinden dan degene die ik heb bedacht. Er is ook een uitvoer van de functie in AVR Terminal. De output is ten eerste van een ziekteverzekeringskaart en de tweede is van een VISA-kaart. Klik op de in de linkerbovenhoek van de afbeelding en kies originele of grote afbeelding om deze beter te zien.

Stap 9: Code downloaden en afronden

In deze instructable heb ik enkele basisprincipes van magnetische kaartlezers besproken en je wat code laten zien om je op weg te helpen in de goede richting bij het lezen van gegevens van magnetische kaarten. Er is nog veel meer werk dat gedaan kan worden, zoals het lezen en decoderen van de 2e track, het berekenen van de LRC en het berekenen van de oneven pariteit op elke byte. De volledige broncode kan hieronder worden gedownload. Het is geschreven in AVR Studio 4.17. Ik hoop dat je deze instructable leuk vond en, zoals altijd, ik kijk uit naar eventuele opmerkingen of suggesties die je hebt. Veel plezier met coderen en AVR'ing!

Aanbevolen: