ESP-IDFを使ってみる

CAN通信(TWAI通信)


ESP32には、CAN2.0B仕様の標準フレームフォーマット(11ビットID)および拡張フレームフォーマット(29ビットID)をサポート するCANコントローラが含まれています。

こ ちらにCAN通信のサンプルが公開されています。
ESP-IDFのver4.1まではCAN Networkの名前でしたが、ESP32-S2の追加に伴い、
ver4.2-dev-2243(ぐらい)からTWAI(Two-Wire Automotive Interface) Networkに名前が変わりました。
ドライバーもdriver/can.hからdriver/twai.hに変わり、APIも全て変わっています。

こ ちらには3つのフォルダーが有りますが、2台のESP32を使って、masterとslave、またはmasterと listen_onlyを同時に動かさないとテストすることができません。
そこで、RaspberryやArduinoを送信元として、受信したデータを表示するだけのツール(candump)を作りました。
ソースはこちらで 公開して いますが、menuconfigでCANのBitrateを、送信元と一致させる必要が有ります。



esp32でCAN通信を行う場合、CAN Bus Transceiverが別途必要になります。
CAN Bus Transceiverには駆動電圧が5Vの製品と、3.3V以上で駆動できる製品が有りますが、
esp32で5Vの製品を使う場合は、受信側のデータラインのレベルシフトが必要になります。
私は、安価(US$1)に入手できて、3.3Vで駆動できるSN65HVD230を使いました。


裏側には2つのチップ抵抗が実装されています。
右側のチップ抵抗が終端抵抗(120Ω)、左側のチップ抵抗(10KΩ)でRsピンをPullDownしています。
Rsピンはモード切替用のピンですが、PullDownでHigh Speedモードになります。
同様の製品にSN65HVD231/232が有りますが、SN65HVD232にはモード切替の機能が無いのでRsのPullDownは不要で す。


1つのCAN Bus上で、5V CAN Bus Transceiverと3.3V CAN Bus Transceiverは混在して使うことができますが
混在して使う場合、終端抵抗を120Ωから150Ωに変更しないと送信が動きませんでした。
モジュールから左側のチップ抵抗(終端抵抗)を外して、150Ωの抵抗をCAN-HとCAN-Lの間に挟んで使いました。
CAN Bus上に既に終端抵抗が2つ有る場合、終端抵抗は不要です。


5V CAN Bus Transceiverと3.3V CAN Bus Transceiverを混在して使う場合の注意点がこちらに公開されて います。
終端抵抗を2つに分割して、+1V Ground Shiftする回路を使うと良さそうなことが書かれています。



CAN Bus TransceiverとESP32の接続は以下の様になります。
CANコントローラを使う場合、2つのGPIO(GPIO32/33)をCANの送受信で使いますが、使用するGPIOは変更することができま す。
CAN通信で使用できるGPIOに特に制限は無い様です。
SN65HVD23x ESP32 CAN Bus
D(CTX) GPIO32
Vss GND
Vdd 3.3V
R(CRX) GPIO33
Vref N/C
CANL
To CAN Bus
CANH
To CAN Bus
Rs GND(*1)

(*1) SN65HVD232の時はN/C

Bitrateが正しいと、以下の様に受信したデータを表示します。
今回はこちらで紹介しているRaspberryPiを送 信元として使い、Bitrateは500Kとしました。




こ ちらに受信フィルター(Acceptance Filter)に関する説明が公開されています。
Bit layout of single filter mode と Bit layout of dual filter mode の図が有りますが、Right side MSBit(図の右側が最上位ビット)で記載されています。
Right side MSBitの図を今まで見たことが無かったので、てっきりLeft side MSBit(図の左側が最上位ビット)だと思い込んで、
メチャクチャはまりました。

例えばsingle filter modeで、Standard FrameのID=0x100だけを許す場合、以下の設定となります。
f_config.acceptance_code = (0x100 << 21);
f_config.acceptance_mask = ~(0x1FF << 21);
f_config.single_filter = true;

また、single filter modeで、Extended FrameのID=0x10000008だけを許す場合、以下の設定となります。
f_config.acceptance_code = (0x10000008 << 3);
f_config.acceptance_mask = ~(0x1FFFFFFF << 3);
f_config.single_filter = true;

続く...