Índice:

Transforme seu Arduino em um leitor de cartão magnético !: 9 etapas (com imagens)
Transforme seu Arduino em um leitor de cartão magnético !: 9 etapas (com imagens)

Vídeo: Transforme seu Arduino em um leitor de cartão magnético !: 9 etapas (com imagens)

Vídeo: Transforme seu Arduino em um leitor de cartão magnético !: 9 etapas (com imagens)
Vídeo: Como abrir sua porta com o cartão do ônibus #ManualMaker Aula 8, Vídeo 2 2024, Junho
Anonim
Transforme seu Arduino em um leitor de cartão magnético!
Transforme seu Arduino em um leitor de cartão magnético!
Transforme seu Arduino em um leitor de cartão magnético!
Transforme seu Arduino em um leitor de cartão magnético!
Transforme seu Arduino em um leitor de cartão magnético!
Transforme seu Arduino em um leitor de cartão magnético!

Todo mundo já usou um leitor de cartão magnético, acredito. Quer dizer, quem anda com dinheiro hoje em dia? Eles também não são difíceis de obter e, durante uma viagem à minha loja de eletrônicos local favorita, encontrei uma lixeira cheia desses caras. Então … é claro, peguei um e trouxe para casa para ver o que tipo de coisas eu poderia fazer com ele e um AVR.

Este instrutível mostrará como conectar um leitor de cartão magnético Magtek a um AVR ou Arduino / clone e ler os dados da primeira faixa do cartão. Apertem seus assentos; leitores de cartão magnético têm uma alta taxa de bits!

Etapa 1: A lista de equipamentos

A Lista de Equipamentos
A Lista de Equipamentos
A Lista de Equipamentos
A Lista de Equipamentos

Aqui estão algumas coisas que você precisa para começar.

  • Leitor de cartão magnético (o meu é um leitor de cabeça dupla Magetk 90 mm. US $ 5,00)
  • AVR, Arduino ou clone (ATmega328p ~ $ 4,30 da Mouser.com
  • placa de ensaio sem solda
  • algum fio
  • talvez um cabeçalho, se você gosta desse tipo de coisa.
  • algo para ler sua porta serial. Eu uso o Terminal AVR do BattleDroids.net

É tudo de que você precisa para começar. Dependendo do leitor de magcard que você acabar recebendo, pode ser necessário modificar essas instruções, e com certeza o código, para trabalhar com seu leitor específico. No entanto, o código que escrevi deve levar você muito longe, espero.

Etapa 2: leitores de cartão magnético com temporização automática

Leitores de cartão magnético com temporização automática
Leitores de cartão magnético com temporização automática
Leitores de cartão magnético com temporização automática
Leitores de cartão magnético com temporização automática
Leitores de cartão magnético com temporização automática
Leitores de cartão magnético com temporização automática
Leitores de cartão magnético com temporização automática
Leitores de cartão magnético com temporização automática

Os leitores de cartão magnético são "auto-sincronizados", o que significa que fornecem um relógio chamado strobe, com o qual o microcontrolador conectado pode sincronizar. Esta é uma benção. Isso significa que você não precisa se preocupar em procurar um sinal de clock e cronometrar o sinal para centralizar diretamente no pulso do clock, e sem a incômoda oscilação no ponto ideal do sinal do clock. Isso faz sentido quando você pensa em furtos de cartão: todos passam em um ritmo diferente, alguns mais devagar, alguns mais rápidos do que outros. O autotemporizador permite que até a minha doce avó possa usar seu cartão sem quebrar o pulso. Me lembra de ter que alterar a configuração para ela que determina quanto tempo é válido entre os cliques para registrar um clique duplo….

Os dados deste leitor de cartão são válidos 1,0 us antes que o estroboscópio seja colocado na linha, portanto, não há preocupação em atrasar-se para entrar no "tempo de bits". Para um leitor de duas cabeças como o que estou usando, há duas faixas de dados disponíveis para leitura. Neste capítulo, vou mostrar a leitura da primeira faixa principal para você começar. Há cinco conexões que você precisa fazer (quatro, se você não se importar em desistir de um controle mais ajustado para menos portas de E / S sendo usadas). Observe a imagem abaixo. O fio vermelho vai para + 5V enquanto o fio preto vai para o aterramento. O fio verde é / CARD_PRESENT; o fio amarelo é / STROBE e o fio branco é / DATA1. A barra (/) significa que os dados estão invertidos. Um sinal baixo (ou seja, 0) é lido como um ou alto. Os outros conectores são marrons para / STROBE2 e laranja para / DATA2. Não vamos usar isso. Se você quiser, pode esquecer / CARD_PRESENT. Esta linha de dados fica baixa após cerca de 17 rotações de fluxo de cabeça para indicar que um cartão está presente (em vez de, digamos, ruído aleatório que faz com que seu leitor envie dados falsos) e é usada para validar que os dados que você está recebendo são dados do cartão e não lixo. Você pode pular esta conexão se verificar a sentinela de início no fluxo de dados. Mais sobre isso mais tarde. Como você pode ver abaixo, usei um cabeçalho macho de ângulo reto conectado a uma placa de pão e conectei meu leitor a ela. Eu conectei / STROBE ao PIND2 (pino digital 2 em um Arduino), / CARD_PRESENT ao PIND3 (para fins ilustrativos) e / DATA1 ao PIND4. Certifique-se de habilitar pullups nesses pinos para que eles não flutuem. Também troquei meu Arduino por um AVR Bare Bones porque gosto da maneira como ele se encaixa na placa de ensaio.

Etapa 3: Noções básicas do cartão magnético

Noções básicas de cartão magnético
Noções básicas de cartão magnético

As funções principais que você precisa fazer para ler um cartão magnético são: 1. Detectar quando o cartão foi passado 2. Ler o fluxo de dados 3. Detectar quando o cartão foi embora 4. Processar os dados 5. Exibir o dados Em primeiro lugar, apresentarei a você alguns princípios básicos do cartão magnético que você precisará saber quando começar a escrever seu próprio código.

Padrões de cartão magnético

Os cartões magnéticos são padronizados pela ISO nos seguintes documentos: 7810 Características físicas do documento de tamanho de cartão de crédito 7811-1 Gravação 7811-2 Faixa magnética - baixa coercividade 7811-3 Localização dos caracteres em relevo 7811-4 Localização das trilhas 1 e 2 7811- 5 Localização do trilho 3 7811-6 Faixa magnética - alta coercividade 7813 Cartões de transações financeiras Como você pode ver, os cartões financeiros são especificados em um documento separado e geralmente têm formatos diferentes, digamos, de cartão de supermercado ou cartão de chamadas internacionais. Você terá que programar para essas diferenças. Eu tinha um cartão de crédito e um cartão de seguro em mãos, então programei para esses tipos (que por acaso são ambos do formato B).

Formatos de cartão

Existem vários formatos diferentes de cartões magnéticos. Os formatos A e B são comuns, sendo B o mais comum que já vi e que é compatível com este código. Os formatos C a M são reservados pela ISO, creio eu, enquanto N a ?? são reservados para uso personalizado institucional. Faixa 1 Para cartões financeiros, a primeira faixa é gravada em 210 bits por polegada e é o primeiro 0,110 "do cartão a partir da parte superior. Os dados são codificados como" dados do cartão "como 7 bits por caractere. Isso é 6 bits para o caractere e um pouco para a paridade. Existem cerca de 79 caracteres alfanuméricos na trilha 1. A ordem física está ao contrário. Ou seja, os dados estão escritos ao contrário no cartão (e, portanto, serão lidos pelo seu firmware) como. a paridade é ímpar. O formato dos dados do cartão é assim:

[SS] [FC] [Nº da conta primária] [FS] [Nome] [FS] [Dados adicionais] [FS] [ES] [LRC] onde:

SS Iniciar sentinela FC Código de formato FS Separador de campo ES Sentinela final LRC Caractere de verificação de redundância longitudinal Rastreie um SS = '%', FC = um dos formatos (muitas vezes será B), FS geralmente é '', ES é '?' e o caractere LRC é comumente '<', embora não seja especificado nos padrões. Além de serem gravados no cartão ao contrário, os dados têm um bit de paridade ímpar e são 0x20 de ASCII. Cuidaremos disso quando processarmos os dados. Faixa 2 A faixa dois tem 0,110 "de largura e começa 0,110 da parte superior do cartão. Sua densidade de gravação é de 75 bits por polegada. Os dados têm 5 bits por caractere e consistem em cerca de 40 símbolos numéricos apenas. Você não deve encontrar nenhum letras nesta pista. O formato dos dados do cartão deve seguir esta estrutura

[SS] [nº da conta primária] [FS] [dados adicionais | dados discricionários] [ES] [LRC]

O SS para a faixa dois é o ponto-e-vírgula: ';' e o FS é '=' Com este conhecimento sagrado em seu currículo, continue para as próximas etapas para ver o código implementando o procedimento descrito acima.

Etapa 4: detectar quando um cartão é passado

Detectar quando um cartão é passado
Detectar quando um cartão é passado

1. Detectar quando um cartão foi passado Formalmente, seria possível verificar o pino / CARD_PRESENT para ver se ele caiu baixo. Felizmente, isso não é realmente necessário. Verificaremos se há um cartão válido mais tarde. Como alternativa, você pode ler o seu pino estroboscópico para ver quando os estroboscópios foram colocados no pino; no entanto, isso renderá muitos zeros de clock. O leitor enviará cerca de 60-70 zeros à esquerda para que você saiba que os dados estão prestes a ser apresentados. No entanto, vamos usar a natureza dos dados binários para determinar quando começar a gravar bits. A sentinela de partida (SS) para a faixa um é o sinal de porcentagem (%). Seu valor binário é 0010 0101, o que significa que será armazenado (e lido) como 1010 001 (são 7 bits, portanto o 8º bit não é transmitido). Agora, o leitor astuto notará que, embora os dados estejam ao contrário, eles não correspondem ao valor ASCII binário. Isso porque é 0x20 fora do hexadecimal. O símbolo% é 0x25 e 0100 0101 é 0x05. Os dados do cartão foram 0x20 subtraídos do valor. Aquele pendurado lá fora no nibble alto é o bit de paridade ímpar. É colocado lá para que haja um número ímpar de "1" s no valor. Então, porque sabemos que um cartão válido sempre começará com esta sentinela de início, e porque o bit de paridade é 1, quando detectamos a primeira transição de ALTO para BAIXO no pino de dados, sabemos que apenas começamos a receber o comece o sentinela a partir de um cartão. Agora, isso nem sempre será verdade, e um plano infalível seria verificar o cartão / CARD_PRESENT para ver se ele também ficou BAIXO. A maneira mais simples de detectar o início do SS é criar uma interrupção externa disparada na borda descendente do / STROBE. Os dados são válidos 1,0 us antes da borda descendente, portanto, quando você tiver amostrado a borda descendente, saberá que pode ler o pino / DATA1 e obter um valor válido. Aqui está o código para criar sua interrupção externa disparada em uma borda descendente.

voidInitInterrupt (void) {// Configurar interrupção BSET (EIMSK, INT0); // máscara de interrupção externa BSET (EICRA, ISC01); // borda descendente BCLR (EICRA, ISC00); // borda descendente BSET (SREG, 7); // I-bit em SREG}

No meu common.h que incluo em todos os meus programas, podem ser encontradas as definições de BSET e BCLR. Consulte esse arquivo se tiver alguma dúvida sobre como definir bits. Agora, quando a interrupção é disparada, queremos amostrar o / DATA1 (em meu código definido como CARD_DATA) e definir um bit em um registrador de E / S de propósito geral. Se estivermos no 7º bit, salve o registro como um caractere em nosso buffer global. Eu uso um registro GPIOR0 porque é um acesso rápido e elegante. O pseudocódigo é mais ou menos assim:

Parar o cronômetro de 16 bits Apagar o cronômetro Se DATA for LOW Definir BIT = 1 em REGISTER Diminuir BIT Definir sinalizador para não pularmos mais 0, senão DATA é HIGH Definir BIT = 0 em REGISTER Decrement BIT Se BIT for 0 Adicionar byte ao buffer Incremento do índice de redefinição do BIT

Se você está se perguntando por que diminuir em vez de aumentar, lembre-se de que os dados estão para trás, então, em vez de gravar os bits conforme os transferimos de LSB para MSB, nós os salvamos de MSB para LSB para que não tenhamos que inverter os bits mais tarde, ao processar os dados. Se você realmente quiser, também pode adicionar hex 0x20 aqui, mas como é cerca de 5us nesses flashes, estou mantendo o processamento nesta rotina de serviço de interrupção ao mínimo.

ISR (INT0_vect) {StopTimer (); ClearTimer (); if (! BCHK (PIND, CARD_DATA1)) // inverso baixo = 1 {BSET (GPIOR0, bit); --pedaço; bDataPresent = 1; } else if (bDataPresent) {BCLR (GPIOR0, bit); --pedaço; } if (bit <0) {buff [idx] = (char) GPIOR0; ++ idx; bit = 6; } StartTimer ();} Se você está se perguntando sobre o que é o tempo, isso é abordado na etapa para determinar quando o cartão saiu do leitor.

Etapa 5: leia o fluxo de dados

Leia o fluxo de dados

Bem, eu já mostrei como ler os dados, pois fazem parte da rotina de serviço de interrupção para nossa interrupção externa de borda descendente. Um método alternativo seria definir um sinalizador no ISR e, no loop principal, pesquisar o sinalizador e ler os dados dessa forma, mas acredito que a forma como apresentei é mais clara. Seja o seu próprio juiz e escreva o seu da forma que seu MCU permitir. Dito isso, vamos prosseguir para descobrir como detectar quando o cartão puxa um Elvis e sai do prédio.

Etapa 6: Detectar o cartão que sai do leitor

Detectar o cartão que sai do leitor
Detectar o cartão que sai do leitor

Detectar quando um cartão acabou

Formalmente, seria amostrado o pino / CARD_PRESENT para ver se ele ficou ALTO novamente, mas não precisamos que nenhum steenkin '/ CARD_PRESENT ocupe outra porta de E / S. É aqui que entram os temporizadores. Cada vez que a interrupção é chamada porque detectamos uma borda descendente em / STROBE, paramos um temporizador, apagamos o valor do temporizador e começamos a leitura. Quando terminamos de ler, iniciamos o cronômetro novamente. Repita ad nauseum ou até que o cronômetro atinja um determinado valor. Isso significa que a última interrupção foi chamada e não chegaram mais dados, então presumimos que seja isso e começamos a processar os dados que coletamos. Para temporizadores, usamos TIMER1, ou seja, o temporizador de 16 bits. Estou usando um ressonador de 16 MHz externamente ao meu AVR. Se você estiver usando um arduino, provavelmente também está. Portanto, escolhi um valor de prescaler de 1024, o que significa que a cada (16.000.000 / 1024) vezes o cronômetro será incrementado. Ou seja, ele 'marcará' 15.625 vezes por segundo. O / CARD_PRESENT ficará ALTO indicando que o cartão deixou o leitor cerca de 150 ms após o último bit de dados. Sabendo disso, decidi verificar a cada 1/4 de segundo. Isso seria mais ou menos assim:

(((F_CPU) / PRESCALER) / 4) que acabou sendo por volta de 3900. Então, quando o contador do cronômetro TCNT1 atingir 3900, então eu sei que já passaram cerca de 300ms e posso concluir com segurança que o cartão saiu do leitor. Fácil

#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) Você viu no ISR onde o cronômetro é iniciado, interrompido e limpo em cada interrupção. Agora, no loop principal, apenas verificamos se o contador do cronômetro atingiu nosso valor-alvo e, em caso afirmativo, iniciamos o processamento de dados

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

StopTimer (); ClearTimer (); ProcessData (); ReadData (); idx = 0; bit = 6; bDataPresent = 0; memset (& buff, 0, MAX_BUFF_SZ1); }} Agora é seguro processar os dados

código formatado por

Etapa 7: processar os dados

Processar os Dados
Processar os Dados

Processe os dados

A fase de processamento consiste em:

  • verificando um SS válido
  • verificando paridade
  • convertendo para ASCII
  • verificando um ES válido
  • verificando LRC

Aqui, não me preocupo em verificar a paridade, pois acabei de definir esse bit como zero. Eu também não calculo o LRC para este pequeno tutorial. Isso seria algo que um firmware mais completo poderia querer fazer. Aqui está o código para processar os dados executando as etapas acima (sem as mencionadas anteriormente). Encontre na imagem abaixo. É comentado e bastante autoexplicativo. Uma nota especial sobre paridade e ASCII: eu simplesmente limpo o bit de paridade (7º bit … ou seja, um 1 com 6 zeros atrás dele) e para converter de "dados do cartão" você deve adicionar 0x20 ao valor. É sobre isso.

Etapa 8: Exibir os dados

Exibir os dados
Exibir os dados
Exibir os dados
Exibir os dados

Exibir os dados

O display vai para um programa de terminal que escrevi especificamente para conectar a um AVR via RS232 ou USB. O programa é denominado Terminal AVR. O método ReadData () é muito feio e você é encorajado a encontrar uma solução mais limpa do que aquela que eu criei. Há também uma saída da função no Terminal AVR. A saída é a primeira de um cartão de seguro saúde e a segunda é de um cartão VISA. Clique no no canto superior esquerdo da imagem e escolha a imagem original ou grande para vê-la melhor.

Etapa 9: download do código e finalização

Neste instrutível, discuti alguns princípios básicos dos leitores de cartão magnético e mostrei alguns códigos para ajudá-lo a começar na direção certa na leitura de dados de cartões magnéticos. Há muito mais trabalho a ser feito, como ler e decodificar a 2ª faixa, calcular o LRC e calcular a paridade ímpar em cada byte. O código-fonte completo está disponível para download abaixo. Foi escrito em AVR Studio 4.17. Espero que tenha gostado deste instrutível e, como sempre, estou ansioso para quaisquer comentários ou sugestões que você possa ter. Feliz codificação e AVR'ing!

Recomendado: