はじめに
M5StickC Plusでは,Grove端子のi2cの他にHAT用のi2cも同時に使いたいシチュエーションがあります.
つまりi2cの通信を2つ同時に行いたいわけですが,これはWire
オブジェクトとWire1
オブジェクトを同時に使うことで簡単に実現できる…ように見えて地味にハマったので備忘録として残しておきます.
前提
- 諸々の開発環境は準備済みであること
- [1]にあるサンプルコードのように,
M5StickC.h
を利用しつつWire
のみを使うコードは動作していること - ライブラリのバージョンは以下の通り
- m5stack/M5Unified@^0.1.9
問題
[2]のページによれば,以下のようにWire
とWire1
をbeginし直せばどちらも使えるはず…とのことでした.
// [2]から引用
void setup() {
M5.begin();
Wire.begin(32, 33);
Wire1.begin(0, 26);
}
これに基づいて書いてみたコードがこちら.
// これでは動きませんでした
#include <M5Unified.h>
#include <Wire.h>
void setup() {
M5.begin();
Wire1.begin(0, 26, 100000UL);
Serial.begin(115200);
}
void loop() {
Serial.println("start-transmission");
Wire1.beginTransmission(0x38);
Serial.print("start-write: ");
bool rw = Wire1.write(0x02);
Serial.println(rw);
uint8_t re = Wire1.endTransmission();
Serial.print("end-transmission: ");
Serial.println(re);
Wire1.requestFrom(0x38, 3);
bool w1 = Wire1.available();
Serial.print("available: ");
Serial.println(w1);
Serial.println("");
if(w1){
Serial.println("OK");
}
M5.update();
delay(100);
}
実際のコードから関係ない処理は全部消して,見やすくなるように書き直しています.Serial.println("OK");
が呼び出されればHATとの通信ができているものとして考えてください.このコードだと,Wire1.endTransmission()
の戻り値がESP_FAIL
を意味する2になってコケていました.
M5Unified.h
を使っていることくらいしか違いがなく𝕏で嘆いていたところ,有識者の方々から色んなコメントが届きました…ありがたや…
解決策
鍵になったのはらびやんさんから教えていただいたWire1.end()
でした
ひとまずこれでM5.begin後に たなかさんの助言どおり WireとWire1を再割当てすると良いと思います。
— らびやん (@lovyan03) October 10, 2023
あとは…もしかすると、一度Wire1.endしてからでないとWire1.beginできないかも。。
このアドバイスをもとに以下のように修正したところ,無事HAT用の端子へWire1を割り当てて通信することができました!!一回end()
呼ばないといけないとは…自力では辿り着けなかった気がします.感謝🙏🙏(delay(100);
はなんとなくおきもちで入れているのでなくても良いかもしれません)
// これなら動く
#include <M5Unified.h>
#include <Wire.h>
void setup() {
//----------------------ここから-------------------------
auto cfg = M5.config();
cfg.pmic_button = false; // これで電源ボタン状態取得を行わなくなる
cfg.internal_imu = false; // これで内蔵IMUを使わなくなる
cfg.internal_rtc = false; // これで内蔵RTCを使わなくなる
M5.begin(cfg);
Wire1.end();
delay(100);
//----------------------ここまで追加----------------------
Wire1.begin(0, 26, 100000UL);
Serial.begin(115200);
}
void loop() {
Serial.println("start-transmission");
Wire1.beginTransmission(0x38);
Serial.print("start-write: ");
bool rw = Wire1.write(0x02);
Serial.println(rw);
uint8_t re = Wire1.endTransmission();
Serial.print("end-transmission: ");
Serial.println(re);
Wire1.requestFrom(0x38, 3);
bool w1 = Wire1.available();
Serial.print("available: ");
Serial.println(w1);
Serial.println("");
if(w1){
Serial.println("OK");
}
M5.update();
delay(100);
}
おわりに
いかがでしたか?groveポートとHATを同時に使いたいシチュエーション,それなりにあると思います.どなたかのお役に立てたら幸いです.各コメント全文は[3]から辿れます.
それでは.
参考
M5StickC Plusくん、Groveのi2cとHATのi2cは同時に叩けないんかい!!!!!!詰んだ!!!今からESP-NOWまじで導入するか…?
— 孔明 (@eternalfriend17) October 9, 2023