前回はアナログ入力を学びました。

今回はI2C通信について学んでゆきます。
I2C通信
ロボットはセンサー入力を使い、動作を変えてゆく自動制御を行います。
プログラムを作成する過程で、現在どのような値が入力されているのか確認したい場面は多くあります。
そこで、I2C通信を使って接続したLCDディスプレイに表示する方法を試します。
使用するLCDはこちらです。
https://akizukidenshi.com/catalog/g/g112031/

このLCDはRaspberry Pi Pico WとI2Cという通信方法でデータの送受信を行います。
I2C(Inter-Integrated Circuit)とは?
I2C(アイ・スクエア・シー、またはアイ・ツー・シー)は、電子部品同士を接続してデータをやり取りするための「シリアル通信方式」の1つです。
シリアル通信とは、データを「1ビットずつ順番に送信」する仕組みで、送信するデータを二進数(0と1)に変換して、1つの線を通じて送る方法です。
I2Cは特に、センサーやディスプレイモジュールなどの電子部品を簡単に接続できるため、マイコンや電子工作で広く使われています。
例えば、Raspberry PiやArduinoを使って温度センサーや液晶ディスプレイを操作する際にも利用されます。
通信手法の種類:シリアル通信とパラレル通信
データを送信する手法には、シリアル通信とパラレル通信の2種類があります。
これらは、データを送信する方法に違いがあり、それぞれの特徴があります。
1. シリアル通信
- データを「1ビットずつ順番に」送る方法。
- 例え: 一列に並んだ荷物を一つずつトラックで運ぶようなイメージ。
- I2Cはシリアル通信の一種です。
- 主に使われる配線は4本(以下の2本が通信に関係):
- SDA(Serial Data): データを送受信する線。
- SCL(Serial Clock): 通信のタイミングを合わせるためのクロック信号。
2. パラレル通信
- 複数のビットを一度にまとめて送信する方法。
- 例え: 一列の荷物を複数台のトラックで同時に運ぶイメージ。
- 一度にたくさんのデータを送れるため、高速通信が可能。
- ただし、多くの信号線が必要になるため、配線が複雑でコストが高くなります。
特徴 | シリアル通信 | パラレル通信 |
---|---|---|
コスト | 配線が少ないため安価 | 多くの信号線が必要なので高価 |
配線の容易さ | 簡単(基本的に4本の線:GND、VCC、SDA、SCL) | 信号線が多く複雑(データ線がビット数に比例して増える) |
通信速度 | 1ビットずつ順番に送るため遅い | 複数ビットを同時に送るため高速 |
I2Cの配線
I2C通信の基本構成
I2C 通信では、デバイス同士を接続するために2本のデータ線を使用します:
- SDA(Serial Data Line): データの送受信を行う線。
- SCL(Serial Clock Line): 通信のタイミングを同期するためのクロック信号を送る線。
これらに加えて、電源線(VCC)とGND(グランド)を接続する必要があります。
Raspberry Pi Pico W の I2C ポート
Raspberry Pi Pico W では、I2C 通信に使用できる GPIO ピンが 固定されたペア で割り当てられています。この割り当ては自由に変更できませんので、設計時に注意が必要です。
以下が、Raspberry Pi Pico W で使用可能な I2C の SDA と SCL の組み合わせです:
I2Cインスタンス | SDAピン | SCLピン |
---|---|---|
I2C0 | GPIO 0 | GPIO 1 |
I2C1 | GPIO 2 | GPIO 3 |
注意
- Raspberry Pi Pico W では、1つの I2C インスタンスに対して SDA と SCL は固定されます。異なるペアを使用する場合は、I2C のインスタンスを切り替えて利用してください。
- どのデバイスをどのポートに接続するかを設計段階で考慮する必要があります。
配線例
I2C 通信を使ってセンサーやディスプレイなどを Raspberry Pi Pico W に接続する場合、以下のように配線します。
必要なピンの接続
- VCC(電源線): 使用するセンサーやデバイスの電源(通常 3.3V または 5V)に接続します。
- GND(グランド): Raspberry Pi Pico W の GND とセンサー・デバイスの GND を接続します。
- SDA(データ線): Raspberry Pi Pico W の GPIO 0 または 2 に接続(使用する I2C インスタンスに応じて選択)。
- SCL(クロック線): Raspberry Pi Pico W の GPIO 1 または 3 に接続(使用する I2C インスタンスに応じて選択)。
I2C Pull-up 抵抗
I2C 通信では、SDA と SCL の両線にプルアップ抵抗が必要です。これにより、通信ラインが正常に動作します。
ポイント
- プルアップ抵抗の値: 通常は 4.7kΩ〜10kΩ を使用します。
- 通常、センサーやモジュールにプルアップ抵抗が組み込まれている場合が多いため、外部プルアップ抵抗が不要な場合もあります。
今回使用するLCDディスプレイはプルアップ抵抗を内蔵しているため不要です。
LCD
それでは液晶ディスプレイに文字を表示させてみましょう。
ただ液晶ディスプレイに文字を表示させるのを1からコーディングするのは非常に複雑になってしまいますので、ここではmicropythonに搭載されているライブラリ「ssd1306」を活用しましょう。
まずThonnyの画面左上の「ツール」をクリックして開き、「パッケージを管理」をクリックします。

画面上部の検索バーに「ssd1306」と記入しEnterキーを押します。

画面右側にライブラリ名が表示されますのでクリックします。

中央下部の「インストール」をクリックします。

画面左側の<インストール>の項目に「ssd1306」が追加されていればインストールは完了です。

これでライブラリが使用できるようになりましたので、プログラムを書いていきましょう。
まずライブラリをインポートします。
今回はRaspberry Pi Pico WとLCDをI2C通信で接続しますので、machineライブラリの中からI2Cというライブラリもインポートしましょう。
from machine import Pin, I2C
import ssd1306
import time
次にI2Cの設定をします。
今回はロボットの回路でLCDディスプレイがSDA:GPIO20、SCL:GPIO21につながっていますのでそれを指定します。
そしてLCDが適切に接続できているかをスキャンして確認します。
スキャンが成功すればI2C接続のアドレス(普通は0x3c:10進数で60)をPC画面に表示します。
from machine import Pin, I2C
import ssd1306
import utime
# I2C通信の初期化 (SDA: ピン20, SCL: ピン21, 通信速度: 400kHz)
i2c = I2C(0, sda=Pin(20), scl=Pin(21), freq=400000)
# 接続されているI2Cデバイスをスキャン
addr = i2c.scan()
if not addr: # I2Cデバイスが見つからなかった場合
print("I2Cデバイスが見つかりません。接続を確認してください。")
raise SystemExit() # プログラムを終了
else: # 見つかった場合
print("I2Cデバイスが見つかりました:", [hex(a) for a in addr])
ディスプレイ表示を設定します。
ディスプレイは定期的に表示する文字を更新してゆくのですが、前回ディスプレイに何か表示されていた場合、画面をリセットする必要があります。
これをしないと変数部分が「■」のように表示されてしまいます。
またこの操作は何度も行うので関数にしておきます。
# OLEDディスプレイを黒で塗りつぶす
def clear():
utime.sleep(1) # 1秒待機
oled.fill(0) # 0で画面全体を黒にする
oled.show() # 表示を更新
これが完了してから表示したい文字列を表示します。
例題
接続したOLEDにHello,Worldと表示するプログラムは下記の通りです。
from machine import Pin, I2C
import ssd1306
import time
# I2C通信設定
i2c = I2C(0, scl=Pin(1), sda=Pin(0), freq=400000)
# OLED初期化(アドレス0x3C)
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
# 表示内容
oled.fill(0) # 画面クリア
oled.text("Hello, World!", 0, 0)
oled.show()

注意点として、アルファベット以外を表記するのは少々手間がかかりますのでご注意ください。
日本語や絵文字は、表記出来ないことはないですがライブラリのインストールやコードの追加が必要になります。
課題11
OLEDディスプレイにセンサ値を表示する回路を作成せよ。
Raspberry Pi Pico W と I2C接続した OLEDディスプレイ(SSD1306) に
可変抵抗やジョイスティックなどのアナログセンサから読み取った値を、リアルタイムで数値表示する。

解答例はこちら
from machine import ADC, Pin, I2C
import ssd1306
import time
# センサ:GPIO26(ADC0)
sensor = ADC(Pin(26))
# I2Cディスプレイ初期化(I2C0, GPIO0=SDA, GPIO1=SCL)
i2c = I2C(0, scl=Pin(1), sda=Pin(0))
oled = ssd1306.SSD1306_I2C(128, 64, i2c) # 128x64ピクセル
while True:
value = sensor.read_u16() # センサ値(0〜65535)
oled.fill(0) # 画面クリア
oled.text("Sensor Value:", 0, 0)
oled.text(str(value), 0, 16)
oled.show()
time.sleep(0.1)
次回はこちら