Librería para usar Lector RFID RDM6300 (EDITADO: 20180419)

Hola, esta es mi primera aportación y no se siquiera si lo estoy colocando en el sitio correcto... pero bueno... si no es así... espero que lo mueva al sitio indicado quien tenga potestad para ello ^w^

Antes que nada tengo que decir que hace escasos días que he empezado con el tema de arduino... y encima la programación en C no es lo mio... y mucho menos la electrónica... pero bueno... cuando te "obligan" a meterte con el tema... poco puedes hacer mas que apechugar y tirar para adelante...

Me pidieron realizar un proyecto algo complicado y con muchos sensores y demás... me topé con el problema de que cuantas más cosas agregaba menos pines libres me quedaban en el arduino... como es normal :stuck_out_tongue_closed_eyes:

Además me ha tocado trabajar con el RDM6300 dado que disponemos de muchos tags de 125mhz que teníamos olvidados en un cajón cogiendo polvo...

Existe una librería ya para el RDM6300 pero no se ajustaba totalmente a mis necesidades así que tomándola de base... junto con mucho "googlear" al final conseguí hacer una librería de fácil uso y que me permite con unas pocas líneas de código en el archivo .ino leer un tag una sola vez incluso cuando no se retira el mismo de la antena de recepción del RDM6300, ya que el RDM6300 sigue leyendo indefinidamente el id del tag mientras no lo retiras... Además incluso retirando el tag, si lo vuelves a acercar en un tiempo inferior al indicado lo ignora, para así evitar que por error sea leida dos o más veces, y eso es debido a que en el proyecto hay que leer tags que identifican una cuenta con un saldo de créditos para el uso del sistema y si por error se lee más de una vez... se puede liar parda...

Sin más les paso la libreria:
Contenido de RDM6300.h


/*
  RFID RDM6300 data decoder library
  (c) Stephane Driussi 20150623
  Modded Trystan4861@gmail.com
*/

#ifndef RDM6300_H
#define RDM6300_H

#include <RDM6300.h>
#include "SoftwareSerial.h"

class RDM6300 {
    public:
        bool isNewTagReaded();
 RDM6300(int RXPin, int waitTime,uint8_t PinBuzzer=0);
 ~RDM6300();
 void begin();
 void end();
 void beep(int amount);
 String DecimalID();
 String HexID();
    private:
 SoftwareSerial _pRFID;
 bool _ignoreCRC;
 int *_IgnoreSameTime;
 int _RXPin;
        int _seq, _cnt;
        bool _new;
        uint8_t _Payload[6],_TempPayload[6],_temp, _checksum;
 long _LastMillis;
 uint8_t _PinBuzzer;
};

#endif

Contenido de RDM6300.cpp


/*
  RFID RDM6300 data decoder library
  (c) Stephane Driussi 20150623
  Modded Trystan4861@gmail.com
*/

#include <Arduino.h>
#include "RDM6300.h"
#include "SoftwareSerial.h"
void RDM6300::beep(int amount)
{
  for (int i=0;i<amount;i++)
  {
    digitalWrite(_PinBuzzer,HIGH);
    int Sleep=millis();
    while(millis()-Sleep<200);
    digitalWrite(_PinBuzzer,LOW);
    if (amount>1){Sleep=millis();while(millis()-Sleep<50);}
  }
}
RDM6300::~RDM6300(){};
RDM6300::RDM6300(int RXPin,int waitTime,uint8_t PinBuzzer=0):_pRFID(RXPin,NULL)
{
 _RXPin=RXPin;
 _IgnoreSameTime = waitTime;
 _LastMillis=0;
 _PinBuzzer=PinBuzzer;
 if (_PinBuzzer!=0) pinMode(_PinBuzzer, OUTPUT);
}
void RDM6300::begin()
{
 _pRFID.begin(9600);
}

void RDM6300::end()
{
 _pRFID.end();
}
String RDM6300::DecimalID()
{
 uint32_t foo= (uint32_t) _Payload[1] << 24;
 for (int i=2;i<5;i++) foo |= (uint32_t) _Payload[i] << ((4-i)*8);
 String result=(String) foo;
 while (result.length()<10) result="0" + result;
 return result;
}
String RDM6300::HexID()
{
 String result;
 for (int i=1;i<5;i++) result+=String(_Payload[i], HEX);
 result.toUpperCase();
 return result;
}
bool RDM6300::isNewTagReaded()
{
 if (!_pRFID.isListening()) _pRFID.listen();
 uint8_t input=_pRFID.read();
 delay(20);
 switch (input)
 {
 case 255:
 return false;
 case 2:
 _cnt=0;
 _checksum = 0; 
 _seq = 1;
 _temp = 0;
 _new = false;
 break;
 default:
 switch(_seq)
 {
 case 1:
 _temp = input - 48;
 if (_temp > 9) _temp -= 7;
 _seq = 2;
 break;
 case 2:
 input -= 48;
 if (input > 9) input -= 7;
 _temp = (_temp << 4) | input;
 if (_Payload[_cnt] != _temp) _new = true;
 _TempPayload[_cnt++] = _temp;
 if(_cnt > 5) _seq = 3; 
 else
 { 
 _seq=1; 
 _checksum ^= _temp;
 }  
 break;
 default:
 if(input == 0x03) _seq = 4; 
 else _seq = 0;
 break;
 }
 break;
 }
  if (_seq == 4) // all data in buffer
  {
    if (_checksum == _TempPayload[5]) 
 {
 _new=_new && true;
 if (!_new) if ((millis()-_LastMillis>_IgnoreSameTime) || (_LastMillis==0)) _new = true;
 if (_new) 
 {
 _LastMillis=millis();
 beep(1);
 }
 }
 if (_new)
 {
 for(_cnt=0;_cnt<=5;_cnt++) _Payload[_cnt]=_TempPayload[_cnt];
 }
    _seq = 0;
    _cnt = 0;
  }
  return _new & _cnt==0;
}

Y por último un pequeño programa de ejemplo de su uso...

/*
RFID RDM6300 Arduino library
(c) Trystan4861 20180323
*/

#include <RDM6300.h>
#define PINTXRFID 6 // PIN del arduino donde se conectará el pin1 (TX) del rdm6300
#define IgnoreTime 6000 // Tiempo de espera entre dos lecturas consecutivas del mismo tag en milisegundos
#define PinBuzzer 7 //PIN del arduino donde se conectará el "+" del buzzer activo
RDM6300 RDM6300(PINTXRFID,PinBuzzer,IgnoreTime); 
void setup()
{
  Serial.begin(9600);  // start serial to PC 
  RDM6300.begin(9600); //start rfid
  Serial.println("Ready");
}
void loop()
{
    if (RDM6300.isNewTagReaded()) Serial.println(RDM6300.DecimalID());
}

(20180327) - Edición: Añadida la función HexID
(20180419) - Edición: Añadida la función beep para hacer que un buzzer suene cuando lea un tag, añadido control de estado de escucha para asegurarse de que cada vez que se usa la función isNewTagReaded el softwareserial se encuentra "escuchando" (útil cuando tienes más de un softwareserial declarado en tu programa, como por ejemplo el uso simultáneo con un ESP8266 por comandos AT a través de UART)

Buenas, como dije me estoy embarcando en esto de la electrónica en estos momentos... y sé que se pueden usar multiplexores o conversores de ISP a I2C, con lo que solventaría muchos de los problemas... pero hace casi 20 años que di sistemas digitales en la uni, de pasada, porque era obligatoria en la carrera que estaba estudiando... En estos momentos estoy en el proceso de adaptación y siempre puede darse el caso de que alguien necesite realizar algo parecido y pueda sacar probecho a mi trabajo... por eso lo he puesto aquí.

Lo del delay es por un problema de timming al guardar en el buffer y acceder luego a él... no encontré otra solución, por eso puse que si tenían mejor forma de hacerlo, me dijesen...

El tema de los millis es para calcular el tiempo pasado para poder volver a leer consecutivamente el mismo tag y que diga que es uno nuevo, mientras lo ignora si aún no pasó ese tiempo, para evitar casos como en los que el uso del tag conlleve por ejemplo gastos de dinero o de créditos. Si imaginamos que el tag es un monedero electrónico para comprar billetes de bus... no vas a pagar 2 o más billetes para un solo viaje... ¿no?

El autor original... podría decirse que soy yo... el de la librería original no se molestaba en leer del RFID... él lo quería todo hecho y lo que hacía era esperar a que se le pasase caracter por caracter lo que uno había obtenido desde el lector y sólo indicaba si era un tag válido o no calculando longitud y checsum del mismo...

Yo lo que hice fue unificar las dos cosas, el procesado del buffer (tag) con la lectura del propio RFID dentro de la librería, dando al usuario final la facilidad de usar unos pocos comandos, convirtiendo todo el tema en una especie de... "caja negra" con la que no tiene que preocuparse de nada más que indicar en qué pin está conectada la patilla TX de la placa RDM6300 y preguntar si hay un tag nuevo o no, dando a su vez dos formas distintas de representar el tag en formato texto para un fácil procesamiento posterior... como enviarlo a un servidor de bases de datos o cualquier otra cosa... también se puede dejar público el array donde se almacena byte a byte por si prefieres trabajar con el ID de esa forma..

Igualmente se agradece tu comentario :slight_smile: