Problem accessing RFID module with I2C

Has anyone had any success using the YHY502 rfid reader from Emartee with the I2C interface? I can't get any response apart from a string of FFs, even using the ByVac usb-I2C adapter. None of their sample code is for I2C, and their responses are always non-I2C specific, so I wonder if it actually works...

What address are you using. Do you know the arduino uses a 7 bit address, most data sheets quote an 8 bit address where the least significant bit is the read / write bit. If this is the case shift the address by one place to the right for use with the arduino.

Here’s the manual for the I2C version: http://www.ehuoyan.com/download/module/YHY502A_v2.6_CN.pdf

Unfortunately it is in Chinese. Perhaps some of the diagrams and tables will be of help.

Hello,

Were you able to get it working? I'm having the same problem. The arduino gets unresponsive when trying to read data from it.

I tried ardubus (kind of pirate-bus for arduino) in order to better troubleshoot, but so far without much results.

I think that it you put the A0, A1, A2 pins at 5v, it will actually mean 111 EDIT 000 /EDIT (negative logic). Therefore, according to this example, the write address should be 0xa0 and the read address should be 0xa1.

I suspect that maybe the problem is related with the I2c Clock. By dafaullt arduino has i2c woring @ 100khz, and t he datasheet has a small reference like: "rate: 40k" - not much explicative.

If you want the datasheet in english I can e-mail it to you.

Thanks João from sunny Portugal

I think that it you put the A0, A1, A2 pins at 5v, it will actually mean 111 (negative logic)

That is not negative logic that is positive logic.

the write address should be 0xa0 and the read address should be 0xa1.

Wrong sort of address the arduino doesn't use read different read and write address. If it is 0xa0 the shift one place to the right and use 0x50 for both read and write.

if you are using I2C devices check - http://www.gammon.com.au/forum/?id=10896 - so much good info

Search for "I2C Scanner" to check the addresses used.

Search for "I2C Scanner" to check the addresses used.

If it is 0xa0 the shift one place to the right and use 0x50 for both read and write.

Both accurate advice.

Here is that scanner sketch, it will tell you what address you have set the device up for, I changed it to print out the address in HEX:

/**
 * I2CScanner.pde -- I2C bus scanner for Arduino
 *
 * 2009, Tod E. Kurt, http://todbot.com/blog/
 *
 */

#include "Wire.h"
extern "C" { 
#include "utility/twi.h"  // from Wire library, so we can do bus scanning
}

// Scan the I2C bus between addresses from_addr and to_addr.
// On each address, call the callback function with the address and result.
// If result==0, address was found, otherwise, address wasn't found
// (can use result to potentially get other status on the I2C bus, see twi.c)
// Assumes Wire.begin() has already been called
void scanI2CBus(byte from_addr, byte to_addr, 
                void(*callback)(byte address, byte result) ) 
{
  byte rc;
  byte data = 0; // not used, just an address to feed to twi_writeTo()
  for( byte addr = from_addr; addr <= to_addr; addr++ ) {
    rc = twi_writeTo(addr, &data, 0, 1);
    callback( addr, rc );
  }
}

// Called when address is found in scanI2CBus()
// Feel free to change this as needed
// (like adding I2C comm code to figure out what kind of I2C device is there)
void scanFunc( byte addr, byte result ) {
  Serial.print("addr: ");
  Serial.print(addr,HEX);
  Serial.print( (result==0) ? " found!":"       ");
  Serial.print( (addr%4) ? "\t":"\n");
}


byte start_address = 1;
byte end_address = 127;

// standard Arduino setup()
void setup()
{
    delay(2000);
    Wire.begin();
    Serial.begin(38400);
    Serial.println("\nI2CScanner ready!");

    Serial.print("starting scanning of I2C bus from ");
    Serial.print(start_address,HEX);
    Serial.print(" to ");
    Serial.print(end_address,HEX);
    Serial.println("...Hex");

    // start the scan, will call "scanFunc()" on result from each address
    scanI2CBus( start_address, end_address, scanFunc );

    Serial.println("\ndone");
}

// standard Arduino loop()
void loop() 
{
    // Nothing to do here, so we'll just blink the built-in LED
    digitalWrite(13,HIGH);
    delay(300);
    digitalWrite(13,LOW);
    delay(300);
}

Lefty

Hello,

Thanks for your prompt replies! My original post had a typo. I meant "000" instead of "111", so it's really negative logic. I have corrected it.

Meanwhile I was able to find the link where I donwloaded the english datasheet: https://docs.google.com/viewer?a=v&pid=explorer&chrome=true&srcid=0B2_rhDNAxM4sNDdiYzdiZGEtNjA1Ni00NGY1LWJhNTktNDM5YzA3ODE0ZDY3&hl=en_US

I'll try this I2C scanner this weekend, but meanwhile, I'm still confused with the addressing: The chapter 4.2 of the datasheet says the first 4 bytes are always 1010 (0xA0) and the next three are the "configrable address" bytes. The last bit is meant for the R/W operation (0 for write and 1 for read). Something like [1010][A2][A1][A0][R/W]. They give an example: If you define A2=0, A1=0, A0=1 the writting address should be [1010][0][0][1]0 and the read address should be [1010][0][0][1]1. So, do you mean it's not possible to program arduino to write in one address and then read on another?

In my design, I have all the A bits connected to +5v, so according to negative logic it means "000". I'm trying to access a simple funtionality that is "read module serial number". For doing this I have to send a I2C frame with the following: 1) RFID write module address: 0xA0 2) Lenght of the command (comand + checksum) : 0x02 3) Command ("give me you serial ID"= 0x02) : 0x02 4) XOR schecksum (lenght + command): 0x00

Then, I suppostly need to read some bytes in 0xA1, right? If its OK, the module will send 7 bytes: 1) Lengt (6 bytes - the length byte itself doesn't count): 0x06 2) Command he is answering (0x02) : 0x02 3) 4 bytes of the command serial ID : 0xXX 0xXX 0xXX 0xXX 4) XOR checksum : 0xXX

If it's not OK, the module will send 3 bytes: 1) Lengt (2 bytes - the length byte itself doesn't count): 0x02 2) Command error 0xFD 3) XOR checksum 0xFF

In a perfect world my code would work, but I don't know what I may be doing wrong. The code stops at the printout "data sent. now receiving". I'll try the 0x50 address this weekend, but I don't understand how it may work... =(

void readrfidtype()
{    
     Wire.beginTransmission(0xA0);  // join I2C, talk to I2C-RFID @ 1010[0000]0 (write) - pins at 5v
                                                // remember: negative logic.
     Wire.send(0x02);                   // Length of command - 2 bytes
     Wire.send(0x02);                   // Read module serial
     Wire.send(0x00);                   // Checksum (0x02 + 0x01)
     Wire.endTransmission();         // leave I2C bus
     Serial.print("data sent. now receiving");         // print the character
     Wire.requestFrom(0xA1,6);     // Read from 10100001 (read)
     // delay(5);

    while(Wire.available())    // slave may send less than requested
  { 
    byte z = Wire.receive();      // receive a byte as character
    Serial.print("RFID: ");         // print the character
    Serial.print(z, HEX);          // print the character
    Serial.print(" ");
  }
 Wire.endTransmission(); 
 Serial.print(" \nthat's all for RFID \n");
}

If this code is really correct, could it be a clock speed problem? The datasheet is not really clear about this, but they state in chapter 4.2: "rate: 40k". Should I change the I2C clock in arduino?

Thanks in advance! João

In your examle: "Something like [1010][A2][A1][A0][R/W]." the arduino I2C library needs you to just send the first seven bits shifted one bit right so, if the "A" bits are all low: [1010][0][0][0] = I2C hex address of 0x50. If the "A" bits are all high: Something like [1010][1][1][1] = 0x57

The I2C scanner sketch should bare that out, if you have the I2C bus and device wired correctly.

Lefty

It works!

With the I2C address scanner I was able to know which address is the module. After all it doesn't use negative logic. I have all the address pins at +5v and the found address was 0x57 (b1010111). I suspected that it had negative logic because it was the only output (even if incomplete) that I had previoulsy received with ardubus...

Then, with ardubus http://code.google.com/p/ardubus/ I did the following commands:

ArduBus v0.3 KungFu Labs - http://www.kungfulabs.com ArduBus Copyright (C) 2010 Santiago Reig

Select I2C bus speed: 1. 50 kHz 2. 100 kHz 3. 400 kHz 4. 40 kHz I2C>3 400 kHz selected 202 I2C READY 205 I2C PULLUP ON I2C>{0x57 0x02 0x02 0x00} 210 I2C START CONDITION 220 I2C WRITE: 0x57 220 I2C WRITE: 0x2 220 I2C WRITE: 0x2 220 I2C WRITE: 0x0 240 I2C STOP CONDITION I2C>{0x57 rrrrrr} 210 I2C START CONDITION 230 I2C READ: 0x6 230 I2C READ: 0x2 230 I2C READ: 0xF 230 I2C READ: 0x4 230 I2C READ: 0x70 230 I2C READ: 0x40 240 I2C STOP CONDITION

So this is the module serial number. I already tried different commands as well as my code and they all work now! And by the way, if you noticed the ardubus output, it works at 400kHz!

Thanks for your help!!! João