Innholdsfortegnelse:

Gjør din Arduino til en magnetisk kortleser !: 9 trinn (med bilder)
Gjør din Arduino til en magnetisk kortleser !: 9 trinn (med bilder)

Video: Gjør din Arduino til en magnetisk kortleser !: 9 trinn (med bilder)

Video: Gjør din Arduino til en magnetisk kortleser !: 9 trinn (med bilder)
Video: ESP8266 Беспроводной ЧМИ Nextion || Внешний ПЛК Arduino 2024, November
Anonim
Gjør din Arduino til en magnetisk kortleser!
Gjør din Arduino til en magnetisk kortleser!
Gjør din Arduino til en magnetisk kortleser!
Gjør din Arduino til en magnetisk kortleser!
Gjør din Arduino til en magnetisk kortleser!
Gjør din Arduino til en magnetisk kortleser!

Alle har brukt en magnetisk kortleser, tror jeg. Jeg mener, hvem bærer kontanter i disse dager? De er ikke vanskelige å få tak i heller, og under en tur til min favoritt lokale elektronikkbutikk fant jeg en kasse full av disse gutta. Så … Selvfølgelig hentet jeg en og tok den med hjem for å se hva slags ting jeg kunne gjøre med den og en AVR.

Denne instruksjonen viser deg hvordan du kobler en Magtek magnetisk kortleser til en AVR eller Arduino/klon og leser data fra det første sporet av kort. Spenn setene dine; magnetiske kortlesere har høy bithastighet!

Trinn 1: Utstyrslisten

Utstyrslisten
Utstyrslisten
Utstyrslisten
Utstyrslisten

Her er noen ting du trenger for å komme i gang.

  • Magnetisk kortleser (Mine er en Magetk 90mm dual-head reader. $ 5,00)
  • AVR, Arduino eller klon (ATmega328p ~ $ 4,30 fra Mouser.com
  • loddefritt brødbrett
  • litt ledning
  • kanskje en header hvis du liker den typen ting.
  • noe å lese seriell port. Jeg bruker AVR Terminal fra BattleDroids.net

Det er alt du trenger for å komme i gang. Avhengig av magkortleseren du ender med å få, må du kanskje endre disse instruksjonene, og mest sikkert koden, for å jobbe med din spesifikke leser. Imidlertid bør koden jeg har skrevet, komme deg ganske langt, håper jeg.

Trinn 2: Selvklokkende magnetiske kortlesere

Selvklokkerende magnetiske kortlesere
Selvklokkerende magnetiske kortlesere
Selvklokkerende magnetiske kortlesere
Selvklokkerende magnetiske kortlesere
Selvklokkerende magnetiske kortlesere
Selvklokkerende magnetiske kortlesere
Selvklokkerende magnetiske kortlesere
Selvklokkerende magnetiske kortlesere

Magnetiske kortlesere er "selvklokkerende", noe som betyr at de gir en klokke som kalles en strobe, som den tilkoblede mikrokontrolleren kan synkronisere mot. Dette er en velsignelse. Det betyr at du ikke trenger å bekymre deg for å lete etter et klokkesignal og timing av signalet for å sentrere direkte på klokkepulsen, og at ingen plagsom skal svinge inn i det søte stedet i klokkesignalet. Dette er fornuftig når du tenker på kortsveip: alle sveiper i et annet tempo, noen tregere, noen raskere enn andre. Selvklokking gir selv min søte bestemor muligheten til å bruke kortet sitt uten å bryte håndleddet. Minner meg om å måtte endre innstillingen for henne som bestemmer hvor lang tid som er gyldig mellom klikk for å registrere et dobbeltklikk….

Denne kortleserens data er gyldige 1,0 oss før stroben settes på linjen, så det er ingen bekymring for å forsinke å komme deg inn i "bitetiden". For en leser med to hoder som den jeg bruker, er det to dataspor tilgjengelig for lesing. I denne artikkelen skal jeg vise lesing fra det første første sporet for å komme i gang. Det er fem tilkoblinger du må gjøre (fire hvis du ikke har noe imot å gi opp mer finjustert kontroll for færre I/O -porter som brukes). Sjekk bildet nedenfor. Den røde ledningen går til +5V mens den svarte ledningen går til bakken. Den grønne ledningen er /CARD_PRESENT; den gule ledningen er /STROBE, og den hvite ledningen er /DATA1. Fremover skråstrek (/) betyr at dataene er invertert. Et lavt signal (dvs. 0) leses som et eller høyt. De andre kontaktene er brune for /STROBE2 og oransje for /DATA2. Vi kommer ikke til å bruke disse. Hvis du vil, kan du glemme omtrent /CARD_PRESENT. Denne datalinjen går lavt etter omtrent 17 hodefluksrotasjoner for å indikere at et kort er tilstede (i stedet for, for eksempel, tilfeldig støy som får leseren til å sende falske data) og brukes til å validere at dataene du får er kortdata og ikke søppel. Du kan hoppe over denne tilkoblingen hvis du ser etter startvaktposten i datastrømmen. Mer om det senere. Som du kan se nedenfor, brukte jeg en rett vinkel mannlig overskrift koblet til et brødbrett og koblet leseren min til det. Jeg koblet /STROBE til PIND2 (digital pin 2 på en Arduino), /CARD_PRESENT til PIND3 (for illustrasjonsformål), og /DATA1 til PIND4. Sørg for at du aktiverer pullups på disse pinnene, slik at pinnene ikke flyter. Jeg byttet også ut min Arduino for en Bare Bones AVR fordi jeg liker måten den passer inn i brødbrettet.

Trinn 3: Grunnleggende om magnetisk kort

Grunnleggende om magnetisk kort
Grunnleggende om magnetisk kort

De viktigste funksjonene du må gjøre for å lese et magnetisk kort er: 1. Oppdag når kortet har blitt sveipet 2. Les datastrømmen 3. Oppdag når kortet har gått 4. Behandle dataene 5. Vis data Først vil jeg introdusere deg for noen grunnleggende magnetiske kort som du må vite når du begynner å skrive din egen kode.

Magnetiske kortstandarder

Magnetiske kort er standardisert av ISO i følgende dokumenter: 7810 Fysiske egenskaper ved kredittkortstørrelsesdokument 7811-1 Embossing 7811-2 Magnetisk stripe-lav coercivity 7811-3 Plassering av pregede tegn 7811-4 Plassering av spor 1 & 2 7811- 5 Plassering av spor 3 7811-6 Magnetisk stripe - høy coercivity 7813 Finansielle transaksjonskort Som du kan se er finansielle kort spesifisert i et eget dokument og har ofte andre formater enn, for eksempel, dagligvarekortet ditt eller internasjonale telefonkort. Du må programmere for disse forskjellene. Jeg hadde nettopp et kredittkort og forsikringskort tilgjengelig, så jeg programmerte for disse typene (som begge tilfeldigvis var format B).

Kortformater

Det finnes flere forskjellige formater for magnetkort. Format A og B er vanlige, med B som det vanligste jeg har sett, og som støttes i denne koden. Format C til M er reservert av ISO, tror jeg, mens N til ?? er forbeholdt institusjonell tilpasset bruk. Spor 1 For finansielle kort registreres det første sporet med 210 bits per tomme og er det første 0.110 "på kortet fra toppen. Dataene er kodet som" kortdata "som 7-bits per tegn. Det er 6-bits for karakteren og litt for paritet. Det er ~ 79 alfanumeriske tegn på spor 1. Den fysiske rekkefølgen er bakover. Det vil si at data er, men det er skrevet bakover på kortet (og vil derfor bli lest av fastvaren) som. paritet er merkelig. Kortdataformatet ser slik ut:

[SS] [FC] [Primær konto #] [FS] [Navn] [FS] [Tilleggsdata] [FS] [ES] [LRC] der:

SS Startvakt FC -formatkode FS Feltutskiller ES Sluttvakt LRC Langsgående redundans Kontroller tegn Spor en SS = '%', FC = et av formatene (kommer til å være B mange ganger), FS er ofte '', ES er '?' og LRC -tegnet er vanligvis '<', selv om det ikke er spesifisert i standardene. I tillegg til at de er skrevet på kortet bakover, har dataene en merkelig paritetsbit og er 0x20 fra ASCII. Vi håndterer dette når vi behandler dataene. Spor 2 Spor to er 0.110 "bredt og starter 0.110 fra toppen av kortet. Opptakstettheten er 75 bits per tomme. Dataene er 5-bits per tegn og består bare av rundt 40 numeriske symboler. Du bør ikke støte på noen bokstaver på dette sporet. Kortdataformatet bør følge denne strukturen

[SS] [primær konto #] [FS] [tilleggsdata | skjønnsmessige data] [ES] [LRC]

SS for spor to er semikolon: ';' og FS er '=' Med denne hellige kunnskapen under beltet, fortsett til de neste trinnene for å se kode som implementerer prosedyren som er beskrevet ovenfor.

Trinn 4: Finn ut når et kort er sveipet

Oppdag når et kort er sveipet
Oppdag når et kort er sveipet

1. Oppdag når et kort har blitt sveipet Formelt ville man sjekke /CARD_PRESENT -pinnen for å se om det har falt lavt. Heldigvis er dette egentlig ikke nødvendig. Vi ser etter gyldig kort senere. Alternativt kan du lese strobe -pinnen din for å se når strober er satt på pinnen, men dette vil gi deg mange klokkende nuller. Leseren vil sende omtrent 60-70 ledende nuller for å fortelle deg at data er i ferd med å bli presentert. Imidlertid skal vi bruke arten av binære data til å bestemme når vi skal begynne å spille inn biter. Startvaktmesteren (SS) for spor ett er prosenttegnet (%). Den binære verdien er 0010 0101, noe som betyr at den vil bli lagret (og lest) som 1010 001 (den er 7-bits, så den 8. biten blir ikke overført). Nå vil den flinke leseren legge merke til at selv om dataene er baklengs, samsvarer de ikke med den binære ASCII -verdien. Det er fordi det er 0x20 av hex. % -Symbolet er 0x25 og 0100 0101 er 0x05. Kortdata har 0x20 trukket fra verdien. Den som henger der ute i den høye nibble er den rare paritetsbiten. Det er satt der slik at det er et oddetall av "1" s i verdien. Så fordi vi vet at et gyldig kort alltid vil starte med denne startvaktmesteren, og fordi paritetsbiten er en 1, så når vi oppdager den første HØY til LAV -overgangen på datapinnen, så vet vi at vi nettopp har begynt å motta start vaktpost fra et kort. Dette kommer ikke alltid til å være sant, og en idiotsikker plan ville være å sjekke /CARD_PRESENT -kortet for å se om det har gått LOW i tillegg. Den enkleste måten å oppdage starten på SS, er å lage et eksternt avbrudd utløst på den fallende kanten av /STROBE. Dataene er gyldige 1,0 oss før fallkanten, så når du har samplet den fallende kanten, vet du at du kan lese /DATA1 -pinnen og få en gyldig verdi. Her er koden for å lage ditt eksterne avbrudd utløst på en fallende kant.

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

I min common.h som jeg inkluderer i alle programmene mine, kan definisjonene av BSET og BCLR bli funnet. Se den filen hvis du har spørsmål om hvordan du setter biter. Nå, når avbruddet utløses, vil vi prøve /DATA1 (i koden min definert som CARD_DATA) og sette litt i et IO -register for generelle formål. Hvis vi er på den 7. biten, lagrer du registeret som et tegn i vår globale buffer. Jeg bruker et GPIOR0 -register fordi det er rask tilgang. Pseudokoden er omtrent slik:

Stop 16-bit timer Timer Clear Timer Hvis DATA er LOW Sett BIT = 1 i REGISTER Dekrement BIT Angi flagg slik at vi ikke hopper over flere 0-er ellers DATA er HØY Sett BIT = 0 i REGISTER Reduser BIT Hvis BIT er 0 Legg byte til buffer Økningsindeks Tilbakestill BIT

Hvis du spør deg selv hvorfor dekrement i stedet for inkrement, husk at dataene er bakover, så i stedet for å registrere bitene mens vi får dem fra LSB til MSB, lagrer vi dem fra MSB til LSB, slik at vi ikke trenger å reversere bitene senere ved behandling av dataene. Hvis du virkelig ville, kan du også legge til 0x20 hex her, men siden det er omtrent 5us på disse strober, holder jeg behandlingen i denne avbruddsrutinen til et minimum.

ISR (INT0_vect) {StopTimer (); ClearTimer (); hvis (! BCHK (PIND, CARD_DATA1)) // invers lav = 1 {BSET (GPIOR0, bit); --bit; bDataPresent = 1; } annet hvis (bDataPresent) {BCLR (GPIOR0, bit); --bit; } hvis (bit <0) {buff [idx] = (char) GPIOR0; ++ idx; bit = 6; } StartTimer ();} Hvis du lurer på hva timingsvirksomheten handler om, er det dekket i trinnet for å bestemme når kortet har forlatt leseren.

Trinn 5: Les datastrømmen

Les datastrømmen

Vel, jeg har allerede vist deg hvordan du leser dataene, ettersom det er en del av Interrupt Service Routine for vårt fallende eksterne avbrudd. En alternativ metode ville være å sette et flagg i ISR, og i hovedløkken avstemme flagget og lese dataene på den måten, men jeg tror måten jeg har presentert det på er renere. Vær din egen dommer og skriv din, men MCU -en din tillater det. Når det er sagt, la oss gå videre til å finne ut hvordan du kan oppdage når kortet trekker en Elvis og har forlatt bygningen.

Trinn 6: Finn ut kortet som forlater leseren

Finn kortet som forlater leseren
Finn kortet som forlater leseren

Oppdag når et kort har gått

Formelt sett ville man prøve /CARD_PRESENT -pinnen for å se om den har gått HIGH igjen, men vi trenger ikke at noen steenkin /CARD_PRESENT tar en annen I /O -port. Det er her timerne kommer inn. Hver gang avbruddet kalles fordi vi har oppdaget en fallende kant på /STROBE, stopper vi en tidtaker, sletter tidtakerverdien og begynner å lese. Når vi er ferdig med å lese, starter vi timeren igjen. Gjenta ad nauseum, eller til timeren når en viss verdi. Det betyr at det siste avbruddet har blitt kalt og ingen flere data har kommet inn, så vi antar at det er det og begynner å behandle dataene vi har samlet inn. For tidtakere bruker vi TIMER1, det vil si 16-biters timeren. Jeg bruker en 16 Mhz resonator eksternt til min AVR. Hvis du bruker en arduino, er du sannsynligvis det også. Så jeg har valgt en forkalkingsverdi på 1024, noe som betyr at hver (16.000, 000 /1024) ganger timeren vil øke. Det vil si at den vil "krysse av" 15, 625 ganger i sekundet. /CARD_PRESENT vil gå HØY for å indikere at kortet har forlatt leseren omtrent 150 ms etter den siste databiten. Da jeg visste dette, bestemte jeg meg for å sjekke omtrent hvert 1/4 av sekund. Det ville se omtrent slik ut:

(((F_CPU) / PRESCALER) / 4) som viser seg å være rundt 3900. Så, når tidtelleren TCNT1 når 3900, så vet jeg at det har gått omtrent 300 ms, og jeg kan ganske trygt konkludere med at kortet har forlatt leseren. Lett

#define PRESCALER 1024#definere CHECK_TIME ((F_CPU / PRESCALER) / 4) // 250 ms#definere StartTimer () BSET (TCCR1B, CS10), BSET (TCCR1B, CS12) // 1024 forhåndskalender#definere StopTimer () BCLR (TCCR1B, CS10), BCLR (TCCR1B, CS12) #define ClearTimer () (TCNT1 = 0) Du har sett i ISR hvor timeren startes, stoppes og slettes ved hver avbrudd. Nå, i hovedsløyfen sjekker vi bare for å se om tidtelleren har nådd vår målverdi, og i så fall starter vi databehandlingen

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

StopTimer (); ClearTimer (); ProcessData (); ReadData (); idx = 0; bit = 6; bDataPresent = 0; memset (& buff, 0, MAX_BUFF_SZ1); }} Nå er det trygt å behandle dataene

kode formatert av

Trinn 7: Behandle dataene

Behandle dataene
Behandle dataene

Behandle dataene

Behandlingsfasen består av:

  • se etter en gyldig SS
  • sjekke paritet
  • konvertere til ASCII
  • se etter et gyldig ES
  • sjekker LRC

Her gidder jeg ikke å sjekke paritet, da jeg bare satte den biten til null. Jeg beregner heller ikke LRC for denne lille opplæringen. Det ville være noe en mer fullt realisert fastvare kanskje vil gjøre. Her er koden for å behandle dataene som gjør trinnene ovenfor (sans de tidligere nevnte). Finn det på bildet nedenfor. Det er kommentert og ganske selvforklarende. En spesiell merknad om paritet og ASCII: Jeg fjerner ganske enkelt paritetsbiten (7. bit … dvs. en 1 med 6 nuller bak) og for å konvertere fra "kortdata" må du legge til 0x20 til verdien. Det er omtrent det.

Trinn 8: Vis dataene

Vis dataene
Vis dataene
Vis dataene
Vis dataene

Vis dataene

Displayet går til et terminalprogram jeg skrev spesielt for å koble til en AVR via RS232 eller USB. Programmet kalles AVR Terminal. ReadData () -metoden er ganske stygg, og du oppfordres til å finne en renere løsning enn den jeg kom på. Det er også en utgang av funksjonen i AVR Terminal. Utgangen er først av et helseforsikringskort, og den andre er av et VISA -kort. Klikk på i øvre venstre hjørne av bildet og velg original eller stort bilde for å se det bedre.

Trinn 9: Nedlasting og pakking av kode

I denne instruksen har jeg diskutert noen grunnleggende om magnetiske kortlesere og vist deg noen kode for å komme i gang i riktig retning med å lese data fra magnetkort. Det er mye mer arbeid som kan gjøres, for eksempel å lese og dekode det andre sporet, beregne LRC og beregne oddetall på hver byte. Full kildekoden er tilgjengelig for nedlasting nedenfor. Den ble skrevet i AVR Studio 4.17. Jeg håper du likte dette lærerikt, og som alltid gleder jeg meg til eventuelle kommentarer eller forslag du måtte ha. God koding og AVR'ing!

Anbefalt: