SPRESENSE SDK によるI2C通信がうまくいかない

投稿者: Anonymous

SPRESENSE SDK を使用したI2C通信が上手く行かずに困ってます。

■環境
PC:Ubuntu 18.04.4 LTS
SDK:v2.0.0
IDE:v1.2.0

■やりたいこと
Adafruitの出しているハプティックドライバを用いてモーターの制御をしようとしております。
https://www.marutsu.co.jp/pc/i/574336/

ハプティックドライバの初期化のために、ハプティックドライバのレジスタをI2C経由で弄る必要があるのですが、上手く行きません。

■やったこと
Spresense SDKでの開発→5.8.7ドライバ開発者のためのガイドライン
https://developer.sony.com/develop/spresense/docs/sdk_developer_guide_ja.html#_sensor_control_unit
を見ながら作業しています。

特に、下記の様な記述があることと、SPRESESEメイン・拡張ボード共に、I2C0というSCUに直接繋がっているI2Cしか使用できないことから、SCU driverを使っています。

SCU に直接つながっている SPI と I2C バスは、SCU とセンサードライバが同時にアクセスが発生すると衝突が発生し、誤作動の原因になります。デバイドライバ開発者は、提供される API を通じてのみ、デバイスにアクセスするようにしてください。

気になるのは、seq_open()やscu_i2ctransfer()などの返り値から成功したかどうかの判定ができるようですが、無効値を入力しても成功の返り値が返ってきます。

■質問
長くなりましたが、質問したいことは2点です。

  1. 今回やりたいことの、モーターを動かすためにSCUを使用するのは、正しいやり方なのでしょうか。i2c_masterの様なnuttxで用意されたライブラリを使用するべきなのでしょうか。
  2. SCUドライバを無効値で使用しても成功判定されるのはなぜでしょうか。

その他、誤り等ございましたらご教授のほどよろしくお願いいたします。

また、非常に汚い状態ですが、ソースを載せておきます。

int ret;
FAR struct seq_s *ada_seq;
uint16_t inst[2];

void init_vibration()
{
    printf("AutoCalib startn");

    ada_seq = seq_open(SEQ_TYPE_NORMAL, SCU_BUS_I2C0);
    if (!ada_seq)
    {
        printf("ada_seq : NULL errorn");
        return -ENOENT;
    }
    else
    {
        printf("openSequencen");
        //printf("ada_seq:%dn", ada_seq);
    }

    seq_setaddress(ada_seq, ADAFRUT_ADDRESS);
    ret = write_adafruit(0, ADAFRUT_ADDRESS, DRV2605_REG_STATUS, 0x00);
    ret = write_adafruit(0, ADAFRUT_ADDRESS, DRV2605_REG_RTPIN, 0x00);
    ret = write_adafruit(0, ADAFRUT_ADDRESS, DRV2605_REG_WAVESEQ1, 1);
    ret = write_adafruit(0, ADAFRUT_ADDRESS, DRV2605_REG_WAVESEQ2, 0x00);
    ret = write_adafruit(0, ADAFRUT_ADDRESS, DRV2605_REG_OVERDRIVE, 0x00);
    ret = write_adafruit(0, ADAFRUT_ADDRESS, DRV2605_REG_SUSTAINPOS, 0x00);
    ret = write_adafruit(0, ADAFRUT_ADDRESS, DRV2605_REG_SUSTAINNEG, 0x00);
    ret = write_adafruit(0, ADAFRUT_ADDRESS, DRV2605_REG_BREAK, 0x00);
    ret = write_adafruit(0, ADAFRUT_ADDRESS, DRV2605_REG_AUDIOMAX, 0x64);

    printf("setup completedn");
}
}

int write_adafruit(int port, int addr, int reg, int instruc)
{
    inst[0] = SCU_INST_SEND(reg);
    inst[1] = SCU_INST_SEND(instruc) | SCU_INST_LAST;

    ret = scu_i2ctransfer(port, addr, inst, 2, NULL, 0);
    if (ret == 0)
    {
        printf("tarnsferokn");
    }
    else
    {
        printf("failed. %dn", ret);
        printf("%dn", errno);
        return ret;
    }
}

解決

こんにちは。

SCUドライバはややこしそうなので、I2Cを使ってデバイスを制御する、ということであれば、
SCUを使わずにI2Cを利用するのはいかがでしょうか。

SDK v2.0.1のコンフィグに、feature/i2ctoolというものがあります。
これはnshのコマンドでI2Cを操作するサンプル(?)のようです。

コードは、spresense/sdk/apps/system/i2c
にあるようなので、これを参考に、I2Cのバスの利用方法を確認して、
所望のデバイスを制御されるのがよいかと思いました。

回答者: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *