[SOLUCIONADO] Problema con salida digital después de unos segundos de funcionar

Buenos días,

Estoy realizando un pequeño proyecto, que consiste en un lector RFID (RDM6300), basando en una librerias existentes con alguna pequeña modificación por mi parte.

Utilizo Arduino Leonardo, aunque también he probado con Arduino Uno la misma aplicación, quitando la opción de keyboard.

El tema es que en ambos casos me sucede lo mismo. Lee correctamente los códigos RFID y los presenta por teclado o consola dependiendo del Arduino elegido, pero la salida de buzzer, funciona solo durante los primeros segundos de funcionamiento del Arduino con cada una de las lecturas, luego sigue leyendo bien, pero no suena. He probado también a cambiar el buzzer por un led con su correspondiente resistencia, para descartar un posible problema de incompatibilidades entre ambos. He probado a poner unos println en la función beep para comprobar que el hilo de ejecución está pasando por la función, y lo hace bien.

Creo que se puede estar escapando algo y espero que alguno me podáis ayudar con mi problema.

Gracias

LectorRFID.ino

/*
  RFID RDM6300 Arduino library
  (c) Trystan4861 20180323
*/
#include <Keyboard.h>
#include "RDM6300.h"
#define PINTXRFID 10 // PIN del arduino donde se conectará el pin1 (TX) del rdm6300
#define IgnoreTime 2000 // Tiempo de espera entre dos lecturas consecutivas del mismo tag en milisegundos
#define PinBuzzer 11 //PIN del arduino donde se conectará el "+" del buzzer activo

RDM6300 RDM6300(PINTXRFID, IgnoreTime, PinBuzzer);
void setup()
{
  Serial.begin(9600);  // start serial to PC
  RDM6300.begin(); //start rfid
  Keyboard.begin();
  //Serial.println("Ready");
}
void loop()
{
  if (RDM6300.isNewTagReaded()) {
    //Serial.println(RDM6300.DecimalID());
    //Serial.println(RDM6300.HexID());
    Keyboard.print(RDM6300.HexIDCompleto());
    Keyboard.releaseAll();  //Release all keyboard buttons
    //delay(200);             //Wait 200ms before hitting ENTER
    Keyboard.press(KEY_RETURN);    //Hit ENTER
    Keyboard.releaseAll();      //Release all keyboard buttons
  }

}

/*
   Función para sacar mensajes por puerto serie con retorno de carro
   Parametro: message
*/
void setMessage(String message) {
  setMessage(message, true);
}

/*
   Función para sacar mensajes por puerto serie
   Parametro:
   message: Mensaje
   newLine: Retorno de carro Si o No
*/
void setMessage(String message, bool newLine) {
  String timeStamp = String(millis());
  String finalMessage = timeStamp + " - " + message;
  if (newLine) Serial.println(finalMessage);
  else Serial.print(message);
}

RDM6300.cpp

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

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

/*
   numPitidos: numero de repeticiones del pitidos deseadas
   duracion: tiempo del pitido en milisegundos
*/
void RDM6300::beep(int numPitidos, int duracion)
{
  for (int i = 0; i < numPitidos; i++)
  {
    digitalWrite(_PinBuzzer, HIGH);
    int Sleep = millis();
    while (millis() - Sleep < duracion);
    digitalWrite(_PinBuzzer, LOW);
    if (numPitidos > 1) {
      Sleep = millis();
      while (millis() - Sleep < 50);
    }
  }
}
RDM6300::~RDM6300() {};
RDM6300::RDM6300(int RXPin, int waitTime, int 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;
}
String RDM6300::HexIDCompleto()
{
  String result;
  for (int i = 0; i < 5; i++) {
    if (_Payload[i] < 0x10) result += "0";
    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, 50);
      }
    }
    if (_new)
    {
      for (_cnt = 0; _cnt <= 5; _cnt++) _Payload[_cnt] = _TempPayload[_cnt];
    }
    _seq = 0;
    _cnt = 0;
  }
  return _new & _cnt == 0;
}

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, int PinBuzzer = 0);
    ~RDM6300();
    void begin();
    void end();
    void beep(int numPitidos, int duracion);
    String DecimalID();
    String HexID();
    String HexIDCompleto();

  private:
    SoftwareSerial _pRFID;
    bool _ignoreCRC;
    int *_IgnoreSameTime;
    int _RXPin;
    int _seq, _cnt;
    bool _new;
    uint8_t _Payload[6], _TempPayload[6], _temp, _checksum;
    long _LastMillis;
    int _PinBuzzer;
};

#endif

Moderador.
códigos mal posteados.
La etiqueta para códigos es </> no la de citas o quote.
Voy a editarlo por ti esta vez, pero tenerlo presente o leer las normas del foro.

Para comenzar tu trabajo se basa en esta Librería para usar Lector RFID RDM6300

Bueno en este post, nadie hizo comentarios asi que no sabemos si funciona bien, pero descartemos que el autor lo habrá probado su buen tiempo.
Puede que el problema que mencionas sea algo para revisar o puede que sea una mala interpretación de tu parte de cómo se usa la librería.

Lo primero que observo es que no respetas lo que el autor sugiere.
Vuelves a crear un Puerto Serie Virtual en 2,3 para reatacar al RFID6300 y no entiendo para que si ya esta hecho o armado en la clase correspondiente.

En el ejemplo el autor que modifica la librería RF6300 original solo puso

if (RDM6300.isNewTagReaded()) Serial.println(RDM6300.DecimalID());

y con eso funcionaba todo

Lo probaste? Probaste el ejemplo de @trystan4861 tal como esta adaptado a tus pines?

Sería algo asi

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

#include <RDM6300.h>
#define PINTXRFID 10     // PIN del arduino donde se conectará el pin1 (TX) del rdm6300
#define IgnoreTime 2000  // Tiempo de espera entre dos lecturas consecutivas del mismo tag en milisegundos
#define PinBuzzer 11        // 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());
}

Hi,
Tu declaras el pin 11 como el buzzer pero en el setup no estas declarando el pin como output. Trata de declararlo para ver si te funciona.Posiblemente en la libreria no declaran el pin como output.

Tu declaras el pin 11 como el buzzer pero en el setup no estas declarando el pin como output.

Metaconta eso lo hace la clase modificada de la libreria.

Mira la librería que el autor compartió.

RDM6300::RDM6300(int RXPin, int waitTime, int PinBuzzer = 0): _pRFID(RXPin, NULL)
{
  _RXPin = RXPin;
  _IgnoreSameTime = waitTime;
  _LastMillis = 0;
  _PinBuzzer = PinBuzzer;
  if (_PinBuzzer != 0) pinMode(_PinBuzzer, OUTPUT);
}

Y cuando define el objeto pone

#define PinBuzzer 11        // PIN del arduino donde se conectará el "+" del buzzer activo
RDM6300 RDM6300(PINTXRFID,PinBuzzer,IgnoreTime);

con lo que SI esta definido. Ademas dice que funciona la primer vez y luego deja de hacerlo.

Gracias por contestar.

Lo primero que probé fue copiando el código del autor directamente y este no funcionaba directamente, por lo que tuve que arreglar ciertas cosas del mismo. Por ejemplo, la función begin() es sin parámetros en el cpp, pero el le llama con el parámetro "9600". Los cambios que he realizado son los mínimos para que compile y funcione el programa.

No entiendo muy bien este comentario "Lo primero que observo es que no respetas lo que el autor sugiere.
Vuelves a crear un Puerto Serie Virtual en 2,3 para reatacar al RFID6300 y no entiendo para que si ya esta hecho o armado en la clase correspondiente." ¿Te refieres a que hay definido un serial en el programa y un softwareSerial en la librería?

Lo curioso de todo el tema es de que funciona durante unos segundos correctamente: lectura y pitido. Pero luego sigue leyendo bien y no pita, sin embargo veo que pasa correctamente por la función beep.

No entiendo muy bien este comentario "Lo primero que observo es que no respetas lo que el autor sugiere.
Vuelves a crear un Puerto Serie Virtual en 2,3 para reatacar al RFID6300 y no entiendo para que si ya esta hecho o armado en la clase correspondiente." ¿Te refieres a que hay definido un serial en el programa y un softwareSerial en la librería?

Y bueno, a todos nos pasa. Asi como Metaconta habla de que no esta definido el pin del Buzzer yo me equivoqué con el tema de SoftwareSerial. Lo mas lindo es que hice una corrección porque luego la vi, ya que crea un puerto virtual con solo _RXPin si mal recuerdo que lo llama asi, y con NULL en el otro caso.
Con eso te respondo. Lo vi, lo quise responder pero atiendo tantas cosas que se me olvida a veces darle post y pierdo lo que escribo. Igual mala mía. Lo que se ve es lo que está escrito.

Volvamos a la pregunta central. Porqué deja de pitar el buzzer?

Busquemos en la librería si en algun momento le dice que deje de hacerlo.
Posible respuesta. no veo en tu código que uses ::beep(numpitidos, duracion)

creo que te falta poner RDM6300.beep(10, 100); en el setup tal vez?

A la función beep le llama función RDM6300::isNewTagReaded() cuando hace una lectura nueva (beep(1, 50);). De hecho, si le pongo una salidas por el puerto serie antes y después de que suene (como se ve en el ejemplo), si que aparecen correctamente en el monitor serie, tanto cuando funciona el beeper como cuando no.

void RDM6300::beep(int numPitidos, int duracion)
{
  for (int i = 0; i < numPitidos; i++)
  {
    Serial.println("Antes de beep");
    digitalWrite(_PinBuzzer, HIGH);
    int Sleep = millis();
    while (millis() - Sleep < duracion);
    digitalWrite(_PinBuzzer, LOW);
    if (numPitidos > 1) {
      Sleep = millis();
      while (millis() - Sleep < 50);
    }
    Serial.println("Despues de beep");
  }
}

Buenas noches. Creo que el error esta en la propia función "beep". Llega un momento en el que la variable Sleep toma valores negativos y el puerto se queda en LOW. Prueba el siguiente código y lo veras en el monitor serie.

#define _PinBuzzer 7
void setup() {
pinMode(_PinBuzzer, OUTPUT);
Serial.begin (9600);
}

void loop(){
beep(1,50);
}

void beep(int numPitidos, int duracion)
{
  for (int i = 0; i < numPitidos; i++)
  {
    //Serial.println("Antes de beep");
    digitalWrite(_PinBuzzer, HIGH);
    int Sleep = millis();
    while (millis() - Sleep < duracion);
    digitalWrite(_PinBuzzer, LOW);
    if (numPitidos > 1) {
      Sleep = millis();
      while (millis() - Sleep < 50);
    }
    Serial.println(Sleep);
  }
}

Saludos a todos.

Buena observación @gonpezzi, toda variable que se compare con millis() nunca debe ser de un tipo diferente a unsigned long.
Asi que en lugar de int que diga unsigned long Sleep.

Está mal definido (o al menos incorrectamente) el tipo de la variable Sleep como int.
Debería ser unsigned long porque es el tipo que retorna la función millis().
unsigned long no tiene signo, nunca podría dar valores negativos, además es de 32 bits.
int tiene signo (por eso si da valores negativos) pero además es de 16 bits.
Al asignar un unsigned long a un int se pierden los 2 bytes superiores y el signo dependerá del valor que quede luego del "recorte".

Saludos

PD: Bueno... "me ganó" @surbyte porque escribió menos... jaja

Aclaro, puse "o al menos incorrectamente" porque podría efectivamente querer truncar el valor devuelto por millis() por alguna razón esotérica que solo el programador conocería. :grin:

SOLUCIONADO :slight_smile:

Efectivamente estaba mal definida la variable "Sleep = millis()" de la función beep como "int" y debía ser "unsigned long". Ha sido cambiar el tipo de variable, subir al Arduino el programa y funciona correctamente.

Estaba ya pensando que era algo de hardware que fallaba después de algún tiempo, pero cuando probé con dos Arduinos diferentes (UNO y Leonardo) y hacía lo mismo, estaba claro que el problema estaba en otro sitio.

Muchas gracias a todos.

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