setWireTimeout()

名称

Wire.setWireTimeout()

説明

マスターモードで利用するときの、通信タイムアウトを設定する。

注意: タイムアウトは、デバイスの問題や雑音、不十分な絶縁、他の電気的な問題などがおこっていることを示唆する。タイムアウトはスケッチが停止するのを防ぐが、問題を解決するわけではない。このような場合、タイムアウトによっては検出されないデータ破損が発生している可能性もある。このため、タイムアウトが発生したときは、以前に送受信したデータも破損している可能性がある。このような問題をより確実に検出するための手段(チェックサムや書き込んだ値を読み戻す)が必要になるかもしれない。タイムアウトや追加の手段は最終的な防御策であり、本来は根本的な原因を解決する必要がある。

書式

void TwoWire::setWireTimeout(uint32_t timeout, bool reset_with_timeout);

引数

timeout タイムアウト(ミリ秒単位)。0のときは、タイムアウトは無効。デフォルト値は25000。
reset_with_timeouttrueの場合、タイムアウト時にI2Cデバイスを自動リセットする。デフォルト値はfalse。

この関数をパラメータ無しで呼ぶ場合は、典型的な設定において問題が発生しない十分な値が、デフォルトのタイムアウトが設定される。

戻り値

なし。

使用例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <Wire.h>

void setup() {
  Wire.begin(); // join i2c bus (address optional for master)
  #if defined(WIRE_HAS_TIMEOUT)
    Wire.setWireTimeout(3000 /* us */, true /* reset_on_timeout */);
  #endif
}

byte x = 0;

void loop() {
  /* First, send a command to the other device */
  Wire.beginTransmission(8); // transmit to device #8
  Wire.write(123);           // send command
  byte error = Wire.endTransmission(); // run transaction
  if (error) {
    Serial.println("Error occured when writing");
    if (error == 5)
      Serial.println("It was a timeout");
  }

  delay(100);

  /* Then, read the result */
  #if defined(WIRE_HAS_TIMEOUT)
  Wire.clearWireTimeoutFlag();
  #endif
  byte len = Wire.requestFrom(8, 1); // request 1 byte from device #8
  if (len == 0) {
    Serial.println("Error occured when reading");
    #if defined(WIRE_HAS_TIMEOUT)
    if (Wire.getWireTimeoutFlag())
      Serial.println("It was a timeout");
    #endif
  }

  delay(100);
}

注意と警告

タイムアウトがどのように実装されているかは、プラットフォームにより異なる。典型的には、トランザクションが完了するのを待っているとき(例えば、バスが再度利用可能になるのを待つ、ACKビットを待つ、全トランザクションが終了するのを待つなど)に、タイムアウト条件が発生する。

このようなタイムアウト状態がおこると、トランザクションは中断され、Wire.endTransmission()Wire.requestFrom()が、それぞれ、エラーコードやゼロバイトを返す。これ自身はバスの問題を解決するものではない(例えば、回路のショートを解決しない)が、少なくとも無限にブロックされることを防ぎ、スケッチが問題を検出し、この状態を解決するのに役立つ。

reset_on_timeoutがtrueに設定され、プラットフォームがこれをサポートしている場合は、I2Cハードウェアがリセットされる。これは、I2Cハードウェアモジュール内の不正な状態を解消するのに役立つ。例えば、AVRプラットフォームでは、ノイズによって引き起こされたタイムアウトが発生した後、通信を再開させるために必要である。

タイムアウトが起こると、Wire.getWireTimeoutFlag()によって検出できるフラグが設定される。これは、Wire.clearWireTimeoutFlag()を使って手動でクリアする必要がある(Wire.setWireTimeout()を呼び出したときにもクリアされる)。

タイムアウトは、クロックストレッチや2番目のマスターがトランザクションを完了するのを待つときにも発生する。これらのケースに対応するには適切なタイムアウトを設定する必要がある。典型的なタイムアウトは25ms(SMBusプロトコルで許されるクロックストレッチの最大値)だが、(かなり)短い値でも通常は動作する。

ポータビリティに関する注意

この関数はWireライブラリの基のバージョンでは利用できない。また、全てのプラットフォームで利用できるわけでもない。プラットフォームやバージョン間の互換が必要な場合は、Wire.setWireTimeout()とWire.getWireTimeoutFlag()、Wire.clearWireTimeout()が利用できるときにだけ定義されるWIRE_HAS_TIMEOUTマクロを利用する。

AVRプラットフォームにタイムアウトが導入された当初は、将来のある時点で有効となる見込みではあるが、互換性のためにデフォルトでは無効になっていた。これは、タイムアウトのデフォルト値がプラットフォーム間で異なることを意味する。デフォルトのタイムアウト設定は、 WIRE_DEFAULT_TIMEOUTとWIRE_DEFAULT_RESET_WITH_TIMEOUTマクロとして利用できる。

タイムアウトを無効にするには、現状はデフォルト値ではあるが、setWireTimeout(0)を利用することが推奨されている。

参照

オリジナルのページ

https://www.arduino.cc/reference/en/language/functions/communication/wire/setwiretimeout/

Last Revision: 2022/02/14

最終更新日

January 4, 2024

inserted by FC2 system