Raspberry PiのI2Cデータ転送速度と波形を見る その1

 2015年後半からRASPBIAN JESSIEは各種設定がGUIベースに切り替わっています。センサや表示器などの接続に使うI2CやSPIなどのシリアル通信を有効にするのも、設定画面でチェックし再起動するだけです。2015-05-05バージョンからpiユーザは、I2Cを扱うのにsudoをつける必要がなくなっています。

2015-11-25バージョンからsudoが必要になりました。

 設定メニューから変更します。「Preferences」-「Raspberry Pi Configuration」を選びます。

 表示された設定画面で、Interfacesのタブを選びます。I2Cの「Enabled」をチェックしOKを押して有効にします。この後、rebootします。再起動するとI2Cが有効になります。

I2Cを利用するにはツールが不可欠

 ツールi2c-toolsとPythonのライブラリsmbusをインストールします。

sudo apt-get install i2c-tools python-smbus

 ターミナルで、i2cdetect -y 1 と打つと、接続されているデバイスを表示できます。

I2C接続の温度デバイスMCP9808をつなぐ

 400kHzのI2Cバス転送速度対応の温度センサMCP9808を用意しました。アドレスはデフォルトで0x18です。A0~A2のピンを使って変更ができますが、ほかのデバイスはつながないので、デフォルトで使いました。



 ラズパイではI2Cバスの'1'を使います。

 二つをジャンパ・ピンで下記の表のように接続します。

MCP9808 ラズパイ
Vdd +3.3V 1番ピン
GND GND 9番ピン
SCL SCL 5番ピン
SDA SDA 3番ピン

 接続したら、ラズパイの電源をつなぎ、ターミナルを起動し、次のコマンドを入れます。

i2cdetect -y 1

 アドレス0x18に温度センサMCP9808がつながっていることが確認できました。

      0  1  2 3  4 5  6  7  8  9 a  b  c  d  e   f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- 18 -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- --
-- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

テスト用のpythonプログラム

 MCP9808の温度は0x05レジスタに2バイトで収納されています。プログラムは、センサから温度を読んで、摂氏に直して表示するルーチンを繰り返します。ファイル名はi2c-loop.pyで保存し、sudo chmod 755 i2c-loop.pyで実行権をつけます。

#!usr/bin/env python
import smbus
import time

i2c = smbus.SMBus(1) # 1 is bus number
addr03=0x18 #MCP9808

def swap16(x):
        return (((x << 8) & 0xFF00) |
               ((x >> 8) & 0x00FF))
#main
print "start"
while 1:
        t=i2c.read_word_data(addr03,0x05) #temp reg
        tswap= swap16(int(hex(t),16))
        temp = (int(hex(tswap),16) & 0x0fff) / 16.0
        temp = round(temp,1)
        print t,hex(t),hex(tswap),temp

 マスタのラズパイからreadコマンドが発行されています。

 これに応答してスレーブのMCP9808からデータが送られてきます。

 プログラムで表示される読み取ったデータは0x8A、C1と上位と下位のバイトが逆順です。なので、上位と下位のバイトを入れ替えます(スワップ)。MCP9808のマニュアルによると、読み取ったデータを0x0FFFでマスクし、16で割ると、摂氏の温度データが得られます。それを小数点第一位で四捨五入して表示します。

低速でも動作するかを10kHzで実験

 I2Cのデータ転送速度のデフォルトは100kHzです。変更するときは、/boot/config.txtに、

dtparam=i2c_baudrate=10000

を追加します。10000は10kHzのデータ転送速度です。

sudo nano /boot/config.txt

 エディタを立ち上げて、カーソル・キーで最下行付近に移動し、下記のように追加します。

 Ctrl+oで保存し、Ctrl+xでエディタを終了します。rebootで再起動します。

 立ち上がったらターミナルで、下記のプログラムを動かします。

python i2c-loop.py

 I2C通信が行われて、MCP9808から温度のデータが送られてきています。

 オシロスコープの画面です。

 拡大してクロックSCLの周波数を測ります。10kHzのクロックだとわかります。

コラム USBオシロスコープでI2C信号を表示してシリアル・デコードする

 オシロスコープを見ると、1,0に相当する電圧や中途半端な電圧が表示されて、信号の素な状態が見れます。しかし、I2Cのコマンドやデータを頭の中でデコードするのは大変です。そういうときはロジック・アナライザを使います。Analog Discovery2のロジック・アナライザの画面です。

 周波数を上げていったときに、どのような波形になるかを見たかったので、PicoScope 5242Bを使って、アナログ信号とI2Cでコードを同時に表示します。その手順は次のようになります。

 事前に、A,Bのプローブの両方を5V/div、1/10アッテネータ、15ビット(解像度は19ビット相当に上げる)に設定します。使っているソフトウェアはBeta 6.12.2.1871です。

 メニューにあるツールのシリアルデコードを選びます。

 作成をクリックし、I2Cを選びます。

 2本あるプローブを、DataとClockどちらにつなぐかを設定します。

 チャネルAをData=SDAに、チャネルBをClock=SCLに設定します。

 中央部にThresholdの電圧が入力されています。まだSDA、SCLには信号が出ていないのでHigh状態で、そのピークの電圧が入っていますが、このままではデコードするには高すぎます。3.0Vに変更しました。

 OKを押すと前の画面に戻ります。ここでもOKを押します。

 繰り返し温度データを読み取りをするプログラムをpython i2c-loop.pyで実行します。上の青色の波形がデータSDAで、その真下に、デコードした値が16進で表示されています。一番下の赤色はクロックのSCLです。