améliorer lecteur de cartes magnétiques

Bonjour,

J’ai acheter un lecteur de cartes magnétiques sur le bon coin, utilisable avec un arduino. J’ai utliser la description du lecteur faite dans l’annonce pour créer un petit code.
la photo du lecteur indique que:

-Deux des trous vont à la masse et au +5v que j’ai connecter a ceux de l’arduino.
-Un troisième trou, qui indique si une carte passe dans le lecteur. avec le voltmètre je vois que le trou donne toujours du +5v, mais lorsqu’une carte passe alors il passe à 0v.
-deux trous “CLK1” et “DATA1” pour la première piste de la bande magnetique.
-deux trous “CLK2” et “DATA2” pour la deuxième piste de la bande magnetique.

petite explication sur CLK et DATA: en fait quand une carte passe dans le lecteur, CLK change constamment de 0v en +5v (un peu comme un signal carré) et à chaque fois que CLK tombe de +5v à 0v il faut lire à ce moment la sur le trou qui corespond a DATA pour avoir la valeur du bit.

Du coup j’ai coder un petit programme avec une interuption exterieur associé à la broche de la pin arduino qui est connecter a CLK. et chaque fois que la broche “Falling” sa appele une fonction qui lit sur la pin qui est connecté à DATA et le stock dans un tableau.
Puis, dans le loop une petite fonction qui permet de voir, à qu’elle moment la carte a fini de passer et à ce moment la affcicher tout le tableaudes données de la carte.

Voici le code:

//Connecter la sortie de presence de carte du lecteur à la pin 2 de l'arduino
//Connecter la sortie d'horloge du lecteur à la pin 3 de l'arduino
//Connecter la sortie de données du lecteur à la pin 4 de l'arduino

volatile int DonneesBinaire[600];
volatile int compteur=0;
volatile int i;
int Presence=1;
int PresenceAvant=1;

void setup() {
  Serial.begin(9600);
  attachInterrupt(1, lecture, FALLING);
  pinMode(4,INPUT);
  pinMode(2,INPUT);
  Serial.println("Lecteur de carte magnetique");
}

void loop() {
  Presence=digitalRead(2);
  if (Presence==1 && PresenceAvant==0) {
    Serial.println("Donnees de la piste en binaire:");
    for (i=1;i<600;i=i+1) 
    {
    Serial.print(DonneesBinaire[i]);
    }
    Serial.println();
    compteur=0;
  }
  PresenceAvant=Presence;
}

void lecture(){
  DonneesBinaire[compteur]=digitalRead(4);
  compteur++;
}

le code fonctionne mais bon, c’est pas tres pratique car pour lire la deuxième piste je doit deconecter les fil de DATA1 et CLK1 pour les connecter à DATA2 et CLK2…
l’idéal serait de faire un code capable de lire les deux pistes en même temps, mais il me semble que en faisais deux interuption (un pour CLK1 et l’autre pour CLK2) et bien une fait concurence à l’autre.

Est ce que quelqu’un à une idée de comment faire?

Bonjour,

Travaille entièrement sous interruptions :wink:
Tu as deux interruptions externes possible avec attachInterrupt() autant en faire bonne usage pour les timing CLK1 et CLK2 :wink:
Et pour la broche de fin de passage d’une carte utilise “PCint” pour avoir une troisième interruption (semi logicielle donc plus lente).

Ton idée de faire un buffer de 600 bits avant d’utiliser les données c’est une grosse connerie, déjà un int c’est deux octets = 16 bits.
Pour quoi donc utilise un buffer de 1200 octets en RAM pour stocker à chaque fois un unique bit 0/1 !

Et si tu veut avoir une lecture viable même à grande vitesse n’utilise pas digitalRead() mais directement les registres AVR :wink:
(cherche “port manipulation” ou regarde le code de wiring_digital.c dans le core arduino)

Pour ta fonction d’interruption CLKn (fonction en deux exemplaires donc) fait comme ça :

  • byte static “val” (au départ = 0) qui contient la valeur de l’octet courant
  • byte static “i” (au départ = 0) qui contient l’index du bit courant
  • si (_BV(PINx) & _BV(PINn)) // lit la valeur de la broche PINn depuis le registre PINx
    → bitSet(val, i) // Broche à HIGH = bit à “1”
  • sinon
    → bitClear(val, i) // Broche à LOW = bit à “0”
  • si (++i == 8 ) // Passe à l’index suivant + vérif si fin de l’octet courant
    → i = 0 // Recommence au bit 0
    → buffer[index++] = val; // met l’octet fini dans le buffer global

En global :

  • buffer tableau qui contient tes octets
  • index (au départ = 0) qui contient l’index courant dans le buffer

Quand l’interruption sur la 3iéme broche s’active :

  • for i = 0; i < index; ++i
    → Serial.print(buffer*)*
    Dans loop() : rien
    Dans setup() : les deux attachInterrupt(), le PCattachInterrupt() et le Serial.begin()

Salut skywodd

Sympas ta réponse, elle est super complète. j'ai mit un peu de temps avant de comprendre tout ce que tu dit.

Ta remarque sur le tableau[600] de int est très pertinante c'est vrai que c'est con d'utilisé autant. Je vais essayer de modifier le code en utilisant une manipulation bit à bit à laquelle je n'avait pas penser non plus.

Par contre je n'ai pas tres bien compris l'utilisation du PCattachinterupt() en cherchant vaguement sur internet j'ai cru comprendre que cette fonction était utilisable seulement sur la carte mega(?!). Or j'utilise une carte arduino uno, enfin peut-être ai-je mal compris.

Antoinemelo: Par contre je n'ai pas tres bien compris l'utilisation du PCattachinterupt() en cherchant vaguement sur internet j'ai cru comprendre que cette fonction était utilisable seulement sur la carte mega(?!). Or j'utilise une carte arduino uno, enfin peut-être ai-je mal compris.

De mémoire c'est l'inverse, elle marche sur les cartes classiques (UNO, 2009, ...) mais pas sur la mega2560 ou sur la leornardo / Due. En tout cas elle marche avec une UNO ;)