JavaScript
IoT
I2C
chirimen
WebI2CAPI

CHIRIMENでI2Cデバイスを使ってみる

More than 1 year has passed since last update.

今日は、CHIRIMENからI2Cデバイスを使ってみたいと思います。

I2Cとは?

I2Cと書いて「アイ・スクエア・シー」と読んだり「アイ・ツー・シー」と読んだりします。
まぁ、私はいい加減な人なので、どっちでもいいです。
で、これは何か?というと、シリアル通信規格の一種です。
I2Cと同じようによく使われるシリアル通信に、UARTやSPIなどがありますが、I2Cは2本の線(SCL/SDA)で構成する1つのバスに複数のモジュールを接続できるのが最大の特徴と思います。配線が少なくて済むのでいろいろ楽です。

参考:
- UM10204 2C バス仕様およびユーザーマニュアル
- I2C(Wikipedia)

I2Cでは「Master」から複数の「Slave」を制御します。例外もありますが、基本的にホストコンピュータ側が「Master」となり、デバイス側が「Slave」として動作します。CHIRIMENはI2C「Master」として動作します。

I2Cに対応したモジュール

I2Cに対応したセンサーやアクチュエータなどは、その多くがI2C Slaveとして動作するデバイスです。

CHIRIMENに接続するI2Cデバイスを選ぶには?

上記スイッチサイエンスや秋月電子で購入できるI2C対応デバイスが全てすぐにCHIRIMENで使えれば良いのですが、残念ながら現時点では「すぐに利用可能」なデバイスは限られています。

CHIRIMENで利用可能なI2C機器は、下記条件を満たしたものに限定される認識です。

  • 1. 対象デバイスのI2Cバス上でのデータ送受信の仕様が、Web I2C APIがサポート可能な仕様であること
  • 2. I2Cバスライン(SDL/SCA)の電圧が3.3Vに対応した機器であること

上記条件を満たした機器であっても、すぐに使えるわけではありません。下記のような作業が必要になります。

  • 3. デバイスを利用するためのドライバーを入手する。あるいは自作する
  • 4. ドライバーを経由してI2Cデバイスを制御するWebアプリを書く

なんだか大変そうですね。確かに全部自分でやろうとすると結構大変です。

そこで最初は、CHIRIMENコミュニティのexamplesに登録されたデバイスから使ってみると良いと思います。

examplesには、CHIRIMENコミュニティ有志によって動作確認されたデバイスのサンプルコードが登録されています。

Web I2C APIを使ってみる → I2CデバイスをCHIRIMENに対応させてみる

それでは、examplesに登録されているデバイスをCHIRIMENにつないでみましょう!

。。。という風に進めたかったのですが、ポカをしてしまい、なぜか現在手元にexamplesに登録されているデバイスが1つもありません。。。。。

なぜか手元のI2Cデバイスは?というと、Arduino、Canzasi、そしてMCP4018(デジタルポテンショメータ)という状況。

いきなりハードル高めで申し訳ありませんが、MCP4018をCHIRIMENで使ってみようと思います。

つまり、最初はexampleを使ってみよう!ということができず、最初っから上記1〜4全部やってみよう!というスパルタ記事です。ええ、書いてる私も泣きそうw

1. Web I2C API に対応できるか? をデータシートで調べる

I2C対応デバイスをCHIRIMENで使えるようにするために、最初の条件を確認してみます。

現時点で Web I2C API が対応しているAPIを知る

現時点のWeb I2C APIは、まだドラフト段階のため、様々なI2C機器のデータ送受信仕様が実現できるようにAPIが網羅されているわけではありません。
現在Web I2C APIで、I2C Slaveデバイスへのデータ書き込みや読み込みに利用可能なAPIは5.5 The I2CSlaveDevice interfaceに記載のある下記APIです。

interface I2CSlaveDevice {
    readonly attribute unsigned short slaveAddress;
    Promise  read8(unsigned short registerNumber);
    Promise  read16(unsigned short registerNumber);
    Promise  write8(unsigned short registerNumber, octet value);
    Promise  write16(unsigned short registerNumber, unsigned short value);
};

上記は全てCHIRIMENで利用可能です。

上記APIを呼び出した時にI2Cバスに流れるデータは下図のようになります。

webI2c-I2CSlave-Interface@2x.png

これをよく覚えておきましょう。

MCP4018のデータシートを読む

MCP4018のデータシートを読んでいきます。
MCP4018はデジタルポテンショメータというもので、デジタルで制御可能な可変抵抗です。
今回買ったのは、10kΩのものです。127段階で10kΩを最大とした抵抗値に変更可能です。

I2Cがどうとか以前に、SC70-6というパッケージサイズが、非常にハンダ付けハードルが高いですが、変換基板等へのハンダ付けの話はここではしませんw
SC70-6の変換基板が入手できればそれが一番ですが、SOT23-8の変換基板でもなんとかなるでしょう。私はaitendoのSOT23-8の変換基板を使いました。

少なくとも、下記を読む必要があります。

  • P.1。概要と各ピンの機能把握。
  • P.36〜 I2Cのコマンドプロトコルについて書かれている

ここで確認することは2つ。

  1. I2Cスレーブアドレス

これは、P.36 Figure 5-9 を見ると、7bitで 0101111となっていますので、0x2Fであることがわかりました。

  1. I2Cコマンド

続いてI2Cコマンドも確認します。
重要なのは、5.4.1 WRITE OPERATIONです。
デジタルポテンショメーターの機能を使う目的では、これに対応するだけでも問題ないでしょう。

ここで気になる部分が。

Data bytes may be written after each Acknowledge.
The command is terminated once a Stop (P) condition
occurs. Refer to Figure 5-12 for the write sequence.
For a single byte write, the master sends a STOP or
RESTART condition after the 1st data byte is sent.
The MSb of each Data Byte is a don’t care, since the
wiper register is only 7-bits wide.

確かに、7bitの分解能しかないMCP4018がシングルバイトのみの書き込みで十分です。
しかし、ここで言うMSbが、何byte目を指すのか。実はこの仕様を正確に把握することが重要になります。

前に書いたように、現行のWeb I2C APIは「1byteだけの書き込み」はサポートしませんが、MCP4018側が下記のような動作を行ってくれれば、2byteを書き込むI2CSlave.write8()がつかえそうです。

  1. 最初に来た1byte(I2CSlave.write8()を使った場合、registerNumberパラメータ)を有効な値として取り扱う。
  2. Stopコンディションの直前に来たデータ(I2CSlave.write8()を使った場合、valueパラメータ)が有効になる

いずれの動作であっても、I2CSlave.write8()がつかえそうです。(書き方は変わりますが)

検証してみたところ、2. の動作となるようです。

さて、MCP4018は5.4.2 READ OPERATIONSにあるように、データReadにも対応しているようですが、正直何に使うのか?なので、ここでは無視することにします。

I2Cバスライン(SDL/SCA)の電圧が3.3Vに対応したデバイスか? をデータシートで調べる

こちらもMCP4018のデータシートを確認する作業です。

P.4 AC/DC CHARACTERISTICSによると、2.7〜5.5Vという電圧に対応しています。
まずは、電源ラインはクリアになりました。3.3Vにも対応しています。

もう1箇所確認が必要なページがP.8です。Digital Inputs/Outputs (SDA, SCK)の項です。
大事な箇所なので、下記にキャプチャーを置きます。

DCi2cbus.png

これを見ると、

  • HIGH = VDDの電圧の70%以上であること
  • LOW = -0.5V〜VDDの電圧の30%以下の範囲であること

となっています。

CHIRIMENのI2Cポートの電圧は3.3Vですので、MCP4018のVDDを3.3Vから供給すれば問題ないはずです。

CHIRIMENの5VからMCP4018のVDDには接続しないでください。
上記の通り、MCP4018がI2CのラインでのHIGHの検出に「VDDの電圧の70%以上」が必要です。
5VをVDDとしてしまうと、MCP4018側がHIGHである、と認識する閾値電圧は 5 * 0.7 = 3.5Vとなり、3.3Vより高くなってしまいます。つまり、CHIRIMEN側がHIGHにしたつもりで3.3Vまで上げたとしても、MCP4018側がHIGHになってないと認識してしまう原因となります。MCP4018に限らず、「VDDの電圧の70%以上をHIGHとする」という仕様はI2Cバス仕様中(3.1.2章)にも記載のある設計仕様ですので、覚えておきましょう。

3. デバイスを利用するためのドライバーを書く

仕様がだいたい理解できましたので、MCP4018をWeb I2C APIから使うコードを書いてみましょう。
i2c-VEML6070のサンプルをベースに書いてみます。

下記のようになりました。

mcp4018.js
var mcp4018 = function(i2cPort){
  this.i2cPort = i2cPort;
  this.slaveAddress = 0x2F;
  this.i2cSlave = null;
};

mcp4018.prototype = {
  init: function(){
    return new Promise((resolve, reject) => {
      this.i2cPort.open(this.slaveAddress).then((i2cSlave) => {
        this.i2cSlave = i2cSlave;
        console.log("i2cPort.open");
        resolve();
      });
    });
  },
  set: function(value){
    if(this.i2cSlave){
      console.log("mcp4018.set("+value+")");
      if(value > 127) value = 127;
      if(value < 0) value = 0;
      this.i2cSlave.write8(0,value);
    }else{
      console.log("i2cSlave has gone.....");
    }
  }
};

少し解説

T.B.D. 解説は後日書く予定

4. ドライバーを経由してI2Cデバイスを制御するWebアプリを書く

MCP4018を制御するドライバーができましたので、引き続きWebアプリを作って完成です。
今回は、下記のような回路を作って、LEDを「ふわふわ」と点滅させてみます。
PWMと違い、アナログ電圧で「ふわふわ」やってますので、精神的な「ふわふわ」感も向上してるはず!?w

Group 5.png

残りのWebアプリのコードは下記の通り、今回はUIなどぜんぜんありませんw

index.html
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
<title>mcp4018 Test</title>
<script src="./webi2c.js"></script>
<script src="./mcp4018.js"></script>
<script src="./main.js"></script>
</head>
<body>
<p>mcp4018 TEST</p>
</body>
</html>

そして、こちらが先ほど作ったmcp4018.jsを使って、LEDの抵抗値を少しづつ変えることで明るさを変更している部分です。

main.js
navigator.requestI2CAccess().then((i2cAccess) => {
  var port = i2cAccess.ports.get(0);
  var value = 0;
  var mode = 0;
  var digipot = new mcp4018(port);
  digipot.init().then(() => {
    console.log("digipot.init() done!");
    setInterval(() => {
      if(mode){
        value -=4;
        if(value < 0){
          value = 0;
          mode = 0;
        }
      }else{
        value +=4;
        if(value > 127){
          value = 127;
          mode = 1;
        }
      }
      digipot.set(value);
    },30);
  },(v) => {
    console.log("digipot init error:"+v);
  });  
}).catch((e) => {
  console.error("digipot I2C bus error!", e);
});

上記ファイルに加え、@MSakamakiさんによるpolyfillから、

  • webi2c.js
  • worker.js

をindex.htmlと同じフォルダに入れる必要があります。

最終的なWebアプリのフォルダの中に必要なファイルは下記になります。

  • index.html
  • main.js
  • mcp4018.js
  • webi2c.js
  • worker.js

上記をWebサーバに置けば完成です!

動作サンプル(CHIRIMENのブラウザからMCP4018との回路組んでからアクセス)

imb_203FC71B-66B8-4B4C-9A50-0B56B188C54B.gif

今回はここまで!

今回は、市販のI2Cデバイスの中からCHIRIMENに対応可能なデバイスの見つけ方(データシートの読み方)と、Web I2C APIへの対応手順について記載してみました。

Web I2C APIへの対応手順については、少し記載が足りないので後日補足予定です。ようするに途中で疲れましたw

次回は、CanzasiというArduinoを利用してI2Cデバイスを作る環境を紹介します。