概要
仕事で必要になるかと思い、勉強も兼ねてAtomS3とパソコン間で相互にCAN通信を行ってみました。
色々なサイトを検索し、各種ライブラリを試したのですがエラーを解決することができず、
最終的にメーカーサイトの例を参考になんとか完成しました。
環境
エディタ:VisualStudioCode(拡張機能:PlatformIO IDE)
ドライバー:"driver/gpio.h"、"driver/twai.h"
CANコンバータ_AtomS3用:https://amzn.asia/d/5gZTPeh
CANコンバータ_パソコン用:https://amzn.asia/d/93V5su6
パソコン側ソフト:microbus(こちらのメーカーサイトよりダウンロード)
使用方法
- パソコン用のCANコンバータを接続します。Windows10は接続するだけで使えるようです。
- 「microbus」を起動し、接続するCANコンバータを設定します。
①設定ボタン
②AddNetworkボタン
③左ペインでinterfaces選択→AddInterfaceボタン
④必要なBitrateを選択して、OKボタン
⑤Startボタンを押す。接続するネットワークを選択してOKボタン。
パソコン側で受信結果が表示されます。設定したCAN ID(10)、データ(255)が反映されています。
同様に2を送信すると設定したCAN ID(20)、データ(65535)が送信できています。
5.パソコン ⇒ AtomS3への送信
microbus右下に必要な情報ID(Address)、データ(Payload)記入しSend Singleボタンを押します。
AtomS3 コード
#include <Arduino.h>
#include "driver/gpio.h"
#include "driver/twai.h"
#include <M5AtomDisplay.h>
#include <M5Unified.h>
//#include <stdlib.h>
#define CAN_RX_PIN GPIO_NUM_1
#define CAN_TX_PIN GPIO_NUM_2
twai_message_t message;
// TWAI Configuration & Installation
void init_CAN(){
//Initialize configuration structures using macro initializers
twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(CAN_TX_PIN, CAN_RX_PIN, TWAI_MODE_NORMAL);
twai_timing_config_t t_config = TWAI_TIMING_CONFIG_500KBITS();
twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
// Install TWAI driver
if (twai_driver_install(&g_config, &t_config, &f_config) == ESP_OK)
{
USBSerial.print("Driver installed\n");
} else {
USBSerial.print("Failed to install driver\n");
return;
}
// Start TWAI driver
if (twai_start() == ESP_OK) {
USBSerial.print("Driver started\n");
} else {
USBSerial.print("Failed to start driver\n");
return;
}
}
void send_CAN(int ID,int value){
message.identifier = ID;//ID設定
// int⇒byte配列変換
byte* bytes = (byte*)&value; // int値の先頭アドレスをbyteポインタにキャストする
for (int i = 0; i < sizeof(value); i++) {
message.data[i] = bytes[i]; // ポインタからbyte値を取得する
}
// Queue message for transmission
if (twai_transmit(&message, pdMS_TO_TICKS(1000)) == ESP_OK) {
USBSerial.printf("Message queued for transmission\n");
} else {
USBSerial.printf("Failed to queue message for transmission\n");
}
}
void receive_CAN(){
USBSerial.printf("Message received\n");
//Process received message
if (message.extd) {
USBSerial.printf("Message is in Extended Format\n");
} else {
USBSerial.printf("Message is in Standard Format\n");
}
USBSerial.printf("ID is %d\n", message.identifier);
if (!(message.rtr)) {
for (int i = 0; i < message.data_length_code; i++) {
USBSerial.printf("Data byte %d = %d\n", i, message.data[i]);
}
}
}
void setup() {
// AtomS3設定
auto cfg = M5.config();
M5.begin(cfg);
USBSerial.begin(115200);
// CAN初期設定
init_CAN();
message.extd = 0;// 0:標準フォーマット 1:拡張フォーマット
message.data_length_code = 8;//DLC 8byte
// Display設定
M5.Display.init();
M5.Display.setRotation(0);
M5.Display.setFont(&fonts::lgfxJapanGothicP_12);
M5.Display.setTextColor(WHITE, BLACK);
// Title表示
M5.Display.setCursor(0,0);
M5.Display.println("CANテスト");
}
void loop() {
//Wait for message to be received
if (twai_receive(&message, pdMS_TO_TICKS(10)) == ESP_OK) {
receive_CAN();
}
if(USBSerial.available() > 0) {
// USBSerialデータ受信
char ch = USBSerial.read();
if(ch == '1'){
send_CAN(10,255);//CANデータ送信(ID,Value)
}else if(ch == '2'){
// CANデータ送信
send_CAN(20,65535);//CANデータ送信(ID,Value)
}
}
delay(10);
}
分からない点
(twai_receive(&message, pdMS_TO_TICKS(10)) == ESP_OK)のところで
受信待ち時間を設定していますが、この値の設定をどうすれば良いのかがいまいち分かりません。
サンプル例では10秒で設定されていましたが、そのままだとAtomS3→パソコンへの送信が最大10秒程度
待たされることになるので、待ち時間を少なくなるように10msecに設定しています。
動作的にには問題はなさそうでした。
参考サイト