【初心者向け】GP2Y0E03をRaspberry Piで使う方法|I2C接続で距離測定してみよう

ラズパイ

電子工作やRaspberry Pi(ラズパイ)で「物体までの距離を測定したい」と思ったことはありませんか?

今回は SHARP製 赤外線距離センサ「GP2Y0E03」 を使って、Raspberry Pi 3B と I2C 接続し、Pythonで距離を測定する方法を、電子工作初心者の方にも分かるように丁寧に解説します。

この記事で分かること

  • GP2Y0E03 とは何か(特徴・用途)
  • Raspberry Pi 3B との配線方法(3.3V対応)
  • I2C通信の有効化と動作確認方法
  • Pythonで距離(cm)を取得するサンプルコード
  • 初心者がつまずきやすいポイントと対策
スポンサーリンク
スポンサーリンク

GP2Y0E03とは?(初心者向け解説)

GP2Y0E03 は、SHARPが製造している赤外線方式の距離センサです。

GP2Y0E03 赤外線測距センサモジュール

今回使用する赤外線センサーです。千石電商の方が安い場合もありますので、そちらもご参照下さい。

特徴

  • 測定距離:約 4〜64cm
  • 出力:I2C(デジタル)+アナログ
  • 電源電圧:2.7〜5.5V
  • Arduino / Raspberry Pi 両対応
  • 小型でロボット・自動化用途に最適

こんな用途におすすめ

  • 障害物検知
  • 近接センサ
  • ロボット制御
  • 自動ドア・人感代替
  • 電子工作の入門教材

配線方法(3.3V・I2C接続)

配線例

⚠️ 電圧の注意点(重要)

Raspberry Pi の I2C は 3.3V専用です。
そのため GP2Y0E03 も 3.3V動作で使用します。

配線対応表

GP2Y0E03Raspberry Pi
VDD3.3V(Pin1)
VIN(IO)3.3V(Pin1)
GNDGND(Pin6)
SDAGPIO2(Pin3)
SCLGPIO3(Pin5)
GPIO13.3V(常時ON)
Vout(A)未接続

※ GPIO1 は動作ON/OFF端子です。
 今回は 常時ON のため 3.3V に接続します。

Raspberry Pi 側の設定

① I2Cを有効化

sudo raspi-config
  • Interface Options
  • I2C → Enable
  • 再起動

② 必要なツールをインストール

sudo apt update
sudo apt install -y i2c-tools python3-pip
pip3 install smbus2

③ センサが認識されているか確認

i2cdetect -y 1

0x40 が表示されれば接続成功です。

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

Pythonで距離を測定するプログラム

距離データの仕組み(簡単解説)

GP2Y0E03 は

  • 距離データ(12bit)
  • スケール調整用「Shift Bit」

を組み合わせて距離(cm)を計算します。

サンプルコード

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

import time
from smbus2 import SMBus

I2C_BUS = 1
ADDR_7BIT = 0x40  # GP2Y0E03: Slave ID 0x80/0x81(8-bit) -> 0x40(7-bit)  :contentReference[oaicite:10]{index=10}

REG_SHIFT = 0x35
REG_DIST_H = 0x5E  # Distance[11:4]  :contentReference[oaicite:11]{index=11}
REG_DIST_L = 0x5F  # Distance[3:0]   :contentReference[oaicite:12]{index=12}

def read_u8(bus, reg):
    return bus.read_byte_data(ADDR_7BIT, reg)

def get_shift_n(bus):
    """Shift Bit(0x35) の下位3bitが n(アプリノートの説明に従う)"""
    v = read_u8(bus, REG_SHIFT)
    n = v & 0x07
    return n

def read_distance_cm(bus):
    """
    測距値 = (Distance[11:4]*16 + Distance[3:0]) / 16 / 2^n  :contentReference[oaicite:13]{index=13}
    ここでは raw12 = (H<<4) | (L & 0x0F) を使い、distance = raw12 / (16*(2^n))
    """
    n = get_shift_n(bus)
    h = read_u8(bus, REG_DIST_H)
    l = read_u8(bus, REG_DIST_L) & 0x0F

    raw12 = (h << 4) | l
    dist_cm = raw12 / (16.0 * (2 ** n))
    return dist_cm, n, raw12

def main():
    with SMBus(I2C_BUS) as bus:
        # 起動直後は最大距離側を出すことがあるため、少し待つ :contentReference[oaicite:14]{index=14}
        time.sleep(0.2)

        while True:
            dist_cm, n, raw12 = read_distance_cm(bus)
            print(f"Distance: {dist_cm:6.2f} cm  (shift n={n}, raw12={raw12})")
            time.sleep(0.2)

if __name__ == "__main__":
    main()

実行結果例

Distance:   4.02 cm  (shift n=2, raw12=257)
Distance:   4.02 cm  (shift n=2, raw12=257)
Distance:   4.02 cm  (shift n=2, raw12=257)

コード解説

このプログラムは何をする?

Raspberry Pi の I²C(SDA/SCL)を使って GP2Y0E03 という距離センサから値を読み取り、
**距離(cm)**としてターミナルに表示し続けるプログラムです。

処理の流れはシンプルで、次の繰り返しです。

  • センサ内部のレジスタから「距離の生データ」を読む
  • 生データを「cm」に変換する
  • 0.2秒ごとに表示する

I²Cアドレスとレジスタ(重要)

I2C_BUS = 1
ADDR_7BIT = 0x40
  • I2C_BUS = 1:Raspberry Pi の I²C-1 を使う
  • ADDR_7BIT = 0x40:GP2Y0E03 の I²C アドレス(7bit表記)

ポイント:
Linux(Raspberry Pi)は 7bitアドレスで扱います。
データシートで 0x80/0x81 と書かれている場合、それは **8bit表記(Write/Read込み)**のことが多く、
7bitに直すと 0x80 >> 1 = 0x40 になります。

どのレジスタを読んでいる?
REG_SHIFT  = 0x35
REG_DIST_H = 0x5E
REG_DIST_L = 0x5F

GP2Y0E03 はセンサ内部に「レジスタ」と呼ばれるメモリ領域があり、
I²Cで **指定した番地(レジスタ番号)**を読むと情報が取れます。

  • 0x5E:距離データの上位(Distance[11:4])
  • 0x5F:距離データの下位(Distance[3:0])
  • 0x35:距離のスケールに関係する Shift 情報(後述)

1バイト読む関数(基本部品)

def read_u8(bus, reg):
    return bus.read_byte_data(ADDR_7BIT, reg)
  • read_byte_data(アドレス, レジスタ) で **1バイト(8bit)**読みます
  • ここでは「指定したレジスタの値を1バイト読む」共通処理を関数化しています

初心者向けポイント:
同じ処理を何度も書くとミスが増えるので、関数にすると読みやすくなります。

Shift値 n を読む(距離変換に必要)

def get_shift_n(bus):
    v = read_u8(bus, REG_SHIFT)
    n = v & 0x07
    return n

REG_SHIFT(0x35) を読むと、距離換算に使う シフト値 n が入っています。

つまり「n は下位3ビットに入っている」という前提で抜き出しています

v & 0x07 の意味:

  • 0x07 は2進数で 00000111
  • AND(&)を取ることで 下位3ビットだけを取り出す
  • つまり「n は下位3ビットに入っている」という前提で抜き出しています

距離の生データ(12bit)を作る

h = read_u8(bus, REG_DIST_H)
l = read_u8(bus, REG_DIST_L) & 0x0F

raw12 = (h << 4) | l

ここが初心者が最初に戸惑うところです。

なぜ “12bit” なの?

GP2Y0E03 の距離データは 12bit(0〜4095)で返ってきます。

  • 上位8bit(Distance[11:4])が 0x5E
  • 下位4bit(Distance[3:0])が 0x5F の下位4bit
& 0x0F の意味

0x0F は2進数で 00001111
ANDを取ることで 下位4bitだけ残す ためです。
(上位4bitは他の用途の可能性があるので捨てます)

(h << 4) | l の意味
  • h << 4:上位8bitを4bit左にずらして「上位側」に配置
  • | l:そこに下位4bitを足して合体(ORで結合)

例(イメージ):

  • h = 10101010
  • l = 00000101(下位4bitが0101)
  • raw12 = 10101010 0101(12bit値)

生データ → cm に変換

dist_cm = raw12 / (16.0 * (2 ** n))

GP2Y0E03 の仕様(アプリノート)で、距離は次の式で求めます。

  • raw12 を一定の倍率で割ることで cm になる
  • n(shift)によって倍率が変わる

ここでは読みやすいように式を整理して

  • 16.0 * (2 ** n) で割っています

初心者向け補足:
2 ** n は「2のn乗」です。
n=2なら 2**2 = 4 になります。

main() の動き(繰り返し表示)

with SMBus(I2C_BUS) as bus:
    time.sleep(0.2)
    while True:
        dist_cm, n, raw12 = read_distance_cm(bus)
        print(...)
        time.sleep(0.2)
with SMBus(...) as bus の意味
  • I²Cバスを開いて使う
  • with を使うと、終了時に自動でクローズしてくれて安全です
最初に 0.2秒待つ理由

センサーは起動直後に値が安定しないことがあり、最大距離側を出す挙動があるため少し待っています。

よくあるトラブルと対策

症状対策
i2cdetectに表示されない配線・I2C有効化を再確認
距離が最大値のまま起動後1秒ほど待つ
値が不安定反射物の色・角度を確認
通信できないVIN(IO)を3.3Vに接続

使用した部品一覧

部品補足リンク
Raspberry Pi 3 Model B他のPiでも可Amazonで見る
GP2Y0E03 距離センサSHARP製Amazonで見る
ジャンパワイヤオス-メス,メス–メス等
microSD / 電源通常のPi環境SanDisk 高耐久

Raspberry pi 用のスターター電子工作キット

ラズパイの電子工作用スターターセットです。基本的な部品をまとめて購入したい方におすすめです。

まとめ

  • GP2Y0E03は初心者でも扱いやすい距離センサ
  • Raspberry Piとは I2C(3.3V)で安全に接続
  • Pythonで簡単に距離(cm)を取得できる
  • 電子工作・IoT入門に最適

今回は、赤外線センサーを用いて電子工作する一例を紹介しました。是非、皆さんも使用してみて下さい。

タイトルとURLをコピーしました