I2Cバスは、通常はマスターがSCLラインを制御することで通信を主導し、スレーブはマスターのタイミングに従います。しかし、スレーブ側の処理が間に合わないとき、スレーブはSCLラインをLowに保持することでマスターを待たせることができます。これを「クロックストレッチ」といいます。
例えばBOSCH社の9軸センサBNO055はしばしばクロックストレッチでACKビットを100μsec以上待たせます。
上: SCL, 下: SDA, 横軸: 50μsec/DIV
ところが、Raspberry Pi PicoのArduino環境 (本家版ではなくEarle Philhower版のほう) では、I2Cのクロックストレッチ待ちは100μsecでタイムアウトしてしまいます。このため、AdafruitのBNO055ライブラリが正しく動作しなくなります。タイムアウト時間が100μsecというのはいささか短いように思われます。
そこで、I2Cドライバのソース( Wire.cpp ) の_clockStretch関数を下記のように修正します。
static bool _clockStretch(pin_size_t pin) { // auto end = time_us_64() + 100; // 100usecでタイムアウト auto end = time_us_64() + 1000; // 1000usecでタイムアウト while ((time_us_64() < end) && (!digitalRead(pin))) { /* noop */ } return digitalRead(pin); }
Wire.cppは、Windowsのインストーラ版であれば下記のディレクトリにあります。
%LOCALAPPDATA%\Arduino15\packages\rp2040\hardware\rp2040\x.x.x\libraries\Wire\ (x.x.x はバージョン番号)