Lecteur de carte à puce

Bonjour je travaille actuellement sur un projet de lecteur de carte à puce pour ouvrir une porte.
Bien que j'aie réussie mon exercice j'ai souhaité l'améliorer en créant une carte admin qui permet de changer le type de carte accepté sauf que problème le programme ne fonctionne et là je bloque donc si quelqu'un pouvait m'expliquer d'où vient l'erreur dans mon programme (je pense que c'est le for mais je ne voix pas comment faire autrement).

Déclaration et initialisation des variables

#include <EEPROM.h>

int RAZ = 5;
int H = 2;
int ACK = 3; // capteur présence carte
int S = 4;
int val ;
int gache = 9;
int ledV = 13;
int ledR = 12;
boolean CarteState;
boolean BitState;
boolean value [8];
boolean value2 [8];

void setup() {
Serial.begin(9600);
// prints title with ending line break
// initialisation des entrées analogiques;
pinMode(RAZ, OUTPUT);
pinMode(H, OUTPUT);
pinMode(S, INPUT);
pinMode(ACK, INPUT);
pinMode(gache, OUTPUT);
pinMode(ledV, OUTPUT);
pinMode(ledR, OUTPUT);
}

Début de la boucle principale avec vérification si il y a présence d'une carte et initialisation de celle-ci

void loop (){

CarteState = digitalRead(ACK);
while (CarteState == HIGH ){
Serial.println("carte absente") ;
delay (1000);
CarteState = digitalRead(ACK);
}
Serial.println("carte presente");

//initialisation de la carte

digitalWrite (RAZ, LOW); //début RAZ
digitalWrite (H,LOW);
delay (25);

digitalWrite (RAZ, LOW);
digitalWrite (H, HIGH);
delay (25);

digitalWrite (RAZ, LOW);
digitalWrite (H, LOW);

delay (50);
//fin initialisation de la carte

Début de lecture du premier valeur qu'on stock dans une variable value et on effectué 7 fois la boucle pour acquérir les 8 premiers bits

digitalWrite (RAZ, HIGH); // lecture bit 1

//debut de lecture carte

for (int i=0; i <= 7; i++)
{
// impulsion de ratio HAUT/BAS fonction de i sur la broche 10
digitalWrite (H, LOW);
delay (25);
value*=digitalRead(S);*

  • digitalWrite (H, HIGH);*
    _ if(value*==HIGH){Serial.println("1");}_
    _
    else {Serial.println("0");}_
    _
    delay (25);_
    _
    }_
    _
    [/quote]_
    C'est à partir de là que je ne suis pas sûr de mon programme
    J'insère une carte ,si les 8 premiers bits (value) de ma carte sont égales à une valeur que j'aurai préalablement stocker dans l'EEPROM alors on allume la led verte et on ouvre la gâche sinon on allume la del rouge
    _
    > for (byte i=0; i <=7; i++)_
    > if ( value == EEPROM.read (i) )
    _> * {
    > * digitalWrite (gache , HIGH);
    > * digitalWrite ( ledV, HIGH);

    > * delay (5000);
    > * digitalWrite (gache , LOW);

    > * digitalWrite ( ledV, LOW);
    > * }

    >
    > * else*
    > * {
    > * digitalWrite ( ledR, HIGH);

    > * delay (5000);
    > * digitalWrite (ledR, LOW);

    > * }
    > * [/quote]

    > Ou sinon si la carte insérer à les mêmes valeurs que celles écrites que celle écrite à la suite (c'est à dire 10110111) alors on enclenche le mode admin et le capteur de carte reste sur le niveau haut pour que je puisse changer de carte sans repartir au début de ma boucle.
    > > if ( value [0] == 1 && value [1] == 0 && value [2] == 1 && value [3] == 1 && value [4] == 0 && value [5] == 1 && value [6] == 1 && value [7] == 1 )// Carte 1 ADMIN
    > > {
    > > // digitalWrite (ACK, HIGH);
    > > digitalWrite (ledR, HIGH);
    > > digitalWrite (ledV, HIGH);
    > > delay (5000);
    > > delay (5000);
    > > delay (5000);
    > > delay (5000);
    > > delay (5000);
    > > delay (5000);
    > > delay (5000);
    > > delay (5000);
    > > delay (5000);
    > > delay (5000);
    > On refait une nouvelle initialisation de la nouvelle carte
    > > //initialisation de la carte
    > >
    > > digitalWrite (RAZ, LOW); //début RAZ
    > > digitalWrite (H,LOW);
    > > delay (25);
    > >
    > > digitalWrite (RAZ, LOW);
    > > digitalWrite (H, HIGH);
    > > delay (25);
    > >
    > > digitalWrite (RAZ, LOW);
    > > digitalWrite (H, LOW);
    > >
    > > delay (50);
    > > //fin initialisation de la carte
    > On relit les 8 premiers bits de la carte mais cette fois-ci on les stock dans une variable value2 et on écrit ses valeurs dans l'EEPROM pour remplacer les anciennes.
    > > digitalWrite (RAZ, HIGH); // lecture bit 1
    > >
    > > //debut de lecture carte
    > >
    > > for (int i=0; i <= 7; i++)
    > > {
    > > // impulsion de ratio HAUT/BAS fonction de i sur la broche 10
    > > digitalWrite (H, LOW);
    > > delay (25);_

    > _> value2=digitalRead(S);_

    > > _ EEPROM.write(i, value2);_

    > > _ digitalWrite (H, HIGH);

    > > if(value==HIGH){Serial.println("1");}

    > > else {Serial.println("0");}

    > > delay (25);

    > > * }
    > > }
    > >
    > > else*

    > > * {
    > > digitalWrite ( ledR, HIGH);
    > > delay (5000);
    > > digitalWrite (ledR, LOW);
    > > }
    > > }[/quote]*

    > > Merci d'avance_

Yep!

Tout d'abord, il n'y a pas de stockage de la variable value, tu ne fais que l'afficher.

Remplacer boolean value[8] par byte value[8] (idem pour value2, tu travailles avec des bytes, autant garder ce type du début à la fin)

for (int i=0; i <= 7; i++)
{
  temp=digitalRead(S); // on stocke temporairement la valeur
  ...
  if(temp==HIGH){value[i] = 1;} // archivage dans le tableau value a l'index i
  else {value[i] = 0;}
...
}

Ensuite, pour la comparaison avec les valeurs stockées dans l'eeprom :

Changes :

for (byte i=0; i <=7; i++)
    if (  value == EEPROM.read (i) )

En :

for (byte i=0; i <=7; i++)
    if (  value[i] == EEPROM.read(i) )

C'est en gros ce que j'ai vu de plus flagrant :wink:

@+

Zoroastre.

Merci de ta réponse par contre je ne comprends pas cette partie?

zoroastre:

for (int i=0; i <= 7; i++)

{
  temp=digitalRead(S); // on stocke temporairement la valeur
  ...
  if(temp==HIGH){value[i] = 1;} // archivage dans le tableau value a l'index i
  else {value[i] = 0;}
...
}

Yep!

byte value[8] est un tableau de 8 bytes.

A chaque incrémentation de i, tu mets la valeur de S dans le tableau value à l'index i
value[0] <- Première lecture i = 0,
value[1] <- Deuxième lecture i = 1,
etc.
Ex : [1, 1, 0, 0, 1, 1, 1, 0]

On pourrait directement faire :

value[i] = digitalRead(S);

ou

if (digitalRead(S) == HIGH) { value[i] = 1; }
...

Comme tu as des changements d'état entre 2, je suis passé par une variable temporaire pour respecter ton code.

Dans ton code original, tu effectuais simplement un Serial.print de la valeur et tu ne remplissais pas le tableau du début à la fin.

value=digitalRead(S);

@+

Zoroastre.

Après test ça marche pas du tout j'ai trouvé et ça bloque au niveau du for qui ne s'effectue pas correctement.

for (byte i=0; i <=7; i++)
    if (  value == EEPROM.read (i) )
    {
    digitalWrite (gache , HIGH);
    digitalWrite ( ledV, HIGH);

    delay (5000);
    digitalWrite (gache , LOW);
    digitalWrite ( ledV, LOW);
  }
 
  else
     {
     digitalWrite ( ledR, HIGH);
     delay (5000);
     digitalWrite (ledR, LOW);
   }

Yep!

Ajoutes des Serial.println(value) ici et là dans ton sketch. Regardes le resultat dans le moniteur et relis ce que j'ai écrit plus haut.
Tu attends une variable de 8 bytes et elle en contiendra qu'un seul...

@+

Zoroastre.

Alors en fait désolé mais les n'apparaissent pas dans mon code mais ils sont bien présent.

Edite tes message et mets le code dans les balises que tu auras avec le boutons "#".

Ok merci donc voici le programme

#include <EEPROM.h>

int RAZ = 5;
int H = 2;
int ACK = 3;
int S = 4;
int val  ;
int gache = 9;
int ledV = 13;
int ledR = 12;
boolean CarteState;
boolean BitState;
byte value [8];
byte value2 [8];


void setup()   {       
Serial.begin(9600); 
  // prints title with ending line break 
    // initialisation des entrées analogiques;
  pinMode(RAZ, OUTPUT);
  pinMode(H, OUTPUT);
  pinMode(S, INPUT);
  pinMode(ACK, INPUT);
  pinMode(gache, OUTPUT);
  pinMode(ledV, OUTPUT);
  pinMode(ledR, OUTPUT);  
}

void loop (){    

CarteState = digitalRead(ACK);
while (CarteState == HIGH ){
  Serial.println("carte absente")  ;
  delay (1000);
  CarteState = digitalRead(ACK);
} 
Serial.println("carte presente");


//initialisation de la carte

digitalWrite (RAZ, LOW); //début RAZ
digitalWrite (H,LOW); 
delay (25);

digitalWrite (RAZ, LOW);
digitalWrite (H, HIGH); 
delay (25);

digitalWrite (RAZ, LOW);
digitalWrite (H, LOW); 
    
delay (50);
//fin initialisation de la carte
digitalWrite (RAZ, HIGH); // lecture bit 1

//debut de lecture carte
 
for (int i=0; i <= 7; i++)
{ 
      // impulsion de ratio HAUT/BAS fonction de i sur la broche 10
    digitalWrite (H, LOW);
    delay (25);
    value[i]=digitalRead(S);
    digitalWrite (H, HIGH);
    if(value[i]==HIGH){Serial.println("1");}
    else {Serial.println("0");}
    delay (25);
}

for (byte i=0; i <=7; i++)
    if (  value [i] == EEPROM.read (i) )
    {
    digitalWrite (gache , HIGH);
    digitalWrite ( ledV, HIGH);

    delay (5000);
    digitalWrite (gache , LOW);
    digitalWrite ( ledV, LOW);
  }
 
  else 
     {
     digitalWrite ( ledR, HIGH);
     delay (5000);
     digitalWrite (ledR, LOW);
   }
   
    if ( value [0] == 1 && value [1] == 0 && value [2] == 1 && value [3] == 1 && value [4] == 0 && value [5] == 1 && value [6] == 1 && value [7] == 1 )// Carte 1 ADMIN
    {
   // digitalWrite (ACK, HIGH);      
    digitalWrite (ledR, HIGH);
    digitalWrite (ledV, HIGH);
         delay (5000);
             delay (5000);
                 delay (5000);
                     delay (5000);
                         delay (5000);
                             delay (5000);
                                 delay (5000);
                                     delay (5000);
                                         delay (5000);
                                             delay (5000);
                                     

  
      //initialisation de la carte

    digitalWrite (RAZ, LOW); //début RAZ
    digitalWrite (H,LOW); 
    delay (25);
    
    digitalWrite (RAZ, LOW);
    digitalWrite (H, HIGH); 
    delay (25);
    
    digitalWrite (RAZ, LOW);
    digitalWrite (H, LOW); 
        
    delay (50);
    //fin initialisation de la carte
    digitalWrite (RAZ, HIGH); // lecture bit 1
    
    //debut de lecture carte
     
    for (int i=0; i <= 7; i++)
    { 
          // impulsion de ratio HAUT/BAS fonction de i sur la broche 10
        digitalWrite (H, LOW);
        delay (25);
        value2[i]=digitalRead(S);
        EEPROM.write(i, value2[i]);
        digitalWrite (H, HIGH);
        if(value[i]==HIGH){Serial.println("1");}
        else {Serial.println("0");}
        delay (25);
    }
      }
     
      else 
         {
         digitalWrite ( ledR, HIGH);
         delay (5000);
         digitalWrite (ledR, LOW);
       }


}

Yop yop,

Question qui m’intéresse et qui pourrait nous aider à comprendre ton code, tu pourrais donner les détails de ton lecteur de carte à puce ?
Sinon pour le programme tu peux remplacer tout tes int (2 octet) par des byte (1 octet pour les valeurs allant de 0 à 255).
Voir également l'instruction #define qui pourrais être intéressante.
Autre chose qui pourrais être intéressant, enfin plus au niveau de l'apprentissage histoire de t’amélioré et bon à savoir, c'est de travaillé au niveau binaire plutôt qu'utilisé des tableau de t'aille 8 (donc 8 octet), 1 octet c'est justement 8 bit. (c'est pas un hasard je suppose que les valeurs de ta carte soient de taille 8 ) (tu peux toujours demandé quelques astuces ou explication si tu veux le faire, on t'aidera)
http://www.mon-club-elec.fr/pmwiki_reference_arduino/pmwiki.php?n=Main.Bitabit
Beaucoup de delay() peut être songer à ceci par exemple http://arduino.cc/en/Tutorial/BlinkWithoutDelay
Là j'ai du mal à comprendre. :disappointed_relieved: :grin:

         delay (5000);
             delay (5000);
                 delay (5000);
                     delay (5000);
                         delay (5000);
                             delay (5000);
                                 delay (5000);
                                     delay (5000);
                                         delay (5000);
                                             delay (5000);

Enfin pas vraiment de solution pour ton programme (manque d'info sur ton lecteur) s'il subsiste encore des problèmes, mais plus quelques petit conseils utiles, on sais jamais. :wink:

Voici les infos sur mon lecteur avec de la doc http://pascool.cool.free.fr/lecteur.doc
Sinon mon lecteur peut lire les 256 bits mais moi je m'intéressent juste aux 8 premiers.
Pour la tempo c'est le seule moyens que j'ai trouvé pour laisser le signal ACK au niveau haut le temps de changer de carte

ichigocool:
Voici les infos sur mon lecteur avec de la doc http://pascool.cool.free.fr/lecteur.doc

J'ai regardé rapidement mais ça à l'air sympa :open_mouth: .

ichigocool:
Sinon mon lecteur peut lire les 256 bits mais moi je m'intéressent juste aux 8 premiers.

ichigocool:
Pour la tempo c'est le seule moyens que j'ai trouvé pour laisser le signal ACK au niveau haut le temps de changer de carte

C'est pas ceci qui te permettrait un tempo entre changement de carte ?

CarteState = digitalRead(ACK);
while (CarteState == HIGH ){
  Serial.println("carte absente")  ;
  delay (1000);
  CarteState = digitalRead(ACK);
} 
Serial.println("carte presente");

Si pas besoin de CarteState dans le reste du code tu peux faire directement:

while (digitalRead(ACK))
{
  Serial.println("carte absente")  ;
  delay (1000);
} 
Serial.println("carte presente");

Tu peux même faire.

void loop()
{
  if(!digitalRead(ACK)) // si l'entrée est à 0 ('!' ici veux dire différent et comme toute valeurs différentes de 0 est considéré comme vrai)
  {
    Serial.println("carte presente");
    //tout le reste du code
  }
  else
  {
    Serial.println("carte absente")  ;
    delay (1000);
  }
}

Il faut initialisé la carte à chaque lecture (en boucle) ?
(je crois que tu as dupliqué du code ou mauvais copier coller)
Lecture 1 seul fois lors de l'insertion de la carte ou constamment ?
(! au cas ou, voir loop comme une boucle infinie)

Alors le CarteState est juste là pour le serial monitor
Oui il faut à chaque fois initialiser dès qu'une carte est mis.
Ensuite je fais une boucle for pour lire les 8 premiers bits.

ichigocool:
Alors le CarteState est juste là pour le serial monitor
Oui il faut à chaque fois initialiser dès qu'une carte est mis.
Ensuite je fais une boucle for pour lire les 8 premiers bits.

Donc initialisation et lecture qu'une seule fois à l'insertion de la carte.
Bien faire attention à la fonction "void loop()" qui correspond à une boucle infinie en réalité (while(1)).

void loop()
{
  //code bouclé constament
}

est identique à

while(1)
{
  //code bouclé constament
}

Le véritable visage du code final arduino.

int main(void)
{
	init();

	setup();
    
	for (;;)
		loop();
        
	return 0;
}

donc tout le code que tu mets dans loop est répété constamment.
Ce que tu dois faire normalement (je suppose) c'est initialisé et lire une seule fois à l'introduction d'une carte ?
Parce que là en plus tu vas rapidement avoir un problème avec ton eeprom qui est limité en cycles de lecture/écriture (100 000 ?)

Oui je sais et justement c'est un lecteur de carte donc tu met ta carte la gâche s'ouvre et tu enlève ta carte donc c'est bon.
En ce qui concerne l'EEPROM il n'y a qu'une carte qui permet d'écrire dans l'eeprom: carte admin

ichigocool:
Oui je sais et justement c'est un lecteur de carte donc tu met ta carte la gâche s'ouvre et tu enlève ta carte donc c'est bon.
En ce qui concerne l'EEPROM il n'y a qu'une carte qui permet d'écrire dans l'eeprom: carte admin

Je sais pas si tu as bien fais attention à ce que j'ai dis sur la fonction loop de l'Arduino ou j'ai rien compris (ça serait pas la première fois :grin:) mais là pour moi tu fais de la lecture constante, tout du moin minimum toute les 50 seconde (10x delay(5000) = delay(50000)).
Pour moi tu dois juste détecté l’insertion d'une carte, initialisé et lire 1 fois jusqu’à la prochaine insertion.
L'eeprom je parle bien sure de l'eeprom arduino, donc minimum une lecture toute les 50 seconde comme je le vois là .

Oui mais dans mon loop il y a 2 boucles possibles, celles ou la carte est la bonne et on ouvre la gâche et l'autre avec la carte admin ou on refait toute l'initialisation et on écrit dans l'eeprom

Mise à part l'indentation qui est foireuse chez moi à cause du copier coller que j'ai fais de ton code, je ne vois rien qui empêche la lecture constante de l'eeprom arduino.

qu'est ce qui empêche la lecture de la carte ou de l'eeprom de l'arduino au prochain tour de la fonction loop ici ? (Manque les {} du for)

for (byte i=0; i <=7; i++)
  if (  value [i] == EEPROM.read (i) )
  {
    digitalWrite (gache , HIGH);
    digitalWrite ( ledV, HIGH);

    delay (5000);
    digitalWrite (gache , LOW);
    digitalWrite ( ledV, LOW);
  }
  else 
  {
     digitalWrite ( ledR, HIGH);
     delay (5000);
     digitalWrite (ledR, LOW);
  }

Que ta gache soit ouverte ou fermée ou même qu'il y ai une carte dedans ou pas la fonction loop ne s'arrête pas de boucler.

Pas compris cette partie, écriture sur la carte ? 5 sec entre chaque écriture d'1bit ?

    for (byte i=0; i <=7; i++)
    {
      if (value [i] == EEPROM.read (i) )
      {
        digitalWrite (gache , HIGH);
        digitalWrite ( ledV, HIGH);
    
        delay (5000);
        digitalWrite (gache , LOW);
        digitalWrite ( ledV, LOW);
      }
      else 
      {
         digitalWrite ( ledR, HIGH);
         delay (5000);
         digitalWrite (ledR, LOW);
      }
    }

J'ai un peux mieux regarder ce que tu voulais faire et presque compris le fonctionnement du lecteur +- .
Comme je le disais, le mieux c'est de détecté une nouvelle insertion de carte et de n'effectuer la lecture qu'une seule fois et non à chaque passage dans loop.
L'action a effectuer dépendra de la lecture précédente, activation d'un mode admin.
J'aurais fais le code ainsi, sans doute que ça ne correspond pas à 100% de ce que tu désires faire mais globalement ça devrait y ressemble je pense (pas tester évidement).

#include <EEPROM.h>

#define RAZ 5
#define H 2
#define ACK 3
#define S 4
#define GACHE 9
#define LED_V 13
#define LED_R 12
boolean cardState;
byte val = 0;
byte mode = 0;

void setup()   
{       
  //Serial.begin(9600); 
  // initialisation des entrées analogiques;
  pinMode(RAZ, OUTPUT);
  pinMode(H, OUTPUT);
  pinMode(S, INPUT);
  pinMode(ACK, INPUT);
  pinMode(GACHE, OUTPUT);
  pinMode(LED_V, OUTPUT);
  pinMode(LED_R, OUTPUT);  
}

void loop ()
{
  if(!digitalRead(ACK) && !cardState) //si on detecte une carte et que l'ancien etat est à 0 (donc absence de carte) c'est qu'il sagit d'une nouvelle carte.
  {
//    Serial.println("carte presente");
    initCard(); //initialisation de la carte
    val = readCard(); //on récupère ça valeur

    if(EEPROM.read (0) != val) //si la nouvelle valeur est différente de celle de l'eeprom sinon on ferme la gache ?
    {
      digitalWrite (GACHE, HIGH); //on ouvre la gache
      digitalWrite (LED_V, HIGH); //led verte: on    
      if(!mode) // si le mode admin est désactivé
      {             
        if(val == 0xED)// si la valeur est égal au code admin (0xED = 11101101 = 237)
        {     
          mode = 1; //mode 1 activé pour la prochaine carte
          digitalWrite (LED_R, HIGH); //led rouge: on
          digitalWrite (LED_V, HIGH); //led verte: on        
        }
        else 
        {
         digitalWrite ( LED_R, HIGH); //led rouge: on
         delay (5000); //pause de 5 sec ?
         digitalWrite (LED_R, LOW); //led rouge: off
        }
      }
      else //Mode admin, à noter qu'il ne passera ici qu'après l'insertion d'une nouvelle carte si le mode admin a été activé lors de la lecture de la carte précédente
      {
        EEPROM.write(val, 0); //on écrit la nouvelle valeur dans l'eeprom
        mode = 0; //on désactive le mode admin
      }
    }
    else
    {
      digitalWrite (GACHE, LOW); //on ferme la gache
      digitalWrite (LED_R, HIGH); //led rouge: on
    }
    cardState = 1; //fin de traitement on met cardState à 1, la carte à été lue. 
                   //Ceci aura pour effet d’empêcher toute nouvelle lecture temps que cardState ne repasse pas à 0 (donc carte absente) avec carte détecté -> ( if(!digitalRead(ACK) && !cardState) ) plus haut
  }
  
  if(digitalRead(ACK)) //absence de carte
  {
//  Serial.println("carte absente")  ;
    cardState = 0; //pret à recevoir une nouvelle carte
    delay (1000); // petit délai d'une seconde
  }
}

void initCard() 
{
    //initialisation de la carte
    digitalWrite (RAZ, LOW); //début RAZ
    digitalWrite (H,LOW); 
    delay (25);
    
    digitalWrite (RAZ, LOW);
    digitalWrite (H, HIGH); 
    delay (25);
    
    digitalWrite (RAZ, LOW);
    digitalWrite (H, LOW); 
        
    delay (50);
    //fin initialisation de la carte
}

byte readCard()
{
  digitalWrite (RAZ, HIGH);
  //debut de lecture carte
  byte tempVal = 0;
  for (byte i=0; i <= 7; i++)
  {
    digitalWrite (H, LOW);
    delay (25);
    tempVal += (digitalRead(S) << i); //On lit la valeur du bit et on ajoute par simple addition la valeur lue décallé de 'i'. (1 << 5) = 0001 0000
    digitalWrite (H, HIGH);
    delay (25);
  }
  
  return tempVal; //On retourne la valeur lue
}

Un grand merci à toi osaka pour ton code car effectivement il y a plein d'idées intéressantes que je vais pouvoir exploiter.
Je récupère la maquette aujourd'hui donc ce soir je fais des tests et on en reparle mais tout cas un grand merci car ça me permet d'élargir mes connaissances