7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JavaScript RoboticsAdvent Calendar 2016

Day 11

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

Last updated at Posted at 2016-12-11

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

I2Cとは?

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

参考:

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

I2Cに対応したモジュール

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

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

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

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

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

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

    1. デバイスを利用するためのドライバーを入手する。あるいは自作する
    1. ドライバーを経由して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です。

.webidl
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デバイスを作る環境を紹介します。

7
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?