10
9

More than 1 year has passed since last update.

ESP32 で arduino-CAN ライブラリを使うと通信速度が半分になる問題と解決策

Last updated at Posted at 2021-10-06

問題

 ESP32でCAN通信を扱う際、Arduino IDE で開発している場合は、arduino-CAN というライブラリを使うことが多いと思います。この arduino-CAN ライブラリ を使って ESP32 でCAN通信を行うと、なぜか通信速度が指定値の半分になる という問題に遭遇することがあります。

問題が発生しているハードウェア

ESP32でCAN通信をする を参考に結線しています。ただし、私の環境では都合によりRX32TX33としています。

問題が発生しているコード

 arduino-CAN のサンプルコード examples/CANSender そのものなので省略します。

原因

 以下のページに、この問題に関する議論がありました。
https://github.com/sandeepmistry/arduino-CAN/issues/62

 チップバージョンがRev2以上のESP32では、CAN通信に関係する、とあるレジスタビットの役割が「通信速度を半分にする」という意味に変更されたそうです。変更前の仕様に従って書かれている arduino-CAN ライブラリは、このビット値を1にセットしてしまうため、通信速度がCAN.begin(baudrate)で指定したbaudrateの半分になってしまうのです。

解決策

 単純に、送りたい速度の2倍を指定してbegin すれば、送ることはできます。

 しかし、1 Mbps で通信したい場合や、根本的な解決を求める場合、setup()内で CAN.begin(baudrate)の後に以下のように追記します。

  // start the CAN bus at 500 kbps
  if (!CAN.begin(500E3)) {
    Serial.println("Starting CAN failed!");
    while (1);
  }
  // 以下2行を追記
  volatile uint32_t* pREG_IER = (volatile uint32_t*)0x3ff6b010;
  *pREG_IER &= ~(uint8_t)0x10;

(詳しい人向け)
CAN割込み関連のレジスタ REG_IER (ESP32 の公式マニュアルでいう TWAI_INT_ENA_REG 0x3ff6b010) の bit 4 の役割が、"Wake-up interrupt" から "divide BRP by 2" に変更されたそうです。CAN.begin(baudrate)のソースコードでこのレジスタに0xffを書き込んでいるため、当該bitが1となり、速度が半分になります。そこで、beginした後に当該ビットに0を書き込んでいます。

おわりに

 複数のプロジェクトで立て続けにこの問題に遭遇し頭を抱えておりました。しかも、ESP32 Technical Reference Manual にもこの仕様変更が反映されていない(執筆時点での最新版v4.5, 2021/7/21)ため原因特定に時間がかかりました。かなりニッチな話題ですが、1度ハマると迷宮入りしそうなポイントに見えます。

10
9
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
9