Raspberry Pi

【温度センサ TMP102】RaspberryPiでI2C通信をする方法【smbus2】

はじめに

RaspberryPiで、温度センサ「TMP102」とI2C通信をする方法を解説します。言語は「Python」ライブラリは「smbus2」を使います。

TMP102は配線・通信が簡単で、初めてI2C通信をする方におすすめのセンサーです。この記事の配線・コードをマネしてもらえれば、初心者でも簡単に温度センサが使えます。

記事内では懐かしの「RaspberryPi2」を使っていますが「RaspberryPi2〜4」「Raspberry Zeroシリーズ」なら解説と同じ方法でGPIOが使えます。

環境

この記事は以下の環境で作成しています。

環境 バージョンなど 備考
RaspberryPi 2 Model B RaspberryPi 2/3/4  Zero各種でも使えます
OS RaspberryPi OS (bullseye) 32bit版です
Python 3.9.2 OS プリインストールのバージョンです
ライブラリ smbus2

RaspberryPiとの接続

RaspberryPiとTMP102をI2Cで接続します。

RaspberryPiとTMP102の接続方法を説明する画像
ピン番号 内容 備考
1 3V3 power センサへの電源供給です
3 SDA I2Cの通信線です
5 SCL I2Cの通信線です
6 Ground センサへのグラウンドです。

ADDR0でアドレスを安定させる

TMP102には「ADDR0」のピンを電源/GNDにつなぐことで、デバイスのアドレスが変わる仕組みが存在します。アドレスが不安定になる場合は、ADDR0への接続を試してみてください。(上記の回路ではGNDに接続しています)。

ADDR0の接続  アドレス
3V3 (OUT) に接続0x49
GNDに接続0x48
未接続0x49 / 0x48 が不安定に切り替わる場合あり

ピンアサイン

RaspberryPi 公式のGitHubより引用

使用する部品

今回の使用する部品は以下の通りです。

温度センサTMP102

今回使い方を解説する温度センサです。

ブレッドボード

どのメーカーのものでも問題ないです。大きい方が自由度が高く・品質もいいので、サンハヤト製の以下のタイプをおすすめします。

あきばお〜楽天市場支店
¥945 (2022/09/18 00:07時点 | 楽天市場調べ)
\楽天ポイント5倍セール!/
楽天市場

ジャンパワイヤ

「オスーメス」タイプであれば、どのメーカーのものでも問題ないです。各色が何本かあると配線が分かりやすくなるのでオススメです。

\楽天ポイント5倍セール!/
楽天市場

プログラム概要

今回のプログラムの概要は以下の通りです。

  • I2Cの設定をする
  • 温度センサからデータを取得する
  • 取得したデータを温度に変換・表示する

実行結果

実行結果は以下の通りです。エアコンの設定値と同程度の室温が表示されました。

esu@raspberrypi:~/repos/tmp102 $ python tmp102.py
26.3125
26.3125
26.3125
26.3125
26.3125
26.3125
26.3125
26.3125
26.3125
26.3125
26.3125
26.3125
26.3125
26.3125

I2Cの設定

I2Cの有効化

RaspberryPiはデフォルトでI2Cの通信が無効化されています。初めてI2C通信を使う方は、こちらの記事を参考に、I2Cを有効化してください。

smbus2のインストール

以下のコマンドで「smbus2」をインストールします。

RaspberryPiでよく使われる「SMBus」は、RaspberryPi OS(bulls eyes) にデフォルトでインストールされていますが、Pythonで使う際の公式のドキュメントの情報量が少なかったので「smbus2」を使用しています。

sudo pip install smbus2

以下のように「Successfully installed …」と表示されればインストールは完了です。

Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting smbus2
  Downloading https://www.piwheels.org/simple/smbus2/smbus2-0.4.2-py2.py3-none-any.whl (13 kB)
Installing collected packages: smbus2
Successfully installed smbus2-0.4.2

全体コード

全体コードは以下の通りです。詳細な内容は後述する「コードのポイント」で解説します。

import time
from smbus2 import SMBus

# バス番号を指定します(基本的に1でOKです)
busNum = 1
smbus2 = SMBus(busNum)

# I2Cのアドレスを指定します
# TMP102の場合は「0x48」です
addr = 0x48

# 温度情報を1秒おきに100回取得します
for i in range(100):
    
    # TMP102の温度情報(12bit)は2byteに分かれて送られるため
    # 2byte分Readします
    data  = []
    data = smbus2.read_i2c_block_data(addr,0,2)

    # 温度データは「1」で、0.0625度を表すため、温度データに「0.0625」を
    # 掛け算することで、実際の”温度”に変換できます。
    tmp  = 0
    tmp  = data[0] << 4
    tmp += data >> 4

    # 温度情報を表示します
    print(tmp * 0.0625)

    # 1秒待機します
    time.sleep(1)

コードのポイント

バス番号の指定

I2C通信に使うバス番号を指定します。前述したピンに接続している場合は「1」を指定します。

# バス番号を指定します(基本的に1でOKです)
busNum = 1
smbus2 = SMBus(busNum)

read_i2c_data_block関数でセンサからデータを取得する

read_i2c_block_data関数で温度データを取得します。

    # TMP102の温度情報(12bit)は2byteに分かれて送られるため
    # 2byte分Readします
    data  = []
    data = smbus2.read_i2c_block_data(addr,0,2)

引数の項目とコード上の指定は以下の通りです。

TMP102からは温度データが2byte送られるので、2byte分のデータを取得します。取得したデータは戻り値として、配列で返されます。

引数 内容 コード上の指定
1 デバイスのアドレス 0x48
2 開始するレジスタのアドレス 0
3 取得したいデータ数
戻り値 指定したデータ数分の受信データ data[]

2つの受信データをシフトして結合する

TMP102は温度データを2byte(16bit)に分けて送信し、そのうち「12bit」しか使用しません。そのため、以下のようにビットシフトとデータの結合を行って、受信データから温度データを作成します。ビットシフトの内容はイメージと合わせて後述します。

        # 受信データの 1つ目は8bit全て、2つ目は下位4bitを使用します
        # そのため、2つのデータをビットシフトして結合します。
        tmp = data[0] << 4
        tmp += data >> 4

        # 温度データは「1」で、0.0625度を表すため、温度データに「0.0625」を
        # 掛け算することで、実際の”温度”に変換できます。
        print(tmp * 0.0625)

① 1つ目のデータ(data[0])を、左に4ビットシフトする

1つ目のデータの「8~1のビット」に、温度データの「12~5ビット」のデータが格納されています。

そのままではビットの番号が合わないので、ビットを左にシフトして温度データのビットの番号に合わせます。シフトした結果は、tmpという変数に代入します。

一つ目のデータのビットシフトの内容を解説する画像

② 2つ目のデータ (data[ 1])を右に4ビットシフトする

2つめのデータの「8~5ビット」に、温度データの「4~1ビット」のデータが格納されています。

こちらもビット番号が合わないので、ビットを右にシフトして温度データのビットの番号に合わせます(右にあふれたデータは削除、左側には0が追加されます)。

シフトすると、tmpの空いている部分にピッタリと合うようになるので、2つ目のデータをtmpに結合(足し算)します。

二つ目のデータのビットシフトの内容を解説する画像

上記の変換を行うことで、「tmp」に、TMP102の温度データ(12bit)の値をセットすることができます。

温度データから実際の温度へ変換する

TMP102からの温度データは、1単位につき「0.0625度」となっています。そのためtmpの内容に0.0625を掛け算すると、実際の温度の数値になります。

上のイメージの、tmp(0001 1010 0000)を十進数にすると「416」になります。
416 × 0.0625の掛け算すると「26度」になります。

まとめ

Raspberry Pi Picoで、Pythonを使ってI2C通信を行う方法について解説しました。参考になればうれしいです。

RaspberryPiで「アナログ入力」を使う方法

このブログでは、RaspberryPiで「A/D変換」を行う方法についても解説しています。A/D変換を使うとRaspberryPiで「Arduino」や「RaspberryPi Pico」のような「アナログ入力」を扱えるようになります。興味のある方は、以下の記事も併せてご覧ください。

UdemyにRaspberryPiの講座があります

実はUdemyで『RaspberryPi』『Pico』『Arduino』の基礎/実践講座が見れます。無料もあるので「動画で学びたい」「本は読み尽くした」という方は以下のリンクをご覧ください。

⇒ RaspberryPiの講座一覧はこちら

以下の記事で、RaspberryPi・RaspberryPi Picoのおすすめ講座3選も解説しています。

応援・要望お待ちしてます

ブログを見ていて「この辺を詳しく知りたい」「このライブラリの使い方を知りたい」「こんなことで困ってる」...etc があれば、コメント・問い合わせ・Twitterで教えてください。質問・ご要望に合わせて解説記事を作ります。

ブログを気に入っていただけたり、「応援してもいいよ」という方がいたら、ブログやSNSでの紹介をお願いします。 あたたかい応援は、中の人の更新の大きな励みになります。

ABOUT ME
えす
現役のソフトウェアエンジニアです。 C++ C# Python を使ってます。10年ちょい設計/開発部門にいましたが、今はQAエンジニアっぽいことをしています。

COMMENT

メールアドレスが公開されることはありません。