添加了can遥控
This commit is contained in:
parent
799ad45397
commit
ad716705ff
@ -75,6 +75,7 @@ target_sources(${CMAKE_PROJECT_NAME} PRIVATE
|
|||||||
User/device/motor_lk.c
|
User/device/motor_lk.c
|
||||||
User/device/motor_lz.c
|
User/device/motor_lz.c
|
||||||
User/device/motor_rm.c
|
User/device/motor_rm.c
|
||||||
|
User/device/rc_can.c
|
||||||
|
|
||||||
# User/module sources
|
# User/module sources
|
||||||
User/module/balance_chassis.c
|
User/module/balance_chassis.c
|
||||||
|
|||||||
312
User/device/rc_can.c
Normal file
312
User/device/rc_can.c
Normal file
@ -0,0 +1,312 @@
|
|||||||
|
/* Includes ----------------------------------------------------------------- */
|
||||||
|
#include "device/rc_can.h"
|
||||||
|
#include "bsp/time.h"
|
||||||
|
#include "device/device.h"
|
||||||
|
/* USER INCLUDE BEGIN */
|
||||||
|
|
||||||
|
/* USER INCLUDE END */
|
||||||
|
|
||||||
|
/* Private constants -------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* USER DEFINE BEGIN */
|
||||||
|
|
||||||
|
/* USER DEFINE END */
|
||||||
|
|
||||||
|
/* Private macro ------------------------------------------------------------ */
|
||||||
|
/* Private types ------------------------------------------------------------ */
|
||||||
|
/* Private variables -------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* USER VARIABLE BEGIN */
|
||||||
|
|
||||||
|
/* USER VARIABLE END */
|
||||||
|
|
||||||
|
/* USER FUNCTION BEGIN */
|
||||||
|
|
||||||
|
/* USER FUNCTION END */
|
||||||
|
|
||||||
|
/* Private function prototypes ---------------------------------------------- */
|
||||||
|
static int8_t RC_CAN_ValidateParams(const RC_CAN_Param_t *param);
|
||||||
|
static int8_t RC_CAN_RegisterIds(RC_CAN_t *rc_can);
|
||||||
|
|
||||||
|
/* Exported functions ------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 初始化RC CAN发送模块
|
||||||
|
* @param rc_can RC_CAN结构体指针
|
||||||
|
* @param param 初始化参数
|
||||||
|
* @return DEVICE_OK 成功,其他值失败
|
||||||
|
*/
|
||||||
|
int8_t RC_CAN_Init(RC_CAN_t *rc_can, RC_CAN_Param_t *param) {
|
||||||
|
if (rc_can == NULL || param == NULL) {
|
||||||
|
return DEVICE_ERR_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 参数验证
|
||||||
|
if (RC_CAN_ValidateParams(param) != DEVICE_OK) {
|
||||||
|
return DEVICE_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_can->param = *param;
|
||||||
|
|
||||||
|
// 初始化header
|
||||||
|
rc_can->header.online = false;
|
||||||
|
rc_can->header.last_online_time = 0;
|
||||||
|
|
||||||
|
// 手动初始化数据结构
|
||||||
|
rc_can->data.joy.ch_l_x = 0.0f;
|
||||||
|
rc_can->data.joy.ch_l_y = 0.0f;
|
||||||
|
rc_can->data.joy.ch_r_x = 0.0f;
|
||||||
|
rc_can->data.joy.ch_r_y = 0.0f;
|
||||||
|
rc_can->data.sw.sw_l = RC_CAN_SW_ERR;
|
||||||
|
rc_can->data.sw.sw_r = RC_CAN_SW_ERR;
|
||||||
|
rc_can->data.sw.ch_res = 0.0f;
|
||||||
|
rc_can->data.mouse.x = 0.0f;
|
||||||
|
rc_can->data.mouse.y = 0.0f;
|
||||||
|
rc_can->data.mouse.z = 0.0f;
|
||||||
|
rc_can->data.mouse.mouse_l = false;
|
||||||
|
rc_can->data.mouse.mouse_r = false;
|
||||||
|
rc_can->data.keyboard.key_value = 0;
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
rc_can->data.keyboard.keys[i] = RC_CAN_KEY_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注册CAN ID队列(从机模式需要接收数据)
|
||||||
|
if (rc_can->param.mode == RC_CAN_MODE_SLAVE) {
|
||||||
|
return RC_CAN_RegisterIds(rc_can);
|
||||||
|
}
|
||||||
|
|
||||||
|
return DEVICE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 更新并发送数据到CAN总线
|
||||||
|
* @param rc_can RC_CAN结构体指针
|
||||||
|
* @param data_type 数据类型
|
||||||
|
* @return DEVICE_OK 成功,其他值失败
|
||||||
|
*/
|
||||||
|
int8_t RC_CAN_SendData(RC_CAN_t *rc_can, RC_CAN_DataType_t data_type) {
|
||||||
|
if (rc_can == NULL) {
|
||||||
|
return DEVICE_ERR_NULL;
|
||||||
|
}
|
||||||
|
if (rc_can->param.mode != RC_CAN_MODE_MASTER) {
|
||||||
|
return DEVICE_ERR;
|
||||||
|
}
|
||||||
|
BSP_CAN_StdDataFrame_t frame;
|
||||||
|
frame.dlc = 8;
|
||||||
|
switch (data_type) {
|
||||||
|
case RC_CAN_DATA_JOYSTICK:
|
||||||
|
frame.id = rc_can->param.joy_id;
|
||||||
|
frame.data[0] = (uint8_t)((int16_t)(rc_can->data.joy.ch_l_x * 32768.0f) & 0xFF);
|
||||||
|
frame.data[1] =
|
||||||
|
(uint8_t)(((int16_t)(rc_can->data.joy.ch_l_x * 32768.0f) >> 8) & 0xFF);
|
||||||
|
frame.data[2] = (uint8_t)((int16_t)(rc_can->data.joy.ch_l_y * 32768.0f) & 0xFF);
|
||||||
|
frame.data[3] =
|
||||||
|
(uint8_t)(((int16_t)(rc_can->data.joy.ch_l_y * 32768.0f) >> 8) & 0xFF);
|
||||||
|
frame.data[4] = (uint8_t)((int16_t)(rc_can->data.joy.ch_r_x * 32768.0f) & 0xFF);
|
||||||
|
frame.data[5] =
|
||||||
|
(uint8_t)(((int16_t)(rc_can->data.joy.ch_r_x * 32768.0f) >> 8) & 0xFF);
|
||||||
|
frame.data[6] = (uint8_t)((int16_t)(rc_can->data.joy.ch_r_y * 32768.0f) & 0xFF);
|
||||||
|
frame.data[7] =
|
||||||
|
(uint8_t)(((int16_t)(rc_can->data.joy.ch_r_y * 32768.0f) >> 8) & 0xFF);
|
||||||
|
break;
|
||||||
|
case RC_CAN_DATA_SWITCH:
|
||||||
|
frame.id = rc_can->param.sw_id;
|
||||||
|
frame.data[0] = (uint8_t)(rc_can->data.sw.sw_l);
|
||||||
|
frame.data[1] = (uint8_t)(rc_can->data.sw.sw_r);
|
||||||
|
frame.data[2] = (uint8_t)((int16_t)(rc_can->data.sw.ch_res * 32768.0f) & 0xFF);
|
||||||
|
frame.data[3] =
|
||||||
|
(uint8_t)(((int16_t)(rc_can->data.sw.ch_res * 32768.0f) >> 8) & 0xFF);
|
||||||
|
frame.data[4] = 0; // 保留字节
|
||||||
|
frame.data[5] = 0; // 保留字节
|
||||||
|
frame.data[6] = 0; // 保留字节
|
||||||
|
frame.data[7] = 0; // 保留字节
|
||||||
|
break;
|
||||||
|
case RC_CAN_DATA_MOUSE:
|
||||||
|
frame.id = rc_can->param.mouse_id;
|
||||||
|
frame.data[0] = (uint8_t)((int16_t)(rc_can->data.mouse.x) & 0xFF);
|
||||||
|
frame.data[1] = (uint8_t)(((int16_t)(rc_can->data.mouse.x) >> 8) & 0xFF);
|
||||||
|
frame.data[2] = (uint8_t)((int16_t)(rc_can->data.mouse.y) & 0xFF);
|
||||||
|
frame.data[3] = (uint8_t)(((int16_t)(rc_can->data.mouse.y) >> 8) & 0xFF);
|
||||||
|
frame.data[4] = (uint8_t)((int16_t)(rc_can->data.mouse.z) & 0xFF);
|
||||||
|
frame.data[5] = (uint8_t)(((int16_t)(rc_can->data.mouse.z) >> 8) & 0xFF);
|
||||||
|
frame.data[6] = (uint8_t)(rc_can->data.mouse.mouse_l ? 1 : 0);
|
||||||
|
frame.data[7] = (uint8_t)(rc_can->data.mouse.mouse_r ? 1 : 0);
|
||||||
|
break;
|
||||||
|
case RC_CAN_DATA_KEYBOARD:
|
||||||
|
frame.id = rc_can->param.keyboard_id;
|
||||||
|
frame.data[0] = (uint8_t)(rc_can->data.keyboard.key_value & 0xFF);
|
||||||
|
frame.data[1] = (uint8_t)((rc_can->data.keyboard.key_value >> 8) & 0xFF);
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
frame.data[2 + i] = (i < 6) ? (uint8_t)(rc_can->data.keyboard.keys[i]) : 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return DEVICE_ERR;
|
||||||
|
}
|
||||||
|
if (BSP_CAN_Transmit(rc_can->param.can, BSP_CAN_FORMAT_STD_DATA, frame.id,
|
||||||
|
frame.data, frame.dlc) != BSP_OK) {
|
||||||
|
return DEVICE_ERR;
|
||||||
|
}
|
||||||
|
return DEVICE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 接收并更新CAN数据
|
||||||
|
* @param rc_can RC_CAN结构体指针
|
||||||
|
* @param data_type 数据类型
|
||||||
|
* @return DEVICE_OK 成功,其他值失败
|
||||||
|
*/
|
||||||
|
int8_t RC_CAN_Update(RC_CAN_t *rc_can, RC_CAN_DataType_t data_type) {
|
||||||
|
if (rc_can == NULL) {
|
||||||
|
return DEVICE_ERR_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 只有从机模式才能接收数据
|
||||||
|
if (rc_can->param.mode != RC_CAN_MODE_SLAVE) {
|
||||||
|
return DEVICE_ERR;
|
||||||
|
}
|
||||||
|
BSP_CAN_Message_t msg;
|
||||||
|
|
||||||
|
switch (data_type) {
|
||||||
|
case RC_CAN_DATA_JOYSTICK:
|
||||||
|
if (BSP_CAN_GetMessage(rc_can->param.can, rc_can->param.joy_id, &msg,
|
||||||
|
BSP_CAN_TIMEOUT_IMMEDIATE) != BSP_OK) {
|
||||||
|
return DEVICE_ERR;
|
||||||
|
}
|
||||||
|
// 解包数据
|
||||||
|
int16_t ch_l_x = (int16_t)((msg.data[1] << 8) | msg.data[0]);
|
||||||
|
int16_t ch_l_y = (int16_t)((msg.data[3] << 8) | msg.data[2]);
|
||||||
|
int16_t ch_r_x = (int16_t)((msg.data[5] << 8) | msg.data[4]);
|
||||||
|
int16_t ch_r_y = (int16_t)((msg.data[7] << 8) | msg.data[6]);
|
||||||
|
|
||||||
|
// 转换为浮点数(范围:-1.0到1.0)
|
||||||
|
rc_can->data.joy.ch_l_x = (float)ch_l_x / 32768.0f;
|
||||||
|
rc_can->data.joy.ch_l_y = (float)ch_l_y / 32768.0f;
|
||||||
|
rc_can->data.joy.ch_r_x = (float)ch_r_x / 32768.0f;
|
||||||
|
rc_can->data.joy.ch_r_y = (float)ch_r_y / 32768.0f;
|
||||||
|
break;
|
||||||
|
case RC_CAN_DATA_SWITCH:
|
||||||
|
if (BSP_CAN_GetMessage(rc_can->param.can, rc_can->param.sw_id, &msg,
|
||||||
|
BSP_CAN_TIMEOUT_IMMEDIATE) != BSP_OK) {
|
||||||
|
return DEVICE_ERR;
|
||||||
|
}
|
||||||
|
// 解包数据
|
||||||
|
rc_can->data.sw.sw_l = (RC_CAN_SW_t)msg.data[0];
|
||||||
|
rc_can->data.sw.sw_r = (RC_CAN_SW_t)msg.data[1];
|
||||||
|
|
||||||
|
int16_t ch_res = (int16_t)((msg.data[3] << 8) | msg.data[2]);
|
||||||
|
rc_can->data.sw.ch_res = (float)ch_res / 32768.0f;
|
||||||
|
break;
|
||||||
|
case RC_CAN_DATA_MOUSE:
|
||||||
|
if (BSP_CAN_GetMessage(rc_can->param.can, rc_can->param.mouse_id, &msg,
|
||||||
|
BSP_CAN_TIMEOUT_IMMEDIATE) != BSP_OK) {
|
||||||
|
return DEVICE_ERR;
|
||||||
|
}
|
||||||
|
// 解包数据
|
||||||
|
int16_t x = (int16_t)((msg.data[1] << 8) | msg.data[0]);
|
||||||
|
int16_t y = (int16_t)((msg.data[3] << 8) | msg.data[2]);
|
||||||
|
int16_t z = (int16_t)((msg.data[5] << 8) | msg.data[4]);
|
||||||
|
rc_can->data.mouse.x = (float)x;
|
||||||
|
rc_can->data.mouse.y = (float)y;
|
||||||
|
rc_can->data.mouse.z = (float)z;
|
||||||
|
rc_can->data.mouse.mouse_l = (msg.data[6] & 0x01) ? true : false;
|
||||||
|
rc_can->data.mouse.mouse_r = (msg.data[7] & 0x01) ? true : false;
|
||||||
|
break;
|
||||||
|
case RC_CAN_DATA_KEYBOARD:
|
||||||
|
if (BSP_CAN_GetMessage(rc_can->param.can, rc_can->param.keyboard_id, &msg,
|
||||||
|
BSP_CAN_TIMEOUT_IMMEDIATE) != BSP_OK) {
|
||||||
|
return DEVICE_ERR;
|
||||||
|
}
|
||||||
|
if (msg.dlc < 2) {
|
||||||
|
return DEVICE_ERR;
|
||||||
|
}
|
||||||
|
// 解包数据
|
||||||
|
rc_can->data.keyboard.key_value =
|
||||||
|
(uint16_t)((msg.data[1] << 8) | msg.data[0]);
|
||||||
|
for (int i = 0; i < 6 && (i + 2) < msg.dlc; i++) {
|
||||||
|
rc_can->data.keyboard.keys[i] = (RC_CAN_Key_t)(msg.data[2 + i]);
|
||||||
|
}
|
||||||
|
// 清空未使用的按键位置
|
||||||
|
for (int i = (msg.dlc > 2 ? msg.dlc - 2 : 0); i < 6; i++) {
|
||||||
|
rc_can->data.keyboard.keys[i] = RC_CAN_KEY_NONE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return DEVICE_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新header状态
|
||||||
|
rc_can->header.online = true;
|
||||||
|
rc_can->header.last_online_time = BSP_TIME_Get_us();
|
||||||
|
|
||||||
|
return DEVICE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Private functions -------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 验证RC_CAN参数
|
||||||
|
* @param param 参数指针
|
||||||
|
* @return DEVICE_OK 成功,其他值失败
|
||||||
|
*/
|
||||||
|
static int8_t RC_CAN_ValidateParams(const RC_CAN_Param_t *param) {
|
||||||
|
if (param == NULL) {
|
||||||
|
return DEVICE_ERR_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查CAN总线有效性
|
||||||
|
if (param->can >= BSP_CAN_NUM) {
|
||||||
|
return DEVICE_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查工作模式有效性
|
||||||
|
if (param->mode != RC_CAN_MODE_MASTER && param->mode != RC_CAN_MODE_SLAVE) {
|
||||||
|
return DEVICE_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查CAN ID是否重复
|
||||||
|
if (param->joy_id == param->sw_id || param->joy_id == param->mouse_id ||
|
||||||
|
param->joy_id == param->keyboard_id || param->sw_id == param->mouse_id ||
|
||||||
|
param->sw_id == param->keyboard_id ||
|
||||||
|
param->mouse_id == param->keyboard_id) {
|
||||||
|
return DEVICE_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DEVICE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 注册CAN ID
|
||||||
|
* @param rc_can RC_CAN结构体指针
|
||||||
|
* @return DEVICE_OK 成功,其他值失败
|
||||||
|
*/
|
||||||
|
static int8_t RC_CAN_RegisterIds(RC_CAN_t *rc_can) {
|
||||||
|
if (BSP_CAN_RegisterId(rc_can->param.can, rc_can->param.joy_id, 0) !=
|
||||||
|
BSP_OK) {
|
||||||
|
return DEVICE_ERR;
|
||||||
|
}
|
||||||
|
if (BSP_CAN_RegisterId(rc_can->param.can, rc_can->param.sw_id, 0) != BSP_OK) {
|
||||||
|
return DEVICE_ERR;
|
||||||
|
}
|
||||||
|
if (BSP_CAN_RegisterId(rc_can->param.can, rc_can->param.mouse_id, 0) !=
|
||||||
|
BSP_OK) {
|
||||||
|
return DEVICE_ERR;
|
||||||
|
}
|
||||||
|
if (BSP_CAN_RegisterId(rc_can->param.can, rc_can->param.keyboard_id, 0) !=
|
||||||
|
BSP_OK) {
|
||||||
|
return DEVICE_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DEVICE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t RC_CAN_OFFLINE(RC_CAN_t *rc_can){
|
||||||
|
if (rc_can == NULL) {
|
||||||
|
return DEVICE_ERR_NULL;
|
||||||
|
}
|
||||||
|
rc_can->header.online = false;
|
||||||
|
return DEVICE_OK;
|
||||||
|
}
|
||||||
|
/* USER CODE BEGIN */
|
||||||
|
|
||||||
|
/* USER CODE END */
|
||||||
157
User/device/rc_can.h
Normal file
157
User/device/rc_can.h
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Includes ----------------------------------------------------------------- */
|
||||||
|
#include "bsp/can.h"
|
||||||
|
#include "device/device.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
/* USER INCLUDE BEGIN */
|
||||||
|
|
||||||
|
/* USER INCLUDE END */
|
||||||
|
|
||||||
|
/* USER DEFINE BEGIN */
|
||||||
|
|
||||||
|
/* USER DEFINE END */
|
||||||
|
|
||||||
|
/* Exported constants ------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* Exported macro ----------------------------------------------------------- */
|
||||||
|
/* Exported types ----------------------------------------------------------- */
|
||||||
|
typedef enum {
|
||||||
|
RC_CAN_SW_ERR = 0,
|
||||||
|
RC_CAN_SW_UP = 1,
|
||||||
|
RC_CAN_SW_MID = 3,
|
||||||
|
RC_CAN_SW_DOWN = 2,
|
||||||
|
} RC_CAN_SW_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
RC_CAN_MODE_MASTER = 0, // 主机模式
|
||||||
|
RC_CAN_MODE_SLAVE = 1, // 从机模式
|
||||||
|
} RC_CAN_Mode_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
RC_CAN_DATA_JOYSTICK = 0,
|
||||||
|
RC_CAN_DATA_SWITCH,
|
||||||
|
RC_CAN_DATA_MOUSE,
|
||||||
|
RC_CAN_DATA_KEYBOARD
|
||||||
|
} RC_CAN_DataType_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
RC_CAN_KEY_NONE = 0xFF, // 无按键
|
||||||
|
RC_CAN_KEY_W = 0,
|
||||||
|
RC_CAN_KEY_S,
|
||||||
|
RC_CAN_KEY_A,
|
||||||
|
RC_CAN_KEY_D,
|
||||||
|
RC_CAN_KEY_SHIFT,
|
||||||
|
RC_CAN_KEY_CTRL,
|
||||||
|
RC_CAN_KEY_Q,
|
||||||
|
RC_CAN_KEY_E,
|
||||||
|
RC_CAN_KEY_R,
|
||||||
|
RC_CAN_KEY_F,
|
||||||
|
RC_CAN_KEY_G,
|
||||||
|
RC_CAN_KEY_Z,
|
||||||
|
RC_CAN_KEY_X,
|
||||||
|
RC_CAN_KEY_C,
|
||||||
|
RC_CAN_KEY_V,
|
||||||
|
RC_CAN_KEY_B,
|
||||||
|
RC_CAN_KEY_NUM,
|
||||||
|
} RC_CAN_Key_t;
|
||||||
|
|
||||||
|
// 遥杆数据包
|
||||||
|
typedef struct {
|
||||||
|
float ch_l_x;
|
||||||
|
float ch_l_y;
|
||||||
|
float ch_r_x;
|
||||||
|
float ch_r_y;
|
||||||
|
} RC_CAN_JoyData_t;
|
||||||
|
|
||||||
|
// 拨杆数据包
|
||||||
|
typedef struct {
|
||||||
|
RC_CAN_SW_t sw_l; // 左拨杆状态
|
||||||
|
RC_CAN_SW_t sw_r; // 右拨杆状态
|
||||||
|
float ch_res; // 第五通道
|
||||||
|
} RC_CAN_SwitchData_t;
|
||||||
|
|
||||||
|
// 鼠标数据包
|
||||||
|
typedef struct {
|
||||||
|
float x; // 鼠标X轴移动
|
||||||
|
float y; // 鼠标Y轴移动
|
||||||
|
float z; // 鼠标Z轴(滚轮)
|
||||||
|
bool mouse_l; // 鼠标左键
|
||||||
|
bool mouse_r; // 鼠标右键
|
||||||
|
} RC_CAN_MouseData_t;
|
||||||
|
|
||||||
|
// 键盘数据包
|
||||||
|
typedef struct {
|
||||||
|
uint16_t key_value; // 键盘按键位映射
|
||||||
|
RC_CAN_Key_t keys[16];
|
||||||
|
} RC_CAN_KeyboardData_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
RC_CAN_JoyData_t joy;
|
||||||
|
RC_CAN_SwitchData_t sw;
|
||||||
|
RC_CAN_MouseData_t mouse;
|
||||||
|
RC_CAN_KeyboardData_t keyboard;
|
||||||
|
} RC_CAN_Data_t;
|
||||||
|
|
||||||
|
// RC_CAN 参数结构
|
||||||
|
typedef struct {
|
||||||
|
BSP_CAN_t can; // 使用的CAN总线
|
||||||
|
RC_CAN_Mode_t mode; // 工作模式
|
||||||
|
uint16_t joy_id; // 遥杆CAN ID
|
||||||
|
uint16_t sw_id; // 拨杆CAN ID
|
||||||
|
uint16_t mouse_id; // 鼠标CAN ID
|
||||||
|
uint16_t keyboard_id; // 键盘CAN ID
|
||||||
|
} RC_CAN_Param_t;
|
||||||
|
|
||||||
|
// RC_CAN 主结构
|
||||||
|
typedef struct {
|
||||||
|
DEVICE_Header_t header;
|
||||||
|
RC_CAN_Param_t param;
|
||||||
|
RC_CAN_Data_t data;
|
||||||
|
} RC_CAN_t;
|
||||||
|
|
||||||
|
/* USER STRUCT BEGIN */
|
||||||
|
|
||||||
|
/* USER STRUCT END */
|
||||||
|
|
||||||
|
/* Exported functions prototypes -------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 初始化RC CAN发送模块
|
||||||
|
* @param rc_can RC_CAN结构体指针
|
||||||
|
* @param param 初始化参数
|
||||||
|
* @return DEVICE_OK 成功,其他值失败
|
||||||
|
*/
|
||||||
|
int8_t RC_CAN_Init(RC_CAN_t *rc_can, RC_CAN_Param_t *param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 更新并发送数据到CAN总线
|
||||||
|
* @param rc_can RC_CAN结构体指针
|
||||||
|
* @param data_type 数据类型
|
||||||
|
* @return DEVICE_OK 成功,其他值失败
|
||||||
|
*/
|
||||||
|
int8_t RC_CAN_SendData(RC_CAN_t *rc_can, RC_CAN_DataType_t data_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 接收并更新CAN数据
|
||||||
|
* @param rc_can RC_CAN结构体指针
|
||||||
|
* @param data_type 数据类型
|
||||||
|
* @return DEVICE_OK 成功,其他值失败
|
||||||
|
*/
|
||||||
|
int8_t RC_CAN_Update(RC_CAN_t *rc_can , RC_CAN_DataType_t data_type);
|
||||||
|
|
||||||
|
int8_t RC_CAN_OFFLINE(RC_CAN_t *rc_can);
|
||||||
|
/* USER FUNCTION BEGIN */
|
||||||
|
|
||||||
|
/* USER FUNCTION END */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@ -261,7 +261,7 @@ int8_t Chassis_Control(Chassis_t *c, const Chassis_CMD_t *c_cmd){
|
|||||||
|
|
||||||
float fn;
|
float fn;
|
||||||
float tp1, tp2;
|
float tp1, tp2;
|
||||||
fn = -20.0f;
|
fn = -25.0f;
|
||||||
|
|
||||||
|
|
||||||
// tp1 = 3*PID_Calc(&c->pid.tp[0], 0.0f, c->vmc_[0].leg.theta, c->vmc_[0].leg.d_theta, c->dt);
|
// tp1 = 3*PID_Calc(&c->pid.tp[0], 0.0f, c->vmc_[0].leg.theta, c->vmc_[0].leg.d_theta, c->dt);
|
||||||
@ -490,7 +490,7 @@ int8_t Chassis_LQRControl(Chassis_t *c, const Chassis_CMD_t *c_cmd) {
|
|||||||
|
|
||||||
// 腿长控制力 = LQR摆杆力矩的径向分量 + PID腿长控制输出 + 基础支撑力
|
// 腿长控制力 = LQR摆杆力矩的径向分量 + PID腿长控制输出 + 基础支撑力
|
||||||
virtual_force[leg] = (Tp[leg]) * sinf(leg_theta[leg]) +
|
virtual_force[leg] = (Tp[leg]) * sinf(leg_theta[leg]) +
|
||||||
pid_output + 25.0f;
|
pid_output + 40.0f;
|
||||||
// + // PID腿长控制输出
|
// + // PID腿长控制输出
|
||||||
// 45.0f; // 基础支撑力
|
// 45.0f; // 基础支撑力
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
/* Includes ----------------------------------------------------------------- */
|
/* Includes ----------------------------------------------------------------- */
|
||||||
#include "module/config.h"
|
#include "module/config.h"
|
||||||
#include "bsp/can.h"
|
#include "bsp/can.h"
|
||||||
|
#include "device/rc_can.h"
|
||||||
|
|
||||||
/* Private typedef ---------------------------------------------------------- */
|
/* Private typedef ---------------------------------------------------------- */
|
||||||
/* Private define ----------------------------------------------------------- */
|
/* Private define ----------------------------------------------------------- */
|
||||||
@ -205,7 +206,16 @@ Config_RobotParam_t robot_config = {
|
|||||||
},
|
},
|
||||||
.lqr_param.max_joint_torque = 20.0f, // 关节电机最大力矩 20Nm
|
.lqr_param.max_joint_torque = 20.0f, // 关节电机最大力矩 20Nm
|
||||||
.lqr_param.max_wheel_torque = 4.5f, // 轮毂电机最大力矩 2.5Nm
|
.lqr_param.max_wheel_torque = 4.5f, // 轮毂电机最大力矩 2.5Nm
|
||||||
}
|
},
|
||||||
|
|
||||||
|
.rc_can_param = {
|
||||||
|
.can = BSP_CAN_2,
|
||||||
|
.mode = RC_CAN_MODE_SLAVE,
|
||||||
|
.joy_id = 0x250,
|
||||||
|
.sw_id = 0x251,
|
||||||
|
.mouse_id = 0x252,
|
||||||
|
.keyboard_id = 0x253,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Private function prototypes ---------------------------------------------- */
|
/* Private function prototypes ---------------------------------------------- */
|
||||||
|
|||||||
@ -13,13 +13,12 @@ extern "C" {
|
|||||||
#include "device/motor_lz.h"
|
#include "device/motor_lz.h"
|
||||||
#include "device/motor_lk.h"
|
#include "device/motor_lk.h"
|
||||||
#include "module/balance_chassis.h"
|
#include "module/balance_chassis.h"
|
||||||
|
#include "device/rc_can.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
DM_IMU_Param_t imu_param;
|
DM_IMU_Param_t imu_param;
|
||||||
MOTOR_LZ_Param_t joint_motors[4];
|
|
||||||
MOTOR_LK_Param_t wheel_motors[2];
|
|
||||||
Chassis_Params_t chassis_param;
|
Chassis_Params_t chassis_param;
|
||||||
|
RC_CAN_Param_t rc_can_param;
|
||||||
} Config_RobotParam_t;
|
} Config_RobotParam_t;
|
||||||
|
|
||||||
/* Exported functions prototypes -------------------------------------------- */
|
/* Exported functions prototypes -------------------------------------------- */
|
||||||
|
|||||||
@ -6,8 +6,11 @@
|
|||||||
/* Includes ----------------------------------------------------------------- */
|
/* Includes ----------------------------------------------------------------- */
|
||||||
#include "task/user_task.h"
|
#include "task/user_task.h"
|
||||||
/* USER INCLUDE BEGIN */
|
/* USER INCLUDE BEGIN */
|
||||||
|
#include "bsp/can.h"
|
||||||
#include "device/dr16.h"
|
#include "device/dr16.h"
|
||||||
|
#include "device/rc_can.h"
|
||||||
#include "module/balance_chassis.h"
|
#include "module/balance_chassis.h"
|
||||||
|
#include "module/config.h"
|
||||||
/* USER INCLUDE END */
|
/* USER INCLUDE END */
|
||||||
|
|
||||||
/* Private typedef ---------------------------------------------------------- */
|
/* Private typedef ---------------------------------------------------------- */
|
||||||
@ -16,7 +19,9 @@
|
|||||||
/* Private variables -------------------------------------------------------- */
|
/* Private variables -------------------------------------------------------- */
|
||||||
/* USER STRUCT BEGIN */
|
/* USER STRUCT BEGIN */
|
||||||
DR16_t dr16;
|
DR16_t dr16;
|
||||||
|
RC_CAN_t rc_can;
|
||||||
Chassis_CMD_t cmd_to_chassis;
|
Chassis_CMD_t cmd_to_chassis;
|
||||||
|
#define USE_RC_CAN
|
||||||
/* USER STRUCT END */
|
/* USER STRUCT END */
|
||||||
|
|
||||||
/* Private function --------------------------------------------------------- */
|
/* Private function --------------------------------------------------------- */
|
||||||
@ -32,12 +37,15 @@ void Task_rc(void *argument) {
|
|||||||
|
|
||||||
uint32_t tick = osKernelGetTickCount(); /* 控制任务运行频率的计时 */
|
uint32_t tick = osKernelGetTickCount(); /* 控制任务运行频率的计时 */
|
||||||
/* USER CODE INIT BEGIN */
|
/* USER CODE INIT BEGIN */
|
||||||
|
BSP_CAN_Init();
|
||||||
DR16_Init(&dr16);
|
DR16_Init(&dr16);
|
||||||
|
RC_CAN_Init(&rc_can, &Config_GetRobotParam()->rc_can_param);
|
||||||
/* USER CODE INIT END */
|
/* USER CODE INIT END */
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
tick += delay_tick; /* 计算下一个唤醒时刻 */
|
tick += delay_tick; /* 计算下一个唤醒时刻 */
|
||||||
/* USER CODE BEGIN */
|
/* USER CODE BEGIN */
|
||||||
|
#ifdef USE_DR16
|
||||||
DR16_StartDmaRecv(&dr16);
|
DR16_StartDmaRecv(&dr16);
|
||||||
if (DR16_WaitDmaCplt(20)) {
|
if (DR16_WaitDmaCplt(20)) {
|
||||||
DR16_ParseData(&dr16);
|
DR16_ParseData(&dr16);
|
||||||
@ -63,51 +71,35 @@ void Task_rc(void *argument) {
|
|||||||
DR16_Offline(&dr16);
|
DR16_Offline(&dr16);
|
||||||
cmd_to_chassis.mode = CHASSIS_MODE_RELAX;
|
cmd_to_chassis.mode = CHASSIS_MODE_RELAX;
|
||||||
}
|
}
|
||||||
|
#elif defined USE_RC_CAN
|
||||||
|
RC_CAN_Update(&rc_can, RC_CAN_DATA_JOYSTICK);
|
||||||
|
RC_CAN_Update(&rc_can, RC_CAN_DATA_SWITCH);
|
||||||
|
if (rc_can.header.online) {
|
||||||
|
switch (rc_can.data.sw.sw_l) {
|
||||||
|
case RC_CAN_SW_UP: // 上位
|
||||||
|
cmd_to_chassis.mode = CHASSIS_MODE_RELAX;
|
||||||
|
break;
|
||||||
|
case RC_CAN_SW_MID: // 中位
|
||||||
|
cmd_to_chassis.mode = CHASSIS_MODE_RECOVER;
|
||||||
|
break;
|
||||||
|
case RC_CAN_SW_DOWN: // 下位
|
||||||
|
cmd_to_chassis.mode = CHASSIS_MODE_WHELL_BALANCE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
cmd_to_chassis.mode = CHASSIS_MODE_RELAX;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cmd_to_chassis.move_vec.vx = rc_can.data.joy.ch_l_y;
|
||||||
|
cmd_to_chassis.move_vec.vy = rc_can.data.joy.ch_l_x;
|
||||||
|
cmd_to_chassis.move_vec.wz = rc_can.data.joy.ch_r_x;
|
||||||
|
cmd_to_chassis.height = rc_can.data.sw.ch_res;
|
||||||
|
} else {
|
||||||
|
RC_CAN_OFFLINE(&rc_can);
|
||||||
|
cmd_to_chassis.mode = CHASSIS_MODE_RELAX;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
osMessageQueuePut(task_runtime.msgq.Chassis_cmd, &cmd_to_chassis, 0, 0);
|
osMessageQueuePut(task_runtime.msgq.Chassis_cmd, &cmd_to_chassis, 0, 0);
|
||||||
// if (DR16_WaitDmaCplt(20)) {
|
|
||||||
// // 根据左拨杆设置底盘模式
|
|
||||||
// switch (dr16.data.sw_l) {
|
|
||||||
// case 1: // 上位
|
|
||||||
// cmd_to_chassis.mode = CHASSIS_MODE_RELAX;
|
|
||||||
// break;
|
|
||||||
// case 3: // 中位
|
|
||||||
// cmd_to_chassis.mode = CHASSIS_MODE_RECOVER;
|
|
||||||
// break;
|
|
||||||
// case 2: // 下位
|
|
||||||
// cmd_to_chassis.mode = CHASSIS_MODE_WHELL_BALANCE;
|
|
||||||
// break;
|
|
||||||
// default:
|
|
||||||
// cmd_to_chassis.mode = CHASSIS_MODE_RELAX;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 解析遥控器摇杆数据为运动向量
|
|
||||||
// // 将遥控器通道值从[364, 1684]映射到[-1.0, 1.0]
|
|
||||||
// float ch_l_y_norm = (float)(dr16.data.ch_l_y - 1024) / 660.0f; // 前后
|
|
||||||
// float ch_l_x_norm = (float)(dr16.data.ch_l_x - 1024) / 660.0f; // 左右
|
|
||||||
// float ch_r_x_norm = (float)(dr16.data.ch_r_y - 1024) / 660.0f; // 旋转
|
|
||||||
|
|
||||||
// // 设置运动向量(根据需要调整增益)
|
|
||||||
// cmd_to_chassis.move_vec.vx = ch_l_y_norm * 2.0f; // 前后运动,增益可调
|
|
||||||
// cmd_to_chassis.move_vec.vy = ch_l_x_norm * 2.0f; // 左右运动,增益可调
|
|
||||||
// cmd_to_chassis.move_vec.wz = ch_r_x_norm * 3.0f; // 旋转运动,增益可调
|
|
||||||
|
|
||||||
// // 设置目标高度(可根据右拨杆或其他输入调整)
|
|
||||||
// cmd_to_chassis.height = dr16.data.res-1024; // 目标高度,范围[-1024, 1024],可根据需要调整比例
|
|
||||||
|
|
||||||
// // 发送命令到底盘控制任务
|
|
||||||
// osMessageQueuePut(task_runtime.msgq.Chassis_cmd, &cmd_to_chassis, 0, 0);
|
|
||||||
|
|
||||||
// } else {
|
|
||||||
// // 超时处理,发送安全命令
|
|
||||||
// cmd_to_chassis.mode = CHASSIS_MODE_RELAX;
|
|
||||||
// cmd_to_chassis.move_vec.vx = 0.0f;
|
|
||||||
// cmd_to_chassis.move_vec.vy = 0.0f;
|
|
||||||
// cmd_to_chassis.move_vec.wz = 0.0f;
|
|
||||||
// cmd_to_chassis.height = 0.0f;
|
|
||||||
// osMessageQueuePut(task_runtime.msgq.Chassis_cmd, &cmd_to_chassis, 0, 0);
|
|
||||||
// }
|
|
||||||
|
|
||||||
/* USER CODE END */
|
/* USER CODE END */
|
||||||
osDelayUntil(tick); /* 运行结束,等待下一次唤醒 */
|
osDelayUntil(tick); /* 运行结束,等待下一次唤醒 */
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user