Raspberry Pi PR

【温度センサ 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より引用

使用する部品

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

RaspberryPi 4 (8GBモデル)

解説はRaspberryPi 「2」 ですが、今買うなら、性能が大幅アップした「4」がおすすめです。 後継機なのでピンアサインは同一で、解説と同じように使えます。

温度センサTMP102

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

ブレッドボード

サンハヤト性のブレッドボードです。少々堅めの指し心地ですが、などの品質も高く、おすすめの一品です。

ジャンプワイヤ (オス-メス タイプ)

RaspberryPiで使う場合は、以下のオスーメスタイプがおすすめです。

プログラム概要

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

  • 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」のような「アナログ入力」を扱えるようになります。興味のある方は、以下の記事も併せてご覧ください。

お知らせ

今月号のInterfaceは『RaspberryPi 5』特集

今月号ののInterfaceは「RaspberryPi 5」特集!

実験などを通じた性能測定や特徴・変更点の解説。新規に追加されたI/Oボード「RP1」の特徴と謎。Pi5のはじめかたやLinuxコマンド入門などが特集されています。

3月25日発売です。

質問・要望 大歓迎です

「こんな解説記事作って」「こんなことがしたいけど、〇〇で困ってる」など、コメント欄で教えてください。 質問・要望に、中の人ができる限り対応します。

使えたよ・設定できたよの一言コメントも大歓迎。気軽に足跡を残してみてください。記事を紹介したい方はブログ、SNSにバシバシ貼ってもらってOKです。

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

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です