Table des matières:

Transformez votre Arduino en lecteur de carte magnétique ! : 9 étapes (avec photos)
Transformez votre Arduino en lecteur de carte magnétique ! : 9 étapes (avec photos)

Vidéo: Transformez votre Arduino en lecteur de carte magnétique ! : 9 étapes (avec photos)

Vidéo: Transformez votre Arduino en lecteur de carte magnétique ! : 9 étapes (avec photos)
Vidéo: Carte Arduino : introduction au code 2024, Juillet
Anonim
Transformez votre Arduino en lecteur de carte magnétique !
Transformez votre Arduino en lecteur de carte magnétique !
Transformez votre Arduino en lecteur de carte magnétique !
Transformez votre Arduino en lecteur de carte magnétique !
Transformez votre Arduino en lecteur de carte magnétique !
Transformez votre Arduino en lecteur de carte magnétique !

Tout le monde a utilisé un lecteur de carte magnétique, je crois. Je veux dire, qui transporte de l'argent liquide ces jours-ci ? Ils ne sont pas difficiles à mettre la main non plus, et lors d'un voyage dans mon magasin d'électronique local préféré, j'ai trouvé une poubelle pleine de ces gars-là. Alors… bien sûr, j'en ai pris un et je l'ai ramené à la maison pour voir ce que je pouvais faire avec et un AVR.

Cette instructable vous montrera comment connecter un lecteur de carte magnétique Magtek à un AVR ou Arduino/clone et lire les données de la première piste de la carte. Bouclez vos sièges; les lecteurs de cartes magnétiques ont un débit binaire élevé !

Étape 1: La liste d'équipement

La liste des équipements
La liste des équipements
La liste des équipements
La liste des équipements

Voici quelques éléments dont vous aurez besoin pour commencer.

  • Lecteur de carte magnétique (le mien est un lecteur à double tête Magek 90 mm. 5,00 $)
  • AVR, Arduino ou clone (ATmega328p ~ 4,30 $ de Mouser.com
  • planche à pain sans soudure
  • du fil
  • peut-être un en-tête si vous aimez ce genre de chose.
  • quelque chose pour lire votre port série. J'utilise le terminal AVR de BattleDroids.net

C'est tout ce dont vous avez besoin pour commencer. Selon le lecteur de cartes magnétiques que vous obtenez, vous devrez peut-être modifier ces instructions, et très certainement le code, pour fonctionner avec votre lecteur spécifique. Cependant, le code que j'ai écrit devrait vous mener assez loin, j'espère.

Étape 2: Lecteurs de cartes magnétiques auto-synchronisés

Lecteurs de cartes magnétiques à auto-horloge
Lecteurs de cartes magnétiques à auto-horloge
Lecteurs de cartes magnétiques à auto-horloge
Lecteurs de cartes magnétiques à auto-horloge
Lecteurs de cartes magnétiques à auto-horloge
Lecteurs de cartes magnétiques à auto-horloge
Lecteurs de cartes magnétiques à auto-horloge
Lecteurs de cartes magnétiques à auto-horloge

Les lecteurs de cartes magnétiques sont « auto-synchronisés », ce qui signifie qu'ils fournissent une horloge appelée stroboscope, contre laquelle le microcontrôleur connecté peut se synchroniser. C'est une aubaine. Cela signifie que vous n'avez pas à vous soucier de rechercher un signal d'horloge et de chronométrer le signal pour qu'il se centre directement sur l'impulsion d'horloge, et pas d'oscillation gênante dans le point idéal du signal d'horloge. Cela a du sens lorsque vous pensez aux glissements de cartes: tout le monde glisse à un rythme différent, certains plus lentement, d'autres plus rapidement que d'autres. L'auto-horloge permet même à ma douce grand-mère d'utiliser sa carte sans se casser le poignet. Cela me rappelle d'avoir à modifier le paramètre pour elle qui détermine combien de temps est valide entre les clics pour enregistrer un double-clic….

Les données de ce lecteur de carte sont valides à 1,0 us avant que le stroboscope ne soit mis en ligne. Pour un lecteur à double tête comme celui que j'utilise, il y a deux pistes de données disponibles à lire. Dans cet 'ible, je vais montrer la lecture de la première piste principale pour vous aider à démarrer. Vous devrez effectuer cinq connexions (quatre si cela ne vous dérange pas de renoncer à un contrôle plus précis pour moins de ports d'E/S utilisés). Découvrez l'image ci-dessous. Le fil rouge passe au +5V tandis que le fil noir passe à la masse. Le fil vert est /CARD_PRESENT; le fil jaune est /STROBE et le fil blanc est /DATA1. La barre oblique (/) signifie que les données sont inversées. Un signal bas (c'est-à-dire 0) est lu comme un, ou haut. Les autres connecteurs sont marron pour /STROBE2 et orange pour /DATA2. Nous ne les utiliserons pas. Si vous le souhaitez, vous pouvez oublier /CARD_PRESENT. Cette ligne de données diminue après environ 17 rotations de flux de tête pour indiquer qu'une carte est présente (au lieu, disons, d'un bruit aléatoire provoquant l'envoi de fausses données par votre lecteur) et est utilisée pour valider que les données que vous obtenez sont des données de carte et pas indésirable. Vous pouvez ignorer cette connexion si vous recherchez la sentinelle de démarrage sur le flux de données. Plus à ce sujet plus tard. Comme vous pouvez le voir ci-dessous, j'ai utilisé un en-tête mâle à angle droit connecté à une planche à pain et connecté mon lecteur à cela. J'ai connecté /STROBE à PIND2 (broche numérique 2 sur un Arduino), /CARD_PRESENT à PIND3 (à des fins d'illustration) et /DATA1 à PIND4. Assurez-vous d'activer les pullups sur ces broches afin que vos broches ne flottent pas. J'ai également échangé mon Arduino contre un AVR Bare Bones parce que j'aime la façon dont il s'intègre dans la maquette.

Étape 3: Notions de base sur les cartes magnétiques

Notions de base sur les cartes magnétiques
Notions de base sur les cartes magnétiques

Les principales fonctions dont vous aurez besoin pour lire une carte magnétique sont: 1. Détecter quand la carte a été glissée 2. Lire le flux de données 3. Détecter quand la carte est partie 4. Traiter les données 5. Afficher le data Tout d'abord, je vais vous présenter quelques notions de base sur les cartes magnétiques que vous devrez connaître lorsque vous commencerez à écrire votre propre code.

Normes de cartes magnétiques

Les cartes magnétiques sont normalisées par l'ISO dans les documents suivants: 7810 Caractéristiques physiques du document format carte de crédit 7811-1 Embossage 7811-2 Piste magnétique - faible coercitivité 7811-3 Emplacement des caractères en relief 7811-4 Emplacement des pistes 1 & 2 7811- 5 Emplacement de la piste 3 7811-6 Piste magnétique - haute coercivité 7813 Cartes de transactions financières Comme vous pouvez le voir, les cartes financières sont spécifiées dans un document séparé et ont souvent des formats différents de, disons, votre carte d'épicerie ou votre carte d'appel internationale. Vous devrez programmer ces différences. J'avais juste une carte de crédit et une carte d'assurance à portée de main, alors j'ai programmé pour ces types (qui se trouvent tous les deux au format B).

Formats de carte

Il existe plusieurs formats de cartes magnétiques. Les formats A et B sont courants, B étant le plus courant que j'ai vu et qui est pris en charge dans ce code. Les formats C à M sont réservés par l'ISO, je crois, tandis que N à ?? sont réservés à un usage institutionnel personnalisé. Piste 1 Pour les cartes financières, la première piste est enregistrée à 210 bits par pouce et correspond au premier 0,110" de la carte à partir du haut. Les données sont codées en tant que "données de carte" en 7 bits par caractère. C'est 6 bits pour le caractère et un peu pour la parité. Il y a ~ 79 caractères alphanumériques sur la piste 1. L'ordre physique est à l'envers. C'est-à-dire que les données sont écrites à l'envers sur la carte (et seront donc lues par votre micrologiciel) sous la forme. Le la parité est impaire. Le format des données de la carte ressemble à ceci:

[SS] [FC] [N° de compte principal] [FS] [Nom] [FS] [Données supplémentaires] [FS][ES][LRC]où:

SS Sentinelle de début FC Code de format FS Séparateur de champs ES Sentinelle de fin LRC Caractère de contrôle de redondance longitudinale Suivre un SS = '%', FC = l'un des formats (va être B souvent), FS est souvent '', ES est '?' et le caractère LRC est généralement '<' bien qu'il ne soit pas spécifié dans les normes. En plus d'être écrites sur la carte à l'envers, les données ont un bit de parité impaire et sont 0x20 à partir de l'ASCII. Nous traiterons cela lorsque nous traiterons les données. Piste 2 La piste 2 mesure 0,110" de large et commence à 0,110 à partir du haut de la carte. Sa densité d'enregistrement est de 75 bits par pouce. Les données sont de 5 bits par caractère et se composent d'environ 40 symboles numériques uniquement. Vous ne devriez en rencontrer aucun. lettres sur cette piste. Le format des données de la carte doit suivre cette structure

[SS] [numéro de compte principal] [FS] [données supplémentaires | données discrétionnaires] [ES] [LRC]

Le SS pour la piste deux est le point-virgule: ';' et le FS est '=' Avec cette connaissance sacrée à votre actif, passez aux étapes suivantes pour voir le code mettant en œuvre la procédure décrite ci-dessus.

Étape 4: Détecter quand une carte est glissée

Détecter quand une carte est glissée
Détecter quand une carte est glissée

1. Détecter quand une carte a été glissée Formellement, on vérifierait la broche /CARD_PRESENT pour voir si elle est tombée bas. Heureusement, ce n'est pas vraiment nécessaire. Nous vérifierons la validité de la carte plus tard. Alternativement, vous pouvez lire votre broche stroboscopique pour voir quand les stroboscopes ont été mis sur la broche, cependant, cela vous rapportera beaucoup de zéros de pointage. Le lecteur enverra environ 60 à 70 zéros non significatifs pour vous informer que les données sont sur le point d'être présentées. Cependant, nous allons utiliser la nature des données binaires pour déterminer quand commencer à enregistrer des bits. La sentinelle de départ (SS) pour la piste 1 est le signe de pourcentage (%). Sa valeur binaire est 0010 0101, ce qui signifie qu'elle sera stockée (et lue) sous la forme 1010 001 (c'est 7 bits donc le 8ème bit n'est pas transmis). Maintenant, le lecteur astucieux remarquera que même si les données sont à l'envers, elles ne correspondent pas à la valeur ASCII binaire. C'est parce que c'est 0x20 hors de l'hex. Le symbole % est 0x25 et 0100 0101 est 0x05. Les données de la carte ont 0x20 soustrait de la valeur. Celui qui traîne là-bas dans le grignotage élevé est le bit de parité impair. Il est placé là pour qu'il y ait un nombre impair de "1" dans la valeur. Donc, parce que nous savons qu'une carte valide commencera toujours par cette sentinelle de démarrage, et parce que le bit de parité est à 1, alors lorsque nous détectons la première transition HAUT à BAS sur la broche de données, nous savons que nous venons de commencer à recevoir le démarrer la sentinelle à partir d'une carte. Maintenant, cela ne sera pas toujours vrai, et un plan infaillible serait de vérifier la carte /CARD_PRESENT pour voir si elle est en plus basse. La façon la plus simple de détecter le démarrage du SS, est de créer une interruption externe déclenchée sur le front descendant du /STROBE. Les données sont valides 1,0 us avant le front descendant, donc lorsque vous avez échantillonné le front descendant, vous savez que vous pouvez lire la broche /DATA1 et obtenir une valeur valide. Voici le code pour créer votre interruption externe déclenchée sur un front descendant.

voidInitInterrupt(void){ // Configuration de l'interruption BSET(EIMSK, INT0); // masque d'interruption externe BSET(EICRA, ISC01); // front descendant BCLR(EICRA, ISC00); // front descendant BSET(SREG, 7); // I-bit dans SREG}

Dans mon common.h que j'inclus dans tous mes programmes, on peut trouver les définitions de BSET et BCLR. Reportez-vous à ce fichier si vous avez des questions sur la façon de définir les bits. Maintenant, lorsque l'interruption est déclenchée, nous voulons échantillonner le /DATA1 (dans mon code défini comme CARD_DATA) et définir un bit dans un registre IO à usage général. Si nous sommes sur le 7ème bit, enregistrez hors du registre en tant que caractère dans notre tampon global. J'utilise un registre GPIOR0 car c'est un accès rapide épatant. Le pseudo code est quelque chose comme ceci:

Arrêter le temporisateur 16 bits Effacer le temporisateur Si DATA est FAIBLE Mettre BIT=1 dans REGISTER Décrémenter BIT Mettre le drapeau afin que nous ne sautions plus de 0 sinon DATA est HAUT Mettre BIT=0 dans REGISTER Décrémenter BIT Si BIT est 0 Ajouter un octet au tampon Incrémenter l'index Reset BIT

Si vous vous demandez pourquoi décrémenter au lieu d'incrémenter, rappelez-vous que les données sont à l'envers, donc au lieu d'enregistrer les bits au fur et à mesure que nous les obtenons de LSB à MSB, nous les sauvegardons de MSB à LSB afin de ne pas avoir à inverser les bits plus tard lors du traitement des données. Si vous le souhaitez vraiment, vous pouvez également ajouter 0x20 hex ici, mais comme il s'agit d'environ 5us sur ces flashs, je minimise le traitement de cette routine de service d'interruption.

ISR(INT0_vect){ StopTimer(); ClearTimer(); if (!BCHK(PIND, CARD_DATA1)) // inverse bas = 1 { BSET(GPIOR0, bit); --bit; bDonnéesPrésent = 1; } else if (bDataPresent) { BCLR(GPIOR0, bit); --bit; } if (bit < 0) { buff[idx] = (char)GPIOR0; ++idx; bits = 6; } StartTimer();} Si vous vous demandez en quoi consiste le secteur du chronométrage, cela est couvert dans l'étape consistant à déterminer quand la carte a quitté le lecteur.

Étape 5: Lire le flux de données

Lire le flux de données

Eh bien, je vous ai déjà montré comment lire les données, car elles font partie de la routine de service d'interruption pour notre interruption externe de front descendant. Une méthode alternative serait de définir un indicateur dans l'ISR et, dans la boucle principale, d'interroger l'indicateur et de lire les données de cette façon, mais je pense que la façon dont je l'ai présentée est plus propre. Soyez votre propre juge et écrivez le vôtre de la manière dont votre MCU le permettra. Cela étant dit, voyons comment détecter lorsque la carte tire un Elvis et a quitté le bâtiment.

Étape 6: Détecter la carte quittant le lecteur

Détecter la carte quittant le lecteur
Détecter la carte quittant le lecteur

Détecter quand une carte est partie

Formellement, on échantillonnerait la broche /CARD_PRESENT pour voir si elle est redevenue HAUTE, mais nous n'avons pas besoin de steenkin' /CARD_PRESENT prenant un autre port d'E/S. C'est là qu'interviennent ces temporisateurs. Chaque fois que l'interruption est appelée parce que nous avons détecté un front descendant sur /STROBE, nous arrêtons un temporisateur, effaçons la valeur du temporisateur et commençons à lire. Lorsque nous avons fini de lire, nous recommençons le chronomètre. Répétez ad nauseum, ou jusqu'à ce que la minuterie atteigne une certaine valeur. Cela signifie que la dernière interruption a été appelée et qu'aucune autre donnée n'est entrée, nous supposons donc que c'est tout et commençons à traiter les données que nous avons collectées. Pour les temporisateurs, nous utilisons TIMER1, c'est-à-dire le temporisateur 16 bits. J'utilise un résonateur 16 Mhz à l'extérieur de mon AVR. Si vous utilisez un arduino, vous l'êtes probablement aussi. J'ai donc choisi une valeur de pré-échelle de 1024, ce qui signifie que toutes les (16 000 000 / 1024) fois la minuterie s'incrémentera. C'est-à-dire qu'il 'tick' 15, 625 fois par seconde. Le /CARD_PRESENT deviendra HAUT indiquant que la carte a quitté le lecteur environ 150 ms après le dernier bit de données. Sachant cela, j'ai juste décidé de vérifier environ tous les 1/4 de seconde. Cela ressemblerait à quelque chose comme ceci:

(((F_CPU) / PRESCALER) / 4) ce qui s'avère être autour de 3900. Ainsi, lorsque le compteur de minuterie TCNT1 atteint 3900, alors je sais que cela fait environ 300 ms et je peux conclure en toute sécurité que la carte a quitté le lecteur. Facile

#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) Vous avez vu dans l'ISR où le temporisateur est démarré, arrêté et effacé à chaque interruption. Maintenant, dans la boucle principale, nous vérifions simplement si le compteur de la minuterie a atteint notre valeur cible, et si c'est le cas, démarrez le traitement des données

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

StopTimer(); ClearTimer(); Données de processus(); ReadData(); idx = 0; bits = 6; bDonnéesPrésent = 0; memset(&buff, 0, MAX_BUFF_SZ1); } } Vous pouvez désormais traiter les données en toute sécurité

code formaté par

Étape 7: Traiter les données

Traiter les données
Traiter les données

Traiter les données

La phase de traitement consiste à:

  • vérification d'un SS valide
  • vérifier la parité
  • conversion en ASCII
  • vérification d'un ES valide
  • vérification LRC

Ici, je ne me soucie pas de vérifier la parité, car je viens de mettre ce bit à zéro. Je ne calcule pas non plus le LRC pour ce petit tutoriel. Ce serait quelque chose qu'un micrologiciel plus pleinement réalisé pourrait vouloir faire. Voici le code pour traiter les données en effectuant les étapes ci-dessus (sans les étapes mentionnées précédemment). Trouvez-le dans l'image ci-dessous. C'est commenté et assez explicite. Une note spéciale sur la parité et l'ASCII: j'efface simplement le bit de parité (7e bit… c'est-à-dire un 1 avec 6 zéros derrière) et pour convertir à partir des "données de la carte", vous devez ajouter 0x20 à la valeur. C'est à peu près ça.

Étape 8: afficher les données

Afficher les données
Afficher les données
Afficher les données
Afficher les données

Afficher les données

L'affichage passe à un programme de terminal que j'ai écrit spécifiquement pour la connexion à un AVR via RS232 ou USB. Le programme s'appelle AVR Terminal. La méthode ReadData () est assez moche et vous êtes encouragé à trouver une solution plus propre que celle que j'ai proposée. Il existe également une sortie de la fonction dans AVR Terminal. La sortie est d'abord d'une carte d'assurance maladie, et la seconde est d'une carte VISA. Cliquez sur le dans le coin supérieur gauche de l'image et choisissez l'image originale ou grande pour mieux la voir.

Étape 9: Téléchargement du code et récapitulation

Dans ce instructable, j'ai discuté de certaines bases des lecteurs de cartes magnétiques et vous ai montré un code pour vous aider à démarrer dans la bonne direction dans la lecture de données à partir de cartes magnétiques. Il y a beaucoup plus de travail qui pourrait être fait, comme lire et décoder la 2ème piste, calculer le LRC et calculer la parité impaire sur chaque octet. Le code source complet est disponible en téléchargement ci-dessous. Il a été écrit dans AVR Studio 4.17. J'espère que vous avez apprécié cette instructable et, comme toujours, j'attends avec impatience tous les commentaires ou suggestions que vous pourriez avoir. Bon codage et AVR'ing !

Conseillé: