RaspberryPiではじめてのI2C通信〜温度計測編〜

#概要
RaspberryPi初心者が書籍「RaspberryPiで学ぶ電子工作」を元に演習を行い、
理解を深めるためのまとめです。
今回は「7章 I2Cデバイスの利用」の中でも温度センサモジュールとの通信のみを行います。

筆者スペックは以下ですので同レベルの方が適していると思います。
・ラズパイを初めて触った
・書籍の6章までは進めた
・Pythonは基本的に書ける
・電子回路は大学座学が理解できるレベル

#登場人物
**主役**
・I2C対応温度センサー（ADT7410使用）
**脇役**
・RaspberryPi3
・ブレッドボード
・ジャンプワイヤ（オスーオス）
・ジャンプワイヤ（オスーメス）

#本章の目的
RaspBerryPiとデバイス間通信の演習として
「I2C通信」を用いてデジタル値を出力するセンサやディスプレイなどを扱うことが目的です。
（6章ではADコンバータとRaspberryPiにおける「SPI通信」を実験しました。）

#超訳 I2C通信とは
・電源・グランドを除き、わずか2線のみで利用可能
・シリアル通信
・通信内容にアドレス情報、確認信号を持つ
・マスタ（RaspberryPi）、スレーブ（温度センサ）の関係で動作する

#やってみる

##温度センサモジュールを作る
購入時の状態では温度センサ（ADT7410）とピンヘッダは分かれているので、
はんだづけする必要があります。
私ははんだを持っていないので詰んでしまいましたが、
メンバーの方が温度センサモジュールを貸してくれました。
先へ進みましょう！

※はんだづけをしなくてもなんとか動かすことができたので、
　持っていない人も諦めずにやってみましょう。


##ラズパイの設定を行う

###I2C用モジュールの有効化
RaspberryPiでI2C通信を行うためにはモジュールの有効化を行う必要があります。
jessie系列のRaspbianであればGUIにて設定が可能ですが、
私はsshを利用して操作しているためwheezy系列と同様にCUIによるraspi-configコマンドにて
設定を行いました。

ちなみに、NOOBS1.4.1以前を用いてインストールされたRaspbianはwheezy系列、
1.4.2以降（私が利用しているのは2.0.0）はjessie系列となっています。

raspi-configコマンドの操作方法は書籍には操作が記載されていないため、
サポートページ中のPDFを参照し進めます。
[RaspberryPiで学ぶ電子工作　サポートページPDF](http://bluebacks.kodansha.co.jp/content/files/special/rspi1/RaspberryPi1-PDF_p01-48.pdf)

バージョンが違うためか、資料と実際の画面遷移が異なってましたが以下のように設定しました。
1. 設定画面の起動
`sudo raspi-config`
2. Advanced Option を選択
<img width="573" alt="AdvancedOption1.png" src="https://qiita-image-store.s3.amazonaws.com/0/143285/d78e203c-f1c4-ed84-9460-aff15dfa617a.png">
3. I2Cを選択
<img width="568" alt="AdvancedOption2.png" src="https://qiita-image-store.s3.amazonaws.com/0/143285/678914c5-a4e1-9484-aead-7a7235d0d51a.png">
4. 確認その1
<img width="566" alt="AdvancedOption3.png" src="https://qiita-image-store.s3.amazonaws.com/0/143285/69640cc2-9600-166a-b676-017599edba1a.png">
5. 確認その2
<img width="565" alt="AdvancedOption4.png" src="https://qiita-image-store.s3.amazonaws.com/0/143285/efb96876-23e3-fafe-0790-f9b7428bfffd.png">

その後は特にRaspberryPiを再起動する必要はありませんでした。


###I2C用モジュールの読み込み
wheezy系列は設定する必要がありますが、
jessie系列は特に設定する必要はありませんでした。


###パッケージのインストール（要ネットワーク）
必要なパッケージをネットワークからインストールします。

1. お決まりのパッケージリスト取得  
`$ sudo apt-get updatge`
2. 必要なパッケージのインストール  
以下コマンドでインストールを行いますが、  
すでにインストールされていたようです。

```
$ sudo apt-get install i2c-tools python-smbus
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています
状態情報を読み取っています... 完了
i2c-tools はすでに最新版です。
i2c-tools は手動でインストールしたと設定されました。
python-smbus はすでに最新版です。
アップグレード: 0 個、新規インストール: 0 個、削除: 0 個、保留: 92 個。
```

ここまできたらラズパイ側の準備は完了です！

##回路を作成する

###はんだづけ版
書籍をもとに以下のように回路を作成します。
![circuit_1.JPG](https://qiita-image-store.s3.amazonaws.com/0/143285/ac9de94b-7fed-46a9-5667-1c18fd320795.jpeg)


###はんだなし版
はんだづけしないで作成した場合は以下の様になっています。
穴の内側にも導体があるのでピンと接触するようにすれば動作はします。
私は置くだけでうまく接触してくれていました。
![circuit_2.JPG](https://qiita-image-store.s3.amazonaws.com/0/143285/f6e2fcd7-fafb-ed47-f659-d2a0ef156037.jpeg)




##動かしてみる

###温度センサ認識チェック
以下コマンドでRaspberryPiから温度センサが認識できるか確認を行います。
認識できていれば温度センサのアドレス「48」が表示されます。

```
$ sudo i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
```

もし表示されない場合ははんだづけ不良などが原因かと思われますが、
私は無事認識されました。いい仕事してくれています。

###温度計測
以下プログラムを用いて温度計測を行います。
私は今回書籍のサポートページで取得できるサンプルプログラムを利用しました。

```
# -*- coding: utf-8 -*-
import smbus
from time import sleep

def read_adt7410():
    word_data = bus.read_word_data(address_adt7410, register_adt7410)
    data = (word_data & 0xff00)>>8 | (word_data & 0xff)<<8
    data = data>>3 # 13ビットデータ
    if data & 0x1000 == 0:  # 温度が正または0の場合
        temperature = data*0.0625
    else: # 温度が負の場合、 絶対値を取ってからマイナスをかける
        temperature = ( (~data&0x1fff) + 1)*-0.0625
    return temperature

bus = smbus.SMBus(1)
address_adt7410 = 0x48
register_adt7410 = 0x00

try:
    while True:
        inputValue = read_adt7410()
        print(inputValue)
        sleep(0.5)

except KeyboardInterrupt:
    pass

```


実行してみましょう！
温度センサの周囲を手で覆ってぬくもりを与えたところ、
ちゃんと温度が上がっていってるのが分かります。
動作確認完了です！

```
$ python 07-01-temp.py
26.0
26.1875
27.0625
27.75
27.75
27.5
27.25
27.375
27.1875
27.0625
27.5
28.125
28.1875
27.875
28.0625
```

#調べたこと
Q. パッケージに高分解能とあるが、どのような意味？
A. ざっくり言うと計測できる間隔が細かいというとのことです。
　今回利用した温度センサは0.0625℃(13bit設定時)間隔で計測可能。

Q. 温度センサの基盤にかかれている記号の意味は？
A. 以下の通り。
・VDD　→　電源電圧
・SCL　→　シリアルクロック
・SDA　→　シリアルデータ
・GND　→　グランド

Q. I2Cって何がいいの？
A. デジタル出力するデバイスを利用できます。
　また、通信内容にアドレスや確認信号を含むため、
　異なるアドレスを持つ複数デバイスの同時利用可能です。　

Q. I2Cで難しい点は？
A. デバイスの仕様を知っていないと利用できません。
　今回で言えば温度センサの仕様として
　レジスタ番地「0x00」、デバイスのアドレス「0x48」を理解して
　プログラミングする必要があるということです。

#終わりに
I2C通信内容なども勉強するとなると大変ですが、動かしてみるだけならさくっとできました。
次のステップとしてはSPI通信との比較や使い分けを学んで行く必要があると感じました。

#参考
[I2C通信の使い方](http://www.picfun.com/c15.html)