// RFIDuino // Marc Boon // April 2009 // Controls a SonMicro SM130/mini RFID reader module by I2C // Arduino analog input 4 is I2C SDA (SM130/mini pin 10/6) // Arduino analog input 5 is I2C SCL (SM130/mini pin 9/5) // Arduino digital input 4 is DREADY (SM130/mini pin 21/18) // Arduino digital output 3 is RESET (SM130/mini pin 18/14) #include // I2C address of SM130 module #define SM130 0x42 // SM130 IO pins int pinRESET = 3; int pinDREADY = 4 ; // SM130 commands #define CMD_RESET 0x80 #define CMD_READ_VERSION 0x81 #define CMD_SEEK_TAG 0x82 #define CMD_SELECT_TAG 0x83 // States #define STATE_RESET 0 #define STATE_IDLE 1 #define STATE_SEEK 2 #define STATE_DRDY 3 int state = STATE_RESET; int response[10]; void setup() { // init IO ports pinMode(pinRESET, OUTPUT); pinMode(pinDREADY, INPUT); Wire.begin(); // init i2c bus master Serial.begin(115200); // init serial port Serial.println("RFIDuino"); sm130_reset(); // reset SM130 (starts seek mode) } void loop() { // state machine switch(state) { case STATE_RESET: { // read firmware version sm130_cmd(CMD_READ_VERSION); delay(5); sm130_readBytes(response, 10); int len = response[0]; if(len > 0) { int i = 2; Serial.print("Version "); while(--len > 0) { Serial.print(char(response[i++])); } Serial.print('\n'); state = STATE_IDLE; } delay(500); break; } case STATE_IDLE: { // wait for DREADY to go LOW if(!digitalRead(pinDREADY)) { // enter seek mode sm130_cmd(CMD_SEEK_TAG); state = STATE_SEEK; } break; } case STATE_SEEK: { // wait for DREADY to go HIGH if(digitalRead(pinDREADY)) { // tag detected state = STATE_DRDY; } break; } case STATE_DRDY: { // read response sm130_readBytes(response, 10); int len = response[0]; if(len > 0) { int type = response[2]; switch(type) { case 1: Serial.print("Mifare UL: "); break; case 2: Serial.print("Mifare 1K: "); break; case 3: Serial.print("Mifare 4K: "); break; default: Serial.print("Unknown Tag: "); } printArrayHex(response + 3, len - 2); Serial.print('\n'); state = STATE_IDLE; } break; } default: // unknown state -> reset sm130_reset(); } } void sm130_reset() { digitalWrite(pinRESET, HIGH); delay(10); digitalWrite(pinRESET, LOW); delay(500); state = STATE_RESET; } void sm130_waitReady() { while(digitalRead(pinDREADY)); // first wait until DREADY is LOW while(!digitalRead(pinDREADY)); // then wait until DREADY is HIGH } void sm130_cmd(int cmd) { Wire.beginTransmission(SM130); Wire.send(1); // length is 1 byte Wire.send(cmd); // command Wire.send(++cmd); // checksum (sum of previous 2 bytes) Wire.endTransmission(); } int sm130_readBytes(int data[], int len) { Wire.requestFrom(SM130, len); int n = Wire.available(); for(int i = 0; i < n; ) { data[i++] = Wire.receive(); } return n; } void printArrayHex(int array[], int len) { for(int i = 0; i < len; ) { if(array[i] < 0x10) { Serial.print('0'); } Serial.print(array[i++], HEX); if(i < len) { Serial.print(' '); } } }