マックの趣味

PCAL9555APW I2C GPIOエクスパンダ

スイッチサイエンス PCAL9555APW I2C GPIOエクスパンダをESP32で動かしてみました。
ネットでは色々出ていますが、どれもそのままでは動かなかったです。
まず、ボードのI2Cアドレスはデフォルトで02H (0x20) です。0x40 とかと書いてあるサイトもありました。
これは、i2c_scanner を使えばわかります。
ESP32の場合は、SCLとSDAがデフォルトでGPIO22とGPIO21になってます。 Wire.begin(); するときに、 Wire.begin(21,22)と書く必要は特に無いようです。
それぞれのPINをPULLUPする必要はないようですが、しても動きます。

pinMode(21, INPUT_PULLUP);
pinMode(22, INPUT_PULLUP);

今回は流れるウインカーを作るために、出力だけ確認しました。スイッチサイエンスさんのサンプルは入力しかありません。
サンプルスケッチにある Wire.endTransmission(false); を入れるとI2Cが止まります。これははまりました。
Aruduinoなら動くのかもしれません。Wire.endTransmission(true); も  Wire.endTransmission(); もどちらでも動きます。
PCAL9555APWのデータシートに書いてあるので詳細は読んでください。
書き込みに必要なレジスタは、
Output port :出力レジスタ
Configuration port :ピンの設定
Output port configuration register 出力方式の設定の三つです。

Output portは出力レジスタで出力したいデータを書きます。デフォルトは全部1になっています。
Configuration portはピンを入力とするか、出力とするかを決めます。入力時はハイインピーダンスになります。デフォルトは、全部入インピーダンス(入力)になっています。
Output port configuration registerは出力方式を設定します。1を書くと、オープンドレイン、0を書くとプッシュプルになるようです。LEDを付けるようなHigh Lowな制御をしたい場合は、プッシュプルに、電流引き込みで使いたい場合は、オープンドレインで使用します。普通はプッシュプルで良いと思います。
データシートにはこの設定は、onfiguration portの前に設定することを推奨と書いています。ただ、逆にしても動作しました。

Portは1と2の二つがありますが、それぞれのレジスタはロールバックするので、Port1 に1バイトを二回書くとPort2にもかかれるようです。
スイッチサイエンスさんの説明では、なぜか、Port2を指定して二バイトを書いてます。
Port1から書いても機能するとは思いますし、それぞれを指定して一バイト書いても機能するかもしれません。
IC2はコマンドを出して、そのあとにデータを出すことでスレーブが動きます。なので、

レジスタアドレス送信 ⇒ データ送信 2バイトの繰り返しになります。

順番は
① Output port configuration register
② Configuration port
③ Output port
になります。通常は動作しながら、出力回路を変更することはありませんし、入力と出力を切り替えることもまずないでしょうから、①と②はスケッチのsetup()で記載して、③のみloop()に書けばいいでしょう。

これをコードにすると、

setup()の中では、
Wire.begin(); : I2Cを初期化します。
Wire.beginTransmission(PCAL9555APW_ADDR); :スレーブのアドレス送信します。
Wire.write(Output port configuration registe); : コマンドレジスタアドレスを送信します。
Wire.write(data); : 1バイトデータを送信します。
Wire.write(data); : 1バイトデータを送信します。(Port2とPort2の2バイトを送信します。)
Wire.write(Configuration port ); : コマンドレジスタアドレスを送信します。
Wire.write(data); : 1バイトデータを送信します。
Wire.write(data); : 1バイトデータを送信します。(Port2とPort2の2バイトを送信します。)
Wire.endTransmission(); :送信終了を知らせます。これでBUSを開放します。

loop()の中では、
Wire.write(Output port ); : コマンドレジスタアドレスを送信します。
Wire.write(data); : 1バイトデータを送信します。
Wire.write(data); : 1バイトデータを送信します。(Port2とPort2の2バイトを送信します。)
Wire.endTransmission(); :送信終了を知らせます。これでBUSを開放します。

dataを適宜変えれば出力は変わります。
なかなか動かなかったので、オシロを買ってしまいました。このオシロは個人でも買える値段だし、I2Cデータをデコードしてくれるので重宝しました。

ランキングに参加中、クリックをお願いします。

  • Xでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

最新の画像もっと見る

最近の「マイコン」カテゴリーもっと見る

最近の記事
バックナンバー
人気記事