🦜

【Raspberry Pi Pico W】I2Cの使い方(micropython×Thonny)

2024/12/12に公開

1. はじめに

個人的にI2Cでよく使うモジュールのサンプルコードを一か所にまとめときました

1.1 この記事について

  • Raspberry Pi Pico W(以下、Pico)でI2Cを使ったサンプルプログラムを記載する
  • 細かい解説というより、備忘録とプログラム+回路図のサンプル重視
  • 入門・解説というより備忘録に近い

1.2 対象読者

  • Picoを使ったことがある
  • Thonnyを使ってPicoにプログラムを書き込み・実行ができる
  • プログラム言語(特にmicropython)が多少読める、書ける

1.3 動作環境

  • PC
    • OS:Windows 11 Home
    • プログラミング環境:Thonny(v4.1.4)
  • Raspberry Pi Pico W
    • ファームウェア:micropython v1.24

2. I2Cについて

2.1 概要

  • 1つのデータ送伝路を使って、1ビットずつ送信する、シリアル通信方式の1つ
  • 2本の信号線(SDA,SCL)ですべてのデータの送受信が行えるため、配線が少なくなる
  • 同一線上に複数のデバイスがある場合でも、個々のデバイスを7bitのアドレスで識別することが可能
よりI2Cについて知りたい方は...

以下のリンクの説明が図説などあって分かりやすいので、一読してみてください。

よく分かる! シリアル通信基礎講座 _ 組込み技術ラボ I2C通信
https://emb.macnica.co.jp/articles/8191/

実際のモジュール紹介(一例)

I2Cで使用可能な製品達(うちにあったもの)

4線(Vcc, GND, SDA, SCL)で通信可能だが、モジュール特融の便利機能のため、Pin数は多いものもある。
それらの使い方については、各製品のデータシートを参照のこと

2.2 picoでI2Cを使用できるpinについて

2.3 machine.I2Cクラスについて

micropythonにはI2Cのクラスが存在するため、それを使うとよい
以下のコードでは、I2Cの通信線でつながっているデバイスのアドレス一覧を表示できる

from machine import Pin, I2C

i2c = I2C(0)  # 未指定だとsda=Pin(4), scl=Pin(5)
address_list = i2c.scan()  # 認識されているデバイスのアドレスのリストを返す
print(address_list)  # 10進数でアドレスを表示(list)
print([hex(x) for x in address_list])  # デバイスのアドレスを16進数表記で表示

実行結果(例)

OLED(128x64)とBMP280を繋いだ場合だと、以下のような結果となる

細かいメソッドなどを知りたい人は...

こちらをどうぞ!!
クラス I2C -- 2線式シリアルプロトコル
https://micropython-docs-ja.readthedocs.io/ja/latest/library/machine.I2C.html#class-i2c-a-two-wire-serial-protocol

3. 実際に使ってみる

  • ThonnyのManage Package経由で導入できるものは少ない
  • ない場合は、先人たちのGithubのサンプルを利用できるとよい
  • それでもない場合は、デバイスのデータシートをよく読み、自力で実装すべし

3.1 有機ELディスプレイに文字を出力する(OLED)

  • OLED(有機ELディスプレイ)上に文字や図形を描画することができる
  • ライブラリ(ssd1306)がThonny上でインストール可能!
  • デバイスは、I2C用の他にSPI用のものもあるため、間違えないように注意!

3.1.1 回路図+配線図(Fritzing)

3.1.2 プログラム例

from machine import Pin, I2C
from ssd1306 import SSD1306_I2C

i2c = I2C(0, sda=Pin(4), scl=Pin(5))  # インスタンスを生成
display = SSD1306_I2C(128, 64, i2c)

display.fill(0)
display.fill_rect(0, 0, 32, 32, 1)
display.fill_rect(2, 2, 28, 28, 0)
display.vline(9, 8, 22, 1)
display.vline(16, 2, 22, 1)
display.vline(23, 8, 22, 1)
display.fill_rect(26, 24, 2, 4, 1)
display.text('MicroPython', 40, 0, 1)
display.text('SSD1306', 40, 12, 1)
display.text('OLED 128x64', 40, 24, 1)
display.show()

下記のプログラムを参考にしました。
https://micropython-docs-ja.readthedocs.io/ja/latest/esp8266/tutorial/ssd1306.html

3.1.3 ライブラリ

「ssd1306.py」を使用します
Thonnyの上部メニュー[Tools]->[Manage packages]->ssd1306で検索->「ssd1306」を選択->【Install】でOK

3.2 気圧をセンシングする(BMP280)

BMP280では温度(℃)・気圧(Pa)を計測できます

3.2.1 回路図+配線図(Fritzing)

3.2.2 プログラム例

コメントアウトを外せば温度も取得できます

from machine import Pin, I2C
from bmp280 import BMP280
from time import sleep_ms

i2c = I2C(0, sda=Pin(4), scl=Pin(5))  # インスタンスを生成
bmp = BMP280(i2c)

while True:
    read_pressure = bmp.pressure  # 圧力値(Pa)を読み取る
    print(f"{read_pressure=}")
    # read_temp = bmp.temperature  # 温度を読み取る
    # print(f"{read_temp=}")
    sleep_ms(100)

3.2.3 使用ライブラリ

下記のgithubの「bmp280.py」を使用させていただきました
https://github.com/dafvid/micropython-bmp280

3.3 物体との距離を計測する(VL53L0X)

3.3.1 回路図+配線図(Fritzing)

3.3.2 プログラム例

from machine import Pin, I2C
from vl53l0x import VL53L0X
from time import sleep_ms

i2c = I2C(0, sda=Pin(4), scl=Pin(5))  # インスタンスを生成
vl53 = VL53L0X(i2c)
 
while True:
    distance = vl53.range  # 距離を計測(mm)
    print(f"Distance(mm)={distance}")
    sleep_ms(1000)

3.3.3 ライブラリ

下記のgithubの「vl53l0x.py」を使用させていただきました
https://github.com/mcauser/deshipu-micropython-vl53l0x?tab=readme-ov-file

3.4 加速度・角速度を計測する(MPU6500)

3.4.1 回路図+配線図(Fritzing)

3.4.2 プログラム例

コメントアウトを外すと、角速度の他に加速度や温度センサ値を取得できます

from machine import Pin, I2C
from mpu6500 import MPU6500
from time import sleep_ms

i2c = I2C(0, sda=Pin(4), scl=Pin(5))  # インスタンスを生成
mpu6500 = MPU6500(i2c)
 
while True:
    # ax, ay, az = mpu6500.acceleration
    gx, gy, gz = mpu6500.gyro
    # temp = mpu6500.temperature
    # print(f"{ax=} {ay=} {az=}")
    print(f"{gx=} {gy=} {gz=}")
    # print(f"{temp=}")
    sleep_ms(100)

3.4.3 ライブラリ

下記のgithubの「mpu6500.py」を使用させていただきました
https://github.com/tuupola/micropython-mpu9250

3.5 色をセンシングする(TCS34725)

RGBCなどを計測できます

3.5.1 回路図+配線図(Fritzing)

3.5.2 プログラム例

from machine import Pin, I2C
from tcs34725 import TCS34725, html_rgb
from time import sleep_ms

i2c = I2C(0, sda=Pin(4), scl=Pin(5))  # インスタンスを生成
tcs = TCS34725(i2c)
 
while True:
    # temp, lux = tcs.read()  # temperature_and_lux
    # print(f"{temp=} {lux=}")
    data = tcs.read(raw=True)
    r, g, b = html_rgb(data)  # rgb値に変換
    print(f"{r=} {g=} {b=}")
    sleep_ms(1000)

3.5.3 ライブラリ

下記のgithubの「tcs34725.py」を使用させていただきました
https://github.com/adafruit/micropython-adafruit-tcs34725?tab=readme-ov-file

4. まとめ

  • I2Cでいろいろなセンサモジュールを簡単に使うことができる
  • 先人たちのGithubを活用させていただくことで、簡単に使える
  • それでも見つからなければ、センサモジュールのデータシートで使い方を確認し、I2Cクラスのメソッドを活用して使う

Discussion