RC-S620Sの使い方について

Arduino に関するご質問などはこちらへ。

RC-S620Sの使い方について

投稿記事by 樫原 輝 » 2014年7月08日(火) 16:06

ご無沙汰しております。
樫原です。

今、ArduinoでFelicaのライター/リーダを使おうとしています。
以下のように配線し、スケッチを書いたところ、FelicaのIDmを読み取ることは出来たのですが、何かゴミが入ってしまいます。
コメントアウトをし、Serial.printlnに関わるところを一つづつ潰して試したのですが、やはり消えません。
アドバイスよろしくお願いします。

配線
RCS620Sコネクタ   Arduino UNO
6(GND)<------------------->GND
3(TXD)<------------------->0(RX)
2(RCD)<------------------->1(TX)
1(VDD)<------------------->3.3V
参考 http://www.switch-science.com/catalog/1029/

↓スケッチ
コード: 全て選択
#include "RCS620S.h"

#define COMMAND_TIMEOUT 400
#define POLLING_INTERVAL 500
#define LED_PIN 13

RCS620S rcs620s;

void setup(){
int ret;

pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);

  Serial.begin(115200);
 
  ret = rcs620s.initDevice();
  while(!ret){}
}

void loop(){
  int ret, i;

  // Polling
  digitalWrite(LED_PIN, HIGH);
  rcs620s.timeout = COMMAND_TIMEOUT;
  ret = rcs620s.polling();
 
  if(ret) {
   
    for(i = 0; i < 8; i++)
    {
      if(rcs620s.idm[i] / 0x10 == 0) Serial.print(0);
      Serial.print(rcs620s.idm[i], HEX);
    }
  } else {
    Serial.print("Polling...");
  }
 
  rcs620s.rfOff();
  digitalWrite(LED_PIN, LOW);
  delay(POLLING_INTERVAL);
   
}


↓ライブラリ(RCS620S.h)
コード: 全て選択
/*
* RC-S620/S sample library for Arduino
*
* Copyright 2010 Sony Corporation
*/

#include <inttypes.h>

#ifndef RCS620S_H_
#define RCS620S_H_

/* --------------------------------
* Constant
* -------------------------------- */

#define RCS620S_MAX_CARD_RESPONSE_LEN    254
#define RCS620S_MAX_RW_RESPONSE_LEN      265

/* --------------------------------
* Class Declaration
* -------------------------------- */

class RCS620S
{
public:
    RCS620S();

    int initDevice(void);
    int polling(uint16_t systemCode = 0xffff);
    int cardCommand(
        const uint8_t* command,
        uint8_t commandLen,
        uint8_t response[RCS620S_MAX_CARD_RESPONSE_LEN],
        uint8_t* responseLen);
    int rfOff(void);

    int push(
        const uint8_t* data,
        uint8_t dataLen);

private:
    int rwCommand(
        const uint8_t* command,
        uint16_t commandLen,
        uint8_t response[RCS620S_MAX_RW_RESPONSE_LEN],
        uint16_t* responseLen);
    void cancel(void);
    uint8_t calcDCS(
        const uint8_t* data,
        uint16_t len);

    void writeSerial(
        const uint8_t* data,
        uint16_t len);
    int readSerial(
        uint8_t* data,
        uint16_t len);
    void flushSerial(void);

    int checkTimeout(unsigned long t0);

public:
    unsigned long timeout;
    uint8_t idm[8];
    uint8_t pmm[8];
};

#endif /* !RCS620S_H_ */



↓ライブラリ(RCS620S.cpp)
コード: 全て選択
/*
* RC-S620/S sample library for Arduino
*
* Copyright 2010 Sony Corporation
*/

#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "Arduino.h"
#include "Print.h"
#include "HardwareSerial.h"

#include "RCS620S.h"

/* --------------------------------
* Constant
* -------------------------------- */

#define RCS620S_DEFAULT_TIMEOUT  1000

/* --------------------------------
* Variable
* -------------------------------- */

/* --------------------------------
* Prototype Declaration
* -------------------------------- */

/* --------------------------------
* Macro
* -------------------------------- */

/* --------------------------------
* Function
* -------------------------------- */

/* ------------------------
* public
* ------------------------ */

RCS620S::RCS620S()
{
    this->timeout = RCS620S_DEFAULT_TIMEOUT;
}

int RCS620S::initDevice(void)
{
    int ret;
    uint8_t response[RCS620S_MAX_RW_RESPONSE_LEN];
    uint16_t responseLen;

    /* RFConfiguration (various timings) */
    ret = rwCommand((const uint8_t*)"\xd4\x32\x02\x00\x00\x00", 6,
                    response, &responseLen);
    if (!ret || (responseLen != 2) ||
        (memcmp(response, "\xd5\x33", 2) != 0)) {
        return 0;
    }

    /* RFConfiguration (max retries) */
    ret = rwCommand((const uint8_t*)"\xd4\x32\x05\x00\x00\x00", 6,
                    response, &responseLen);
    if (!ret || (responseLen != 2) ||
        (memcmp(response, "\xd5\x33", 2) != 0)) {
        return 0;
    }

    /* RFConfiguration (additional wait time = 24ms) */
    ret = rwCommand((const uint8_t*)"\xd4\x32\x81\xb7", 4,
                    response, &responseLen);
    if (!ret || (responseLen != 2) ||
        (memcmp(response, "\xd5\x33", 2) != 0)) {
        return 0;
    }

    return 1;
}

int RCS620S::polling(uint16_t systemCode)
{
    int ret;
    uint8_t buf[9];
    uint8_t response[RCS620S_MAX_RW_RESPONSE_LEN];
    uint16_t responseLen;

    /* InListPassiveTarget */
    memcpy(buf, "\xd4\x4a\x01\x01\x00\xff\xff\x00\x00", 9);
    buf[5] = (uint8_t)((systemCode >> 8) & 0xff);
    buf[6] = (uint8_t)((systemCode >> 0) & 0xff);

    ret = rwCommand(buf, 9, response, &responseLen);
    if (!ret || (responseLen != 22) ||
        (memcmp(response, "\xd5\x4b\x01\x01\x12\x01", 6) != 0)) {
        return 0;
    }

    memcpy(this->idm, response + 6, 8);
    memcpy(this->pmm, response + 14, 8);

    return 1;
}

int RCS620S::cardCommand(
    const uint8_t* command,
    uint8_t commandLen,
    uint8_t response[RCS620S_MAX_CARD_RESPONSE_LEN],
    uint8_t* responseLen)
{
    int ret;
    uint16_t commandTimeout;
    uint8_t buf[RCS620S_MAX_RW_RESPONSE_LEN];
    uint16_t len;

    if (this->timeout >= (0x10000 / 2)) {
        commandTimeout = 0xffff;
    } else {
        commandTimeout = (uint16_t)(this->timeout * 2);
    }

    /* CommunicateThruEX */
    buf[0] = 0xd4;
    buf[1] = 0xa0;
    buf[2] = (uint8_t)((commandTimeout >> 0) & 0xff);
    buf[3] = (uint8_t)((commandTimeout >> 8) & 0xff);
    buf[4] = (uint8_t)(commandLen + 1);
    memcpy(buf + 5, command, commandLen);

    ret = rwCommand(buf, 5 + commandLen, buf, &len);
    if (!ret || (len < 4) ||
        (buf[0] != 0xd5) || (buf[1] != 0xa1) || (buf[2] != 0x00) ||
        (len != (3 + buf[3]))) {
        return 0;
    }

    *responseLen = (uint8_t)(buf[3] - 1);
    memcpy(response, buf + 4, *responseLen);

    return 1;
}

int RCS620S::rfOff(void)
{
    int ret;
    uint8_t response[RCS620S_MAX_RW_RESPONSE_LEN];
    uint16_t responseLen;

    /* RFConfiguration (RF field) */
    ret = rwCommand((const uint8_t*)"\xd4\x32\x01\x00", 4,
                    response, &responseLen);
    if (!ret || (responseLen != 2) ||
        (memcmp(response, "\xd5\x33", 2) != 0)) {
        return 0;
    }

    return 1;
}

int RCS620S::push(
    const uint8_t* data,
    uint8_t dataLen)
{
    int ret;
    uint8_t buf[RCS620S_MAX_CARD_RESPONSE_LEN];
    uint8_t responseLen;

    if (dataLen > 224) {
        return 0;
    }

    /* Push */
    buf[0] = 0xb0;
    memcpy(buf + 1, this->idm, 8);
    buf[9] = dataLen;
    memcpy(buf + 10, data, dataLen);

    ret = cardCommand(buf, 10 + dataLen, buf, &responseLen);
    if (!ret || (responseLen != 10) || (buf[0] != 0xb1) ||
        (memcmp(buf + 1, this->idm, 8) != 0) || (buf[9] != dataLen)) {
        return 0;
    }

    buf[0] = 0xa4;
    memcpy(buf + 1, this->idm, 8);
    buf[9] = 0x00;

    ret = cardCommand(buf, 10, buf, &responseLen);
    if (!ret || (responseLen != 10) || (buf[0] != 0xa5) ||
        (memcmp(buf + 1, this->idm, 8) != 0) || (buf[9] != 0x00)) {
        return 0;
    }

    delay(1000);

    return 1;
}

/* ------------------------
* private
* ------------------------ */

int RCS620S::rwCommand(
    const uint8_t* command,
    uint16_t commandLen,
    uint8_t response[RCS620S_MAX_RW_RESPONSE_LEN],
    uint16_t* responseLen)
{
    int ret;
    uint8_t buf[9];

    flushSerial();

    uint8_t dcs = calcDCS(command, commandLen);

    /* transmit the command */
    buf[0] = 0x00;
    buf[1] = 0x00;
    buf[2] = 0xff;
    if (commandLen <= 255) {
        /* normal frame */
        buf[3] = commandLen;
        buf[4] = (uint8_t)-buf[3];
        writeSerial(buf, 5);
    } else {
        /* extended frame */
        buf[3] = 0xff;
        buf[4] = 0xff;
        buf[5] = (uint8_t)((commandLen >> 8) & 0xff);
        buf[6] = (uint8_t)((commandLen >> 0) & 0xff);
        buf[7] = (uint8_t)-(buf[5] + buf[6]);
        writeSerial(buf, 8);
    }
    writeSerial(command, commandLen);
    buf[0] = dcs;
    buf[1] = 0x00;
    writeSerial(buf, 2);

    /* receive an ACK */
    ret = readSerial(buf, 6);
    if (!ret || (memcmp(buf, "\x00\x00\xff\x00\xff\x00", 6) != 0)) {
        cancel();
        return 0;
    }

    /* receive a response */
    ret = readSerial(buf, 5);
    if (!ret) {
        cancel();
        return 0;
    } else if  (memcmp(buf, "\x00\x00\xff", 3) != 0) {
        return 0;
    }
    if ((buf[3] == 0xff) && (buf[4] == 0xff)) {
        ret = readSerial(buf + 5, 3);
        if (!ret || (((buf[5] + buf[6] + buf[7]) & 0xff) != 0)) {
            return 0;
        }
        *responseLen = (((uint16_t)buf[5] << 8) |
                        ((uint16_t)buf[6] << 0));
    } else {
        if (((buf[3] + buf[4]) & 0xff) != 0) {
            return 0;
        }
        *responseLen = buf[3];
    }
    if (*responseLen > RCS620S_MAX_RW_RESPONSE_LEN) {
        return 0;
    }

    ret = readSerial(response, *responseLen);
    if (!ret) {
        cancel();
        return 0;
    }

    dcs = calcDCS(response, *responseLen);

    ret = readSerial(buf, 2);
    if (!ret || (buf[0] != dcs) || (buf[1] != 0x00)) {
        cancel();
        return 0;
    }

    return 1;
}

void RCS620S::cancel(void)
{
    /* transmit an ACK */
  writeSerial((const uint8_t*)"\x00\x00\xff\x00\xff\x00", 6);
    delay(1);
    flushSerial();
}

uint8_t RCS620S::calcDCS(
    const uint8_t* data,
    uint16_t len)
{
    uint8_t sum = 0;

    for (uint16_t i = 0; i < len; i++) {
        sum += data[i];
    }

    return (uint8_t)-(sum & 0xff);
}

void RCS620S::writeSerial(
    const uint8_t* data,
    uint16_t len)
{
    Serial.write(data, len);
}

int RCS620S::readSerial(
    uint8_t* data,
    uint16_t len)
{
    uint16_t nread = 0;
    unsigned long t0 = millis();

    while (nread < len) {
        if (checkTimeout(t0)) {
            return 0;
        }

        if (Serial.available() > 0) {
            data[nread] = Serial.read();
            nread++;
        }
    }

    return 1;
}

void RCS620S::flushSerial(void)
{
    Serial.flush();
}

int RCS620S::checkTimeout(unsigned long t0)
{
    unsigned long t = millis();

    if ((t - t0) >= this->timeout) {
        return 1;
    }

    return 0;
}
樫原 輝
 
記事: 133
登録日時: 2011年7月07日(木) 17:26

Re: RC-S620Sの使い方について

投稿記事by 樫原 輝 » 2014年7月08日(火) 16:10

こんにちは
先ほどの書き込みに、出力結果が書き込めなかったので、ここに記載します。

出力結果(Arduinoのシリアルモニタ)
コード: 全て選択
÷ÔJÿÿâ0127005CA4E07B73ÿüÔ2ùÿ
÷ÔJÿÿâ0127005CA4E07B73ÿüÔ2ùÿ
÷ÔJÿÿâ0127005CA4E07B73ÿüÔ2ùÿ
÷ÔJÿÿâ0127005CA4E07B73ÿüÔ2ùÿ
÷ÔJÿÿâ0127005CA4E07B73ÿüÔ2ùÿ
÷ÔJÿÿâ0127005CA4E07B73ÿüÔ2ùÿ
樫原 輝
 
記事: 133
登録日時: 2011年7月07日(木) 17:26

Re: RC-S620Sの使い方について

投稿記事by yamaguch » 2014年7月08日(火) 17:54

樫原さん、こんにちは、

シリアルモニタは Arduino とパソコンとのシリアル通信に Arduino の 0, 1 ピンを使います。
一方、Felica のライブラリも同じ 0, 1 ピンを使ってシリアル通信をしているので競合しているようです。

Felica のライブラリを Serial(HardwareSerial) ではなく SoftwareSerial を使うように書き直すか、シリアルモニタを使わないで LCD 等の表示デバイスを使うようにするといいでしょう。

山口
yamaguch
 
記事: 482
登録日時: 2010年7月06日(火) 17:37

Re: RC-S620Sの使い方について

投稿記事by 樫原 輝 » 2014年7月10日(木) 23:09

山口さん、こんにちは。

回答有難うございます。
後日LCDディスプレイを買って試してみたいと思います。
ありがとうございました。
樫原 輝
 
記事: 133
登録日時: 2011年7月07日(木) 17:26


Return to Arduino 質問箱

cron