ESP32-S3与达妙DM-J4310-2EC的CAN FD通信示范
ESP32-S3与达妙DM-J4310-2EC的CAN FD通信示范
⚠️ 重要说明
ESP32-S3的TWAI模块原生不支持CAN FD,仅支持经典CAN(CAN 2.0,最高1Mbps)。达妙DM-J4310-2EC电机同时支持CAN FD和经典CAN,因此有两种方案:
| 方案 | 说明 | 推荐度 |
|---|---|---|
| 方案A | ESP32-S3 + 外置CAN FD控制器(如MCP2518FD) | ⭐⭐⭐⭐ 支持完整CAN FD |
| 方案B | ESP32-S3原生TWAI + 经典CAN模式(1Mbps) | ⭐⭐⭐⭐⭐ 简单实用 |
📋 方案B:ESP32-S3原生TWAI经典CAN通信(推荐入门)
1. 硬件连接
ESP32-S3 CAN收发器(TJA1050/ISO1050) 达妙DM-J4310-2EC
───────── ────────────────────── ─────────────────
GPIO17 (TX) ───→ TX CAN_H ───────────┐
GPIO18 (RX) ←─── RX CAN_L ───────────┤
3.3V ───→ VCC GND ───────────┼──→ 共地
GND ───→ GNC 24V/48V ─────────┘ (电机电源独立)
2. ESP-IDF 代码示例
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/twai.h"
#include "esp_log.h"
#define TAG "CAN_DAMIAO"
// TWAI引脚配置 (ESP32-S3)
#define TX_GPIO_NUM 17
#define RX_GPIO_NUM 18
// 达妙电机CAN配置
#define DAMIAO_CAN_BAUDRATE 1000000 // 1Mbps
#define MOTOR_ID 1 // 电机ID(需通过调试工具设置)
// 达妙电机CAN报文ID定义
#define CMD_ENABLE_ID (0x000 + MOTOR_ID) // 使能命令
#define CMD_CONTROL_ID (0x100 + MOTOR_ID) // 控制命令
#define CMD_READ_ID (0x200 + MOTOR_ID) // 读取命令
#define FEEDBACK_ID (0x300 + MOTOR_ID) // 反馈数据
// 达妙电机控制命令定义
#define CMD_ENABLE_MOTOR 0x0001
#define CMD_DISABLE_MOTOR 0x0000
#define CMD_MIT_MODE 0x0004 // MIT控制模式
// MIT控制数据结构 (8字节)
typedef struct {
int16_t position_cmd; // 位置指令 (单位: 0.01°)
int16_t velocity_cmd; // 速度指令 (单位: 0.01°/s)
int16_t torque_cmd; // 转矩指令 (单位: 0.01Nm)
int16_t kp; // 位置刚度系数
int16_t kd; // 速度阻尼系数
} mit_control_t;
// 反馈数据结构
typedef struct {
int16_t position; // 实际位置
int16_t velocity; // 实际速度
int16_t torque; // 实际转矩
int16_t temperature; // 电机温度
} motor_feedback_t;
// 初始化TWAI驱动
esp_err_t twai_init(void)
{
// 通用配置
twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(TX_GPIO_NUM, RX_GPIO_NUM, TWAI_MODE_NORMAL);
// 时序配置 (1Mbps)
twai_timing_config_t t_config = TWAI_TIMING_CONFIG_1MBITS();
// 过滤器配置 (接收所有消息)
twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
// 安装驱动
ESP_ERROR_CHECK(twai_driver_install(&g_config, &t_config, &f_config));
ESP_LOGI(TAG, "TWAI驱动安装成功");
// 启动驱动
ESP_ERROR_CHECK(twai_start());
ESP_LOGI(TAG, "TWAI驱动已启动");
return ESP_OK;
}
// 发送CAN消息
esp_err_t can_send(uint32_t id, uint8_t *data, uint8_t len)
{
twai_message_t message;
message.identifier = id;
message.data_length_code = len;
message.extd = 0; // 标准帧
message.rtr = 0; // 数据帧
memcpy(message.data, data, len);
esp_err_t ret = twai_transmit(&message, pdMS_TO_TICKS(100));
if (ret != ESP_OK) {
ESP_LOGE(TAG, "发送失败: %s", esp_err_to_name(ret));
}
return ret;
}
// 接收CAN消息
esp_err_t can_receive(twai_message_t *message, TickType_t ticks_to_wait)
{
return twai_receive(message, ticks_to_wait);
}
// 电机使能
void motor_enable(void)
{
uint8_t data[8] = {0};
data[0] = CMD_ENABLE_MOTOR & 0xFF;
data[1] = (CMD_ENABLE_MOTOR >> 8) & 0xFF;
can_send(CMD_ENABLE_ID, data, 8);
ESP_LOGI(TAG, "发送电机使能命令");
}
// 电机禁用
void motor_disable(void)
{
uint8_t data[8] = {0};
data[0] = CMD_DISABLE_MOTOR & 0xFF;
data[1] = (CMD_DISABLE_MOTOR >> 8) & 0xFF;
can_send(CMD_ENABLE_ID, data, 8);
ESP_LOGI(TAG, "发送电机禁用命令");
}
// MIT模式控制
void motor_mit_control(int16_t pos, int16_t vel, int16_t tor, int16_t kp, int16_t kd)
{
uint8_t data[8] = {0};
data[0] = pos & 0xFF;
data[1] = (pos >> 8) & 0xFF;
data[2] = vel & 0xFF;
data[3] = (vel >> 8) & 0xFF;
data[4] = tor & 0xFF;
data[5] = (tor >> 8) & 0xFF;
data[6] = kp & 0xFF;
data[7] = (kp >> 8) & 0xFF;
can_send(CMD_CONTROL_ID, data, 8);
}
// 读取电机反馈
void motor_read_feedback(void)
{
uint8_t data[8] = {0};
can_send(CMD_READ_ID, data, 8);
}
// 解析反馈数据
void parse_feedback(twai_message_t *msg, motor_feedback_t *fb)
{
if (msg->identifier == FEEDBACK_ID && msg->data_length_code >= 8) {
fb->position = msg->data[0] | (msg->data[1] << 8);
fb->velocity = msg->data[2] | (msg->data[3] << 8);
fb->torque = msg->data[4] | (msg->data[5] << 8);
fb->temperature = msg->data[6] | (msg->data[7] << 8);
ESP_LOGI(TAG, "反馈: 位置=%d, 速度=%d, 转矩=%d, 温度=%d",
fb->position, fb->velocity, fb->torque, fb->temperature);
}
}
// 接收任务
void can_receive_task(void *pvParameters)
{
twai_message_t message;
motor_feedback_t feedback;
while (1) {
if (can_receive(&message, pdMS_TO_TICKS(100)) == ESP_OK) {
parse_feedback(&message, &feedback);
}
}
}
// 主应用
void app_main(void)
{
ESP_LOGI(TAG, "达妙电机CAN通信示例启动");
// 初始化TWAI
twai_init();
// 创建接收任务
xTaskCreate(can_receive_task, "can_rx", 4096, NULL, 5, NULL);
// 延时等待
vTaskDelay(pdMS_TO_TICKS(500));
// 使能电机
motor_enable();
vTaskDelay(pdMS_TO_TICKS(100));
// MIT模式控制循环
while (1) {
// 位置控制:移动到90度 (9000 = 90.00°)
motor_mit_control(9000, 0, 0, 100, 50);
vTaskDelay(pdMS_TO_TICKS(1000));
// 位置控制:移动到0度
motor_mit_control(0, 0, 0, 100, 50);
vTaskDelay(pdMS_TO_TICKS(1000));
// 读取反馈
motor_read_feedback();
vTaskDelay(pdMS_TO_TICKS(100));
}
}
3. CMakeLists.txt 配置
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(damiao_can_motor)
4. menuconfig 配置
Component config → TWAI →
✓ Enable TWAI driver
✓ TWAI Alert Enabled
✓ TWAI ISR in IRAM
🔧 方案A:外置CAN FD控制器(如需CAN FD高速通信)
硬件连接
ESP32-S3 MCP2518FD 达妙DM-J4310-2EC
───────── ────────── ─────────────────
GPIO10 (SCK) ─→ SCK
GPIO11 (MOSI) ─→ SI
GPIO12 (MISO) ←→ SO
GPIO13 (CS) ─→ CS
GPIO14 (INT) ←→ INT
3.3V ─→ VCC
GND ─→ GND
CAN_H/L ───────────→ 电机
使用SPI CAN FD库(如ESP-IDF的SPI + MCP2518FD驱动)
📊 达妙电机通信协议摘要
| 功能 | CAN ID | 数据格式 | 说明 |
|---|---|---|---|
| 使能/禁用 | 0x000+ID | uint16命令+填充 | 0x0001使能, 0x0000禁用 |
| MIT控制 | 0x100+ID | 位置/速度/转矩/Kp/Kd | 各2字节,有符号 |
| 位置模式 | 0x100+ID | 目标位置+速度+加速度 | - |
| 速度模式 | 0x100+ID | 目标速度+加速度 | - |
| 读取反馈 | 0x200+ID | 请求命令 | - |
| 反馈数据 | 0x300+ID | 位置/速度/转矩/温度 | 自动上报或请求后 |
⚙️ 电机配置步骤
- 使用达妙调试工具设置电机ID(1-127)
- 设置CAN波特率:经典CAN设为1Mbps
- 设置控制模式:MIT/位置/速度
- 下载固件到ESP32-S3
- 连接CAN总线,确保共地
- 测试通信
🔍 常见问题排查
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| 无响应 | 电机ID不匹配 | 使用调试工具确认ID |
| 通信错误 | 波特率不一致 | 确认电机设为1Mbps |
| 数据异常 | 字节序错误 | 达妙使用小端序 |
| 总线错误 | 终端电阻缺失 | CAN总线两端加120Ω电阻 |
| TWAI错误 | 引脚配置错误 | 确认TX/RX引脚正确 |
如需完整项目代码,可访问达妙官方Gitee仓库获取参考例程。
欢迎讨论,相互学习。
cdtxw@foxmail.com

浙公网安备 33010602011771号