catalinaの備忘録

ソフトウェアやハードウェアの備忘録。後で逆引きできるように。

TWE-Liteで外部センサとI2C通信

ずいぶんと長い間放置してたものを再開してみました。かたりぃなです。
再開したのはこれ。
catalina1344.hatenablog.jp
もう一年くらい前なんですね。

構成の再検討

TWE-LiteのライターがないからArduinoでなんとかできないかなーとかやっていましたが、
電圧が5Vと3.3Vで違っていたり、色々面倒になってきたのでTWE-Liteのライター買ってきました。
これでTWE-Liteとセンサ、LEDだけで目的達成できそうです。
http://akizukidenshi.com/catalog/g/gM-08264/

TWE-Lite Rの工夫ポイント

そのままではちょっと使いづらかったので、写真のように二階建てにしてみました。
これでブレッドボード上でなんでもできますし、USB給電の電流を気にする必要もほぼなくなります。
(ジャンパーピンでUSB給電OFFに設定して、外部から電源引っ張ってきてます)
f:id:Catalina1344:20160201220115j:plain

センサのアナログ値を直接TWE-Liteに突っ込んでみる

使うセンサは三軸加速度センサKXP84にしました。(道具箱に転がってた)
http://akizukidenshi.com/download/KXP84-2050_Specifications_Rev2.pdf
このコのアナログ出力のXYZの電圧をそのままTwe-Liteのアナログ入力に突っ込んでみましたが、ダメでした。
KXP84のレンジが1.2V~3.5Vであるのに対して、Twe-LiteのADCは0~2.4Vのようです。
アナログの世界では太刀打ちできないのでデジタル世界でなんとかできないかと考えてみました。
TWE-LiteではI2C使えるのでこいつでなんとかなりそうです。
センサ側はSPIもついてるのですが、TWE-Lite側に実装がなさそうなので、I2Cメインで考えます。

TWE-Liteのコードの全体を眺めてみる

東京コスモス様から公開されているソースコードを落としてきて全体を眺めてみました。
やってることは組み込みソフトウェア的だなぁといったところです。(当たり前か)
組み込み系特有な部分はありますが、今回の目的だけであればふつうにC言語ペリフェラルのライブラリ叩いてるだけなので、そこまで難しくはないと思います。
マニュアルも公開されているので、読みながらやれば目的の機能を追加するくらいはできそうです。(その結果、全体の整合性がどうなるかは未確認)
「超簡単!TWEアプリ」はやってることが多いので読むなら機能を絞っておかないと迷いそうです。
特に低消費電力向けにスリープモードがいくつもあったりとか。このあたりはたぶんZigBee固有なお話だったはず。
http://mono-wireless.com/jp/products/TWE-ZERO/index.html

I2Cの実装を眺めてみる

BH1715というチップとI2C通信する機能があったので眺めてみました。
センサの値が確定するまでタイマイベントを待つ以外はふつうのI2Cの通信のように見えます。
I2Cの仕様詳しくは知らなかったのですが、BH1715の資料が日本語だったこともあり、コードと照らし合わせやすかったです。
http://rohmfs.rohm.com/jp/products/databook/datasheet/ic/sensor/light/bh1715fvc-j.pdf?_ga=1.179572772.1693979872.1454157489

マネして書いてみたコードがこちら。
I2CプロジェクトのMain.cにあるvHandleSerialInputで適当なキー入力をトリガとして以下のコードを起動するようにしました。
BH1715と違ってセンサの測定結果が出るまで待たなくていいので単純です。

    bool_t bres = bKXP84startRead();
    if (bres) {
        vfPrintf(&sSerStream, LB "KXP 84 write success");
    } else {
        vfPrintf(&sSerStream, LB "KXP 84 is not found.");
    }
    // Sr + SAD + R + RA
    vfPrintf(&sSerStream, "I2C Bus read start");
    uint8* recv_data = i16KXP84readResult();
    vfPrintf(&sSerStream, "KXP84.read finish");
    vfPrintf(&sSerStream, "X=[%X%X],Y=[%X%X],Z=[%X%X]",
        recv_data[0],
        recv_data[1],
        recv_data[2],
        recv_data[3],
        recv_data[4],
        recv_data[5]);

ここで呼び出しているbKXP84startReadとi16KXP84readResultの関数もマネしながら書いてみました。

PUBLIC bool_t bKXP84startRead()
{
    bool_t bOk = TRUE;

    uint8	read_address = 0x00;
    bOk &= bSMBusWrite(KPX84_ADDRESS, read_address, 0, NULL);

    return bOk;
}

PUBLIC uint8* i16KXP84readResult()
{
    bool_t bOk = TRUE;
    bOk &= bSMBusSequentialRead(KPX84_ADDRESS, 6, WorkBuffer);
    return WorkBuffer;
}

ソースコードの説明

KXP80のI2C仕様の12,13ページがメインです。
今回の手順はこの資料のSequence 4に相当します。
レジスタマップは資料後半にありますが、アドレス0から2バイト単位にX,Y,Zの加速度が格納されるようです。
http://akizukidenshi.com/download/KXP84-2050_Specifications_Rev2.pdf
まずMasterが通信開始の合図を出し、SAD+Wを出力します。
その後ACKを受けたMasterはRA(Register Address)を出す必要があるので、このアドレスを指定しておきます。
ここまでbSMBusWriteでやってくれます。
続いてi16KXP84readResultでSrとSAD+RをMasterが出してあげると、先の手順で指定したレジスタアドレスから順にデータを送ってきてくれます。
ACK/NACKの処理はbSMBusSequentialReadでやってくれます。

回路を作る

KXP84-2050からみたつなぎ方を言葉でメモしていきます。
VCCとGNDはそのままつなぎます。
MOTとFFは今は使わないので一旦放置。自由落下と過度加速度の検知に使うらしいです。
SCL/SCLKをTWE-LITEのSCLに
SDA/SDOをTWE-LITEのSDAに
ちなみにこの2つの線がI2Cなのでプルアップ必要かなと思いましたが、完成済みKXP84モジュール内部でプルアップされているので不要っぽいです。
モジュール内部のプルアップを抵抗の先はIO_VDDになっているので、こいつを持ちあげておきます。
CSは今回は使いませんが、プルアップしておきます。
RESETもプルアップ。あとでTWE-Liteからリセット制御できるようにしましょう。
ADDR0はプルダウンしておきます。この信号線でKXP84のI2C-SlaveAddressの最下位ビットが決まるとのこと。(つまりプルダウンした状態であればアドレスは0x18)

動作確認

ファームウェア書き込み後、PC側で端末(TeraTerm)を起動して設定をTWE-Liteにあわせておく。
起動させてターミナルで出力を確認

read finishX=[9270],Y=[AE38],Z=[8F30]
read finishX=[9270],Y=[AE38],Z=[8F30]

2回採取してみましたがよさげな値です。
センサを傾けると値が変わります。
アナログで測定した値とだいたい合っているので、一旦これで良しとします。

感想

今回とれた値をTWE-Liteのパケットで送信してあげて、受けた側(魔法陣モジュール側)で適当にLED制御すれば目的のものが作れそうです。
デバッグソースコードと睨めっこになってしまうのがちょっと辛い。オシロかロジアナ欲しいです。
いっそ完成品買えば早いかもしれませんが、TWE-LiteからのI2Cの扱い方の勉強になったということで良しとします。
http://akizukidenshi.com/catalog/g/gM-09453/

最後にどうでもいいこと

TWE-Liteにファームウェアを書き込むとき、ライターに間違えたファイルを放り込むとこんなメッセージが出ます。
f:id:Catalina1344:20160201231155p:plain
ちょっぴりお茶目っ気があってクスっとしてしまいました。