Erreur codage decodage weigand

Les boîtiers claviers lecteur RFID pour entrée sécurisée semblent avoir pour une majorité, le gros défaut de laisser accessible de l'extérieur l'accès aux paramétrage. Certes protégé par un code d'accès, mais plus ennuyeux, laissant la sortie push ou celle d'un relais facilement shuntable pour un initié. D'où l'idée de convertir un code keypad arduino 4 x3 en weigand , clavier et antenne RFID seules en externe, inteface nano arduino et boîtier weigand de tonton Ali en interne. Seules les touches du clavier de 0 à 9 seront affectées, tout paramétrage ne pouvant s'exécuter que sur le boîtier interne. L'intérêt étant de conserver leurs grandes possibilités de paramétrage, en toute sécurité.
j'ai réussi à combiner 2 nano v3, l'une codeuse, la seconde décodeuse weigand, toutefois une erreur d'interprétation se traduit sur la console reliée au décodage.
Le codage keypad étant correct, l'affichage à la console validant bien la touche numérique 0 à 9 sélectionnée . Quand à celle du décodage, j'obtiens une valeur hexadécimale ne correspondant pas, évidemment aussi en décimal.
Etrangement comme décalé de +10 à chaque touche en hexa!
le problème n'est sans doute que d'un côté, codage ou décodage, mais lequel?
Voici en premier le code du codeur.



#include "Arduino.h"
#include "wiegandOutput.h"
#include <Keypad.h>//https://github.com/Chris--A/Keypad

const int ROW_NUM = 4;
const int COLUMN_NUM = 3;

char Keys [ROW_NUM][COLUMN_NUM]={
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
  };

  byte pin_rows[ROW_NUM] = {5,4,3,2};
  byte pin_column[COLUMN_NUM] = {9,8,7};
  Keypad keypad = Keypad(makeKeymap(Keys),pin_rows,pin_column,ROW_NUM,COLUMN_NUM);
    
  WiegandOut wiegandOut(12,11);

void setup() {
  Serial.begin(9600);}

void loop(){

  char key = keypad.getKey();
  if (key) {
    Serial.println(key);
   wiegandOut.send(key,26,false); // Send 26 bits with facility code
   }}
type or paste code here

et ensuite le code plus connu du décodeur:

#include <Wiegand.h>

WIEGAND wg;

void setup() {
	Serial.begin(9600);  
	
	// default Wiegand Pin 2 and Pin 3 see image on README.md
	// for non UNO board, use wg.begin(pinD0, pinD1) where pinD0 and pinD1 
	// are the pins connected to D0 and D1 of wiegand reader respectively.
	wg.begin();
}

void loop() {
	if(wg.available())
	{
		Serial.print("Wiegand HEX = ");
		Serial.print(wg.getCode(),HEX);
		Serial.print(", DECIMAL = ");
		Serial.print(wg.getCode());
		Serial.print(", Type W");
		Serial.println(wg.getWiegandType());    
	}
}

voici également ce que je lis en console décodage

Le code ASCII de '1' est 49, de '2' est 50 etc
le code ASCII de '0' est 48

donc la console en décodage vous dit que vous avez tapé 1234567890

je ne vois pas le problème

si vous voulez voir le caractère ASCII faites

#include <Wiegand.h>

WIEGAND wg;

void setup() {
  Serial.begin(9600);  
  wg.begin();
}

void loop() {
  if (wg.available()) 
    Serial.print((char) wg.getCode());
}

explication:

getCode() retourne un unsigned long et donc est imprimé sous forme de nombre par println(). Avec un cast en char, vous lui dites d'interpréter uniquement l'octet de poids faible sous forme de caractère.

Vous pourriez aussi faire sans doute

void loop() {
  if (wg.available()) 
    Serial.write(wg.getCode());
}

qui prendra l'octet de poids faible, sans interprétation.

Bonjour @J-M-L
Question ➜ est-ce qu'une méthode est préférable entre un cast comme ceci

Serial.print((char) wg.getCode());

ou comme cela

Serial.print(static_cast<char>(wg.getCode()));

(De ce que je pense avoir compris cette version est évaluée à la compilation, ce qui permet d'éviter des erreurs de conversion de type)

J'ai vu les deux utilisés et je ne sais pas laquelle choisir :woozy_face:

Cordialement,
Pandaroux007

1 Like

Dans le cas présent, getCode() retourne un uint32_t et le cast (char) d'un uint32_t va prendre l'octet de poids faible (les 8 bits de droite) et donc c''est le comportement attendu - on reste dans la spec et donc pas de souci dans ce cas.

Cela dit, Le static_cast ne change pas la manière dont la troncature se produit ; il rend juste l'intention de la conversion plus explicite et sécurise le processus en vérifiant si le type de conversion est bien adapté ➜ donc oui La méthode à préférer en C++ en général est effectivement d'utiliser static_cast<char>(wg.getCode()).

➜ dans le doute préférez les conversions C++ formelle

PS/ il y a du choix

Cast traditionnel : Pour des conversions simples, mais à éviter dans le code moderne C++ au profit des autres cast.

static_cast : à privilégier pour les conversions entre types compatibles et sûrs.

dynamic_cast : à utiliser pour les conversions dans des hiérarchies de classes polymorphiques.

reinterpret_cast : Utilisé pour des conversions bas niveau et spécifiques entre types totalement différents.

const_cast : Pour ajouter ou retirer la constance d’un objet, généralement à éviter sauf dans des cas très spécifiques.

Donc préférez static_cast dans la majorité des cas, car il est plus sûr et explicite que le cast traditionnel. Utilisez les autres types de cast lorsque la situation l'exige spécifiquement (par exemple, dynamic_cast pour le polymorphisme, reinterpret_cast pour des conversions de bas niveau).

Okey, merci pour l'info @J-M-L :slight_smile:

Merci JML, je n'avais pas compris que le résultat obtenu était écrit en asci, nécessitant modifier le code en conséquence. Bonne fêtes de fin d'année à vous et tous les arduinautes.

vous avez défini les valeurs associées à vos touches ainsi

comme vous avez des apostrophes autour des chiffres, c'est interprété comme "le code ascii du symbole fourni"

si vous mettez

char Keys [ROW_NUM][COLUMN_NUM]={
  {1,2,3},
  {4,5,6},
  {7,8,9},
  {10, 11, 12}
  };

alors vous enverrez la valeur telle que définie dans le tableau

Vous ne pouvez juste pas utiliser la valeur 0 car elle est utilisée par la bibliothèque Keypad pour représenter la valeur NO_KEY (pas d'appui)

Rapide essai cet apm avec les 2 métodes proposées, à chaque saisie d'un chiffre au clavier, j'obtiens un ? (point d'interrogation) inversé à la console décodage!

à quel débit est réglé le terminal ?

9600 bauds

vous pouvez poster les codes ?

le code générateur weigand reste inchangé naturellement.
Voici le code créant l'affichage de point d'interrogation:

#include <Wiegand.h>

WIEGAND wg;

void setup() {
  Serial.begin(9600);  
  wg.begin();
}

void loop() {
  if (wg.available()) 
    Serial.print((char) wg.getCode());
}

Voici l'écran console obtenu:

Paradoxallement en rétablissant ensuite pour essai les codes initiaux tels que à l'origine de ce post, j'obtiens un affichage quelque peu différent tant en hexa qu'en décimal, identique mais écrit différemment.

alors que hier j'obtennais:

comment vous faites l'émission ? vous avez changé le code ?

l'émission reste inchangée, le code également.
je viens à l'instant de m'appercevoir avoir interverti D0 et D1 au remontage, suite avoir fait un essai sur un boîtier acces control en réception weigand puisque le code généré semble correct. Déception, l'entrée de ce boîtier semble réservée à une autre fonction wiegand ( RFID ou autre) , mais ne permet vraisemblablement pas de simuler un clavier externe. je devrais trouver une autre façon pour agir de la sorte. Par contre, en rétablissant le bon ordre pour D0 et D1, j'ai retrouvé l'affichage comme précédemment des codes hexa et déci.

et mon code ne fonctionne pas ?

#include <Wiegand.h>

WIEGAND wg;

void setup() {
  Serial.begin(9600);  
  wg.begin();
}

void loop() {
  if (wg.available()) 
    Serial.print((char) wg.getCode());
}

pouvez vous préciser quelle bibliothèque Wiegand.h vous utilisez ?

Et pardonnez-moi cette inversion, puisqu'également , elle était à l'origine de l'erreur d'affichage. En résumé, votre proposition fonctionne bel et bien, la console affiche la valeur précise de la touche enfoncée. Il me reste a trouver un boîtier control access acceptant de recevoir un code wiegand qui remplace celui par son propre clavier. Ou à défaut, abandonner wiegand pour le classique keypad et les sorties de la Nano affectées pour chacune aux touches clavier du dit boîtier, via
optocoupleurs soudés en // ou directement si comme parfois chacune se ferme à la masse lorsqu'elle est sillicitée. Ou peut être avez vous une solution plus intéressante à proposer?

pas de souci — c'est rassurant :slight_smile:


oui pas simple de trouver cela

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.