2つのI2Cポートで入出力してみた
はたしてこの記事タイトルの表現が正しいのかもよくわかりませんが。。
前回記事では2つのI2C機器を同一のGPIOポートで動かしてみましたが、今回は別々のポートを使って動かしてみました。
この記事の前にTwitterではM5StackのVRを使って動かしましたが、このVRはI2C機器ではありません。
で、何故か手元にM5Stackのジョイスティックがあるではないですか。。😆じゃぁ、せっかくなのでこれでXY座標を読み出せるかと昨晩から試してみました。
PICOの標準のI2Cポートは SDA:G21 SCL:G22 です。こちらは4ピンのLCDを接続し、ジョイスティックはもちろんGroveポートに繋ぎます。でもGroveのG32 G33 はもちろんI2Cではありません。
前回の記事でも書きましたが、I2Cポートを明示的に指定する方法はわからなかったので、今回のために再度ググってみたら、、
Wire.begin(SDA,SCL); でした orz
リファレンスではbegin()の引数は機器のアドレスを指定するという記事ばかりで、GPIOピンを指定するというのは見つかりませんでしたが、この記述で指定しているコードを公開されている方がおられてなんだかなぁ…という思いです。
そういえば、SPI.begin()も引数でハマってたし。。。
ただし落とし穴?がありました。
2つの機器でI2CポートのGPIOピンが違うので、それをどうやって切り替えるかです。
いろいろググってみたり実験してみたりで、メインループ void loop() 内で、
Wire.begin(32,33); //ジョイスティック
……
Wire.begin(21,22); //LCD
……
とすれば動くだろうと思ったのですが、一方をコメントアウトして別々にすれば、それぞれはちゃんと動くのですが、両方同時に動かすとジョイスティックの値はシリアルモニターには出力されますが、LCDは光もしません。。
さらにググって見つけたのは Wire.end() でした。
つまり begin で開いたら、end で閉じなさいということでした。まぁ言われてみれば当たり前と言えば当たり前。。orz
Wire.begin(32,33); //ジョイスティック
……
Wire.end();
Wire.begin(21,22); //LCD
……
Wire.end();
です。
ということで、できあがったコードは以下の通りです。
#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
/** LCDのインスタンスを生成 */
Adafruit_SSD1306 lcd01(128, 64, &Wire, -1);
void setup() {
// Serial.begin(9600);
}
void loop() {
/** ジョイスティックからI2C通信によるデータ取得 */
int joyStickX = 0; // ジョイスティックX軸
int joyStickY = 0; // ジョイスティックY軸
int joyStickP = 0; // スティックレバーの押し(push)状態
Wire.begin(32, 33); // Grove端子をI2C通信に設定(SDA, SCL)
Wire.requestFrom(0x52, 3); // I2Cデータ取得(アドレス、バイト数)
while (Wire.available()) { // 受信データがあれば
joyStickX = map(Wire.read(), 0, 255, -50, 50); // X軸アナログ値を取得 (0-255) して map関数で -50〜50 に変換
joyStickY = map(Wire.read(), 0, 255, -50, 50); // Y軸アナログ値を取得 (0-255) して map関数で -50〜50 に変換
joyStickP = Wire.read(); // スティックレバーの押し状態取得(off:0 on:1)
}
Wire.end(); // ポートを変更するためにI2C通信をクローズ
/** 取得データをLCD出力 */
Wire.begin(21, 22); // ピン配置をI2C通信に設定(SDA, SCL)
lcd01.begin(SSD1306_SWITCHCAPVCC, 0x3c); // ディスプレイの表示に必要な電圧を生成, アドレスは0x3C
lcd01.setTextSize(2); // テキストサイズ2は大サイズ
lcd01.setTextColor(WHITE); // これがないとフォントカラーはBLACKとなる
lcd01.clearDisplay(); // ディスプレイのバッファを初期化
lcd01.setCursor(0,10); // ディスプレイの描画座標指定 X=0, Y=10
lcd01.printf("x:%3d\ny:%3d\np:%3d\n", joyStickX, joyStickY, joyStickP);
lcd01.display(); // ディスプレイのバッファをLCDに出力し画面表示する
Wire.end(); // ポートを変更するためにI2C通信をクローズ
// Serial.printf("x:%3d y:%3d p:%1d\n", joyStickX, joyStickY, joyStickP);
delay(50);
}
実際に動いているところ。動画はやっぱり苦手。。。