Raspberry Pi i2cモジュールを使ってみる

Raspberry Pi でi2cモジュールを使ってみようと思います。

i2cの設定

i2cモジュールを使用するため、Raspberry piの設定を使用と思います。
なお使用したOSのバージョンはRaspbian GNU/Linux 8 (jessie)です。

まず、i2c-toolsをインストールします。
$ sudo apt-get update
$ sudo apt-get install i2c-tools
raspi-configで設定します。(GUIでも設定はできます。)
$ sudo raspi-config

Image from Gyazo
Image from Gyazo

5 Interfacing Options → I2C → はい
i2c-devが書かれているか確認する。
$ sudo vi /etc/modules
設定ファイルのバックアップをする。
$ sudo cp -i /boot/config.txt /boot/config.txt.$(date +%Y%m%d)
/boot/config.txtdtparam=i2c_baudrate=50000を追記する。
(LCDモニターも使うことを予定しているため、50000とした。)
$ sudo vi /boot/config.txt

〜ページの行末〜
dtparam=i2c_baudrate=50000

pythonでi2cを使えるようにするため、smbusをインストールする。
$ sudo apt-get install python-smbus
再起動する。
$ sudo reboot

i2cモジュールを接続して、アドレスを確認する。コマンドの後の数字はi2cのチャネル番号です。(0または1)
$ sudo i2cdetect 1

piユーザーにi2cのグループがついていない場合は、プログラムで実行できるように追加しておきます。
(再インストールした際にi2cの設定をしたら、ユーザーが追加されていたので多分これから設定する人(OSが最新版)は大丈夫だろうと思います。)

温度・気圧センサーlps25h
LPS25Hは、STMicroelectronicsの温度センサーと気圧センサーのモジュールです。
気圧センサーはMEMSセンサーとなっているようです。最近注目されてきているMEMS(メムス)ですが、LIGAプロセスや半導体製造プロセスなどを使って作成するようです。振動子や圧力センサーなどではすでに実用されているものがあります。この製品もその一つです。

接続方法

Raspberry Pi との接続は、以下のようにRaspberry pi 側 4箇所(VDD:電源、SCL:クロック、SDA:通信、GN)とデバイス側6箇所でした。(上記に加えて、CS:i2cモード選択,SDO:デバイスアドレス選択)
プルアップはRaspberry Pi の内部で行われているので、不要です。
この接続の場合はデータのアドレスは0x5dになります。

Image from Gyazo

プログラムを参考にしたサイトのリンクを貼っておきます。
iwasakiyouhei.com

geckour.orz.hm

プログラムについて

プログラムの大まかな流れとしては、
①通信確認(WHO_AM_I)としてレジスタアドレス0x0Fから0xBDを読み込む。
②モード切り替えのためレジスタアドレス0x20へ0x90を書き込む。
③レジスタから8bitデータを読み込む×5
④読み込んだデータを結合して気圧は24bit、温度は16bitのデータにする。(シフトして論理和で結合する。)
⑤補正の計算する。気圧:Pout(hPa) = PRESS_OUT / 4096、気温:T(°C) = 42.5 + (TEMP_OUT / 480)
⑥出力する。
作ったプログラムは以下です。

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import smbus
import time
import sys

Device_add = 0x5d 

#通信確認
whoami = smbus.SMBus(1).read_byte_data(Device_add, 0x0f)
if whoami != 0xbd:
    print('接続できません')
    sys.exit()

#レジスタ切り替え(モード変更)
smbus.SMBus(1).write_byte_data(Device_add, 0x20, 0x90) 
time.sleep(1)

#データ読み込み

buff = [0 for i in range(5)]
buff[0] = smbus.SMBus(1).read_byte_data(Device_add, 0x28)
#print("buff[0]=%x" % buff[0])
buff[1] = smbus.SMBus(1).read_byte_data(Device_add, 0x29)
#print("buff[1]=%x" % buff[1])
buff[2] = smbus.SMBus(1).read_byte_data(Device_add, 0x2A)
#print("buff[2]=%x" % buff[2])
buff[3] = smbus.SMBus(1).read_byte_data(Device_add, 0x2B)
#print("buff[3]=%x" % buff[3])
buff[4] = smbus.SMBus(1).read_byte_data(Device_add, 0x2C)
#print("buff[4]=%x" % buff[4])

Data = [0 for i in range(2)]

"""---------------------------
圧力データ24bitデータ
8bitデータをシフトして結合
---------------------------"""

Data[0] = (buff[2] << 16 | buff[1] << 8 | buff[0])

"""---------------------------
温度データ16bitデータ
8bitデータをシフトして結合
---------------------------"""

Data[1] = (buff[4] << 8 | buff[3])

"""------------------------
圧力データの計算
Pout(hPa) = PRESS_OUT / 4096
-------------------------"""

Data[0] = float(Data[0]) / 4096

"""---------------------------
マイナスデータの補正と
温度データの計算
T(°C) = 42.5 + (TEMP_OUT / 480)
----------------------------"""

if Data[1] & 0x8000:
    Data[1] = -((Data[1] - 1) ^ 0xffff)
Data[1] = float(Data[1]) / 480.0 + 42.5

#出力-------------------------

print("Pressure %.2f hPa" % (Data[0]))
print("Temperature %.2f degree" % (Data[1]))

プログラムの補足

・bitの結合について
前のプログラムで
Data[0] = (buff[2] << 16 | buff[1] << 8 | buff[0])
と気圧のデータを処理している場所があると思います。
例えば
buff[2] = 0x0f(16進数) = 00001111(2進数)
buff[1] = 0x4e(16進数) = 01001110(2進数)
buff[0] = 0x33(16進数) = 00110011(2進数)
とする場合
上位のbitの場合buff[2]を16bit 左にシフトしているので
00001111 00000000 00000000(2進)
となります。
これらを論理和で計算する場合は、

Image from Gyazo

・負の値の補正
前のプログラムの
if Data[1] & 0x8000:
Data[1] = -((Data[1] – 1) ^ 0xffff)
の部分の補足です。
マイナスの場合に2の補数でデータが格納されているので
そのままだと正の値で計算されてしまうので
絶対値にして、マイナス符号をつけて、格納します。
2の補数は反転して( 排他的論理和(xor)をffff(16進)と行うことで反転します。)
それに1を足すことで作ります。
2補数の作成例

Image from Gyazo

このプログラムの場合は2の補数を戻すので、
1を引いて、反転する(xor ffff(16進数))ことで求めます。

ADコンバーターADS1015
12ビットADC(ADS1015)です。
アナログ-デジタル変換(ADC)は連続しているアナログ信号を離散値であるデジタル信号に変換します。これによってPCなどで取り扱えるようにします。ADS1015はデジタル化したデータi2cのシリアル通信でデータのやり取りをします。
今回は、Cds光導電セルの値を取得します。

接続

下図のように接続しました。

Image from Gyazo

パッケージのインストール

データ取得の専用パッケージをインストールします。
$ sudo pip install adafruit-ads1x15
専用パッケージを呼び出します。
import Adafruit_ADS1x15
データの読み込みは
adc.read_adc(0,gain=GAIN)/500.0
で行っていますが、
Gain の設定は以下のようになっています。リンク参照。

Raspberry Pi アナログ入力 (I2C A/D コンバータ)

ADS1015 について Raspberry Pi には A/D コンバータが内蔵されていません。デジタル入出力、アナログ出力に加えてアナログ入力を行うためには外部 IC を利用する必要があります。ここでは I2C デバイスの ADS1015 を利用します。事前に I2C 設定を行っておいてくだ...

Gain=1( 0.0V – 4.096V)
変換は11bit(2048)の分解能なので、
取得値×(4.096/2048)=取得値×(1/500)
となります。

プログラム

コードは以下です。

#! /usr/bin/env python
# -*- coding: utf-8 -*-

import time, signal, sys 
import Adafruit_ADS1x15

adc = Adafruit_ADS1x15.ADS1015()
GAIN = 1 
Volts = adc.read_adc(0,gain=GAIN)/500.0
print( str(Volts) + "V")