添加文件1和文件2

This commit is contained in:
2025-11-27 20:08:38 +08:00
parent 5d4099938c
commit edc427c423
1675 changed files with 1068907 additions and 2830 deletions

View File

@@ -0,0 +1,33 @@
#ifndef __CToC_H
#define __CToC_H
#include "main.h"
#include "M3508.h"
#define CToC_MasterID1 0x019//ID1
#define CToC_SlaveID1 0x149//ID1
#define CToC_SlaveID2 0x189//ID2
//<2F>жϻص<CFBB><D8B5><EFBFBD><EFBFBD><EFBFBD>
//<2F>жϽ<D0B6><CFBD>ܶ<EFBFBD><DCB6><EFBFBD><EFBFBD><EFBFBD>ID-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>-<2D><><EFBFBD>ɽ<EFBFBD><C9BD><EFBFBD>-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݰ<EFBFBD>
//motor_chassis<69><73>motor_measure_t <20><><EFBFBD>͵<EFBFBD><CDB5><EFBFBD><EFBFBD><EFBFBD><E9A3AC><EFBFBD><EFBFBD>װ<EFBFBD>е<EFBFBD><D0B5><EFBFBD>ת<EFBFBD>ӽǶȣ<C7B6><C8A3><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>ת<EFBFBD>٣<EFBFBD><D9A3><EFBFBD><EFBFBD>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD><EFBFBD><E5BAAF>
#define get_motor_measure(ptr, data) \
{ \
(ptr)->last_ecd = (ptr)->ecd; \
(ptr)->ecd = (uint16_t)((data)[0] << 8 | (data)[1]); \
(ptr)->speed_rpm = (uint16_t)((data)[2] << 8 | (data)[3]); \
(ptr)->given_current = (uint16_t)((data)[4] << 8 | (data)[5]); \
(ptr)->temperate = (data)[6]; \
}
extern uint8_t CToC_SlaveSendRefereeSystemData(void);
extern void can_filter_init(void);
extern void CToC_CANDataProcess(uint32_t ID,uint8_t *Data);
extern void Update_Motor_Measure(uint8_t motor_id, motor_measure_t* measure);
extern void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan);
#endif

View File

@@ -0,0 +1,42 @@
#ifndef __M3508_H
#define __M3508_H
#include "main.h"
#include "PID.h"
// <20><><EFBFBD>̲<EFBFBD><CCB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ʻ<EFBFBD>е<EFBFBD><EFBFBD><E1B9B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#define WHEEL_RADIUS 0.075f// <20><><EFBFBD>Ӱ뾶 (<28><>)
#define WHEELBASE_WIDTH 0.21f // <20>־<EFBFBD><D6BE><EFBFBD><EFBFBD><EFBFBD>/2 (<28><>)
#define WHEELBASE_LENGTH 0.17f // <20>־೤<D6BE><E0B3A4>/2 (<28><>)
typedef struct
{
uint16_t ecd;//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ -16384--+16384
int16_t speed_rpm;//ת<><D7AA> תÿ<D7AA><C3BF><EFBFBD><EFBFBD>
int16_t given_current;//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
uint8_t temperate;//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int16_t last_ecd;//<2F>ϴα<CFB4><CEB1><EFBFBD><EFBFBD><EFBFBD>ֵ
} motor_measure_t;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƽ<C6BD><E1B9B9>
typedef struct {
motor_measure_t measure; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD>ٶȵ<D9B6>λ<EFBFBD><CEBB>RPM<50><4D>
PID_Controller_t speed_pid; // <20>ٶȻ<D9B6>PID
float target_speed; // Ŀ<><C4BF><EFBFBD>ٶ<EFBFBD> (rad/s)
} Motor_Controller_t;
extern motor_measure_t motor_chassis[4];
extern Motor_Controller_t motor_controller[4];
extern int16_t motor_commands[4];
extern void CAN_cmd_chassis(int16_t motor1, int16_t motor2, int16_t motor3, int16_t motor4);
extern float RPM_To_RadPerSec(int16_t rpm);
extern int16_t RadPerSec_To_RPM(float rad_per_sec);
extern void Set_Motor_Target_Speed(uint8_t motor_id, float target_speed_rad_s);
extern void Motor_Speed_Control_Task(float dt);
extern void Drive_Motor(float vx, float vy, float vz);
extern float Map_Remote_to_Speed(int16_t input, float max_speed);
extern void Process_Remote_Control(void);
#endif

View File

@@ -0,0 +1,9 @@
#ifndef __RefreeSystem_H
#define __RefreeSystem_H
#include "main.h"
extern uint8_t RefereeSystem_Status;
extern uint8_t RefereeSystem_ShooterStatus;
#endif

View File

@@ -0,0 +1,39 @@
#ifndef __Remote_H
#define __Remote_H
#include "main.h"
typedef struct
{
uint16_t Remote_R_RL;
uint16_t Remote_R_UD;
uint16_t Remote_L_RL;
uint16_t Remote_L_UD;
uint8_t Remote_LS;
uint8_t Remote_RS;
int16_t Remote_Mouse_RL;
int16_t Remote_Mouse_DU;
int16_t Remote_Mouse_Wheel;
uint8_t Remote_Mouse_KeyL;
uint8_t Remote_Mouse_KeyR;
uint8_t Remote_Key_W;
uint8_t Remote_Key_S;
uint8_t Remote_Key_A;
uint8_t Remote_Key_D;
uint8_t Remote_Key_Q;
uint8_t Remote_Key_E;
uint8_t Remote_Key_Shift;
uint8_t Remote_Key_Ctrl;
uint8_t Remote_KeyPush_Ctrl;
uint8_t Remote_KeyPush_Shift;
int16_t Remote_ThumbWheel;
}Remote_Data;
extern Remote_Data Remote_RxData;
extern uint8_t Remote_Status;
extern uint8_t Remote_StartFlag;
#endif

View File

@@ -34,11 +34,14 @@ extern "C" {
extern CAN_HandleTypeDef hcan1;
extern CAN_HandleTypeDef hcan2;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_CAN1_Init(void);
void MX_CAN2_Init(void);
/* USER CODE BEGIN Prototypes */

View File

@@ -1,52 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file dma.h
* @brief This file contains all the function prototypes for
* the dma.c file
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __DMA_H__
#define __DMA_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* DMA memory to memory transfer handles -------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_DMA_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __DMA_H__ */

View File

@@ -60,33 +60,8 @@ void Error_Handler(void);
/* Private defines -----------------------------------------------------------*/
/* USER CODE BEGIN Private defines */
#define DBUS_MAX_LEN (50)
#define DBUS_BUFLEN (18)
#define DBUS_HUART huart3
typedef __packed struct
{
int16_t ch0;
int16_t ch1;
int16_t ch2;
int16_t ch3;
int16_t roll;
uint8_t sw1;
uint8_t sw2;
} rc_info_t;
#define rc_Init \
{ \
0, \
0, \
0, \
0, \
0, \
0, \
0, \
}
void uart_receive_handler(UART_HandleTypeDef *huart);
void dbus_uart_init(void);
void rc_callback_handler(rc_info_t *rc, uint8_t *buff);
/* USER CODE END Private defines */

View File

@@ -0,0 +1,22 @@
#ifndef __PID_H
#define __PID_H
#include "main.h"
typedef struct {
float kp; // ????
float ki; // ????
float kd; // ????
float integral; // ???
float prev_error; // ?????
float output; // ???
float integral_limit; // ????
float output_limit; // ????
} PID_Controller_t;
extern void PID_Init(PID_Controller_t* pid, float kp, float ki, float kd, float integral_limit, float output_limit);
extern float PID_Calculate(PID_Controller_t* pid, float error, float dt);
extern void Motor_PID_Init();
extern void PID_PositionClean(PID_Controller_t* pid);
#endif

View File

@@ -64,7 +64,7 @@
/* #define HAL_MMC_MODULE_ENABLED */
/* #define HAL_SPI_MODULE_ENABLED */
/* #define HAL_TIM_MODULE_ENABLED */
#define HAL_UART_MODULE_ENABLED
/* #define HAL_UART_MODULE_ENABLED */
/* #define HAL_USART_MODULE_ENABLED */
/* #define HAL_IRDA_MODULE_ENABLED */
/* #define HAL_SMARTCARD_MODULE_ENABLED */

View File

@@ -55,9 +55,8 @@ void SVC_Handler(void);
void DebugMon_Handler(void);
void PendSV_Handler(void);
void SysTick_Handler(void);
void DMA1_Stream1_IRQHandler(void);
void CAN1_RX0_IRQHandler(void);
void USART3_IRQHandler(void);
void CAN2_RX0_IRQHandler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */

View File

@@ -1,52 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file usart.h
* @brief This file contains all the function prototypes for
* the usart.c file
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USART_H__
#define __USART_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern UART_HandleTypeDef huart3;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_USART3_UART_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __USART_H__ */

View File

@@ -0,0 +1,149 @@
#include "main.h"
#include "can.h"
#include "gpio.h"
#include "CToC.h"
#include "RefreeSystem.h"
#include "Remote.h"
#include "M3508.h"
static CAN_TxHeaderTypeDef TxMessage;
static uint8_t DATE_CAIPAN[8];
uint8_t CToC_SlaveSendRefereeSystemData(void)
{
uint32_t send_mail_box;
TxMessage.StdId=CToC_MasterID1;
TxMessage.IDE = CAN_ID_STD;
TxMessage.RTR = CAN_RTR_DATA;
TxMessage.DLC=0x08;
DATE_CAIPAN[0]=RefereeSystem_ShooterStatus;
DATE_CAIPAN[1]=0;
DATE_CAIPAN[2]=0;
DATE_CAIPAN[3]=0;
DATE_CAIPAN[4]=0;
DATE_CAIPAN[5]=0;
DATE_CAIPAN[6]=0;
DATE_CAIPAN[7]=0;
HAL_StatusTypeDef status = HAL_CAN_AddTxMessage(&hcan2, &TxMessage,DATE_CAIPAN, &send_mail_box);
if (status != HAL_OK) {
return 0;
}
uint16_t i = 0;
while ((HAL_CAN_IsTxMessagePending(&hcan2, send_mail_box)) && (i < 0xFFF)) {
i++;
}
if (i >= 0xFFF) {
return 0;
}
return 1;
}
void can_filter_init(void)
{
CAN_FilterTypeDef can_filter_st;
// ==================== CAN1 ?? ====================
// CAN1??ID
can_filter_st.FilterActivation = ENABLE;
can_filter_st.FilterMode = CAN_FILTERMODE_IDMASK;
can_filter_st.FilterScale = CAN_FILTERSCALE_32BIT;
can_filter_st.FilterIdHigh = 0x0000; // ??ID
can_filter_st.FilterIdLow = 0x0000;
can_filter_st.FilterMaskIdHigh = 0x0000;
can_filter_st.FilterMaskIdLow = 0x0007; // ??ID
can_filter_st.FilterBank = 0;
can_filter_st.FilterFIFOAssignment = CAN_RX_FIFO0;
can_filter_st.SlaveStartFilterBank = 14; // CAN2??14???
HAL_CAN_ConfigFilter(&hcan1, &can_filter_st);
HAL_CAN_Start(&hcan1);
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
// ==================== CAN2 ?? ====================
// CAN2??ID 0x200-0x207???
can_filter_st.FilterIdHigh = 0; // ?????ID
can_filter_st.FilterIdLow = 0; // ?????ID
can_filter_st.FilterMaskIdHigh = 0; // ???????ID
can_filter_st.FilterMaskIdLow = 0; // ???????ID
can_filter_st.FilterBank = 14; // CAN2??????14
can_filter_st.FilterFIFOAssignment = CAN_RX_FIFO0;
HAL_CAN_ConfigFilter(&hcan2, &can_filter_st);
HAL_CAN_Start(&hcan2);
HAL_CAN_ActivateNotification(&hcan2, CAN_IT_RX_FIFO0_MSG_PENDING);
}
Remote_Data Remote_RxData;
void CToC_CANDataProcess(uint32_t ID,uint8_t *Data)
{
if(ID==CToC_SlaveID1)//?????????
{
Remote_RxData.Remote_R_RL=(uint16_t)((uint16_t)Data[0]<<8 | Data[1]);//?????
Remote_RxData.Remote_R_UD=(uint16_t)((uint16_t)Data[2]<<8 | Data[3]);//?????
Remote_RxData.Remote_L_RL=(uint16_t)((uint16_t)Data[4]<<8 | Data[5]);//?????
Remote_RxData.Remote_L_UD=(uint16_t)((uint16_t)Data[6]<<8 | Data[7]);//?????
}
else if(ID==CToC_SlaveID2)//?????????
{
Remote_Status=Data[0];//???????
Remote_RxData.Remote_RS=Data[1];//?????????
Remote_RxData.Remote_KeyPush_Ctrl=Data[2];//??Ctrl??
Remote_RxData.Remote_KeyPush_Shift=Data[3];//??Shift??
Remote_StartFlag=Data[4];//????????
Remote_RxData.Remote_LS=Data[5];//?????????
}
}
/**
* @brief <20><><EFBFBD>µ<EFBFBD><C2B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD><DDB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param motor_id: <20><><EFBFBD><EFBFBD>ID (0-3)
* @param measure: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
*/
void Update_Motor_Measure(uint8_t motor_id, motor_measure_t* measure)
{
if (motor_id < 4) {
// ֱ<>ӽṹ<D3BD>帳ֵ<E5B8B3><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
motor_controller[motor_id].measure = *measure;
}
}
//can<61><6E><EFBFBD>ز<EFBFBD><D8B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E5B6A8>
// CAN2<4E><32><EFBFBD>ջص<D5BB><D8B5><EFBFBD><EFBFBD><EFBFBD>
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
CAN_RxHeaderTypeDef rx_header;
uint8_t rx_data[8];
HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rx_header, rx_data);
// <20>ж<EFBFBD><D0B6><EFBFBD>CAN1<4E><31><EFBFBD><EFBFBD>CAN2
if (hcan->Instance == CAN1) {
// CAN1<4E><31><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (ID 1-4)
switch (rx_header.StdId) {
case 1: case 2: case 3: case 4: {
static uint8_t i = 0;
i = rx_header.StdId - 1;
get_motor_measure(&motor_chassis[i], rx_data);
Update_Motor_Measure(i, &motor_chassis[i]);
break;
}
default:
break;
}
}
else if (hcan->Instance == CAN2) {
// CAN2<4E><32><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
CToC_CANDataProcess(rx_header.StdId, rx_data);
}
}
//HAL<41><4C><EFBFBD><EFBFBD><EFBFBD>պ<EFBFBD><D5BA><EFBFBD>HAL_CAN_GetRxMessage
HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo, CAN_RxHeaderTypeDef *pHeader, uint8_t aData[]);

View File

@@ -0,0 +1,170 @@
#include "main.h"
#include "M3508.h"
#include "can.h"
#include "gpio.h"
#include <string.h>
#include <stdlib.h>
#include <math.h> // <20><><EFBFBD><EFBFBD>isnan<61><6E>isinf<6E><66><EFBFBD><EFBFBD>
#include "PID.h"
#include "Remote.h"
#include "CToC.h"
// <20>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD>
Motor_Controller_t motor_controller[4] = {0};
// <20><EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int16_t motor_commands[4] = {0};
motor_measure_t motor_chassis[4] = {0};
static CAN_TxHeaderTypeDef chassis_tx_message;
static uint8_t chassis_can_send_data[8];
void CAN_cmd_chassis(int16_t motor1, int16_t motor2, int16_t motor3, int16_t motor4)
{
uint32_t send_mail_box;
chassis_tx_message.StdId = 0x200;
chassis_tx_message.IDE = CAN_ID_STD;
chassis_tx_message.RTR = CAN_RTR_DATA;
chassis_tx_message.DLC = 0x08;
chassis_can_send_data[0] = motor1 >> 8;
chassis_can_send_data[1] = motor1;
chassis_can_send_data[2] = motor2 >> 8;
chassis_can_send_data[3] = motor2;
chassis_can_send_data[4] = motor3 >> 8;
chassis_can_send_data[5] = motor3;
chassis_can_send_data[6] = motor4 >> 8;
chassis_can_send_data[7] = motor4;
HAL_CAN_AddTxMessage(&hcan1, &chassis_tx_message,
chassis_can_send_data, &send_mail_box);
}
/**
* @brief <20><>RPMת<4D><D7AA>Ϊrad/s
*/
float RPM_To_RadPerSec(int16_t rpm)
{
return (float)rpm * 2.0f * 3.1415926535f / 60.0f;
}
/**
* @brief <20><>rad/sת<73><D7AA>ΪRPM
*/
int16_t RadPerSec_To_RPM(float rad_per_sec)
{
return (int16_t)(rad_per_sec * 60.0f / (2.0f * 3.1415926535f));
}
/**
* @brief <20><><EFBFBD>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD>ٶ<EFBFBD>
* @param motor_id: <20><><EFBFBD><EFBFBD>ID (0-3)
* @param target_speed_rad_s: Ŀ<><C4BF><EFBFBD>ٶ<EFBFBD> (rad/s)
*/
void Set_Motor_Target_Speed(uint8_t motor_id, float target_speed_rad_s)
{
if (motor_id < 4) {
motor_controller[motor_id].target_speed = target_speed_rad_s;
}
}
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD>ٶȿ<D9B6><C8BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>񣨴<EFBFBD><F1A3A8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><D6A4>
*/
void Motor_Speed_Control_Task(float dt)
{
for (int i = 0; i < 4; i++) {
// <20><>֤<EFBFBD><D6A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (isnan(motor_controller[i].measure.speed_rpm) ||
motor_controller[i].measure.speed_rpm > 10000 ||
motor_controller[i].measure.speed_rpm < -10000) {
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><ECB3A3>ʹ<EFBFBD><CAB9>Ĭ<EFBFBD><C4AC>ֵ
motor_controller[i].measure.speed_rpm = 0;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>RPMת<4D><D7AA>Ϊrad/s
float actual_speed_rads = RPM_To_RadPerSec(motor_controller[i].measure.speed_rpm);
// <20><>֤ת<D6A4><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (isnan(actual_speed_rads) || isinf(actual_speed_rads)) {
actual_speed_rads = 0.0f;
}
// <20><><EFBFBD><EFBFBD><EFBFBD>ٶ<EFBFBD><D9B6><EFBFBD><EFBFBD><EFBFBD>
float speed_error = motor_controller[i].target_speed - actual_speed_rads;
// <20><>֤<EFBFBD><D6A4><EFBFBD><EFBFBD>ֵ
if (isnan(speed_error) || isinf(speed_error)) {
speed_error = 0.0f;
}
// PID<49><44><EFBFBD><EFBFBD>
float pid_output = PID_Calculate(&motor_controller[i].speed_pid, speed_error, dt);
// <20><>֤PID<49><44><EFBFBD><EFBFBD>
if (isnan(pid_output) || isinf(pid_output)) {
pid_output = 0.0f;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>PID״̬
PID_PositionClean(&motor_controller[i].speed_pid);
}
// <20><EFBFBD><E6B4A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
motor_commands[i] = (int16_t)pid_output;
}
}
/**
* @brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><C4B7><EFBFBD>ٶȽ<D9B6><C8BD><EFBFBD><E3BAAF>
* @param vx: X<><58><EFBFBD><EFBFBD><EFBFBD>ٶ<EFBFBD> (m/s) - <20><><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param vy: Y<><59><EFBFBD><EFBFBD><EFBFBD>ٶ<EFBFBD> (m/s) - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD><C6A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param vz: <20><>ת<EFBFBD><D7AA><EFBFBD>ٶ<EFBFBD> (rad/s) - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EBA3AC><EFBFBD><EFBFBD>˳ʱ<CBB3><CAB1>
*/
void Drive_Motor(float vx, float vy, float vz)
{
float A = WHEELBASE_WIDTH + WHEELBASE_LENGTH;
// <20><>׼<EFBFBD><D7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><C4B7><EFBFBD>˶<EFBFBD>ѧ<EFBFBD><D1A7><EFBFBD><EFBFBD><EFBFBD>ʽ
// <20><><EFBFBD>ӱ<EFBFBD><D3B1>ţ<EFBFBD>0-<2D><><EFBFBD><EFBFBD>, 1-<2D><><EFBFBD><EFBFBD>, 2-<2D><><EFBFBD><EFBFBD>, 3-<2D><><EFBFBD><EFBFBD>
// <20><>׼<EFBFBD><D7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><C4B7><EFBFBD>˶<EFBFBD>ѧ<EFBFBD><D1A7><EFBFBD><EFBFBD><EFBFBD>ʽ
float wheel1_speed = ( vx +vy + vz * A ) / WHEEL_RADIUS; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
float wheel2_speed = ( vx - vy + vz * A ) / WHEEL_RADIUS; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
float wheel3_speed = (-vx -vy + vz * A ) / WHEEL_RADIUS; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
float wheel4_speed = (-vx +vy +vz * A ) / WHEEL_RADIUS; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Set_Motor_Target_Speed(0, wheel1_speed); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Set_Motor_Target_Speed(1, wheel2_speed); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Set_Motor_Target_Speed(2, wheel3_speed); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Set_Motor_Target_Speed(3, wheel4_speed); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
float Map_Remote_to_Speed(int16_t input, float max_speed)
{
if (input > 660) input = 660;
if (input < -660) input = -660;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD>0
if (abs(input) < 50) {
return 0.0f;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٶ<EFBFBD>
return (input / 660.0f) * max_speed;
}
/**
* @brief <20><><EFBFBD><EFBFBD>ң<EFBFBD><D2A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݲ<EFBFBD><DDB2><EFBFBD><EFBFBD>õ<EFBFBD><C3B5><EFBFBD><EFBFBD>ٶ<EFBFBD>
*/
void Process_Remote_Control(void)
{
// ӳ<><D3B3>ң<EFBFBD><D2A3><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD>ٶ<EFBFBD> (m/s)
float vx = Map_Remote_to_Speed(Remote_RxData.Remote_L_UD,2.0f); // ǰ<><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2m/s
float vy = Map_Remote_to_Speed(Remote_RxData.Remote_L_RL, 2.0f); // <20><><EFBFBD>ҷ<EFBFBD><D2B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2m/s
float vz = Map_Remote_to_Speed(Remote_RxData.Remote_R_RL, 3.0f); // <20><>ת<EFBFBD><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>3rad/s
// <20><><EFBFBD><EFBFBD><EFBFBD>˶<EFBFBD>ѧ<EFBFBD><D1A7><EFBFBD><EFBFBD>
Drive_Motor(vx, vy, vz);
}

View File

@@ -0,0 +1,119 @@
#include "PID.h"
#include "main.h"
#include "M3508.h"
#include <math.h> // <20><><EFBFBD><EFBFBD>isnan<61><6E>isinf<6E><66><EFBFBD><EFBFBD>
#include "Remote.h"
#include "CToC.h"
/**
* @brief PID<49><44><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>
*/
void PID_Init(PID_Controller_t* pid, float kp, float ki, float kd, float integral_limit, float output_limit)
{
pid->kp = kp;
pid->ki = ki;
pid->kd = kd;
pid->integral = 0.0f;
pid->prev_error = 0.0f;
pid->output = 0.0f;
pid->integral_limit = integral_limit;
pid->output_limit = output_limit;
}
/**
* @brief PID<49><44><EFBFBD><EFBFBD><E3BAAF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
float PID_Calculate(PID_Controller_t* pid, float error, float dt)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7>
if (dt <= 0.0f || dt > 1.0f) {
dt = 0.01f; // ʹ<><CAB9>Ĭ<EFBFBD><C4AC>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
// <20><><EFBFBD><EFBFBD>error<6F>Ƿ<EFBFBD>ΪNaN<61><4E><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (isnan(error) || isinf(error)) {
error = 0.0f;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
float proportional = pid->kp * error;
// <20><><EFBFBD><EFBFBD>proportional<61>Ƿ<EFBFBD>ΪNaN
if (isnan(proportional) || isinf(proportional)) {
proportional = 0.0f;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EEA3A8><EFBFBD>޷<EFBFBD><DEB7><EFBFBD>
pid->integral += error * dt;
if (pid->integral > pid->integral_limit) {
pid->integral = pid->integral_limit;
} else if (pid->integral < -pid->integral_limit) {
pid->integral = -pid->integral_limit;
}
float integral = pid->ki * pid->integral;
// <20><><EFBFBD><EFBFBD>integral<61>Ƿ<EFBFBD>ΪNaN
if (isnan(integral) || isinf(integral)) {
integral = 0.0f;
pid->integral = 0.0f;
}
// ΢<><CEA2><EFBFBD><EFBFBD><EEA3A8><EFBFBD><EFBFBD>dt<64><74><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
float derivative = 0.0f;
if (dt > 0.001f) { // ȷ<><C8B7>dt<64><EFBFBD>󣬱<EFBFBD><F3A3ACB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ժ<EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD>
derivative = pid->kd * (error - pid->prev_error) / dt;
}
// <20><><EFBFBD><EFBFBD>derivative<76>Ƿ<EFBFBD>ΪNaN
if (isnan(derivative) || isinf(derivative)) {
derivative = 0.0f;
}
pid->prev_error = error;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
pid->output = proportional + integral + derivative;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD>ΪNaN
if (isnan(pid->output) || isinf(pid->output)) {
pid->output = 0.0f;
// <20><><EFBFBD><EFBFBD>PID״̬
pid->integral = 0.0f;
pid->prev_error = 0.0f;
}
// <20><><EFBFBD><EFBFBD><EFBFBD>޷<EFBFBD>
if (pid->output > pid->output_limit) {
pid->output = pid->output_limit;
} else if (pid->output < -pid->output_limit) {
pid->output = -pid->output_limit;
}
return pid->output;
}
/**
* @brief <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD>PID<49><44><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
void Motor_PID_Init(void)
{
// PID<49><44><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>ʵ<EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD>
float speed_kp = 400.0f; // <20>ٶȻ<D9B6><C8BB><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5>
float speed_ki = 0.05f; // <20>ٶȻ<D9B6><C8BB><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5>
float speed_kd = 300.0f; // <20>ٶȻ<D9B6>΢<EFBFBD><CEA2>ϵ<EFBFBD><CFB5>
for (int i = 0; i < 4; i++) {
PID_Init(&motor_controller[i].speed_pid, speed_kp, speed_ki, speed_kd, 3000.0f, 3000.0f);
}
}
/*
*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><><CEBB>ʽPID<49><44><EFBFBD><EFBFBD>
*<2A><><EFBFBD><EFBFBD>˵<EFBFBD><CBB5><><CEBB>ʽPID<49><44><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E1B9B9>
*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:<3A><>
*<2A><>ע:<3A><><EFBFBD><EFBFBD>PID<49>ڲ<EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<C4A3>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD><ECB3A3><EFBFBD><EFBFBD>
*/
void PID_PositionClean(PID_Controller_t* pid)
{
pid->integral = 0.0f; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EEA3AC>ֹ<EFBFBD><D6B9><EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD>
pid->prev_error = 0.0f; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EEA3AC>ֹ΢<D6B9>ֳ<EFBFBD><D6B3><EFBFBD>
pid->output = 0.0f; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
}

View File

@@ -0,0 +1,5 @@
#include "RefreeSystem.h"
#include "main.h"
uint8_t RefereeSystem_Status =0;
uint8_t RefereeSystem_ShooterStatus=1;

View File

@@ -0,0 +1,4 @@
#include "main.h"
#include "Remote.h"
uint8_t Remote_Status;
uint8_t Remote_StartFlag=1;

View File

@@ -25,6 +25,7 @@
/* USER CODE END 0 */
CAN_HandleTypeDef hcan1;
CAN_HandleTypeDef hcan2;
/* CAN1 init function */
void MX_CAN1_Init(void)
@@ -58,6 +59,40 @@ void MX_CAN1_Init(void)
/* USER CODE END CAN1_Init 2 */
}
/* CAN2 init function */
void MX_CAN2_Init(void)
{
/* USER CODE BEGIN CAN2_Init 0 */
/* USER CODE END CAN2_Init 0 */
/* USER CODE BEGIN CAN2_Init 1 */
/* USER CODE END CAN2_Init 1 */
hcan2.Instance = CAN2;
hcan2.Init.Prescaler = 3;
hcan2.Init.Mode = CAN_MODE_NORMAL;
hcan2.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan2.Init.TimeSeg1 = CAN_BS1_10TQ;
hcan2.Init.TimeSeg2 = CAN_BS2_3TQ;
hcan2.Init.TimeTriggeredMode = DISABLE;
hcan2.Init.AutoBusOff = DISABLE;
hcan2.Init.AutoWakeUp = DISABLE;
hcan2.Init.AutoRetransmission = DISABLE;
hcan2.Init.ReceiveFifoLocked = DISABLE;
hcan2.Init.TransmitFifoPriority = DISABLE;
if (HAL_CAN_Init(&hcan2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN CAN2_Init 2 */
/* USER CODE END CAN2_Init 2 */
}
static uint32_t HAL_RCC_CAN1_CLK_ENABLED=0;
void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle)
{
@@ -69,7 +104,10 @@ void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle)
/* USER CODE END CAN1_MspInit 0 */
/* CAN1 clock enable */
__HAL_RCC_CAN1_CLK_ENABLE();
HAL_RCC_CAN1_CLK_ENABLED++;
if(HAL_RCC_CAN1_CLK_ENABLED==1){
__HAL_RCC_CAN1_CLK_ENABLE();
}
__HAL_RCC_GPIOD_CLK_ENABLE();
/**CAN1 GPIO Configuration
@@ -90,6 +128,37 @@ void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle)
/* USER CODE END CAN1_MspInit 1 */
}
else if(canHandle->Instance==CAN2)
{
/* USER CODE BEGIN CAN2_MspInit 0 */
/* USER CODE END CAN2_MspInit 0 */
/* CAN2 clock enable */
__HAL_RCC_CAN2_CLK_ENABLE();
HAL_RCC_CAN1_CLK_ENABLED++;
if(HAL_RCC_CAN1_CLK_ENABLED==1){
__HAL_RCC_CAN1_CLK_ENABLE();
}
__HAL_RCC_GPIOB_CLK_ENABLE();
/**CAN2 GPIO Configuration
PB5 ------> CAN2_RX
PB6 ------> CAN2_TX
*/
GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_CAN2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* CAN2 interrupt Init */
HAL_NVIC_SetPriority(CAN2_RX0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(CAN2_RX0_IRQn);
/* USER CODE BEGIN CAN2_MspInit 1 */
/* USER CODE END CAN2_MspInit 1 */
}
}
void HAL_CAN_MspDeInit(CAN_HandleTypeDef* canHandle)
@@ -101,7 +170,10 @@ void HAL_CAN_MspDeInit(CAN_HandleTypeDef* canHandle)
/* USER CODE END CAN1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_CAN1_CLK_DISABLE();
HAL_RCC_CAN1_CLK_ENABLED--;
if(HAL_RCC_CAN1_CLK_ENABLED==0){
__HAL_RCC_CAN1_CLK_DISABLE();
}
/**CAN1 GPIO Configuration
PD0 ------> CAN1_RX
@@ -115,6 +187,30 @@ void HAL_CAN_MspDeInit(CAN_HandleTypeDef* canHandle)
/* USER CODE END CAN1_MspDeInit 1 */
}
else if(canHandle->Instance==CAN2)
{
/* USER CODE BEGIN CAN2_MspDeInit 0 */
/* USER CODE END CAN2_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_CAN2_CLK_DISABLE();
HAL_RCC_CAN1_CLK_ENABLED--;
if(HAL_RCC_CAN1_CLK_ENABLED==0){
__HAL_RCC_CAN1_CLK_DISABLE();
}
/**CAN2 GPIO Configuration
PB5 ------> CAN2_RX
PB6 ------> CAN2_TX
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_5|GPIO_PIN_6);
/* CAN2 interrupt Deinit */
HAL_NVIC_DisableIRQ(CAN2_RX0_IRQn);
/* USER CODE BEGIN CAN2_MspDeInit 1 */
/* USER CODE END CAN2_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */

View File

@@ -1,55 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file dma.c
* @brief This file provides code for the configuration
* of all the requested memory to memory DMA transfers.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "dma.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/*----------------------------------------------------------------------------*/
/* Configure DMA */
/*----------------------------------------------------------------------------*/
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/**
* Enable DMA controller clock
*/
void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Stream1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
}
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */

View File

@@ -45,9 +45,9 @@ void MX_GPIO_Init(void)
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
/*Configure GPIO pin Output Level */

View File

@@ -19,15 +19,16 @@
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "can.h"
#include "dma.h"
#include "usart.h"
#include "gpio.h"
#include "CToC.h"
#include "RefreeSystem.h"
#include "Remote.h"
#include "M3508.h"
#include "PID.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <string.h>
#include <stdlib.h>
#include <math.h> // 用于isnan、isinf函数
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
@@ -48,9 +49,7 @@
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
uint8_t dbus_buf[DBUS_BUFLEN];
rc_info_t rc = rc_Init;
extern UART_HandleTypeDef huart3;//遥控器
/* USER CODE END PV */
@@ -62,494 +61,6 @@ void SystemClock_Config(void);
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
static int uart_receive_dma_no_it(UART_HandleTypeDef* huart, uint8_t* pData, uint32_t Size)
{
uint32_t tmp1 = 0;
tmp1 = huart->RxState;
if (tmp1 == HAL_UART_STATE_READY)
{
if ((pData == NULL) || (Size == 0))
{
return HAL_ERROR;
}
huart->pRxBuffPtr = pData;
huart->RxXferSize = Size;
huart->ErrorCode = HAL_UART_ERROR_NONE;
HAL_DMA_Start(huart->hdmarx, (uint32_t)&huart->Instance->DR, (uint32_t)pData, Size);
SET_BIT(huart->Instance->CR3, USART_CR3_DMAR);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
void dbus_uart_init(void)
{
__HAL_UART_CLEAR_IDLEFLAG(&DBUS_HUART);
__HAL_UART_ENABLE_IT(&DBUS_HUART, UART_IT_IDLE);
uart_receive_dma_no_it(&DBUS_HUART, dbus_buf, DBUS_MAX_LEN);
}
void rc_callback_handler(rc_info_t *rc, uint8_t *buff)
{
rc->ch0 = (buff[0] | buff[1] << 8) & 0x07FF;
rc->ch0 -= 1024;
rc->ch1 = (buff[1] >> 3 | buff[2] << 5) & 0x07FF;
rc->ch1 -= 1024;
rc->ch2 = (buff[2] >> 6 | buff[3] << 2 | buff[4] << 10) & 0x07FF;
rc->ch2 -= 1024;
rc->ch3 = (buff[4] >> 1 | buff[5] << 7) & 0x07FF;
rc->ch3 -= 1024;
rc->roll = (buff[16] | (buff[17] << 8)) & 0x07FF;
rc->roll -= 1024;
rc->sw1 = ((buff[5] >> 4) & 0x000C) >> 2;
rc->sw2 = (buff[5] >> 4) & 0x0003;
// if ((abs(rc->ch0) > 660) || \
// (abs(rc->ch1) > 660) || \
// (abs(rc->ch2) > 660) || \
// (abs(rc->ch3) > 660))
//
// {
// memset(rc, 0, sizeof(rc_info_t));
// }
}
uint16_t dma_current_data_counter(DMA_Stream_TypeDef *dma_stream)
{
return ((uint16_t)(dma_stream->NDTR));
}
static void uart_rx_idle_callback(UART_HandleTypeDef* huart)
{
__HAL_UART_CLEAR_IDLEFLAG(huart);
if (huart == &DBUS_HUART)
{
__HAL_DMA_DISABLE(huart->hdmarx);
if ((DBUS_MAX_LEN - dma_current_data_counter(huart->hdmarx->Instance)) == DBUS_BUFLEN)
{
rc_callback_handler(&rc, dbus_buf);
}
__HAL_DMA_SET_COUNTER(huart->hdmarx, DBUS_MAX_LEN);
__HAL_DMA_ENABLE(huart->hdmarx);
}
}
void uart_receive_handler(UART_HandleTypeDef *huart)
{
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE) &&
__HAL_UART_GET_IT_SOURCE(huart, UART_IT_IDLE))
{
uart_rx_idle_callback(huart);
}
}//遥控器
typedef struct
{
uint16_t ecd;//编码器值 -16384--+16384
int16_t speed_rpm;//转速 转每分钟
int16_t given_current;//输出电流值
uint8_t temperate;//电机温度
int16_t last_ecd;//上次编码器值
} motor_measure_t;
motor_measure_t motor_chassis[4] = {0};
/**
* @brief 更新电机测量数据到控制器
* @param motor_id: 电机ID (0-3)
* @param measure: 电机测量数据指针
*/
static CAN_TxHeaderTypeDef chassis_tx_message;
static uint8_t chassis_can_send_data[8];
void CAN_cmd_chassis(int16_t motor1, int16_t motor2, int16_t motor3, int16_t motor4)
//can总线数据发送函数
//motor1-右上 motor2-左上 motor3-左下 motor4-右下
//以c板的正方向为基准
{
uint32_t send_mail_box;
chassis_tx_message.StdId = 0x200;
chassis_tx_message.IDE = CAN_ID_STD;
chassis_tx_message.RTR = CAN_RTR_DATA;
chassis_tx_message.DLC = 0x08;
chassis_can_send_data[0] = motor1 >> 8;
chassis_can_send_data[1] = motor1;
chassis_can_send_data[2] = motor2 >> 8;
chassis_can_send_data[3] = motor2;
chassis_can_send_data[4] = motor3 >> 8;
chassis_can_send_data[5] = motor3;
chassis_can_send_data[6] = motor4 >> 8;
chassis_can_send_data[7] = motor4;
HAL_CAN_AddTxMessage(&hcan1, &chassis_tx_message,
chassis_can_send_data, &send_mail_box);
}
//滤波器 只接受 ID 1-4 的电机
//此段后续可优化为列表模式
void can_filter_init(void)
{
CAN_FilterTypeDef can_filter_st;
can_filter_st.FilterActivation = ENABLE;
can_filter_st.FilterMode = CAN_FILTERMODE_IDMASK;
can_filter_st.FilterScale = CAN_FILTERSCALE_32BIT;
can_filter_st.FilterIdHigh = 0x0000;//高八位
can_filter_st.FilterIdLow = 0x0000;//低八位
can_filter_st.FilterMaskIdHigh = 0x0000;
can_filter_st.FilterMaskIdLow = 0x0007;
can_filter_st.FilterBank = 0;
can_filter_st.FilterFIFOAssignment = CAN_RX_FIFO0;
HAL_CAN_ConfigFilter(&hcan1, &can_filter_st);
HAL_CAN_Start(&hcan1);
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
can_filter_st.SlaveStartFilterBank = 14;
can_filter_st.FilterBank = 14;
HAL_CAN_ConfigFilter(&hcan1, &can_filter_st);
HAL_CAN_Start(&hcan1);
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
}
//过滤器笔记
//SlaveStartFilterBank参数只有在双CAN模式CAN1和CAN2下才需要如果只有CAN1可以不用设置
// PID控制器结构体
typedef struct {
float kp; // 比例系数
float ki; // 积分系数
float kd; // 微分系数
float integral; // 积分项
float prev_error; // 上一次误差
float output; // 输出值
float integral_limit; // 积分限幅
float output_limit; // 输出限幅
} PID_Controller_t;
// 电机控制结构体
typedef struct {
motor_measure_t measure; // 电机测量值速度单位RPM
PID_Controller_t speed_pid; // 速度环PID
float target_speed; // 目标速度 (rad/s)
} Motor_Controller_t;
// 四个电机的控制器
Motor_Controller_t motor_controller[4] = {0};
// 存储四个电机的控制命令
int16_t motor_commands[4] = {0};
// 底盘参数(根据实际机械结构调整)
#define WHEEL_RADIUS 0.075f// 轮子半径 (米)
#define WHEELBASE_WIDTH 0.21f // 轮距宽度/2 (米)
#define WHEELBASE_LENGTH 0.17f // 轮距长度/2 (米)
/**
* @brief 更新电机测量数据到控制器
* @param motor_id: 电机ID (0-3)
* @param measure: 电机测量数据指针
*/
void Update_Motor_Measure(uint8_t motor_id, motor_measure_t* measure)
{
if (motor_id < 4) {
// 直接结构体赋值(更简洁)
motor_controller[motor_id].measure = *measure;
}
}
//中断回调函数
//判断接受对象的ID-符合条件-完成解码-发送数据包
//motor_chassismotor_measure_t 类型的数组,其中装有电机转子角度,电机转子转速,控制电流,温度
//定义函数
#define get_motor_measure(ptr, data) \
{ \
(ptr)->last_ecd = (ptr)->ecd; \
(ptr)->ecd = (uint16_t)((data)[0] << 8 | (data)[1]); \
(ptr)->speed_rpm = (uint16_t)((data)[2] << 8 | (data)[3]); \
(ptr)->given_current = (uint16_t)((data)[4] << 8 | (data)[5]); \
(ptr)->temperate = (data)[6]; \
}
//can传回参数结构体定义
//回调函数
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
CAN_RxHeaderTypeDef rx_header;
uint8_t rx_data[8];
HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rx_header, rx_data);
switch (rx_header.StdId)
{
case 1:
case 2:
case 3:
case 4:
{
static uint8_t i = 0;
//读取电机ID
i = rx_header.StdId - 1;
get_motor_measure(&motor_chassis[i], rx_data);
Update_Motor_Measure(i, &motor_chassis[i]);
break;
}
default:
{
break;
}
}
}
//HAL库接收函数HAL_CAN_GetRxMessage
HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo, CAN_RxHeaderTypeDef *pHeader, uint8_t aData[]);
/**
* @brief 将RPM转换为rad/s
*/
float RPM_To_RadPerSec(int16_t rpm)
{
return (float)rpm * 2.0f * 3.1415926535f / 60.0f;
}
/**
* @brief 将rad/s转换为RPM
*/
int16_t RadPerSec_To_RPM(float rad_per_sec)
{
return (int16_t)(rad_per_sec * 60.0f / (2.0f * 3.1415926535f));
}
/**
* @brief PID控制器初始化
*/
void PID_Init(PID_Controller_t* pid, float kp, float ki, float kd, float integral_limit, float output_limit)
{
pid->kp = kp;
pid->ki = ki;
pid->kd = kd;
pid->integral = 0.0f;
pid->prev_error = 0.0f;
pid->output = 0.0f;
pid->integral_limit = integral_limit;
pid->output_limit = output_limit;
}
/**
* @brief PID计算函数带保护
*/
float PID_Calculate(PID_Controller_t* pid, float error, float dt)
{
// 检查输入参数有效性
if (dt <= 0.0f || dt > 1.0f) {
dt = 0.01f; // 使用默认时间间隔
}
// 检查error是否为NaN或无穷大
if (isnan(error) || isinf(error)) {
error = 0.0f;
}
// 比例项
float proportional = pid->kp * error;
// 检查proportional是否为NaN
if (isnan(proportional) || isinf(proportional)) {
proportional = 0.0f;
}
// 积分项(带限幅)
pid->integral += error * dt;
if (pid->integral > pid->integral_limit) {
pid->integral = pid->integral_limit;
} else if (pid->integral < -pid->integral_limit) {
pid->integral = -pid->integral_limit;
}
float integral = pid->ki * pid->integral;
// 检查integral是否为NaN
if (isnan(integral) || isinf(integral)) {
integral = 0.0f;
pid->integral = 0.0f;
}
// 微分项添加dt保护
float derivative = 0.0f;
if (dt > 0.001f) { // 确保dt足够大避免除以很小的数
derivative = pid->kd * (error - pid->prev_error) / dt;
}
// 检查derivative是否为NaN
if (isnan(derivative) || isinf(derivative)) {
derivative = 0.0f;
}
pid->prev_error = error;
// 计算总输出
pid->output = proportional + integral + derivative;
// 检查总输出是否为NaN
if (isnan(pid->output) || isinf(pid->output)) {
pid->output = 0.0f;
// 重置PID状态
pid->integral = 0.0f;
pid->prev_error = 0.0f;
}
// 输出限幅
if (pid->output > pid->output_limit) {
pid->output = pid->output_limit;
} else if (pid->output < -pid->output_limit) {
pid->output = -pid->output_limit;
}
return pid->output;
}
/**
* @brief 初始化所有电机的PID控制器
*/
void Motor_PID_Init(void)
{
// PID参数需要根据实际电机调试
float speed_kp = 400.0f; // 速度环比例系数
float speed_ki = 0.05f; // 速度环积分系数
float speed_kd = 300.0f; // 速度环微分系数
for (int i = 0; i < 4; i++) {
PID_Init(&motor_controller[i].speed_pid, speed_kp, speed_ki, speed_kd, 3000.0f, 3000.0f);
}
}
/*
*函数简介:位置式PID清理
*参数说明:位置式PID参数结构体
*返回类型:无
*备注:重置PID内部状态用于模式切换或异常情况
*/
void PID_PositionClean(PID_Controller_t* pid)
{
pid->integral = 0.0f; // 清理积分项,防止积分饱和
pid->prev_error = 0.0f; // 清理上一次误差,防止微分冲击
pid->output = 0.0f; // 清理输出值
}
/**
* @brief 设置单个电机的目标速度
* @param motor_id: 电机ID (0-3)
* @param target_speed_rad_s: 目标速度 (rad/s)
*/
void Set_Motor_Target_Speed(uint8_t motor_id, float target_speed_rad_s)
{
if (motor_id < 4) {
motor_controller[motor_id].target_speed = target_speed_rad_s;
}
}
/**
* @brief 电机速度控制任务(带数据验证)
*/
void Motor_Speed_Control_Task(float dt)
{
for (int i = 0; i < 4; i++) {
// 验证电机反馈数据
if (isnan(motor_controller[i].measure.speed_rpm) ||
motor_controller[i].measure.speed_rpm > 10000 ||
motor_controller[i].measure.speed_rpm < -10000) {
// 数据异常,使用默认值
motor_controller[i].measure.speed_rpm = 0;
}
// 将电机反馈的RPM转换为rad/s
float actual_speed_rads = RPM_To_RadPerSec(motor_controller[i].measure.speed_rpm);
// 验证转换结果
if (isnan(actual_speed_rads) || isinf(actual_speed_rads)) {
actual_speed_rads = 0.0f;
}
// 计算速度误差
float speed_error = motor_controller[i].target_speed - actual_speed_rads;
// 验证误差值
if (isnan(speed_error) || isinf(speed_error)) {
speed_error = 0.0f;
}
// PID计算
float pid_output = PID_Calculate(&motor_controller[i].speed_pid, speed_error, dt);
// 验证PID输出
if (isnan(pid_output) || isinf(pid_output)) {
pid_output = 0.0f;
// 重置这个电机的PID状态
PID_PositionClean(&motor_controller[i].speed_pid);
}
// 存储控制命令
motor_commands[i] = (int16_t)pid_output;
}
}
/**
* @brief 麦克纳姆轮速度解算函数
* @param vx: X方向速度 (m/s) - 正数前进,负数后退
* @param vy: Y方向速度 (m/s) - 正数右移,负数左移
* @param vz: 旋转角速度 (rad/s) - 正数逆时针,负数顺时针
*/
void Drive_Motor(float vx, float vy, float vz)
{
float A = WHEELBASE_WIDTH + WHEELBASE_LENGTH;
// 标准麦克纳姆轮运动学逆解算公式
// 轮子编号0-右上, 1-左上, 2-左下, 3-右下
// 标准麦克纳姆轮运动学逆解算公式
float wheel1_speed = ( vx +vy + vz * A ) / WHEEL_RADIUS; // 右上轮
float wheel2_speed = ( vx - vy + vz * A ) / WHEEL_RADIUS; // 左上轮
float wheel3_speed = (-vx -vy + vz * A ) / WHEEL_RADIUS; // 左下轮
float wheel4_speed = (-vx +vy +vz * A ) / WHEEL_RADIUS; // 右下轮
Set_Motor_Target_Speed(0, wheel1_speed); // 右上轮
Set_Motor_Target_Speed(1, wheel2_speed); // 左上轮
Set_Motor_Target_Speed(2, wheel3_speed); // 左下轮
Set_Motor_Target_Speed(3, wheel4_speed); // 右下轮
}
float Map_Remote_to_Speed(int16_t input, float max_speed)
{
if (input > 660) input = 660;
if (input < -660) input = -660;
// 死区内直接返回0
if (abs(input) < 50) {
return 0.0f;
}
// 不在死区内,正常计算速度
return (input / 660.0f) * max_speed;
}
/**
* @brief 处理遥控器数据并设置底盘速度
*/
void Process_Remote_Control(void)
{
// 映射遥控器值到速度 (m/s)
float vx = Map_Remote_to_Speed(rc.ch2,2.0f); // 前后方向最大2m/s
float vy = Map_Remote_to_Speed(-rc.ch3, 2.0f); // 左右方向最大2m/s
float vz = Map_Remote_to_Speed(rc.ch0, 3.0f); // 旋转方向最大3rad/s
// 调用运动学解算
Drive_Motor(vx, vy, vz);
}
/* USER CODE END 0 */
@@ -582,12 +93,9 @@ int main(void)
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_CAN1_Init();
MX_USART3_UART_Init();
MX_CAN2_Init();
/* USER CODE BEGIN 2 */
dbus_uart_init();
HAL_CAN_Start(&hcan1);
Motor_PID_Init();
can_filter_init();
uint32_t last_control_time = 0;

View File

@@ -56,8 +56,7 @@
/* External variables --------------------------------------------------------*/
extern CAN_HandleTypeDef hcan1;
extern DMA_HandleTypeDef hdma_usart3_rx;
extern UART_HandleTypeDef huart3;
extern CAN_HandleTypeDef hcan2;
/* USER CODE BEGIN EV */
/* USER CODE END EV */
@@ -200,20 +199,6 @@ void SysTick_Handler(void)
/* please refer to the startup file (startup_stm32f4xx.s). */
/******************************************************************************/
/**
* @brief This function handles DMA1 stream1 global interrupt.
*/
void DMA1_Stream1_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Stream1_IRQn 0 */
/* USER CODE END DMA1_Stream1_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_usart3_rx);
/* USER CODE BEGIN DMA1_Stream1_IRQn 1 */
/* USER CODE END DMA1_Stream1_IRQn 1 */
}
/**
* @brief This function handles CAN1 RX0 interrupts.
*/
@@ -229,17 +214,17 @@ void CAN1_RX0_IRQHandler(void)
}
/**
* @brief This function handles USART3 global interrupt.
* @brief This function handles CAN2 RX0 interrupts.
*/
void USART3_IRQHandler(void)
void CAN2_RX0_IRQHandler(void)
{
/* USER CODE BEGIN USART3_IRQn 0 */
uart_receive_handler(&huart3);
/* USER CODE END USART3_IRQn 0 */
HAL_UART_IRQHandler(&huart3);
/* USER CODE BEGIN USART3_IRQn 1 */
/* USER CODE BEGIN CAN2_RX0_IRQn 0 */
/* USER CODE END USART3_IRQn 1 */
/* USER CODE END CAN2_RX0_IRQn 0 */
HAL_CAN_IRQHandler(&hcan2);
/* USER CODE BEGIN CAN2_RX0_IRQn 1 */
/* USER CODE END CAN2_RX0_IRQn 1 */
}
/* USER CODE BEGIN 1 */

View File

@@ -1,142 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file usart.c
* @brief This file provides code for the configuration
* of the USART instances.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "usart.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
UART_HandleTypeDef huart3;
DMA_HandleTypeDef hdma_usart3_rx;
/* USART3 init function */
void MX_USART3_UART_Init(void)
{
/* USER CODE BEGIN USART3_Init 0 */
/* USER CODE END USART3_Init 0 */
/* USER CODE BEGIN USART3_Init 1 */
/* USER CODE END USART3_Init 1 */
huart3.Instance = USART3;
huart3.Init.BaudRate = 100000;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
huart3.Init.Mode = UART_MODE_TX_RX;
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart3) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART3_Init 2 */
/* USER CODE END USART3_Init 2 */
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(uartHandle->Instance==USART3)
{
/* USER CODE BEGIN USART3_MspInit 0 */
/* USER CODE END USART3_MspInit 0 */
/* USART3 clock enable */
__HAL_RCC_USART3_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
/**USART3 GPIO Configuration
PC11 ------> USART3_RX
PC10 ------> USART3_TX
*/
GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* USART3 DMA Init */
/* USART3_RX Init */
hdma_usart3_rx.Instance = DMA1_Stream1;
hdma_usart3_rx.Init.Channel = DMA_CHANNEL_4;
hdma_usart3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_usart3_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart3_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart3_rx.Init.Mode = DMA_CIRCULAR;
hdma_usart3_rx.Init.Priority = DMA_PRIORITY_LOW;
hdma_usart3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_usart3_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(uartHandle,hdmarx,hdma_usart3_rx);
/* USART3 interrupt Init */
HAL_NVIC_SetPriority(USART3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART3_IRQn);
/* USER CODE BEGIN USART3_MspInit 1 */
/* USER CODE END USART3_MspInit 1 */
}
}
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
if(uartHandle->Instance==USART3)
{
/* USER CODE BEGIN USART3_MspDeInit 0 */
/* USER CODE END USART3_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART3_CLK_DISABLE();
/**USART3 GPIO Configuration
PC11 ------> USART3_RX
PC10 ------> USART3_TX
*/
HAL_GPIO_DeInit(GPIOC, GPIO_PIN_11|GPIO_PIN_10);
/* USART3 DMA DeInit */
HAL_DMA_DeInit(uartHandle->hdmarx);
/* USART3 interrupt Deinit */
HAL_NVIC_DisableIRQ(USART3_IRQn);
/* USER CODE BEGIN USART3_MspDeInit 1 */
/* USER CODE END USART3_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */