背景
ESP32内蔵の回路とCANのトランシーバーを組み合わせてCAN通信する方法を把握しました。備忘録を兼ねて記事に残します。
使ったもの
- ESP32DevKitC
今回利用するマイコンESP32が載った開発ボードです。 - MCP2562FD
CANのトランシーバーです。 - ブレッドボード
部品の信号線を引き出します。 - ジャンパワイヤ
ブレッドボード上は硬いもの、ブレッドボード間は柔らかいものを利用しました。 - 120Ω抵抗
CAN busの終端抵抗に利用します。 - microB-USBケーブル
ESP32へのプログラム書き込みに利用します。 - CAN2.0の通信相手
以前取り組んだCAN2.0の通信を可能にしたteensy4.1との通信を行います。
通信速度は500kbpsで行います。 - プログラム書き込み環境 PlatformIO
ubuntu24.04 にVSCodeとPlatformIOをインストールした環境を使いました
ESP32の内蔵回路はCAN2.0
ESP32のデータシートにTWAI Controllerという名前で説明があり、それによるとCAN2.0に対応しており、信号線はGPIOのどれにでも割り当てられるとのことでした。ESP32でCANを扱う回路
利用するライブラリESP32_CANの標準割当RXが16、TXが17にCANのトランシーバーを繋ぎます。繋ぐとこうなりました。
プログラム
ESP32_CANライブラリを利用するために、platformioのlib_depsに関連ライブラリを記述します。lib_deps =
https://github.com/collin80/esp32_can
https://github.com/collin80/can_common
記事を書いている時点で利用したライブラリや環境はこちらです。
PlatformIO Core, version 6.1.19
PACKAGES:
- contrib-piohome @ 3.4.4
- framework-arduinoespressif32 @ 3.3.2
- framework-arduinoespressif32-libs @ 5.5.0+sha.07e9bf4970
- tool-esptoolpy @ 5.1.0
- toolchain-xtensa-esp-elf @ 14.2.0+20250730
Dependency Graph
|-- ESP32_CAN @ 0.3.1+sha.c329e6b
|-- can_common @ 0.4.0+sha.8585f9d
ESP32_CANで内蔵CAN回路をコールバックなしで扱うプログラムです。
ESP32_CANのサンプルプログラムを参考にしました。
#include <Arduino.h>
#include <esp32_can.h>
void setup() {
Serial.begin(115200);
Serial.println("Initializing ...");
if (CAN0.begin(500000)) {
Serial.println("Builtin CAN Init OK ...");
} else {
Serial.println("Builtin CAN Init Failed ...");
}
CAN0.watchFor(); // allow anything through
Serial.println("Ready ...!");
CAN_FRAME txFrame;
txFrame.rtr = 0;
txFrame.id = 0x123;
txFrame.extended = false;
txFrame.length = 4;
txFrame.data.byte[0] = 0x10;
txFrame.data.byte[1] = 0x1A;
txFrame.data.byte[2] = 0xFF;
txFrame.data.byte[3] = 0x5D;
CAN0.sendFrame(txFrame);
}
byte i = 0;
// CAN message frame
CAN_FRAME message;
unsigned long sentAt = 0;
void loop() {
if (CAN0.read(message)) {
Serial.println("received at " + String(millis()));
Serial.print("ID: ");
Serial.println(message.id, HEX);
Serial.print("Extended: ");
if (message.extended) {
Serial.println("Yes");
} else {
Serial.println("No");
}
Serial.print("Length: ");
Serial.println(message.length, DEC);
for (i = 0; i < message.length; ++i) {
Serial.print(message.data.byte[i], HEX);
Serial.print(" ");
}
Serial.println();
}
if (millis() - sentAt >= 2000UL) {
sentAt = millis();
Serial.println("send data at " + String(sentAt));
message.id++;
for (i = 0; i < message.length; ++i) {
message.data.byte[i];
}
CAN0.sendFrame(message);
}
}
500kbpsでCANを有効にしています。
if (CAN0.begin(500000)) {
Serial.println("Builtin CAN Init OK ...");
ESP32_CANの標準割当はRXが16、TXが17ですが、利用するピンを変えたい場合はsetCANPins関数で指定します。
CAN0.setCANPins(GPIO_NUM_16, GPIO_NUM_17); // rx, tx
if (CAN0.begin(500000)) {
2秒ごとにidが0xAA、送信データの最初がマイコン内部時計の秒数の情報を送信します。
if (millis() - sentAt >= 2000UL) {
sentAt = millis();
Serial.println("send data at " + String(sentAt));
message.id = 0xAA;
for (i = 1; i < message.length; ++i) {
message.data.byte[i];
}
message.data.byte[0] = sentAt / 1000;
CAN0.sendFrame(message);
}動作確認
CAN2.0 500kbpsで通信するTeensy4.1と繋いで情報をやりとりします。Teensy側で情報の最初が期待通り2ずつ増えているのを確認できました。
teensy sent at 292846
MB 99 OVERRUN: 0 LEN: 8 EXT: 0 TS: 36194 ID: AA Buffer: EA 2 3 4 5 6 7 8 at 293229
teensy sent at 294847
MB 99 OVERRUN: 0 LEN: 8 EXT: 0 TS: 53082 ID: AA Buffer: EC 2 3 4 5 6 7 8 at 295229
ESP32側でTeensyから情報を受け取れているのを確認できました。
send data at 236000
received at 237619
ID: E0
Extended: No
Length: 8
1 2 3 4 5 6 7 8
おわり
ESP32とCANのトランシーバーを組み合わせ、ESP32に内蔵されたCAN 2.0の回路でCAN通信出来ました。気になっていた機能の使い方が分かってよかったです。
参考
ESP32_CANESP32のデータシート




0 件のコメント :
コメントを投稿