【MicroPython】XIAO ESP32C6でAQM1602を表示!SoftI2CでI2C通信成功

MicroPython XIAO ESP32C6でAQM1602を表示!SoftI2CでI2C通信成功
スポンサーリンク

正直に言うと、XIAO ESP32C6でのI2C通信にここまで悩まされるとは思っていませんでした。
これまでRP2040やESP32などでは、I2C(0)を使い、指定のSDA/SCLピンをつなげば簡単にI2Cデバイスが認識されていたのです。
しかし今回は i2c.scan() を実行しても、返ってくるのは空リスト []
「配線ミスか?」「LCDが壊れたか?」と何度もチェックしましたが、同じAQM1602がRP2040では正常に動作するので、そうではなさそう。
ESP32C6にはハードウェアI2Cとして使用できるピンが限られていたり、正確な情報がまだ少ない、という背景もあり、「実際には動くのかもしれないが、正しいピン指定や初期化方法が把握しづらい」という状況だったのかもしれません。
結果として、「SoftI2Cを使ってみたらすんなり動いた」が情報不足でしたというのが今回の教訓でした。

スポンサーリンク

なぜハードI2Cがうまくいかなかったのか?

i2c通信を良く理解していない

machine.I2C を使ったハードウェアI2Cの場合でも、どのGPIOピンをSDAとSCLにするかは自由に設定できます。これは、多くのMicroPythonが動作するマイコン(ESP32シリーズやRaspberry Pi Picoなど)が持つI2Cコントローラの柔軟な機能の一つなのだそうです。

正しいコード

import machine

sda=machine.Pin(0)
scl=machine.Pin(1)
i2c=machine.I2C(0,sda=sda, scl=scl, freq=400000)
print(i2c.scan())
>>> %Run -c $EDITOR_CONTENT
[62]
>>>

正しく表示されました

ESP32-C6の持つハードウェアI2Cコントローラを使い、そのSDAとSCLピンとしてGPIO0とGPIO1を割り当てたという設定で、私はこれをよく理解していませんでした。
GPIOピンの選択肢が広いことは、開発者にとって非常に便利な機能になります。

失敗例(一部のチップでは使える)

from machine import Pin, I2C
i2c = I2C(0, sda=Pin(4), scl=Pin(5), freq=100000)
print(i2c.scan())

i2c.scan()が常に空リスト [] を返す状態に

SoftI2Cを使ってみた

SoftI2C()でGPIO0(scl)とGPIO1(sda)を任意で指定

今回はscl=Pin(1), sda=Pin(0)に設定しました。
freq=は100000から400000の設定が可能で、こちらを省いた場合デフォルトで100000になるそうです。

from machine import Pin, SoftI2C
import time
i2c = SoftI2C(scl=Pin(1), sda=Pin(0), freq=100000)
print(i2c.scan())

上記のプログラムを実行した場合[62]が表示されます

>>> %Run -c $EDITOR_CONTENT
[62]
>>>

C6ピンレイアウト

接続図

実際にLCDへ表示する例

from machine import Pin, SoftI2C
import time
LCD_ADDR = 0x3E
i2c = SoftI2C(scl=Pin(1), sda=Pin(0), freq=200000)
print(i2c.scan())
# コマンド送信
def lcd_command(cmd):
    i2c.writeto(LCD_ADDR, bytearray([0x00, cmd]))  # 0x00 はコマンド送信
# データ送信
def lcd_data(data):
    i2c.writeto(LCD_ADDR, bytearray([0x40, data]))  # 0x40 はデータ送信
# LCD 初期化
def lcd_init():
    time.sleep(0.05)  # 電源投入後の待機
    for cmd in [0x38, 0x39, 0x14, 0x70, 0x56, 0x6C]:
        lcd_command(cmd)
        time.sleep_ms(2)
    time.sleep_ms(200)
    for cmd in [0x38, 0x0C, 0x01]:
        lcd_command(cmd)
        time.sleep_ms(2)
# LCD に文字列を表示
def lcd_print(text):
    for char in text:
        lcd_data(ord(char))  # 1文字ずつ送信
#   LCD 文字表示位置指定 col  row
def set_cursor(col, row):
        if row == 0:
            address = 0x00 + col
        elif row == 1:
            address = 0x40 + col
        else:
            print("error")
        lcd_command(0x80 | address) # Set DDRAM addre
        time.sleep_ms(2)
# 実行 set_cursor(col,row) row は 0 か 1 です
lcd_init()
set_cursor(0,0)
lcd_print("Hello AQM1602")
set_cursor(0,1)
lcd_print("Hello ESC32-C6")

SoftI2Cのメリットと注意点

  • 任意のGPIOが使える → ピン配置の自由度が高い
  • SoftI2C は freq= で通信速度を自由に指定可能
  • 通常は 100_000 で十分ですが、表示が遅いと感じる場合は 400_000 を試す価値あり
  • 安定性と信号品質に注意しつつ調整を!

🟪 まとめ

XIAO ESP32C6は小型で高性能なマイコンですが、I2Cに関しては情報が少なく、
ハードI2Cではうまく動かせないという現実に直面しました。

今回のように、SoftI2Cを使うことも出来ますが、import machine でのESP32-C6の持つハードウェアI2Cコントローラを使うのがいいと思います。

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