Innehållsförteckning:

Förvandla din Arduino till en magnetisk kortläsare !: 9 steg (med bilder)
Förvandla din Arduino till en magnetisk kortläsare !: 9 steg (med bilder)

Video: Förvandla din Arduino till en magnetisk kortläsare !: 9 steg (med bilder)

Video: Förvandla din Arduino till en magnetisk kortläsare !: 9 steg (med bilder)
Video: #3 Hur man programmerar Outseal Arduino PLC - Kontakter och reläer 2024, November
Anonim
Förvandla din Arduino till en magnetisk kortläsare!
Förvandla din Arduino till en magnetisk kortläsare!
Förvandla din Arduino till en magnetisk kortläsare!
Förvandla din Arduino till en magnetisk kortläsare!
Förvandla din Arduino till en magnetisk kortläsare!
Förvandla din Arduino till en magnetisk kortläsare!

Alla har använt en magnetisk kortläsare, tror jag. Jag menar, vem bär på kontanter nuförtiden? De är inte heller svåra att få tag på, och under en resa till min favorit lokala elektronikbutik hittade jag en papperskorg full av dessa killar. Så…. Jag hämtade självklart en och tog hem den för att se vad jag kunde göra med den och en AVR.

Denna instruktör visar dig hur du ansluter en Magtek magnetisk kortläsare till en AVR eller Arduino/klon och läser data från det första spåret på kortet. Spänn dina säten; magnetiska kortläsare har en hög bithastighet!

Steg 1: Utrustningslistan

Utrustningslistan
Utrustningslistan
Utrustningslistan
Utrustningslistan

Här är några saker du behöver för att komma igång.

  • Magnetisk kortläsare (Min är en Magetk 90 mm dubbelhuvudläsare. $ 5,00)
  • AVR, Arduino eller klon (ATmega328p ~ $ 4,30 från Mouser.com
  • lödlös brödbräda
  • lite tråd
  • kanske en rubrik om du gillar den sorten.
  • något att läsa din seriella port. Jag använder AVR Terminal från BattleDroids.net

Det är allt du behöver för att komma igång. Beroende på vilken magkortläsare du får får du kanske behöva ändra dessa instruktioner, och mest säkert koden, för att arbeta med din specifika läsare. Men koden jag har skrivit borde komma dig ganska långt, hoppas jag.

Steg 2: Självklockande magnetiska kortläsare

Självklockande magnetiska kortläsare
Självklockande magnetiska kortläsare
Självklockande magnetiska kortläsare
Självklockande magnetiska kortläsare
Självklockande magnetiska kortläsare
Självklockande magnetiska kortläsare
Självklockande magnetiska kortläsare
Självklockande magnetiska kortläsare

Magnetiska kortläsare är "självklockande", vilket innebär att de tillhandahåller en klocka som kallas en strobe, mot vilken den anslutna mikrokontrollern kan synkronisera. Detta är en välsignelse. Det betyder att du inte behöver oroa dig för att leta efter en klocksignal och tajma signalen för att centrera direkt på klockpulsen, och ingen störande oscillerar in i klocksignalens sötpunkt. Det här är vettigt när du tänker på kortsvepningar: alla sveper i en annan takt, vissa långsammare, vissa snabbare än andra. Självklockning gör att även min söta mormor kan använda sitt kort utan att bryta handleden. Påminner mig om att behöva ändra inställningen för henne som avgör hur lång tid som gäller mellan klick för att registrera ett dubbelklick ….

Denna kortläsares data är giltiga 1,0 oss innan stroben sätts på linjen, så det finns ingen oro för att dröja för att komma in i "bettiden". För en dubbelhuvudläsare som den jag använder finns det två dataspår att läsa. I den här artikeln kommer jag att visa läsning från det första första spåret för att komma igång. Det finns fem anslutningar du måste göra (fyra om du inte har något emot att ge upp mer finjusterad kontroll för färre I/O -portar som används). Kolla in bilden nedan. Den röda tråden går till +5V medan den svarta tråden går till marken. Den gröna tråden är /CARD_PRESENT; den gula tråden är /STROBE, och den vita tråden är /DATA1. Snedstrecket (/) betyder att data är inverterade. En låg signal (dvs. 0) läses som en eller hög. De andra kontakterna är bruna för /STROBE2 och orange för /DATA2. Vi kommer inte att använda dessa. Om du vill kan du glömma /CARD_PRESENT. Denna datalinje går låg efter cirka 17 huvudflödesrotationer för att indikera att ett kort är närvarande (istället för, till exempel, slumpmässigt brus som får din läsare att skicka falska data) och används för att validera att data du får är kortdata och inte skrot. Du kan hoppa över denna anslutning om du söker efter startvakt i dataströmmen. Mer om det senare. Som du kan se nedan använde jag en rätvinklig manlig header ansluten till ett brödbräda och kopplade min läsare till den. Jag kopplade /STROBE till PIND2 (digital pin 2 på en Arduino), /CARD_PRESENT till PIND3 (för illustration) och /DATA1 till PIND4. Se till att du aktiverar pullups på dessa stift så att dina stift inte flyter. Jag bytte också ut min Arduino för en Bare Bones AVR eftersom jag gillar hur den passar in i brödbrädan.

Steg 3: Grundläggande om magnetkort

Magnetiska kortgrunder
Magnetiska kortgrunder

De primära funktionerna du behöver göra för att läsa ett magnetkort är: 1. Upptäck när kortet har svepts 2. Läs dataströmmen 3. Upptäck när kortet har gått 4. Bearbeta data 5. Visa data Först ska jag presentera dig för några grundläggande magnetiska kort som du måste veta när du börjar skriva din egen kod.

Magnetiska kortstandarder

Magnetkort är standardiserade av ISO i följande dokument: 7810 Fysiska egenskaper hos kreditkortsstorleksdokument 7811-1 Prägling 7811-2 Magnetremsa-låg coercivity 7811-3 Placering av präglade tecken 7811-4 Placering av spår 1 & 2 7811- 5 Placering av spår 3 7811-6 Magnetband - hög coercivity 7813 Finansiella transaktionskort Som du kan se är finansiella kort specificerade i ett separat dokument och har ofta andra format än, till exempel, ditt livsmedelskort eller internationella telefonkort. Du måste programmera för dessa skillnader. Jag hade precis ett kreditkort och försäkringskort till hands, så jag programmerade för dessa typer (som båda råkar vara format B).

Kortformat

Det finns flera olika format för magnetkort. Format A och B är vanliga, med B är det vanligaste jag har sett, och som stöds i denna kod. Format C till M är reserverade av ISO, tror jag, medan N till ?? är reserverade för institutionell anpassad användning. Spår 1 För finansiella kort spelas det första spåret in med 210 bitar per tum och är det första 0.110 "på kortet uppifrån. Data kodas som" kortdata "som 7-bitar per tecken. Det är 6-bitar för karaktären och lite för paritet. Det finns ~ 79 alfanumeriska tecken på spår 1. Den fysiska ordningen är bakåt. Det vill säga, data är men det är skrivet bakåt på kortet (och kommer därför att läsas av din firmware) som. paritet är udda. Kortdataformatet ser ut så här:

[SS] [FC] [Primärkonto #] [FS] [Namn] [FS] [Ytterligare data] [FS] [ES] [LRC] där:

SS Startvakt FC Formatkod FS Fältavskiljare ES Sändvakt LRC Längsgående redundans Kontrollera tecken Spåra en SS = '%', FC = ett av formaten (kommer att vara B många gånger), FS är ofta '', ES är '?' och LRC -tecknet är vanligtvis '<' även om det inte anges i standarderna. Förutom att de skrivs på kortet bakåt har data en udda paritetsbit och är 0x20 från ASCII. Vi kommer att hantera detta när vi behandlar data. Spår 2 Spår två är 0.110 "brett och börjar 0.110 från toppen av kortet. Inspelningstätheten är 75 bitar per tum. Data är 5-bitar per tecken och består endast av cirka 40 numeriska symboler. Du bör inte stöta på några bokstäver på detta spår. Kortdataformatet bör följa denna struktur

[SS] [primärkonto #] [FS] [ytterligare data | diskretionära data] [ES] [LRC]

SS för spår två är semikolon: ';' och FS är '=' Med denna heliga kunskap under ditt bälte, fortsätt till nästa steg för att se kod som implementerar proceduren som beskrivs ovan.

Steg 4: Upptäck när ett kort sveps

Upptäck när ett kort är svept
Upptäck när ett kort är svept

1. Upptäck när ett kort har svept Formellt skulle man kontrollera /CARD_PRESENT -stiftet för att se om det har sjunkit lågt. Lyckligtvis är detta verkligen inte nödvändigt. Vi kommer att kontrollera om det är giltigt kort senare. Alternativt kan du läsa din strobstift för att se när strober har satts på stiftet, men detta kommer att ge dig massor av klockande nollor. Läsaren skickar cirka 60-70 ledande nollor för att meddela dig att data är på väg att presenteras. Vi kommer dock att använda naturen av binära data för att avgöra när vi ska börja spela in bitar. Startvaktmästaren (SS) för spår ett är procenttecknet (%). Det binära värdet är 0010 0101 vilket betyder att det kommer att lagras (och läsas) som 1010 001 (det är 7-bitar så den 8: e biten överförs inte). Nu kommer den kloka läsaren att märka att även om data ligger bakåt matchar det inte det binära ASCII -värdet. Det beror på att det är 0x20 av hex. % -Symbolen är 0x25 och 0100 0101 är 0x05. Kortdata har 0x20 subtraherats från värdet. Den som hänger där ute i den höga nibble är den udda paritetsbiten. Det sätts dit så att det finns ett udda antal "1" i värdet. Så eftersom vi vet att ett giltigt kort alltid kommer att börja med denna startvakt, och eftersom paritetsbiten är en 1, när vi upptäcker den första övergången HÖG till LÅG på datapinnen, då vet vi att vi precis har börjat ta emot starta vaktpost från ett kort. Nu kommer detta inte alltid att stämma, och en idiotsäker plan skulle vara att kontrollera /CARD_PRESENT -kortet för att se om det har gått LÅGT dessutom. Det enklaste sättet att upptäcka starten av SS är att skapa ett externt avbrott som utlöses på den nedåtgående kanten av /STROBE. Uppgifterna är giltiga 1,0 oss före den fallande kanten, så när du har samplat den fallande kanten vet du att du kan läsa /DATA1 -stiftet och få ett giltigt värde. Här är koden för att skapa ditt externa avbrott utlöst på en fallande kant.

voidInitInterrupt (void) {// Setup interrupt BSET (EIMSK, INT0); // extern avbrottsmask BSET (EICRA, ISC01); // fallande kant BCLR (EICRA, ISC00); // fallande kant BSET (SREG, 7); // I-bit i SREG}

I min vanliga. H som jag inkluderar i alla mina program, finns definitionerna av BSET och BCLR. Se den filen om du har några frågor om hur du ställer in bitar. Nu, när avbrottet utlöses, vill vi prova /DATA1 (i min kod definierad som CARD_DATA) och ställa in lite i ett IO -register för allmänna ändamål. Om vi är på den 7: e biten, spara av registret som ett tecken i vår globala buffert. Jag använder ett GPIOR0 -register eftersom det är snabb åtkomst. Pseudokoden är ungefär så här:

Stoppa 16-bitars timer Rensa timer Om DATA är LÅG Ställ in BIT = 1 i REGISTER Minska BIT Ställ in flagga så att vi inte hoppar över fler 0: or annars DATA är HÖG Ställ in BIT = 0 i REGISTER Minska BIT Om BIT är 0 Lägg byte till buffert Ökningsindex Återställ BIT

Om du frågar dig själv varför minska i stället för att öka, kom ihåg att data är bakåt, så istället för att spela in bitarna när vi får dem från LSB till MSB, sparar vi dem från MSB till LSB så att vi inte behöver vända bitarna senare vid behandling av uppgifterna. Om du verkligen ville kan du också lägga till 0x20 hex här, men eftersom det handlar om 5us på dessa strober håller jag behandlingen i denna avbrottsrutin till ett minimum.

ISR (INT0_vect) {StopTimer (); ClearTimer (); om (! BCHK (PIND, CARD_DATA1)) // invers låg = 1 {BSET (GPIOR0, bit); --bit; bDataPresent = 1; } annars if (bDataPresent) {BCLR (GPIOR0, bit); --bit; } if (bit <0) {buff [idx] = (char) GPIOR0; ++ idx; bit = 6; } StartTimer ();} Om du undrar vad timingsverksamheten handlar om, är det täckt i steget för att bestämma när kortet har lämnat läsaren.

Steg 5: Läs dataströmmen

Läs dataströmmen

Tja, jag har redan visat dig hur du läser data, eftersom det är en del av Interrupt Service Routine för vårt fallande externa avbrott. En alternativ metod skulle vara att sätta en flagga i ISR, och i huvudslingan undersöka flaggan och läsa data på det sättet, men jag tror att sättet jag har presenterat det är renare. Var din egen domare och skriv din men din MCU tillåter det. Som sagt, låt oss gå vidare för att ta reda på hur man upptäcker när kortet drar en Elvis och har lämnat byggnaden.

Steg 6: Upptäck kortet som lämnar läsaren

Upptäck kortet som lämnar läsaren
Upptäck kortet som lämnar läsaren

Upptäck när ett kort har försvunnit

Formellt skulle man prova /CARD_PRESENT -stiftet för att se om det har gått HIGH igen, men vi behöver ingen steenkin /CARD_PRESENT som tar upp en annan I /O -port. Det är här dessa timers kommer in. Varje gång avbrottet anropas eftersom vi har upptäckt en fallande kant på /STROBE, stoppar vi en timer, rensar timervärdet och börjar läsa. När vi har läst klart startar vi timern igen. Upprepa ad nauseum, eller tills timern når ett visst värde. Det betyder att det senaste avbrottet har anropats och att inga fler data har kommit in, så vi antar att det är det och börjar bearbeta data vi har samlat in. För timers använder vi TIMER1, dvs 16-bitars timern. Jag använder en 16 Mhz resonator externt till min AVR. Om du använder en arduino, så är du förmodligen också. Så jag har valt ett förkalkningsvärde på 1024 vilket innebär att varje (16 000, 000 /1024) gånger timern ökar. Det vill säga, det kommer att "ticka" 15, 625 gånger i sekunden. /CARD_PRESENT går HÖG för att indikera att kortet har lämnat läsaren cirka 150 ms efter den senaste databiten. När jag visste detta bestämde jag mig för att kolla ungefär var 1/4 sekund. Det skulle se ut ungefär så här:

(((F_CPU) / PRESCALER) / 4) vilket visar sig vara runt 3900. Så, när timermätaren TCNT1 når 3900, då vet jag att det har gått cirka 300 ms och jag kan ganska säkert dra slutsatsen att kortet har lämnat läsaren. Lätt

#define PRESCALER 1024#definiera CHECK_TIME ((F_CPU / PRESCALER) / 4) // 250 ms#definiera StartTimer () BSET (TCCR1B, CS10), BSET (TCCR1B, CS12) // 1024 förskalare#definiera StopTimer () BCLR (TCCR1B, CS10), BCLR (TCCR1B, CS12) #define ClearTimer () (TCNT1 = 0) Du har sett i ISR där timern startas, stoppas och rensas vid varje avbrott. Nu, i huvudslingan kontrollerar vi bara om timräknaren har nått vårt målvärde, och i så fall startar vi databehandlingen

för (;;) {if (TCNT1> = CHECK_TIME) {

StopTimer (); ClearTimer (); ProcessData (); ReadData (); idx = 0; bit = 6; bDataPresent = 0; memset (& buff, 0, MAX_BUFF_SZ1); }} Nu är det säkert att bearbeta data

kod formaterad av

Steg 7: Bearbeta data

Behandla upterna
Behandla upterna

Behandla uppgifterna

Behandlingsfasen består av:

  • söker efter ett giltigt SS
  • kontrollera paritet
  • konvertera till ASCII
  • söker efter ett giltigt ES
  • kontrollera LRC

Här bryr jag mig inte om att kontrollera paritet, eftersom jag bara satte den biten till noll. Jag beräknar inte heller LRC för denna lilla handledning. Det skulle vara något som en mer fullt realiserad firmware kanske vill göra. Här är koden för att bearbeta data som gör ovanstående steg (sans det tidigare nämnda). Hitta den i bilden nedan. Det är kommenterat och ganska självförklarande. En särskild anteckning om paritet och ASCII: Jag rensar helt enkelt paritetsbiten (7: e bit … dvs en 1 med 6 nollor bakom) och för att konvertera från "kortdata" måste du lägga till 0x20 till värdet. Det är ungefär det.

Steg 8: Visa data

Visa data
Visa data
Visa data
Visa data

Visa data

Displayen går till ett terminalprogram jag skrev speciellt för att ansluta till en AVR via RS232 eller USB. Programmet kallas AVR Terminal. ReadData () -metoden är ganska ful och du uppmuntras att hitta en renare lösning än den jag kom på. Det finns också en utmatning av funktionen i AVR Terminal. Utmatningen är först av ett sjukförsäkringskort, och den andra är av ett VISA -kort. Klicka på i det övre vänstra hörnet av bilden och välj original eller stor bild för att se den bättre.

Steg 9: Kodnedladdning och omslutning

I denna instruerbara har jag diskuterat några grunderna för magnetkortläsare och visat dig lite kod för att komma igång i rätt riktning när det gäller att läsa data från magnetkort. Det finns mycket mer arbete som kan göras, till exempel att läsa och avkoda det andra spåret, beräkna LRC och beräkna udda pariteten på varje byte. Hela källkoden finns tillgänglig för nedladdning nedan. Det skrevs i AVR Studio 4.17. Jag hoppas att du njöt av detta instruerbara och som alltid ser jag fram emot alla kommentarer eller förslag som du kan ha. Glad kodning och AVR'ing!

Rekommenderad: