添加陀螺仪

This commit is contained in:
Robofish 2025-09-30 16:32:29 +08:00
parent 7905d42542
commit fd58bb0462
8 changed files with 861 additions and 55 deletions

View File

@ -141,13 +141,13 @@ int8_t DR16_ParseData(DR16_t *dr16){
uint16_t key_value = dr16->raw_data.key;
// 解析键盘位映射W-B键位0-15
for (int i = CMD_KEY_W; i <= CMD_KEY_B; i++) {
for (int i = DR16_KEY_W; i <= DR16_KEY_B; i++) {
dr16->data.keyboard.key[i] = (key_value & (1 << i)) != 0;
}
// 解析鼠标点击
dr16->data.keyboard.key[CMD_L_CLICK] = dr16->data.mouse.l_click;
dr16->data.keyboard.key[CMD_R_CLICK] = dr16->data.mouse.r_click;
dr16->data.keyboard.key[DR16_L_CLICK] = dr16->data.mouse.l_click;
dr16->data.keyboard.key[DR16_R_CLICK] = dr16->data.mouse.r_click;
// 解析第五通道
dr16->data.ch_res = 2.0f * ((float)dr16->raw_data.res - DR16_CH_VALUE_MID) / full_range;

View File

@ -38,33 +38,33 @@ typedef struct __packed {
} DR16_RawData_t;
typedef enum {
CMD_SW_ERR = 0,
CMD_SW_UP = 1,
CMD_SW_MID = 3,
CMD_SW_DOWN = 2,
DR16_SW_ERR = 0,
DR16_SW_UP = 1,
DR16_SW_MID = 3,
DR16_SW_DOWN = 2,
} DR16_SwitchPos_t;
/* 键盘按键值 */
typedef enum {
CMD_KEY_W = 0,
CMD_KEY_S,
CMD_KEY_A,
CMD_KEY_D,
CMD_KEY_SHIFT,
CMD_KEY_CTRL,
CMD_KEY_Q,
CMD_KEY_E,
CMD_KEY_R,
CMD_KEY_F,
CMD_KEY_G,
CMD_KEY_Z,
CMD_KEY_X,
CMD_KEY_C,
CMD_KEY_V,
CMD_KEY_B,
CMD_L_CLICK,
CMD_R_CLICK,
CMD_KEY_NUM,
DR16_KEY_W = 0,
DR16_KEY_S,
DR16_KEY_A,
DR16_KEY_D,
DR16_KEY_SHIFT,
DR16_KEY_CTRL,
DR16_KEY_Q,
DR16_KEY_E,
DR16_KEY_R,
DR16_KEY_F,
DR16_KEY_G,
DR16_KEY_Z,
DR16_KEY_X,
DR16_KEY_C,
DR16_KEY_V,
DR16_KEY_B,
DR16_L_CLICK,
DR16_R_CLICK,
DR16_KEY_NUM,
} DR16_Key_t;
typedef struct {
@ -87,7 +87,7 @@ typedef struct {
} mouse; /* 鼠标值 */
union {
bool key[CMD_KEY_NUM]; /* 键盘按键值 */
bool key[DR16_KEY_NUM]; /* 键盘按键值 */
uint16_t value; /* 键盘按键值的位映射 */
} keyboard;

View File

@ -0,0 +1,541 @@
/*
RC CAN数据发送模块
DR16遥控器数据通过CAN总线发送
motor_rm的结构设计
Example:
RC_CAN_t rc_can;
RC_CAN_Param_t param = {
.can = BSP_CAN_1,
.enabled = true,
.send_period = 10 // 10ms发送一次
};
RC_CAN_Init(&rc_can, &param);
// 在主循环中
while(1) {
if (DR16_ParseData(&dr16) == DEVICE_OK) {
RC_CAN_SendData(&rc_can, &dr16);
}
osDelay(param.send_period);
}
*/
/* Includes ----------------------------------------------------------------- */
#include "rc_can.h"
#include "device/dr16.h"
#include "bsp/time.h"
#include <string.h>
/* USER INCLUDE BEGIN */
/* USER INCLUDE END */
/* Private define ----------------------------------------------------------- */
#define RC_CAN_SCALE_FACTOR 1000.0f // 将[-1.0, 1.0]转换为[-1000, 1000]
#define RC_CAN_DATA_JOYSTICK 0
#define RC_CAN_DATA_SWITCH 1
#define RC_CAN_DATA_MOUSE 2
#define RC_CAN_DATA_KEYBOARD 3
#define RC_CAN_DATA_STATUS 4
/* USER DEFINE BEGIN */
/* USER DEFINE END */
/* Private macro ------------------------------------------------------------ */
/* Private typedef ---------------------------------------------------------- */
/* Private variables -------------------------------------------------------- */
/* Private function -------------------------------------------------------- */
/**
* @brief
* @param value [-1.0, 1.0]
* @return [-1000, 1000]
*/
static int16_t RC_CAN_ScaleFloat(float value) {
if (value > 1.0f) value = 1.0f;
if (value < -1.0f) value = -1.0f;
return (int16_t)(value * RC_CAN_SCALE_FACTOR);
}
/**
* @brief
* @param rc_can RC_CAN结构体指针
* @param dr16 DR16数据结构体指针
*/
static void RC_CAN_UpdateJoystickData(RC_CAN_t *rc_can, const DR16_t *dr16) {
rc_can->joystick_data.ch_l_x = RC_CAN_ScaleFloat(dr16->data.ch_l_x);
rc_can->joystick_data.ch_l_y = RC_CAN_ScaleFloat(dr16->data.ch_l_y);
rc_can->joystick_data.ch_r_x = RC_CAN_ScaleFloat(dr16->data.ch_r_x);
rc_can->joystick_data.ch_r_y = RC_CAN_ScaleFloat(dr16->data.ch_r_y);
}
/**
* @brief
* @param rc_can RC_CAN结构体指针
* @param dr16 DR16数据结构体指针
*/
static void RC_CAN_UpdateSwitchData(RC_CAN_t *rc_can, const DR16_t *dr16) {
rc_can->switch_data.sw_l = (uint8_t)dr16->data.sw_l;
rc_can->switch_data.sw_r = (uint8_t)dr16->data.sw_r;
rc_can->switch_data.ch_res = RC_CAN_ScaleFloat(dr16->data.ch_res);
rc_can->switch_data.reserved = 0;
}
/**
* @brief
* @param rc_can RC_CAN结构体指针
* @param dr16 DR16数据结构体指针
*/
static void RC_CAN_UpdateMouseData(RC_CAN_t *rc_can, const DR16_t *dr16) {
rc_can->mouse_data.mouse_x = dr16->data.mouse.x;
rc_can->mouse_data.mouse_y = dr16->data.mouse.y;
rc_can->mouse_data.mouse_z = dr16->data.mouse.z;
rc_can->mouse_data.mouse_l = dr16->data.mouse.l_click ? 1 : 0;
rc_can->mouse_data.mouse_r = dr16->data.mouse.r_click ? 1 : 0;
}
/**
* @brief
* @param rc_can RC_CAN结构体指针
* @param dr16 DR16数据结构体指针
*/
static void RC_CAN_UpdateKeyboardData(RC_CAN_t *rc_can, const DR16_t *dr16) {
rc_can->keyboard_data.key_value = dr16->data.keyboard.value;
memset(rc_can->keyboard_data.reserved, 0, sizeof(rc_can->keyboard_data.reserved));
}
/**
* @brief
* @param rc_can RC_CAN结构体指针
* @param dr16 DR16数据结构体指针
*/
static void RC_CAN_UpdateStatusData(RC_CAN_t *rc_can, const DR16_t *dr16) {
rc_can->status_data.online = dr16->header.online ? 1 : 0;
rc_can->status_data.data_valid = 1; // 假设数据有效
rc_can->status_data.timestamp = (uint32_t)(BSP_TIME_Get() / 1000); // 转换为ms
rc_can->status_data.reserved = 0;
}
/**
* @brief
* @param value [-1000, 1000]
* @return [-1.0, 1.0]
*/
static float RC_CAN_UnscaleInt(int16_t value) {
float result = (float)value / RC_CAN_SCALE_FACTOR;
if (result > 1.0f) result = 1.0f;
if (result < -1.0f) result = -1.0f;
return result;
}
/**
* @brief CAN消息
* @param rc_can RC_CAN结构体指针
* @param msg CAN消息指针
*/
static void RC_CAN_ProcessRxMessage(RC_CAN_t *rc_can, BSP_CAN_Message_t *msg) {
uint32_t current_time = (uint32_t)(BSP_TIME_Get() / 1000); // 转换为ms
switch (msg->parsed_id) {
case RC_CAN_DR16_JOYSTICK_ID:
if (msg->dlc >= sizeof(RC_CAN_JoystickData_t)) {
memcpy(&rc_can->joystick_data, msg->data, sizeof(RC_CAN_JoystickData_t));
rc_can->rx_status.joystick_updated = true;
rc_can->rx_status.last_joystick_time = current_time;
}
break;
case RC_CAN_DR16_SWITCH_ID:
if (msg->dlc >= sizeof(RC_CAN_SwitchData_t)) {
memcpy(&rc_can->switch_data, msg->data, sizeof(RC_CAN_SwitchData_t));
rc_can->rx_status.switch_updated = true;
rc_can->rx_status.last_switch_time = current_time;
}
break;
case RC_CAN_DR16_MOUSE_ID:
if (msg->dlc >= sizeof(RC_CAN_MouseData_t)) {
memcpy(&rc_can->mouse_data, msg->data, sizeof(RC_CAN_MouseData_t));
rc_can->rx_status.mouse_updated = true;
rc_can->rx_status.last_mouse_time = current_time;
}
break;
case RC_CAN_DR16_KEYBOARD_ID:
if (msg->dlc >= sizeof(RC_CAN_KeyboardData_t)) {
memcpy(&rc_can->keyboard_data, msg->data, sizeof(RC_CAN_KeyboardData_t));
rc_can->rx_status.keyboard_updated = true;
rc_can->rx_status.last_keyboard_time = current_time;
}
break;
case RC_CAN_DR16_STATUS_ID:
if (msg->dlc >= sizeof(RC_CAN_StatusData_t)) {
memcpy(&rc_can->status_data, msg->data, sizeof(RC_CAN_StatusData_t));
rc_can->rx_status.status_updated = true;
rc_can->rx_status.last_status_time = current_time;
// 更新整体在线状态
rc_can->header.online = (rc_can->status_data.online == 1);
rc_can->header.last_online_time = BSP_TIME_Get();
}
break;
default:
// 未知ID忽略
break;
}
}
/* USER FUNCTION BEGIN */
/* USER FUNCTION END */
/* Exported functions ------------------------------------------------------- */
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->initialized) {
return DEVICE_ERR_INITED;
}
// 复制参数
memcpy(&rc_can->param, param, sizeof(RC_CAN_Param_t));
// 初始化头部信息
rc_can->header.online = false;
rc_can->header.last_online_time = 0;
// 清零数据包
memset(&rc_can->joystick_data, 0, sizeof(RC_CAN_JoystickData_t));
memset(&rc_can->switch_data, 0, sizeof(RC_CAN_SwitchData_t));
memset(&rc_can->mouse_data, 0, sizeof(RC_CAN_MouseData_t));
memset(&rc_can->keyboard_data, 0, sizeof(RC_CAN_KeyboardData_t));
memset(&rc_can->status_data, 0, sizeof(RC_CAN_StatusData_t));
// 初始化接收状态
memset(&rc_can->rx_status, 0, sizeof(RC_CAN_RxStatus_t));
// 如果是接收模式注册CAN ID
if (param->mode == RC_CAN_MODE_RECEIVER || param->mode == RC_CAN_MODE_BOTH) {
BSP_CAN_RegisterId(param->can, RC_CAN_DR16_JOYSTICK_ID, 0);
BSP_CAN_RegisterId(param->can, RC_CAN_DR16_SWITCH_ID, 0);
BSP_CAN_RegisterId(param->can, RC_CAN_DR16_MOUSE_ID, 0);
BSP_CAN_RegisterId(param->can, RC_CAN_DR16_KEYBOARD_ID, 0);
BSP_CAN_RegisterId(param->can, RC_CAN_DR16_STATUS_ID, 0);
}
// 初始化状态
rc_can->last_send_time = 0;
rc_can->initialized = true;
return DEVICE_OK;
}
int8_t RC_CAN_SendData(RC_CAN_t *rc_can, const void *dr16_ptr) {
if (rc_can == NULL || dr16_ptr == NULL) {
return DEVICE_ERR_NULL;
}
const DR16_t *dr16 = (const DR16_t *)dr16_ptr;
if (!rc_can->initialized) {
return DEVICE_ERR;
}
if (!rc_can->param.enabled) {
return DEVICE_OK; // 未启用时直接返回成功
}
uint64_t current_time = BSP_TIME_Get() / 1000; // 转换为ms
// 检查发送周期
if (current_time - rc_can->last_send_time < rc_can->param.send_period) {
return DEVICE_OK; // 未到发送时间
}
// 更新所有数据包
RC_CAN_UpdateJoystickData(rc_can, dr16);
RC_CAN_UpdateSwitchData(rc_can, dr16);
RC_CAN_UpdateMouseData(rc_can, dr16);
RC_CAN_UpdateKeyboardData(rc_can, dr16);
RC_CAN_UpdateStatusData(rc_can, dr16);
int8_t result = DEVICE_OK;
// 发送所有数据包
if (RC_CAN_SendJoystickData(rc_can) != DEVICE_OK) result = DEVICE_ERR;
if (RC_CAN_SendSwitchData(rc_can) != DEVICE_OK) result = DEVICE_ERR;
if (RC_CAN_SendMouseData(rc_can) != DEVICE_OK) result = DEVICE_ERR;
if (RC_CAN_SendKeyboardData(rc_can) != DEVICE_OK) result = DEVICE_ERR;
if (RC_CAN_SendStatusData(rc_can) != DEVICE_OK) result = DEVICE_ERR;
// 更新发送时间和在线状态
rc_can->last_send_time = (uint32_t)current_time;
rc_can->header.online = true;
rc_can->header.last_online_time = BSP_TIME_Get();
return result;
}
int8_t RC_CAN_SendJoystickData(RC_CAN_t *rc_can) {
if (rc_can == NULL) {
return DEVICE_ERR_NULL;
}
BSP_CAN_StdDataFrame_t tx_frame;
tx_frame.id = RC_CAN_DR16_JOYSTICK_ID;
tx_frame.dlc = sizeof(RC_CAN_JoystickData_t);
memcpy(tx_frame.data, &rc_can->joystick_data, sizeof(RC_CAN_JoystickData_t));
return BSP_CAN_TransmitStdDataFrame(rc_can->param.can, &tx_frame) == BSP_OK ?
DEVICE_OK : DEVICE_ERR;
}
int8_t RC_CAN_SendSwitchData(RC_CAN_t *rc_can) {
if (rc_can == NULL) {
return DEVICE_ERR_NULL;
}
BSP_CAN_StdDataFrame_t tx_frame;
tx_frame.id = RC_CAN_DR16_SWITCH_ID;
tx_frame.dlc = sizeof(RC_CAN_SwitchData_t);
memcpy(tx_frame.data, &rc_can->switch_data, sizeof(RC_CAN_SwitchData_t));
return BSP_CAN_TransmitStdDataFrame(rc_can->param.can, &tx_frame) == BSP_OK ?
DEVICE_OK : DEVICE_ERR;
}
int8_t RC_CAN_SendMouseData(RC_CAN_t *rc_can) {
if (rc_can == NULL) {
return DEVICE_ERR_NULL;
}
BSP_CAN_StdDataFrame_t tx_frame;
tx_frame.id = RC_CAN_DR16_MOUSE_ID;
tx_frame.dlc = sizeof(RC_CAN_MouseData_t);
memcpy(tx_frame.data, &rc_can->mouse_data, sizeof(RC_CAN_MouseData_t));
return BSP_CAN_TransmitStdDataFrame(rc_can->param.can, &tx_frame) == BSP_OK ?
DEVICE_OK : DEVICE_ERR;
}
int8_t RC_CAN_SendKeyboardData(RC_CAN_t *rc_can) {
if (rc_can == NULL) {
return DEVICE_ERR_NULL;
}
BSP_CAN_StdDataFrame_t tx_frame;
tx_frame.id = RC_CAN_DR16_KEYBOARD_ID;
tx_frame.dlc = sizeof(RC_CAN_KeyboardData_t);
memcpy(tx_frame.data, &rc_can->keyboard_data, sizeof(RC_CAN_KeyboardData_t));
return BSP_CAN_TransmitStdDataFrame(rc_can->param.can, &tx_frame) == BSP_OK ?
DEVICE_OK : DEVICE_ERR;
}
int8_t RC_CAN_SendStatusData(RC_CAN_t *rc_can) {
if (rc_can == NULL) {
return DEVICE_ERR_NULL;
}
BSP_CAN_StdDataFrame_t tx_frame;
tx_frame.id = RC_CAN_DR16_STATUS_ID;
tx_frame.dlc = sizeof(RC_CAN_StatusData_t);
memcpy(tx_frame.data, &rc_can->status_data, sizeof(RC_CAN_StatusData_t));
return BSP_CAN_TransmitStdDataFrame(rc_can->param.can, &tx_frame) == BSP_OK ?
DEVICE_OK : DEVICE_ERR;
}
int8_t RC_CAN_SetEnabled(RC_CAN_t *rc_can, bool enabled) {
if (rc_can == NULL) {
return DEVICE_ERR_NULL;
}
rc_can->param.enabled = enabled;
return DEVICE_OK;
}
bool RC_CAN_IsOnline(const RC_CAN_t *rc_can) {
if (rc_can == NULL) {
return false;
}
return rc_can->header.online;
}
int8_t RC_CAN_Update(RC_CAN_t *rc_can) {
if (rc_can == NULL) {
return DEVICE_ERR_NULL;
}
if (!rc_can->initialized) {
return DEVICE_ERR;
}
// 只在接收模式下处理接收
if (rc_can->param.mode != RC_CAN_MODE_RECEIVER && rc_can->param.mode != RC_CAN_MODE_BOTH) {
return DEVICE_OK;
}
BSP_CAN_Message_t rx_msg;
int8_t result = DEVICE_OK;
// 处理所有可能的接收ID
uint32_t can_ids[] = {
RC_CAN_DR16_JOYSTICK_ID,
RC_CAN_DR16_SWITCH_ID,
RC_CAN_DR16_MOUSE_ID,
RC_CAN_DR16_KEYBOARD_ID,
RC_CAN_DR16_STATUS_ID
};
for (int i = 0; i < 5; i++) {
while (BSP_CAN_GetMessage(rc_can->param.can, can_ids[i], &rx_msg, BSP_CAN_TIMEOUT_IMMEDIATE) == BSP_OK) {
RC_CAN_ProcessRxMessage(rc_can, &rx_msg);
}
}
return result;
}
int8_t RC_CAN_GetJoystickData(const RC_CAN_t *rc_can, float *ch_l_x, float *ch_l_y,
float *ch_r_x, float *ch_r_y) {
if (rc_can == NULL || ch_l_x == NULL || ch_l_y == NULL ||
ch_r_x == NULL || ch_r_y == NULL) {
return DEVICE_ERR_NULL;
}
*ch_l_x = RC_CAN_UnscaleInt(rc_can->joystick_data.ch_l_x);
*ch_l_y = RC_CAN_UnscaleInt(rc_can->joystick_data.ch_l_y);
*ch_r_x = RC_CAN_UnscaleInt(rc_can->joystick_data.ch_r_x);
*ch_r_y = RC_CAN_UnscaleInt(rc_can->joystick_data.ch_r_y);
return DEVICE_OK;
}
int8_t RC_CAN_GetSwitchData(const RC_CAN_t *rc_can, uint8_t *sw_l, uint8_t *sw_r,
float *ch_res) {
if (rc_can == NULL || sw_l == NULL || sw_r == NULL || ch_res == NULL) {
return DEVICE_ERR_NULL;
}
*sw_l = rc_can->switch_data.sw_l;
*sw_r = rc_can->switch_data.sw_r;
*ch_res = RC_CAN_UnscaleInt(rc_can->switch_data.ch_res);
return DEVICE_OK;
}
int8_t RC_CAN_GetMouseData(const RC_CAN_t *rc_can, int16_t *mouse_x, int16_t *mouse_y,
int16_t *mouse_z, bool *mouse_l, bool *mouse_r) {
if (rc_can == NULL || mouse_x == NULL || mouse_y == NULL ||
mouse_z == NULL || mouse_l == NULL || mouse_r == NULL) {
return DEVICE_ERR_NULL;
}
*mouse_x = rc_can->mouse_data.mouse_x;
*mouse_y = rc_can->mouse_data.mouse_y;
*mouse_z = rc_can->mouse_data.mouse_z;
*mouse_l = (rc_can->mouse_data.mouse_l != 0);
*mouse_r = (rc_can->mouse_data.mouse_r != 0);
return DEVICE_OK;
}
int8_t RC_CAN_GetKeyboardData(const RC_CAN_t *rc_can, uint16_t *key_value) {
if (rc_can == NULL || key_value == NULL) {
return DEVICE_ERR_NULL;
}
*key_value = rc_can->keyboard_data.key_value;
return DEVICE_OK;
}
int8_t RC_CAN_GetRemoteStatus(const RC_CAN_t *rc_can, bool *remote_online,
bool *data_valid, uint32_t *timestamp) {
if (rc_can == NULL || remote_online == NULL ||
data_valid == NULL || timestamp == NULL) {
return DEVICE_ERR_NULL;
}
*remote_online = (rc_can->status_data.online != 0);
*data_valid = (rc_can->status_data.data_valid != 0);
*timestamp = rc_can->status_data.timestamp;
return DEVICE_OK;
}
bool RC_CAN_IsDataUpdated(RC_CAN_t *rc_can, uint8_t data_type) {
if (rc_can == NULL || data_type > RC_CAN_DATA_STATUS) {
return false;
}
bool updated = false;
switch (data_type) {
case RC_CAN_DATA_JOYSTICK:
updated = rc_can->rx_status.joystick_updated;
rc_can->rx_status.joystick_updated = false; // 清除更新标志
break;
case RC_CAN_DATA_SWITCH:
updated = rc_can->rx_status.switch_updated;
rc_can->rx_status.switch_updated = false;
break;
case RC_CAN_DATA_MOUSE:
updated = rc_can->rx_status.mouse_updated;
rc_can->rx_status.mouse_updated = false;
break;
case RC_CAN_DATA_KEYBOARD:
updated = rc_can->rx_status.keyboard_updated;
rc_can->rx_status.keyboard_updated = false;
break;
case RC_CAN_DATA_STATUS:
updated = rc_can->rx_status.status_updated;
rc_can->rx_status.status_updated = false;
break;
default:
updated = false;
break;
}
return updated;
}
bool RC_CAN_IsDataTimeout(const RC_CAN_t *rc_can) {
if (rc_can == NULL) {
return true;
}
uint32_t current_time = (uint32_t)(BSP_TIME_Get() / 1000); // 转换为ms
uint32_t timeout_ms = rc_can->param.timeout_ms;
// 检查所有数据类型是否超时
bool timeout = false;
if (current_time - rc_can->rx_status.last_joystick_time > timeout_ms) timeout = true;
if (current_time - rc_can->rx_status.last_switch_time > timeout_ms) timeout = true;
if (current_time - rc_can->rx_status.last_mouse_time > timeout_ms) timeout = true;
if (current_time - rc_can->rx_status.last_keyboard_time > timeout_ms) timeout = true;
if (current_time - rc_can->rx_status.last_status_time > timeout_ms) timeout = true;
return timeout;
}
/* USER FUNCTION BEGIN */
/* USER FUNCTION END */

View File

@ -7,6 +7,9 @@ extern "C" {
/* Includes ----------------------------------------------------------------- */
#include "bsp/can.h"
#include "device/device.h"
#include <stdint.h>
#include <stdbool.h>
/* USER INCLUDE BEGIN */
/* USER INCLUDE END */
@ -16,6 +19,13 @@ extern "C" {
/* USER DEFINE END */
/* Exported constants ------------------------------------------------------- */
// CAN ID 定义
#define RC_CAN_DR16_JOYSTICK_ID 0x300 // 遥杆数据
#define RC_CAN_DR16_SWITCH_ID 0x301 // 拨杆数据
#define RC_CAN_DR16_MOUSE_ID 0x302 // 鼠标数据
#define RC_CAN_DR16_KEYBOARD_ID 0x303 // 键盘数据
#define RC_CAN_DR16_STATUS_ID 0x304 // 状态数据
/* Exported macro ----------------------------------------------------------- */
/* Exported types ----------------------------------------------------------- */
@ -26,20 +36,94 @@ typedef enum {
RC_CAN_SW_DOWN = 2,
} RC_CAN_SW_t;
typedef struct {
float ch_l_x;
float ch_l_y;
float ch_r_x;
float ch_r_y;
RC_CAN_SW_t sw_l;
RC_CAN_SW_t sw_r;
flaot res;
} RC_CAN_DR16_t;
// 遥杆数据包 (CAN ID: 0x300)
typedef struct __packed {
int16_t ch_l_x; // 左侧摇杆X轴 (-1000~1000)
int16_t ch_l_y; // 左侧摇杆Y轴 (-1000~1000)
int16_t ch_r_x; // 右侧摇杆X轴 (-1000~1000)
int16_t ch_r_y; // 右侧摇杆Y轴 (-1000~1000)
} RC_CAN_JoystickData_t;
typedef struct {
f
} RC_CAN_DR16_t;
// 拨杆数据包 (CAN ID: 0x301)
typedef struct __packed {
uint8_t sw_l; // 左拨杆状态
uint8_t sw_r; // 右拨杆状态
int16_t ch_res; // 第五通道 (-1000~1000)
uint32_t reserved; // 保留字节
} RC_CAN_SwitchData_t;
// 鼠标数据包 (CAN ID: 0x302)
typedef struct __packed {
int16_t mouse_x; // 鼠标X轴移动
int16_t mouse_y; // 鼠标Y轴移动
int16_t mouse_z; // 鼠标Z轴(滚轮)
uint8_t mouse_l; // 鼠标左键
uint8_t mouse_r; // 鼠标右键
} RC_CAN_MouseData_t;
// 键盘数据包 (CAN ID: 0x303)
typedef struct __packed {
uint16_t key_value; // 键盘按键位映射
uint8_t reserved[6]; // 保留字节
} RC_CAN_KeyboardData_t;
// 状态数据包 (CAN ID: 0x304)
typedef struct __packed {
uint8_t online; // 在线状态 (1:在线, 0:离线)
uint8_t data_valid; // 数据有效性 (1:有效, 0:无效)
uint32_t timestamp; // 时间戳(ms)
uint16_t reserved; // 保留字节
} RC_CAN_StatusData_t;
// 工作模式枚举
typedef enum {
RC_CAN_MODE_SENDER, // 发送模式连接DR16的板子
RC_CAN_MODE_RECEIVER, // 接收模式(其他板子)
RC_CAN_MODE_BOTH // 双向模式(可发送也可接收)
} RC_CAN_Mode_t;
// 接收数据状态
typedef struct {
bool joystick_updated;
bool switch_updated;
bool mouse_updated;
bool keyboard_updated;
bool status_updated;
uint32_t last_joystick_time;
uint32_t last_switch_time;
uint32_t last_mouse_time;
uint32_t last_keyboard_time;
uint32_t last_status_time;
} RC_CAN_RxStatus_t;
// RC_CAN 参数结构
typedef struct {
BSP_CAN_t can; // 使用的CAN总线
RC_CAN_Mode_t mode; // 工作模式
bool enabled; // 是否启用发送(仅发送模式有效)
uint32_t send_period; // 发送周期(ms)
uint32_t timeout_ms; // 接收超时时间(ms)
} RC_CAN_Param_t;
// RC_CAN 主结构
typedef struct {
RC_CAN_Param_t param;
DEVICE_Header_t header;
// 数据包
RC_CAN_JoystickData_t joystick_data;
RC_CAN_SwitchData_t switch_data;
RC_CAN_MouseData_t mouse_data;
RC_CAN_KeyboardData_t keyboard_data;
RC_CAN_StatusData_t status_data;
// 接收状态(仅接收模式有效)
RC_CAN_RxStatus_t rx_status;
// 状态信息
uint32_t last_send_time;
bool initialized;
} RC_CAN_t;
/* USER STRUCT BEGIN */
@ -47,6 +131,149 @@ typedef struct {
/* 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 DR16数据到CAN总线
* @param rc_can RC_CAN结构体指针
* @param dr16 DR16数据结构体指针
* @return DEVICE_OK
*/
int8_t RC_CAN_SendData(RC_CAN_t *rc_can, const void *dr16);
/**
* @brief
* @param rc_can RC_CAN结构体指针
* @return DEVICE_OK
*/
int8_t RC_CAN_SendJoystickData(RC_CAN_t *rc_can);
/**
* @brief
* @param rc_can RC_CAN结构体指针
* @return DEVICE_OK
*/
int8_t RC_CAN_SendSwitchData(RC_CAN_t *rc_can);
/**
* @brief
* @param rc_can RC_CAN结构体指针
* @return DEVICE_OK
*/
int8_t RC_CAN_SendMouseData(RC_CAN_t *rc_can);
/**
* @brief
* @param rc_can RC_CAN结构体指针
* @return DEVICE_OK
*/
int8_t RC_CAN_SendKeyboardData(RC_CAN_t *rc_can);
/**
* @brief
* @param rc_can RC_CAN结构体指针
* @return DEVICE_OK
*/
int8_t RC_CAN_SendStatusData(RC_CAN_t *rc_can);
/**
* @brief 使
* @param rc_can RC_CAN结构体指针
* @param enabled 使
* @return DEVICE_OK
*/
int8_t RC_CAN_SetEnabled(RC_CAN_t *rc_can, bool enabled);
/**
* @brief 线
* @param rc_can RC_CAN结构体指针
* @return true 线false 线
*/
bool RC_CAN_IsOnline(const RC_CAN_t *rc_can);
/**
* @brief CAN数据
* @param rc_can RC_CAN结构体指针
* @return DEVICE_OK
*/
int8_t RC_CAN_Update(RC_CAN_t *rc_can);
/**
* @brief
* @param rc_can RC_CAN结构体指针
* @param ch_l_x X轴输出指针
* @param ch_l_y Y轴输出指针
* @param ch_r_x X轴输出指针
* @param ch_r_y Y轴输出指针
* @return DEVICE_OK
*/
int8_t RC_CAN_GetJoystickData(const RC_CAN_t *rc_can, float *ch_l_x, float *ch_l_y,
float *ch_r_x, float *ch_r_y);
/**
* @brief
* @param rc_can RC_CAN结构体指针
* @param sw_l
* @param sw_r
* @param ch_res
* @return DEVICE_OK
*/
int8_t RC_CAN_GetSwitchData(const RC_CAN_t *rc_can, uint8_t *sw_l, uint8_t *sw_r,
float *ch_res);
/**
* @brief
* @param rc_can RC_CAN结构体指针
* @param mouse_x X轴输出指针
* @param mouse_y Y轴输出指针
* @param mouse_z Z轴输出指针
* @param mouse_l
* @param mouse_r
* @return DEVICE_OK
*/
int8_t RC_CAN_GetMouseData(const RC_CAN_t *rc_can, int16_t *mouse_x, int16_t *mouse_y,
int16_t *mouse_z, bool *mouse_l, bool *mouse_r);
/**
* @brief
* @param rc_can RC_CAN结构体指针
* @param key_value
* @return DEVICE_OK
*/
int8_t RC_CAN_GetKeyboardData(const RC_CAN_t *rc_can, uint16_t *key_value);
/**
* @brief DR16状态
* @param rc_can RC_CAN结构体指针
* @param remote_online DR16在线状态输出指针
* @param data_valid
* @param timestamp
* @return DEVICE_OK
*/
int8_t RC_CAN_GetRemoteStatus(const RC_CAN_t *rc_can, bool *remote_online,
bool *data_valid, uint32_t *timestamp);
/**
* @brief
* @param rc_can RC_CAN结构体指针
* @param data_type (0:, 1:, 2:, 3:, 4:)
* @return true false
*/
bool RC_CAN_IsDataUpdated(RC_CAN_t *rc_can, uint8_t data_type);
/**
* @brief
* @param rc_can RC_CAN结构体指针
* @return true false
*/
bool RC_CAN_IsDataTimeout(const RC_CAN_t *rc_can);
/* USER FUNCTION BEGIN */
/* USER FUNCTION END */

View File

@ -21,22 +21,22 @@ Config_RobotParam_t robot_config = {
.shoot_param = {
.trig_step_angle=M_2PI/8,
.fric_motor_param[0] = {
.can = BSP_CAN_1,
.id = 0x205,
.module = MOTOR_M3508,
.reverse = false,
.gear=false,
},
.fric_motor_param[1] = {
.can = BSP_CAN_1,
.id = 0x206,
.can = BSP_CAN_2,
.id = 0x201,
.module = MOTOR_M3508,
.reverse = true,
.gear=false,
},
.fric_motor_param[1] = {
.can = BSP_CAN_2,
.id = 0x202,
.module = MOTOR_M3508,
.reverse = false,
.gear=false,
},
.trig_motor_param = {
.can = BSP_CAN_1,
.id = 0x202,
.id = 0x201,
.module = MOTOR_M2006,
.reverse = false,
.gear=true,
@ -80,7 +80,6 @@ Config_RobotParam_t robot_config = {
.out = 30.0f,
},
}
};
/* Private function prototypes ---------------------------------------------- */

View File

@ -115,7 +115,9 @@ int8_t Shoot_Control(Shoot_t *c, const Shoot_CMD_t *cmd)
case SHOOT_STATE_READY:/*准备射击*/
for(int i=0;i<SHOOT_FRIC_NUM;i++)
{ /* 计算跟随输出->计算修正输出->加和、滤波、输出 */
c->output.out_follow[i]=PID_Calc(&c->pid.fric_follow[i],c->target_variable.target_rpm/MAX_FRIC_RPM,c->feedback.fric_rpm[i],0,c->dt);
// c->output.out_follow[i]=PID_Calc(&c->pid.fric_follow[i],c->target_variable.target_rpm/MAX_FRIC_RPM,c->feedback.fric_rpm[i],0,c->dt);
c->output.out_follow[i]=PID_Calc(&c->pid.fric_follow[i],3000.0f/MAX_FRIC_RPM,c->feedback.fric_rpm[i],0,c->dt);
c->output.out_err[i]=PID_Calc(&c->pid.fric_err[i],c->feedback.fric_avgrpm,c->feedback.fric_rpm[i],0,c->dt);
ScaleSumTo1(&c->output.out_follow[i], &c->output.out_err[i]);
c->output.out_fric[i]=c->output.out_follow[i]+c->output.out_err[i];
@ -138,7 +140,8 @@ int8_t Shoot_Control(Shoot_t *c, const Shoot_CMD_t *cmd)
// c->target_variable.target_angle+=c->param->trig_step_angle;
for(int i=0;i<SHOOT_FRIC_NUM;i++)
{
c->output.out_follow[i]=PID_Calc(&c->pid.fric_follow[i],c->target_variable.target_rpm/MAX_FRIC_RPM,c->feedback.fric_rpm[i],0,c->dt);
// c->output.out_follow[i]=PID_Calc(&c->pid.fric_follow[i],c->target_variable.target_rpm/MAX_FRIC_RPM,c->feedback.fric_rpm[i],0,c->dt);
c->output.out_follow[i]=PID_Calc(&c->pid.fric_follow[i],3000.0f/MAX_FRIC_RPM,c->feedback.fric_rpm[i],0,c->dt);
c->output.out_err[i]=PID_Calc(&c->pid.fric_err[i],c->feedback.fric_avgrpm,c->feedback.fric_rpm[i],0,c->dt);
ScaleSumTo1(&c->output.out_follow[i], &c->output.out_err[i]);
c->output.out_fric[i]=c->output.out_follow[i]+c->output.out_err[i];

View File

@ -6,6 +6,10 @@
/* Includes ----------------------------------------------------------------- */
#include "task/user_task.h"
/* USER INCLUDE BEGIN */
#include "bsp/pwm.h"
#include "component/ahrs.h"
#include "component/pid.h"
#include "device/bmi088.h"
/* USER INCLUDE END */
@ -14,7 +18,17 @@
/* Private macro ------------------------------------------------------------ */
/* Private variables -------------------------------------------------------- */
/* USER STRUCT BEGIN */
BMI088_t bmi088;
AHRS_t gimbal_ahrs;
AHRS_Magn_t magn;
AHRS_Eulr_t eulr_to_send;
KPID_t imu_temp_ctrl_pid;
BMI088_Cali_t cali_bmi088= {
.gyro_offset = {0.0f,0.0f,0.0f},
};
/* USER STRUCT END */
/* Private function --------------------------------------------------------- */
@ -26,11 +40,33 @@ void Task_atti_esti(void *argument) {
osDelay(ATTI_ESTI_INIT_DELAY); /* 延时一段时间再开启任务 */
/* USER CODE INIT BEGIN */
BMI088_Init(&bmi088,&cali_bmi088);
AHRS_Init(&gimbal_ahrs, &magn, BMI088_GetUpdateFreq(&bmi088));
/* USER CODE INIT END */
while (1) {
/* USER CODE BEGIN */
BMI088_WaitNew();
BMI088_AcclStartDmaRecv();
BMI088_AcclWaitDmaCplt();
BMI088_GyroStartDmaRecv();
BMI088_GyroWaitDmaCplt();
/* 锁住RTOS内核防止数据解析过程中断造成错误 */
osKernelLock();
/* 接收完所有数据后,把数据从原始字节加工成方便计算的数据 */
BMI088_ParseAccl(&bmi088);
BMI088_ParseGyro(&bmi088);
// IST8310_Parse(&ist8310);
/* 根据设备接收到的数据进行姿态解析 */
AHRS_Update(&gimbal_ahrs, &bmi088.accl, &bmi088.gyro, &magn);
/* 根据解析出来的四元数计算欧拉角 */
AHRS_GetEulr(&eulr_to_send, &gimbal_ahrs);
osKernelUnlock();
/* USER CODE END */
}

View File

@ -43,15 +43,15 @@ void Task_rc(void *argument) {
}
for_shoot.online = dr16.header.online;
switch (dr16.data.sw_r) {
case CMD_SW_UP:
case DR16_SW_UP:
for_shoot.ready = false;
for_shoot.firecmd = false;
break;
case CMD_SW_MID:
case DR16_SW_MID:
for_shoot.ready = true;
for_shoot.firecmd = false;
break;
case CMD_SW_DOWN:
case DR16_SW_DOWN:
for_shoot.ready = true;
for_shoot.firecmd = true;
break;