This commit is contained in:
parent
01af6b8ba2
commit
7000565792
|
@ -78,10 +78,21 @@ void Error_Handler(void);
|
||||||
/* Private defines -----------------------------------------------------------*/
|
/* Private defines -----------------------------------------------------------*/
|
||||||
#define LED_BLUE_Pin LL_GPIO_PIN_13
|
#define LED_BLUE_Pin LL_GPIO_PIN_13
|
||||||
#define LED_BLUE_GPIO_Port GPIOC
|
#define LED_BLUE_GPIO_Port GPIOC
|
||||||
|
#define MOTOR_B_Pin LL_GPIO_PIN_15
|
||||||
|
#define MOTOR_B_GPIO_Port GPIOC
|
||||||
|
#define MOTOR_A_Pin LL_GPIO_PIN_0
|
||||||
|
#define MOTOR_A_GPIO_Port GPIOA
|
||||||
|
#define MOTOR_A_EXTI_IRQn EXTI0_IRQn
|
||||||
#define AIN1_Pin LL_GPIO_PIN_4
|
#define AIN1_Pin LL_GPIO_PIN_4
|
||||||
#define AIN1_GPIO_Port GPIOA
|
#define AIN1_GPIO_Port GPIOA
|
||||||
#define AIN2_Pin LL_GPIO_PIN_5
|
#define AIN2_Pin LL_GPIO_PIN_5
|
||||||
#define AIN2_GPIO_Port GPIOA
|
#define AIN2_GPIO_Port GPIOA
|
||||||
|
#define KEY_ADD_Pin LL_GPIO_PIN_6
|
||||||
|
#define KEY_ADD_GPIO_Port GPIOA
|
||||||
|
#define KEY_SUB_Pin LL_GPIO_PIN_7
|
||||||
|
#define KEY_SUB_GPIO_Port GPIOA
|
||||||
|
#define KEY_S_Pin LL_GPIO_PIN_0
|
||||||
|
#define KEY_S_GPIO_Port GPIOB
|
||||||
#define OLED_SDA_Pin LL_GPIO_PIN_12
|
#define OLED_SDA_Pin LL_GPIO_PIN_12
|
||||||
#define OLED_SDA_GPIO_Port GPIOB
|
#define OLED_SDA_GPIO_Port GPIOB
|
||||||
#define OLDE_SCK_Pin LL_GPIO_PIN_13
|
#define OLDE_SCK_Pin LL_GPIO_PIN_13
|
||||||
|
|
|
@ -55,10 +55,11 @@ void SVC_Handler(void);
|
||||||
void DebugMon_Handler(void);
|
void DebugMon_Handler(void);
|
||||||
void PendSV_Handler(void);
|
void PendSV_Handler(void);
|
||||||
void SysTick_Handler(void);
|
void SysTick_Handler(void);
|
||||||
|
void EXTI0_IRQHandler(void);
|
||||||
void DMA1_Channel4_IRQHandler(void);
|
void DMA1_Channel4_IRQHandler(void);
|
||||||
void DMA1_Channel5_IRQHandler(void);
|
void DMA1_Channel5_IRQHandler(void);
|
||||||
void TIM1_UP_IRQHandler(void);
|
void TIM1_UP_IRQHandler(void);
|
||||||
void TIM2_IRQHandler(void);
|
void TIM3_IRQHandler(void);
|
||||||
void USART1_IRQHandler(void);
|
void USART1_IRQHandler(void);
|
||||||
/* USER CODE BEGIN EFP */
|
/* USER CODE BEGIN EFP */
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ extern "C" {
|
||||||
|
|
||||||
void MX_TIM1_Init(void);
|
void MX_TIM1_Init(void);
|
||||||
void MX_TIM2_Init(void);
|
void MX_TIM2_Init(void);
|
||||||
|
void MX_TIM3_Init(void);
|
||||||
|
|
||||||
/* USER CODE BEGIN Prototypes */
|
/* USER CODE BEGIN Prototypes */
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
void MX_GPIO_Init(void)
|
void MX_GPIO_Init(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
LL_EXTI_InitTypeDef EXTI_InitStruct = {0};
|
||||||
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
|
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||||
|
|
||||||
/* GPIO Ports Clock Enable */
|
/* GPIO Ports Clock Enable */
|
||||||
|
@ -74,18 +75,13 @@ void MX_GPIO_Init(void)
|
||||||
LL_GPIO_Init(GPIOC, &GPIO_InitStruct);
|
LL_GPIO_Init(GPIOC, &GPIO_InitStruct);
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
GPIO_InitStruct.Pin = LL_GPIO_PIN_15;
|
GPIO_InitStruct.Pin = MOTOR_B_Pin;
|
||||||
GPIO_InitStruct.Mode = LL_GPIO_MODE_FLOATING;
|
GPIO_InitStruct.Mode = LL_GPIO_MODE_FLOATING;
|
||||||
LL_GPIO_Init(GPIOC, &GPIO_InitStruct);
|
LL_GPIO_Init(MOTOR_B_GPIO_Port, &GPIO_InitStruct);
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
GPIO_InitStruct.Pin = LL_GPIO_PIN_0;
|
GPIO_InitStruct.Pin = LL_GPIO_PIN_2|LL_GPIO_PIN_3|LL_GPIO_PIN_8|LL_GPIO_PIN_11
|
||||||
GPIO_InitStruct.Mode = LL_GPIO_MODE_FLOATING;
|
|LL_GPIO_PIN_12|LL_GPIO_PIN_15;
|
||||||
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
|
||||||
|
|
||||||
/**/
|
|
||||||
GPIO_InitStruct.Pin = LL_GPIO_PIN_2|LL_GPIO_PIN_3|LL_GPIO_PIN_6|LL_GPIO_PIN_7
|
|
||||||
|LL_GPIO_PIN_8|LL_GPIO_PIN_11|LL_GPIO_PIN_12|LL_GPIO_PIN_15;
|
|
||||||
GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
|
GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
|
||||||
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
@ -98,10 +94,22 @@ void MX_GPIO_Init(void)
|
||||||
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
GPIO_InitStruct.Pin = LL_GPIO_PIN_0|LL_GPIO_PIN_1|LL_GPIO_PIN_2|LL_GPIO_PIN_10
|
GPIO_InitStruct.Pin = KEY_ADD_Pin|KEY_SUB_Pin;
|
||||||
|LL_GPIO_PIN_11|LL_GPIO_PIN_14|LL_GPIO_PIN_15|LL_GPIO_PIN_3
|
GPIO_InitStruct.Mode = LL_GPIO_MODE_INPUT;
|
||||||
|LL_GPIO_PIN_4|LL_GPIO_PIN_5|LL_GPIO_PIN_6|LL_GPIO_PIN_7
|
GPIO_InitStruct.Pull = LL_GPIO_PULL_DOWN;
|
||||||
|LL_GPIO_PIN_8|LL_GPIO_PIN_9;
|
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
/**/
|
||||||
|
GPIO_InitStruct.Pin = KEY_S_Pin;
|
||||||
|
GPIO_InitStruct.Mode = LL_GPIO_MODE_INPUT;
|
||||||
|
GPIO_InitStruct.Pull = LL_GPIO_PULL_DOWN;
|
||||||
|
LL_GPIO_Init(KEY_S_GPIO_Port, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
/**/
|
||||||
|
GPIO_InitStruct.Pin = LL_GPIO_PIN_1|LL_GPIO_PIN_2|LL_GPIO_PIN_10|LL_GPIO_PIN_11
|
||||||
|
|LL_GPIO_PIN_14|LL_GPIO_PIN_15|LL_GPIO_PIN_3|LL_GPIO_PIN_4
|
||||||
|
|LL_GPIO_PIN_5|LL_GPIO_PIN_6|LL_GPIO_PIN_7|LL_GPIO_PIN_8
|
||||||
|
|LL_GPIO_PIN_9;
|
||||||
GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
|
GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
|
||||||
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
@ -112,6 +120,23 @@ void MX_GPIO_Init(void)
|
||||||
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
|
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
|
||||||
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
/**/
|
||||||
|
LL_GPIO_AF_SetEXTISource(LL_GPIO_AF_EXTI_PORTA, LL_GPIO_AF_EXTI_LINE0);
|
||||||
|
|
||||||
|
/**/
|
||||||
|
EXTI_InitStruct.Line_0_31 = LL_EXTI_LINE_0;
|
||||||
|
EXTI_InitStruct.LineCommand = ENABLE;
|
||||||
|
EXTI_InitStruct.Mode = LL_EXTI_MODE_IT;
|
||||||
|
EXTI_InitStruct.Trigger = LL_EXTI_TRIGGER_RISING;
|
||||||
|
LL_EXTI_Init(&EXTI_InitStruct);
|
||||||
|
|
||||||
|
/**/
|
||||||
|
LL_GPIO_SetPinMode(MOTOR_A_GPIO_Port, MOTOR_A_Pin, LL_GPIO_MODE_FLOATING);
|
||||||
|
|
||||||
|
/* EXTI interrupt init*/
|
||||||
|
NVIC_SetPriority(EXTI0_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
|
||||||
|
NVIC_EnableIRQ(EXTI0_IRQn);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* USER CODE BEGIN 2 */
|
/* USER CODE BEGIN 2 */
|
||||||
|
|
|
@ -101,6 +101,7 @@ int main(void)
|
||||||
MX_TIM2_Init();
|
MX_TIM2_Init();
|
||||||
MX_USART1_UART_Init();
|
MX_USART1_UART_Init();
|
||||||
MX_TIM1_Init();
|
MX_TIM1_Init();
|
||||||
|
MX_TIM3_Init();
|
||||||
/* USER CODE BEGIN 2 */
|
/* USER CODE BEGIN 2 */
|
||||||
my_mem_init(SRAMIN); // Initialize internal memory pool 1
|
my_mem_init(SRAMIN); // Initialize internal memory pool 1
|
||||||
board_init();
|
board_init();
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#include "sys.h"
|
#include "sys.h"
|
||||||
#include "flow.h"
|
#include "flow.h"
|
||||||
#include "board.h"
|
#include "board.h"
|
||||||
|
#include "btn.h"
|
||||||
|
#include "work.h"
|
||||||
/* USER CODE END Includes */
|
/* USER CODE END Includes */
|
||||||
|
|
||||||
/* Private typedef -----------------------------------------------------------*/
|
/* Private typedef -----------------------------------------------------------*/
|
||||||
|
@ -201,6 +203,26 @@ void SysTick_Handler(void)
|
||||||
/* please refer to the startup file (startup_stm32f1xx.s). */
|
/* please refer to the startup file (startup_stm32f1xx.s). */
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function handles EXTI line0 interrupt.
|
||||||
|
*/
|
||||||
|
void EXTI0_IRQHandler(void)
|
||||||
|
{
|
||||||
|
/* USER CODE BEGIN EXTI0_IRQn 0 */
|
||||||
|
|
||||||
|
/* USER CODE END EXTI0_IRQn 0 */
|
||||||
|
if (LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_0) != RESET)
|
||||||
|
{
|
||||||
|
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_0);
|
||||||
|
/* USER CODE BEGIN LL_EXTI_LINE_0 */
|
||||||
|
work_encoder_exti();
|
||||||
|
/* USER CODE END LL_EXTI_LINE_0 */
|
||||||
|
}
|
||||||
|
/* USER CODE BEGIN EXTI0_IRQn 1 */
|
||||||
|
|
||||||
|
/* USER CODE END EXTI0_IRQn 1 */
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function handles DMA1 channel4 global interrupt.
|
* @brief This function handles DMA1 channel4 global interrupt.
|
||||||
*/
|
*/
|
||||||
|
@ -242,26 +264,27 @@ void TIM1_UP_IRQHandler(void)
|
||||||
{
|
{
|
||||||
TIM_IRQ_HANDLER(TASK_TIM);
|
TIM_IRQ_HANDLER(TASK_TIM);
|
||||||
LL_IncTick();
|
LL_IncTick();
|
||||||
|
button_ticks();
|
||||||
FLOW_TICK_UPDATE();
|
FLOW_TICK_UPDATE();
|
||||||
}
|
}
|
||||||
/* USER CODE END TIM1_UP_IRQn 1 */
|
/* USER CODE END TIM1_UP_IRQn 1 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function handles TIM2 global interrupt.
|
* @brief This function handles TIM3 global interrupt.
|
||||||
*/
|
*/
|
||||||
void TIM2_IRQHandler(void)
|
void TIM3_IRQHandler(void)
|
||||||
{
|
{
|
||||||
/* USER CODE BEGIN TIM2_IRQn 0 */
|
/* USER CODE BEGIN TIM3_IRQn 0 */
|
||||||
|
|
||||||
/* USER CODE END TIM2_IRQn 0 */
|
/* USER CODE END TIM3_IRQn 0 */
|
||||||
/* USER CODE BEGIN TIM2_IRQn 1 */
|
/* USER CODE BEGIN TIM3_IRQn 1 */
|
||||||
if (IS_TIM_IT_FLAG(PWM_TIM))
|
if (IS_TIM_IT_FLAG(WORK_TIM))
|
||||||
{
|
{
|
||||||
TIM_IRQ_HANDLER(PWM_TIM);
|
TIM_IRQ_HANDLER(WORK_TIM);
|
||||||
// GPIO_TOGGLE(PWM_GPIO_Port, PWM_Pin);
|
work_process();
|
||||||
}
|
}
|
||||||
/* USER CODE END TIM2_IRQn 1 */
|
/* USER CODE END TIM3_IRQn 1 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -38,7 +38,7 @@ void MX_TIM1_Init(void)
|
||||||
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM1);
|
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM1);
|
||||||
|
|
||||||
/* TIM1 interrupt Init */
|
/* TIM1 interrupt Init */
|
||||||
NVIC_SetPriority(TIM1_UP_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
|
NVIC_SetPriority(TIM1_UP_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),3, 0));
|
||||||
NVIC_EnableIRQ(TIM1_UP_IRQn);
|
NVIC_EnableIRQ(TIM1_UP_IRQn);
|
||||||
|
|
||||||
/* USER CODE BEGIN TIM1_Init 1 */
|
/* USER CODE BEGIN TIM1_Init 1 */
|
||||||
|
@ -74,10 +74,6 @@ void MX_TIM2_Init(void)
|
||||||
/* Peripheral clock enable */
|
/* Peripheral clock enable */
|
||||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2);
|
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2);
|
||||||
|
|
||||||
/* TIM2 interrupt Init */
|
|
||||||
NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),15, 0));
|
|
||||||
NVIC_EnableIRQ(TIM2_IRQn);
|
|
||||||
|
|
||||||
/* USER CODE BEGIN TIM2_Init 1 */
|
/* USER CODE BEGIN TIM2_Init 1 */
|
||||||
|
|
||||||
/* USER CODE END TIM2_Init 1 */
|
/* USER CODE END TIM2_Init 1 */
|
||||||
|
@ -86,7 +82,7 @@ void MX_TIM2_Init(void)
|
||||||
TIM_InitStruct.Autoreload = 7199;
|
TIM_InitStruct.Autoreload = 7199;
|
||||||
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
|
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
|
||||||
LL_TIM_Init(TIM2, &TIM_InitStruct);
|
LL_TIM_Init(TIM2, &TIM_InitStruct);
|
||||||
LL_TIM_DisableARRPreload(TIM2);
|
LL_TIM_EnableARRPreload(TIM2);
|
||||||
LL_TIM_SetClockSource(TIM2, LL_TIM_CLOCKSOURCE_INTERNAL);
|
LL_TIM_SetClockSource(TIM2, LL_TIM_CLOCKSOURCE_INTERNAL);
|
||||||
LL_TIM_OC_EnablePreload(TIM2, LL_TIM_CHANNEL_CH2);
|
LL_TIM_OC_EnablePreload(TIM2, LL_TIM_CHANNEL_CH2);
|
||||||
TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM2;
|
TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM2;
|
||||||
|
@ -111,6 +107,40 @@ void MX_TIM2_Init(void)
|
||||||
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
|
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
|
||||||
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
}
|
||||||
|
/* TIM3 init function */
|
||||||
|
void MX_TIM3_Init(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* USER CODE BEGIN TIM3_Init 0 */
|
||||||
|
|
||||||
|
/* USER CODE END TIM3_Init 0 */
|
||||||
|
|
||||||
|
LL_TIM_InitTypeDef TIM_InitStruct = {0};
|
||||||
|
|
||||||
|
/* Peripheral clock enable */
|
||||||
|
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM3);
|
||||||
|
|
||||||
|
/* TIM3 interrupt Init */
|
||||||
|
NVIC_SetPriority(TIM3_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),1, 0));
|
||||||
|
NVIC_EnableIRQ(TIM3_IRQn);
|
||||||
|
|
||||||
|
/* USER CODE BEGIN TIM3_Init 1 */
|
||||||
|
|
||||||
|
/* USER CODE END TIM3_Init 1 */
|
||||||
|
TIM_InitStruct.Prescaler = 7199;
|
||||||
|
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
|
||||||
|
TIM_InitStruct.Autoreload = 99;
|
||||||
|
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
|
||||||
|
LL_TIM_Init(TIM3, &TIM_InitStruct);
|
||||||
|
LL_TIM_DisableARRPreload(TIM3);
|
||||||
|
LL_TIM_SetClockSource(TIM3, LL_TIM_CLOCKSOURCE_INTERNAL);
|
||||||
|
LL_TIM_SetTriggerOutput(TIM3, LL_TIM_TRGO_RESET);
|
||||||
|
LL_TIM_DisableMasterSlaveMode(TIM3);
|
||||||
|
/* USER CODE BEGIN TIM3_Init 2 */
|
||||||
|
|
||||||
|
/* USER CODE END TIM3_Init 2 */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* USER CODE BEGIN 1 */
|
/* USER CODE BEGIN 1 */
|
||||||
|
|
|
@ -88,7 +88,7 @@ void MX_USART1_UART_Init(void)
|
||||||
LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_4, LL_DMA_MDATAALIGN_BYTE);
|
LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_4, LL_DMA_MDATAALIGN_BYTE);
|
||||||
|
|
||||||
/* USART1 interrupt Init */
|
/* USART1 interrupt Init */
|
||||||
NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
|
NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),5, 0));
|
||||||
NVIC_EnableIRQ(USART1_IRQn);
|
NVIC_EnableIRQ(USART1_IRQn);
|
||||||
|
|
||||||
/* USER CODE BEGIN USART1_Init 1 */
|
/* USER CODE BEGIN USART1_Init 1 */
|
||||||
|
|
|
@ -125,7 +125,7 @@
|
||||||
<SetRegEntry>
|
<SetRegEntry>
|
||||||
<Number>0</Number>
|
<Number>0</Number>
|
||||||
<Key>CMSIS_AGDI</Key>
|
<Key>CMSIS_AGDI</Key>
|
||||||
<Name>-X"Any" -UAny -O206 -S0 -C0 -P00000000 -N00("ARM CoreSight SW-DP") -D00(1BA01477) -L00(0) -TO65554 -TC10000000 -TT10000000 -TP20 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO15 -FD20000000 -FC1000 -FN1 -FF0STM32F10x_128.FLM -FS08000000 -FL020000 -FP0($$Device:STM32F103C8$Flash\STM32F10x_128.FLM)</Name>
|
<Name>-X"Any" -UAny -O206 -S0 -C0 -P00000000 -N00("ARM CoreSight SW-DP") -D00(1BA01477) -L00(0) -TO65554 -TC10000000 -TT10000000 -TP20 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC1000 -FN1 -FF0STM32F10x_128.FLM -FS08000000 -FL020000 -FP0($$Device:STM32F103C8$Flash\STM32F10x_128.FLM)</Name>
|
||||||
</SetRegEntry>
|
</SetRegEntry>
|
||||||
<SetRegEntry>
|
<SetRegEntry>
|
||||||
<Number>0</Number>
|
<Number>0</Number>
|
||||||
|
@ -163,17 +163,12 @@
|
||||||
<Ww>
|
<Ww>
|
||||||
<count>2</count>
|
<count>2</count>
|
||||||
<WinNumber>1</WinNumber>
|
<WinNumber>1</WinNumber>
|
||||||
<ItemText>0x00000E0F,0x0A</ItemText>
|
<ItemText>work,0x0A</ItemText>
|
||||||
</Ww>
|
</Ww>
|
||||||
<Ww>
|
<Ww>
|
||||||
<count>3</count>
|
<count>3</count>
|
||||||
<WinNumber>1</WinNumber>
|
<WinNumber>1</WinNumber>
|
||||||
<ItemText>0x0000270F,0x0A</ItemText>
|
<ItemText>ch</ItemText>
|
||||||
</Ww>
|
|
||||||
<Ww>
|
|
||||||
<count>4</count>
|
|
||||||
<WinNumber>1</WinNumber>
|
|
||||||
<ItemText>0x000003E7,0x0A</ItemText>
|
|
||||||
</Ww>
|
</Ww>
|
||||||
</WatchWindow1>
|
</WatchWindow1>
|
||||||
<Tracepoint>
|
<Tracepoint>
|
||||||
|
@ -182,7 +177,7 @@
|
||||||
<DebugFlag>
|
<DebugFlag>
|
||||||
<trace>0</trace>
|
<trace>0</trace>
|
||||||
<periodic>1</periodic>
|
<periodic>1</periodic>
|
||||||
<aLwin>1</aLwin>
|
<aLwin>0</aLwin>
|
||||||
<aCover>0</aCover>
|
<aCover>0</aCover>
|
||||||
<aSer1>0</aSer1>
|
<aSer1>0</aSer1>
|
||||||
<aSer2>0</aSer2>
|
<aSer2>0</aSer2>
|
||||||
|
@ -218,20 +213,6 @@
|
||||||
<pszMrulep></pszMrulep>
|
<pszMrulep></pszMrulep>
|
||||||
<pSingCmdsp></pSingCmdsp>
|
<pSingCmdsp></pSingCmdsp>
|
||||||
<pMultCmdsp></pMultCmdsp>
|
<pMultCmdsp></pMultCmdsp>
|
||||||
<SystemViewers>
|
|
||||||
<Entry>
|
|
||||||
<Name>System Viewer\GPIOA</Name>
|
|
||||||
<WinId>35905</WinId>
|
|
||||||
</Entry>
|
|
||||||
<Entry>
|
|
||||||
<Name>System Viewer\GPIOC</Name>
|
|
||||||
<WinId>35903</WinId>
|
|
||||||
</Entry>
|
|
||||||
<Entry>
|
|
||||||
<Name>System Viewer\TIM2</Name>
|
|
||||||
<WinId>35904</WinId>
|
|
||||||
</Entry>
|
|
||||||
</SystemViewers>
|
|
||||||
</TargetOption>
|
</TargetOption>
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
|
@ -373,6 +354,30 @@
|
||||||
<RteFlg>0</RteFlg>
|
<RteFlg>0</RteFlg>
|
||||||
<bShared>0</bShared>
|
<bShared>0</bShared>
|
||||||
</File>
|
</File>
|
||||||
|
<File>
|
||||||
|
<GroupNumber>4</GroupNumber>
|
||||||
|
<FileNumber>10</FileNumber>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<tvExp>0</tvExp>
|
||||||
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
<bDave2>0</bDave2>
|
||||||
|
<PathWithFileName>..\User\application\key.c</PathWithFileName>
|
||||||
|
<FilenameWithoutPath>key.c</FilenameWithoutPath>
|
||||||
|
<RteFlg>0</RteFlg>
|
||||||
|
<bShared>0</bShared>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<GroupNumber>4</GroupNumber>
|
||||||
|
<FileNumber>11</FileNumber>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<tvExp>0</tvExp>
|
||||||
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
<bDave2>0</bDave2>
|
||||||
|
<PathWithFileName>..\User\application\work.c</PathWithFileName>
|
||||||
|
<FilenameWithoutPath>work.c</FilenameWithoutPath>
|
||||||
|
<RteFlg>0</RteFlg>
|
||||||
|
<bShared>0</bShared>
|
||||||
|
</File>
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Group>
|
<Group>
|
||||||
|
@ -383,7 +388,7 @@
|
||||||
<RteFlg>0</RteFlg>
|
<RteFlg>0</RteFlg>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>5</GroupNumber>
|
<GroupNumber>5</GroupNumber>
|
||||||
<FileNumber>10</FileNumber>
|
<FileNumber>12</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -395,7 +400,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>5</GroupNumber>
|
<GroupNumber>5</GroupNumber>
|
||||||
<FileNumber>11</FileNumber>
|
<FileNumber>13</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -407,7 +412,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>5</GroupNumber>
|
<GroupNumber>5</GroupNumber>
|
||||||
<FileNumber>12</FileNumber>
|
<FileNumber>14</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -419,7 +424,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>5</GroupNumber>
|
<GroupNumber>5</GroupNumber>
|
||||||
<FileNumber>13</FileNumber>
|
<FileNumber>15</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -431,7 +436,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>5</GroupNumber>
|
<GroupNumber>5</GroupNumber>
|
||||||
<FileNumber>14</FileNumber>
|
<FileNumber>16</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -443,7 +448,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>5</GroupNumber>
|
<GroupNumber>5</GroupNumber>
|
||||||
<FileNumber>15</FileNumber>
|
<FileNumber>17</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -455,7 +460,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>5</GroupNumber>
|
<GroupNumber>5</GroupNumber>
|
||||||
<FileNumber>16</FileNumber>
|
<FileNumber>18</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -467,7 +472,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>5</GroupNumber>
|
<GroupNumber>5</GroupNumber>
|
||||||
<FileNumber>17</FileNumber>
|
<FileNumber>19</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -487,7 +492,7 @@
|
||||||
<RteFlg>0</RteFlg>
|
<RteFlg>0</RteFlg>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>6</GroupNumber>
|
<GroupNumber>6</GroupNumber>
|
||||||
<FileNumber>18</FileNumber>
|
<FileNumber>20</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -499,7 +504,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>6</GroupNumber>
|
<GroupNumber>6</GroupNumber>
|
||||||
<FileNumber>19</FileNumber>
|
<FileNumber>21</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -511,7 +516,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>6</GroupNumber>
|
<GroupNumber>6</GroupNumber>
|
||||||
<FileNumber>20</FileNumber>
|
<FileNumber>22</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -523,7 +528,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>6</GroupNumber>
|
<GroupNumber>6</GroupNumber>
|
||||||
<FileNumber>21</FileNumber>
|
<FileNumber>23</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -535,7 +540,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>6</GroupNumber>
|
<GroupNumber>6</GroupNumber>
|
||||||
<FileNumber>22</FileNumber>
|
<FileNumber>24</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -547,7 +552,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>6</GroupNumber>
|
<GroupNumber>6</GroupNumber>
|
||||||
<FileNumber>23</FileNumber>
|
<FileNumber>25</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -559,7 +564,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>6</GroupNumber>
|
<GroupNumber>6</GroupNumber>
|
||||||
<FileNumber>24</FileNumber>
|
<FileNumber>26</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -571,7 +576,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>6</GroupNumber>
|
<GroupNumber>6</GroupNumber>
|
||||||
<FileNumber>25</FileNumber>
|
<FileNumber>27</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -583,7 +588,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>6</GroupNumber>
|
<GroupNumber>6</GroupNumber>
|
||||||
<FileNumber>26</FileNumber>
|
<FileNumber>28</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -595,7 +600,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>6</GroupNumber>
|
<GroupNumber>6</GroupNumber>
|
||||||
<FileNumber>27</FileNumber>
|
<FileNumber>29</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -607,7 +612,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>6</GroupNumber>
|
<GroupNumber>6</GroupNumber>
|
||||||
<FileNumber>28</FileNumber>
|
<FileNumber>30</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -619,7 +624,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>6</GroupNumber>
|
<GroupNumber>6</GroupNumber>
|
||||||
<FileNumber>29</FileNumber>
|
<FileNumber>31</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -631,7 +636,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>6</GroupNumber>
|
<GroupNumber>6</GroupNumber>
|
||||||
<FileNumber>30</FileNumber>
|
<FileNumber>32</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -643,7 +648,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>6</GroupNumber>
|
<GroupNumber>6</GroupNumber>
|
||||||
<FileNumber>31</FileNumber>
|
<FileNumber>33</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -655,7 +660,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>6</GroupNumber>
|
<GroupNumber>6</GroupNumber>
|
||||||
<FileNumber>32</FileNumber>
|
<FileNumber>34</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -675,7 +680,7 @@
|
||||||
<RteFlg>0</RteFlg>
|
<RteFlg>0</RteFlg>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>7</GroupNumber>
|
<GroupNumber>7</GroupNumber>
|
||||||
<FileNumber>33</FileNumber>
|
<FileNumber>35</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -687,7 +692,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>7</GroupNumber>
|
<GroupNumber>7</GroupNumber>
|
||||||
<FileNumber>34</FileNumber>
|
<FileNumber>36</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -699,7 +704,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>7</GroupNumber>
|
<GroupNumber>7</GroupNumber>
|
||||||
<FileNumber>35</FileNumber>
|
<FileNumber>37</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -711,7 +716,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>7</GroupNumber>
|
<GroupNumber>7</GroupNumber>
|
||||||
<FileNumber>36</FileNumber>
|
<FileNumber>38</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -723,7 +728,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>7</GroupNumber>
|
<GroupNumber>7</GroupNumber>
|
||||||
<FileNumber>37</FileNumber>
|
<FileNumber>39</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -735,7 +740,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>7</GroupNumber>
|
<GroupNumber>7</GroupNumber>
|
||||||
<FileNumber>38</FileNumber>
|
<FileNumber>40</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -747,7 +752,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>7</GroupNumber>
|
<GroupNumber>7</GroupNumber>
|
||||||
<FileNumber>39</FileNumber>
|
<FileNumber>41</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -759,7 +764,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>7</GroupNumber>
|
<GroupNumber>7</GroupNumber>
|
||||||
<FileNumber>40</FileNumber>
|
<FileNumber>42</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -779,7 +784,7 @@
|
||||||
<RteFlg>0</RteFlg>
|
<RteFlg>0</RteFlg>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>8</GroupNumber>
|
<GroupNumber>8</GroupNumber>
|
||||||
<FileNumber>41</FileNumber>
|
<FileNumber>43</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -791,7 +796,7 @@
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>8</GroupNumber>
|
<GroupNumber>8</GroupNumber>
|
||||||
<FileNumber>42</FileNumber>
|
<FileNumber>44</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -803,6 +808,74 @@
|
||||||
</File>
|
</File>
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
|
<Group>
|
||||||
|
<GroupName>User/lib/control</GroupName>
|
||||||
|
<tvExp>0</tvExp>
|
||||||
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
<cbSel>0</cbSel>
|
||||||
|
<RteFlg>0</RteFlg>
|
||||||
|
<File>
|
||||||
|
<GroupNumber>9</GroupNumber>
|
||||||
|
<FileNumber>45</FileNumber>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<tvExp>0</tvExp>
|
||||||
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
<bDave2>0</bDave2>
|
||||||
|
<PathWithFileName>..\User\lib\control\src\pid.c</PathWithFileName>
|
||||||
|
<FilenameWithoutPath>pid.c</FilenameWithoutPath>
|
||||||
|
<RteFlg>0</RteFlg>
|
||||||
|
<bShared>0</bShared>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<GroupNumber>9</GroupNumber>
|
||||||
|
<FileNumber>46</FileNumber>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<tvExp>0</tvExp>
|
||||||
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
<bDave2>0</bDave2>
|
||||||
|
<PathWithFileName>..\User\lib\control\src\pid_auto_tune.c</PathWithFileName>
|
||||||
|
<FilenameWithoutPath>pid_auto_tune.c</FilenameWithoutPath>
|
||||||
|
<RteFlg>0</RteFlg>
|
||||||
|
<bShared>0</bShared>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<GroupNumber>9</GroupNumber>
|
||||||
|
<FileNumber>47</FileNumber>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<tvExp>0</tvExp>
|
||||||
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
<bDave2>0</bDave2>
|
||||||
|
<PathWithFileName>..\User\lib\control\src\pid_common.c</PathWithFileName>
|
||||||
|
<FilenameWithoutPath>pid_common.c</FilenameWithoutPath>
|
||||||
|
<RteFlg>0</RteFlg>
|
||||||
|
<bShared>0</bShared>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<GroupNumber>9</GroupNumber>
|
||||||
|
<FileNumber>48</FileNumber>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<tvExp>0</tvExp>
|
||||||
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
<bDave2>0</bDave2>
|
||||||
|
<PathWithFileName>..\User\lib\control\src\pid_fuzzy.c</PathWithFileName>
|
||||||
|
<FilenameWithoutPath>pid_fuzzy.c</FilenameWithoutPath>
|
||||||
|
<RteFlg>0</RteFlg>
|
||||||
|
<bShared>0</bShared>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<GroupNumber>9</GroupNumber>
|
||||||
|
<FileNumber>49</FileNumber>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<tvExp>0</tvExp>
|
||||||
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
<bDave2>0</bDave2>
|
||||||
|
<PathWithFileName>..\User\lib\control\src\pid_neural.c</PathWithFileName>
|
||||||
|
<FilenameWithoutPath>pid_neural.c</FilenameWithoutPath>
|
||||||
|
<RteFlg>0</RteFlg>
|
||||||
|
<bShared>0</bShared>
|
||||||
|
</File>
|
||||||
|
</Group>
|
||||||
|
|
||||||
<Group>
|
<Group>
|
||||||
<GroupName>::CMSIS</GroupName>
|
<GroupName>::CMSIS</GroupName>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
|
|
|
@ -339,7 +339,7 @@
|
||||||
<MiscControls></MiscControls>
|
<MiscControls></MiscControls>
|
||||||
<Define>STM32,STM32F103xB,USE_FULL_LL_DRIVER,HSE_VALUE=8000000,HSE_STARTUP_TIMEOUT=100,LSE_STARTUP_TIMEOUT=5000,LSE_VALUE=32768,HSI_VALUE=8000000,LSI_VALUE=40000,VDD_VALUE=3300,PREFETCH_ENABLE=1</Define>
|
<Define>STM32,STM32F103xB,USE_FULL_LL_DRIVER,HSE_VALUE=8000000,HSE_STARTUP_TIMEOUT=100,LSE_STARTUP_TIMEOUT=5000,LSE_VALUE=32768,HSI_VALUE=8000000,LSI_VALUE=40000,VDD_VALUE=3300,PREFETCH_ENABLE=1</Define>
|
||||||
<Undefine></Undefine>
|
<Undefine></Undefine>
|
||||||
<IncludePath>../Core/Inc;../Drivers/STM32F1xx_HAL_Driver/Inc;../Drivers/CMSIS/Device/ST/STM32F1xx/Include;../Drivers/CMSIS/Include;../User;../User/application;../User/board;../User/system/inc;../User/system/bsp;../User/lib/inc;../User/lib/flow</IncludePath>
|
<IncludePath>../Core/Inc;../Drivers/STM32F1xx_HAL_Driver/Inc;../Drivers/CMSIS/Device/ST/STM32F1xx/Include;../Drivers/CMSIS/Include;../User;../User/application;../User/board;../User/system/inc;../User/system/bsp;../User/lib/inc;../User/lib/flow;../User/lib/control/inc</IncludePath>
|
||||||
</VariousControls>
|
</VariousControls>
|
||||||
</Cads>
|
</Cads>
|
||||||
<Aads>
|
<Aads>
|
||||||
|
@ -596,6 +596,16 @@
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<FilePath>..\User\application\app.c</FilePath>
|
<FilePath>..\User\application\app.c</FilePath>
|
||||||
</File>
|
</File>
|
||||||
|
<File>
|
||||||
|
<FileName>key.c</FileName>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<FilePath>..\User\application\key.c</FilePath>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<FileName>work.c</FileName>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<FilePath>..\User\application\work.c</FilePath>
|
||||||
|
</File>
|
||||||
</Files>
|
</Files>
|
||||||
</Group>
|
</Group>
|
||||||
<Group>
|
<Group>
|
||||||
|
@ -1260,6 +1270,36 @@
|
||||||
</File>
|
</File>
|
||||||
</Files>
|
</Files>
|
||||||
</Group>
|
</Group>
|
||||||
|
<Group>
|
||||||
|
<GroupName>User/lib/control</GroupName>
|
||||||
|
<Files>
|
||||||
|
<File>
|
||||||
|
<FileName>pid.c</FileName>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<FilePath>..\User\lib\control\src\pid.c</FilePath>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<FileName>pid_auto_tune.c</FileName>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<FilePath>..\User\lib\control\src\pid_auto_tune.c</FilePath>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<FileName>pid_common.c</FileName>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<FilePath>..\User\lib\control\src\pid_common.c</FilePath>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<FileName>pid_fuzzy.c</FileName>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<FilePath>..\User\lib\control\src\pid_fuzzy.c</FilePath>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<FileName>pid_neural.c</FileName>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<FilePath>..\User\lib\control\src\pid_neural.c</FilePath>
|
||||||
|
</File>
|
||||||
|
</Files>
|
||||||
|
</Group>
|
||||||
<Group>
|
<Group>
|
||||||
<GroupName>::CMSIS</GroupName>
|
<GroupName>::CMSIS</GroupName>
|
||||||
</Group>
|
</Group>
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,6 +2,9 @@
|
||||||
#include "app.h"
|
#include "app.h"
|
||||||
#include "board.h"
|
#include "board.h"
|
||||||
#include "flow.h"
|
#include "flow.h"
|
||||||
|
#include "key.h"
|
||||||
|
#include "work.h"
|
||||||
|
|
||||||
static struct flow business_fw; // 业务流程
|
static struct flow business_fw; // 业务流程
|
||||||
static struct flow idle_fw; // 空闲任务
|
static struct flow idle_fw; // 空闲任务
|
||||||
|
|
||||||
|
@ -12,18 +15,24 @@ static uint8_t business_inspection(struct flow *fl)
|
||||||
FL_HEAD(fl);
|
FL_HEAD(fl);
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if (app.pwm_percent > 0)
|
switch (work.type)
|
||||||
{
|
{
|
||||||
GPIO_SET(AIN1_GPIO_Port, AIN1_Pin);
|
case WORK_PWM_MAP:
|
||||||
GPIO_RESET(AIN2_GPIO_Port, AIN2_Pin);
|
ssd1306_clear_buffer();
|
||||||
|
ssd1306_f8x16_string(0, 0, " PERCENT:");
|
||||||
|
ssd1306_f8x16_number(88, 0, work.pwm_percent, 0);
|
||||||
|
ssd1306_update_screen();
|
||||||
|
break;
|
||||||
|
case WORK_MOTOR_POS:
|
||||||
|
/* code */
|
||||||
|
break;
|
||||||
|
case WORK_MOTOR_SPEED:
|
||||||
|
/* code */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
FL_LOCK_DELAY(fl, FL_CLOCK_100MSEC);
|
||||||
{
|
|
||||||
GPIO_RESET(AIN1_GPIO_Port, AIN1_Pin);
|
|
||||||
GPIO_SET(AIN2_GPIO_Port, AIN2_Pin);
|
|
||||||
}
|
|
||||||
PWM_SET_DUTY(PWM_TIM, PWM_CHANNEL, ABS(app.pwm_percent));
|
|
||||||
FL_LOCK_DELAY(fl, FL_CLOCK_SEC*2);
|
|
||||||
}
|
}
|
||||||
FL_TAIL(fl);
|
FL_TAIL(fl);
|
||||||
}
|
}
|
||||||
|
@ -67,13 +76,12 @@ void app_run(void)
|
||||||
*/
|
*/
|
||||||
void app_init(void)
|
void app_init(void)
|
||||||
{
|
{
|
||||||
|
key_init();
|
||||||
|
work_init();
|
||||||
|
|
||||||
FL_INIT(&business_fw); // 业务流程
|
FL_INIT(&business_fw); // 业务流程
|
||||||
FL_INIT(&idle_fw); // 空闲任务
|
FL_INIT(&idle_fw); // 空闲任务
|
||||||
|
|
||||||
ENABLE_TIM(TASK_TIM);
|
ENABLE_TIM(TASK_TIM);
|
||||||
ENABLE_TIM(PWM_TIM);
|
ENABLE_TIM(WORK_TIM);
|
||||||
PWM_START(PWM_TIM, PWM_CHANNEL);
|
|
||||||
PWM_SET_DUTY(PWM_TIM, PWM_CHANNEL, 0);
|
|
||||||
|
|
||||||
app.pwm_feq = PWM_GET_FREQ(PWM_TIM);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
#include "key.h"
|
||||||
|
#include "btn.h"
|
||||||
|
#include "work.h"
|
||||||
|
/* 按钮 */
|
||||||
|
struct Button key_1;
|
||||||
|
struct Button key_2;
|
||||||
|
struct Button key_3;
|
||||||
|
struct Button key_4;
|
||||||
|
struct Button key_5;
|
||||||
|
struct Button key_6;
|
||||||
|
|
||||||
|
static uint8_t read_button_gpio(button_id_e button_id)
|
||||||
|
{
|
||||||
|
switch (button_id)
|
||||||
|
{
|
||||||
|
case KEY_ADD:
|
||||||
|
return GPIO_READ(KEY_ADD_GPIO_Port, KEY_ADD_Pin);
|
||||||
|
case KEY_SUB:
|
||||||
|
return GPIO_READ(KEY_SUB_GPIO_Port, KEY_SUB_Pin);
|
||||||
|
case KEY_S:
|
||||||
|
return GPIO_READ(KEY_S_GPIO_Port, KEY_S_Pin);
|
||||||
|
default:
|
||||||
|
return ACTIVE_LEVEL_HIGH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void key_1_press_down_handler(void *btn)
|
||||||
|
{
|
||||||
|
work_key_handle_cb(KEY_ADD);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void key_2_press_down_handler(void *btn)
|
||||||
|
{
|
||||||
|
work_key_handle_cb(KEY_SUB);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void key_3_press_down_handler(void *btn)
|
||||||
|
{
|
||||||
|
work_key_handle_cb(KEY_S);
|
||||||
|
}
|
||||||
|
|
||||||
|
void key_init(void)
|
||||||
|
{
|
||||||
|
GPIO_SET_INPUT(KEY_ADD_GPIO_Port, KEY_ADD_Pin);
|
||||||
|
GPIO_SET_INPUT(KEY_SUB_GPIO_Port, KEY_SUB_Pin);
|
||||||
|
GPIO_SET_INPUT(KEY_S_GPIO_Port, KEY_S_Pin);
|
||||||
|
|
||||||
|
button_init(&key_1, read_button_gpio, ACTIVE_LEVEL_LOW, KEY_ADD, KEY_ADD);
|
||||||
|
button_init(&key_2, read_button_gpio, ACTIVE_LEVEL_LOW, KEY_SUB, KEY_SUB);
|
||||||
|
button_init(&key_3, read_button_gpio, ACTIVE_LEVEL_LOW, KEY_S, KEY_S);
|
||||||
|
|
||||||
|
button_attach(&key_1, PRESS_DOWN, key_1_press_down_handler);
|
||||||
|
button_attach(&key_2, PRESS_DOWN, key_2_press_down_handler);
|
||||||
|
button_attach(&key_3, PRESS_DOWN, key_3_press_down_handler);
|
||||||
|
|
||||||
|
button_start(&key_1);
|
||||||
|
button_start(&key_2);
|
||||||
|
button_start(&key_3);
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
#ifndef _KEY_H_
|
||||||
|
#define _KEY_H_
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
KEY_ADD = 1,
|
||||||
|
KEY_SUB,
|
||||||
|
KEY_S,
|
||||||
|
} button_id_e;
|
||||||
|
|
||||||
|
void key_init(void);
|
||||||
|
#endif // _KEY_H_
|
|
@ -0,0 +1,130 @@
|
||||||
|
#include "work.h"
|
||||||
|
#include "board.h"
|
||||||
|
|
||||||
|
work_t work;
|
||||||
|
|
||||||
|
static void pwm_map(void)
|
||||||
|
{
|
||||||
|
set_motor_pwm(work.pwm_percent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void motor_pos(void)
|
||||||
|
{
|
||||||
|
work.pid.sub_type = PID_SUB_TYPE_POSITION;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void motor_speed(void)
|
||||||
|
{
|
||||||
|
work.pid.sub_type = PID_SUB_TYPE_INCREMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pwm_map_key_handle(button_id_e id)
|
||||||
|
{
|
||||||
|
int8_t min = -100, max = 100;
|
||||||
|
int8_t step = 10;
|
||||||
|
switch (id)
|
||||||
|
{
|
||||||
|
case KEY_ADD:
|
||||||
|
if (work.pwm_percent < max)
|
||||||
|
{
|
||||||
|
work.pwm_percent += step;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_SUB:
|
||||||
|
if (work.pwm_percent > min)
|
||||||
|
{
|
||||||
|
work.pwm_percent -= step;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_S:
|
||||||
|
work.pwm_percent = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void motot_pos_key_handle(button_id_e id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void motor_speed_key_handle(button_id_e id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void work_key_handle_cb(button_id_e id)
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (work.type)
|
||||||
|
{
|
||||||
|
case WORK_PWM_MAP:
|
||||||
|
pwm_map_key_handle(id);
|
||||||
|
break;
|
||||||
|
case WORK_MOTOR_POS:
|
||||||
|
motot_pos_key_handle(id);
|
||||||
|
break;
|
||||||
|
case WORK_MOTOR_SPEED:
|
||||||
|
motor_speed_key_handle(id);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DBG_ASSERT(FALSE __DBG_LINE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void work_process(void)
|
||||||
|
{
|
||||||
|
switch (work.type)
|
||||||
|
{
|
||||||
|
case WORK_PWM_MAP:
|
||||||
|
pwm_map();
|
||||||
|
break;
|
||||||
|
case WORK_MOTOR_POS:
|
||||||
|
motor_pos();
|
||||||
|
break;
|
||||||
|
case WORK_MOTOR_SPEED:
|
||||||
|
motor_speed();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void work_encoder_exti(void)
|
||||||
|
{
|
||||||
|
if (GPIO_READ(MOTOR_B_GPIO_Port, MOTOR_B_Pin))
|
||||||
|
{
|
||||||
|
work.encoder_cnt++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
work.encoder_cnt--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void work_init(void)
|
||||||
|
{
|
||||||
|
osel_memset((uint8_t *)&work, 0, sizeof(work_t));
|
||||||
|
PWM_START(PWM_TIM, PWM_CHANNEL);
|
||||||
|
PWM_SET_DUTY(PWM_TIM, PWM_CHANNEL, 0);
|
||||||
|
work.pwm_feq = PWM_GET_FREQ(PWM_TIM);
|
||||||
|
|
||||||
|
work.type = WORK_PWM_MAP;
|
||||||
|
work.pid_params.kp = 100;
|
||||||
|
work.pid_params.ki = 0.01;
|
||||||
|
work.pid_params.kd = 50;
|
||||||
|
work.pid_params.dead_zone = 0;
|
||||||
|
// PID初始化
|
||||||
|
|
||||||
|
{
|
||||||
|
work.pid.type = PID_TYPE_FUZZY;
|
||||||
|
work.pid.sub_type = PID_SUB_TYPE_POSITION;
|
||||||
|
work.pid.pid_u.fuzzy.deadzone_dir = DEAD_ZONE_BOTH;
|
||||||
|
pid_constructor(&work.pid);
|
||||||
|
work.pid.pid_u.fuzzy.set_ctrl_prm(&work.pid.pid_u.fuzzy, work.pid_params.kp, work.pid_params.ki,
|
||||||
|
work.pid_params.kd, work.pid_params.dead_zone, 0, -100, 100);
|
||||||
|
work.pid.pid_u.fuzzy.set_kd_enable(&work.pid.pid_u.fuzzy, TRUE);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
#ifndef __WORK_H__
|
||||||
|
#define __WORK_H__
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "key.h"
|
||||||
|
#include "pid.h"
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
// PWM占空比映射到电机
|
||||||
|
WORK_PWM_MAP = 0,
|
||||||
|
// 电机位置控制
|
||||||
|
WORK_MOTOR_POS = 1,
|
||||||
|
// 电机速度控制
|
||||||
|
WORK_MOTOR_SPEED = 2,
|
||||||
|
} work_e;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
work_e type;
|
||||||
|
int32_t encoder_cnt; // 编码器位置
|
||||||
|
float32 pwm_percent; // PWM占空比
|
||||||
|
uint32_t pwm_feq; // PWM频率
|
||||||
|
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
float32 kp;
|
||||||
|
float32 ki;
|
||||||
|
float32 kd;
|
||||||
|
float32 dead_zone;
|
||||||
|
} pid_params;
|
||||||
|
} work_t;
|
||||||
|
extern work_t work;
|
||||||
|
|
||||||
|
void work_init(void);
|
||||||
|
void work_process(void);
|
||||||
|
void work_key_handle_cb(button_id_e id);
|
||||||
|
void work_encoder_exti(void);
|
||||||
|
#endif // __WORK_H__
|
|
@ -24,6 +24,29 @@ static void motor_init(void)
|
||||||
GPIO_RESET(AIN2_GPIO_Port, AIN2_Pin);
|
GPIO_RESET(AIN2_GPIO_Port, AIN2_Pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置电机PWM占空比
|
||||||
|
*
|
||||||
|
* 根据给定的百分比设置电机的PWM占空比,以控制电机的转速。
|
||||||
|
*
|
||||||
|
* @param percent PWM占空比百分比,范围应在[-100, 100]之间。
|
||||||
|
* -100%表示反转最大速度,0%表示停止,100%表示正转最大速度。
|
||||||
|
*/
|
||||||
|
void set_motor_pwm(float32 percent)
|
||||||
|
{
|
||||||
|
if (percent > 0)
|
||||||
|
{
|
||||||
|
GPIO_SET(AIN1_GPIO_Port, AIN1_Pin);
|
||||||
|
GPIO_RESET(AIN2_GPIO_Port, AIN2_Pin);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GPIO_RESET(AIN1_GPIO_Port, AIN1_Pin);
|
||||||
|
GPIO_SET(AIN2_GPIO_Port, AIN2_Pin);
|
||||||
|
}
|
||||||
|
PWM_SET_DUTY(PWM_TIM, PWM_CHANNEL, ABS(percent));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 通过UART发送数据
|
* @brief 通过UART发送数据
|
||||||
*
|
*
|
||||||
|
|
|
@ -8,9 +8,12 @@
|
||||||
#define TASK_TIM TIM1
|
#define TASK_TIM TIM1
|
||||||
#define PWM_TIM TIM2
|
#define PWM_TIM TIM2
|
||||||
#define PWM_CHANNEL LL_TIM_CHANNEL_CH2
|
#define PWM_CHANNEL LL_TIM_CHANNEL_CH2
|
||||||
|
#define WORK_TIM TIM3
|
||||||
|
|
||||||
extern uart_t *uart;
|
extern uart_t *uart;
|
||||||
|
|
||||||
void board_init(void);
|
void board_init(void);
|
||||||
void uart_send(uint8_t *data, uint16_t len);
|
void uart_send(uint8_t *data, uint16_t len);
|
||||||
|
void set_motor_pwm(float32 percent);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -482,11 +482,16 @@ void ssd1306_clear(void)
|
||||||
ssd1306_update_screen();
|
ssd1306_update_screen();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ssd1306_clear_buffer(void)
|
||||||
|
{
|
||||||
|
osel_memset(_buffer, 0, ARRAY_LEN(_buffer));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 在指定区域内绘制BMP
|
* @brief 在指定区域内绘制BMP
|
||||||
*
|
*
|
||||||
* 在指定坐标区域内绘制一个BMP,使用SSD1306 OLED显示屏
|
* 在指定坐标区域内绘制一个BMP,使用SSD1306 OLED显示屏
|
||||||
* ssd1306_draw_bmp(0, 0, 128, 2);
|
* ssd1306_draw_bmp(0, 0, SSD1306_WIDTH, 2);
|
||||||
* @param x0 BMP绘制的起始X坐标
|
* @param x0 BMP绘制的起始X坐标
|
||||||
* @param y0 BMP绘制的起始Y坐标
|
* @param y0 BMP绘制的起始Y坐标
|
||||||
* @param x1 BMP绘制的结束X坐标
|
* @param x1 BMP绘制的结束X坐标
|
||||||
|
@ -532,7 +537,7 @@ void ssd1306_f6x8_string(uint8_t x, uint8_t y, const uint8_t *ch)
|
||||||
y++;
|
y++;
|
||||||
}
|
}
|
||||||
for (i = 0; i < 6; i++)
|
for (i = 0; i < 6; i++)
|
||||||
_buffer[(y * 128) + x + i] = F6x8[c][i];
|
_buffer[(y * SSD1306_WIDTH) + x + i] = F6x8[c][i];
|
||||||
x += 6;
|
x += 6;
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
|
@ -564,7 +569,7 @@ void ssd1306_f6x8_string_number(uint8_t x, uint8_t y, const uint8_t *ch, uint8_t
|
||||||
y++;
|
y++;
|
||||||
}
|
}
|
||||||
for (i = 0; i < 6; i++)
|
for (i = 0; i < 6; i++)
|
||||||
_buffer[(y * 128) + x + i] = F6x8[c][i];
|
_buffer[(y * SSD1306_WIDTH) + x + i] = F6x8[c][i];
|
||||||
x += 6;
|
x += 6;
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
|
@ -600,7 +605,7 @@ void ssd1306_f6x8_string_number(uint8_t x, uint8_t y, const uint8_t *ch, uint8_t
|
||||||
y++;
|
y++;
|
||||||
}
|
}
|
||||||
for (i = 0; i < 6; i++)
|
for (i = 0; i < 6; i++)
|
||||||
_buffer[(y * 128) + x + i] = F6x8[c][i];
|
_buffer[(y * SSD1306_WIDTH) + x + i] = F6x8[c][i];
|
||||||
x += 6;
|
x += 6;
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
|
@ -608,7 +613,7 @@ void ssd1306_f6x8_string_number(uint8_t x, uint8_t y, const uint8_t *ch, uint8_t
|
||||||
{
|
{
|
||||||
c = unit - 32;
|
c = unit - 32;
|
||||||
for (i = 0; i < 6; i++)
|
for (i = 0; i < 6; i++)
|
||||||
_buffer[(y * 128) + x + i] = F6x8[c][i];
|
_buffer[(y * SSD1306_WIDTH) + x + i] = F6x8[c][i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -633,9 +638,9 @@ void ssd1306_f8x16_string(uint8_t x, uint8_t y, const uint8_t *ch)
|
||||||
y++;
|
y++;
|
||||||
}
|
}
|
||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++)
|
||||||
_buffer[(y * 128) + x + i] = F8X16[c * 16 + i];
|
_buffer[(y * SSD1306_WIDTH) + x + i] = F8X16[c * 16 + i];
|
||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++)
|
||||||
_buffer[((y + 1) * 128) + x + i] = F8X16[c * 16 + i + 8];
|
_buffer[((y + 1) * SSD1306_WIDTH) + x + i] = F8X16[c * 16 + i + 8];
|
||||||
x += 8;
|
x += 8;
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
|
@ -665,7 +670,7 @@ void ssd1306_f8x16_number(uint8_t x, uint8_t y, float32 num, uint8_t dot_num)
|
||||||
|
|
||||||
c = 8 - i;
|
c = 8 - i;
|
||||||
|
|
||||||
if (num > 10000)
|
if (num >= 10000)
|
||||||
{
|
{
|
||||||
ch[i++] = num / 10000 + 48;
|
ch[i++] = num / 10000 + 48;
|
||||||
ch[i++] = (uint8_t)(num) % 10000 / 1000 + 48;
|
ch[i++] = (uint8_t)(num) % 10000 / 1000 + 48;
|
||||||
|
@ -673,20 +678,20 @@ void ssd1306_f8x16_number(uint8_t x, uint8_t y, float32 num, uint8_t dot_num)
|
||||||
ch[i++] = (uint8_t)(num) % 100 / 10 + 48;
|
ch[i++] = (uint8_t)(num) % 100 / 10 + 48;
|
||||||
ch[i++] = (uint8_t)(num) % 10 + 48;
|
ch[i++] = (uint8_t)(num) % 10 + 48;
|
||||||
}
|
}
|
||||||
else if (num > 1000)
|
else if (num >= 1000)
|
||||||
{
|
{
|
||||||
ch[i++] = (uint8_t)(num) % 10000 / 1000 + 48;
|
ch[i++] = (uint8_t)(num) % 10000 / 1000 + 48;
|
||||||
ch[i++] = (uint8_t)(num) % 1000 / 100 + 48;
|
ch[i++] = (uint8_t)(num) % 1000 / 100 + 48;
|
||||||
ch[i++] = (uint8_t)(num) % 100 / 10 + 48;
|
ch[i++] = (uint8_t)(num) % 100 / 10 + 48;
|
||||||
ch[i++] = (uint8_t)(num) % 10 + 48;
|
ch[i++] = (uint8_t)(num) % 10 + 48;
|
||||||
}
|
}
|
||||||
else if (num > 100)
|
else if (num >= 100)
|
||||||
{
|
{
|
||||||
ch[i++] = (uint8_t)(num) % 1000 / 100 + 48;
|
ch[i++] = (uint8_t)(num) % 1000 / 100 + 48;
|
||||||
ch[i++] = (uint8_t)(num) % 100 / 10 + 48;
|
ch[i++] = (uint8_t)(num) % 100 / 10 + 48;
|
||||||
ch[i++] = (uint8_t)(num) % 10 + 48;
|
ch[i++] = (uint8_t)(num) % 10 + 48;
|
||||||
}
|
}
|
||||||
else if (num > 10)
|
else if (num >= 10)
|
||||||
{
|
{
|
||||||
ch[i++] = (uint8_t)(num) % 100 / 10 + 48;
|
ch[i++] = (uint8_t)(num) % 100 / 10 + 48;
|
||||||
ch[i++] = (uint8_t)(num) % 10 + 48;
|
ch[i++] = (uint8_t)(num) % 10 + 48;
|
||||||
|
@ -723,9 +728,9 @@ void ssd1306_f8x16_number(uint8_t x, uint8_t y, float32 num, uint8_t dot_num)
|
||||||
y++;
|
y++;
|
||||||
}
|
}
|
||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++)
|
||||||
_buffer[(y * 128) + x + i] = F8X16[c * 16 + i];
|
_buffer[(y * SSD1306_WIDTH) + x + i] = F8X16[c * 16 + i];
|
||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++)
|
||||||
_buffer[((y + 1) * 128) + x + i] = F8X16[c * 16 + i + 8];
|
_buffer[((y + 1) * SSD1306_WIDTH) + x + i] = F8X16[c * 16 + i + 8];
|
||||||
x += 8;
|
x += 8;
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,7 @@ void ssd1306_update_screen(void);
|
||||||
|
|
||||||
void ssd1306_fill(uint8_t color);
|
void ssd1306_fill(uint8_t color);
|
||||||
void ssd1306_clear(void);
|
void ssd1306_clear(void);
|
||||||
|
void ssd1306_clear_buffer(void);
|
||||||
void ssd1306_draw_bmp(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t *bmp);
|
void ssd1306_draw_bmp(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t *bmp);
|
||||||
void ssd1306_f6x8_string(uint8_t x, uint8_t y, const uint8_t *ch);
|
void ssd1306_f6x8_string(uint8_t x, uint8_t y, const uint8_t *ch);
|
||||||
void ssd1306_f6x8_string_number(uint8_t x, uint8_t y, const uint8_t *ch, uint8_t unit, float32 num);
|
void ssd1306_f6x8_string_number(uint8_t x, uint8_t y, const uint8_t *ch, uint8_t unit, float32 num);
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
#include "pid_c.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 设置PID控制器参数
|
|
||||||
* @param {PID_C} *self - PID控制器结构体指针
|
|
||||||
* @param {float32} kp - 比例系数
|
|
||||||
* @param {float32} ki - 积分系数
|
|
||||||
* @param {float32} kd - 微分系数
|
|
||||||
* @param {float32} out_min - 最小输出
|
|
||||||
* @param {float32} out_max - 最大输出
|
|
||||||
* @return {*} - 空
|
|
||||||
*/
|
|
||||||
static void _set_ctrl_prm(struct PID_C *self, float32 kp, float32 ki, float32 kd, float32 out_min, float32 out_max)
|
|
||||||
{
|
|
||||||
self->pri.kp = kp; /*比例系数*/
|
|
||||||
self->pri.ki = ki; /*积分系数*/
|
|
||||||
self->pri.kd = kd; /*微分系数*/
|
|
||||||
|
|
||||||
self->pri.deadband = 0.5; /*死区*/
|
|
||||||
self->pri.maximum = out_max; /*最大输出*/
|
|
||||||
self->pri.minimum = out_min; /*最小输出*/
|
|
||||||
self->pri.last_error = 0; /*上一次误差*/
|
|
||||||
self->pri.prev_error = 0; /*上上次误差*/
|
|
||||||
}
|
|
||||||
|
|
||||||
static float32 _PID(struct PID_C *self, float32 target, float32 feedback)
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* 实现PID算法
|
|
||||||
*/
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pid_c_constructor(struct PID_C *self)
|
|
||||||
{
|
|
||||||
self->set_ctrl_prm = _set_ctrl_prm;
|
|
||||||
self->PID = _PID;
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
#ifndef __PID_C_H__
|
|
||||||
#define __PID_C_H__
|
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
typedef struct PID_C
|
|
||||||
{
|
|
||||||
/* 设置PID三个参数 */
|
|
||||||
void (*set_ctrl_prm)(struct PID_C *self, float32 kp, float32 ki, float32 kd, float32 out_min, float32 out_max);
|
|
||||||
/* 控制接口 */
|
|
||||||
float32 (*PID)(struct PID_C *self, float32 target, float32 feedback);
|
|
||||||
|
|
||||||
// 自定义参数
|
|
||||||
/* 实际值与目标值之间的误差 */
|
|
||||||
float32 err;
|
|
||||||
/* 输出值 */
|
|
||||||
float32 out;
|
|
||||||
/* private */
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
float32 kp; /*比例学习速度*/
|
|
||||||
float32 ki; /*积分学习速度*/
|
|
||||||
float32 kd; /*微分学习速度*/
|
|
||||||
float32 ki_error; /*积分误差*/
|
|
||||||
float32 last_error; /*前一拍偏差*/
|
|
||||||
float32 prev_error; /*前两拍偏差*/
|
|
||||||
float32 deadband; /*死区*/
|
|
||||||
float32 maximum; /*输出值的上限*/
|
|
||||||
float32 minimum; /*输出值的下限*/
|
|
||||||
} pri;
|
|
||||||
} pid_c_t;
|
|
||||||
|
|
||||||
extern void pid_c_constructor(struct PID_C *self);
|
|
||||||
|
|
||||||
#endif // __PID_C_H__
|
|
|
@ -1,285 +0,0 @@
|
||||||
#include "pid_g.h"
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 复位PID积分及微分控制数据
|
|
||||||
* @param {PID_G} *self
|
|
||||||
* @return {*}
|
|
||||||
*/
|
|
||||||
static void _restctrl(struct PID_G *self)
|
|
||||||
{
|
|
||||||
self->pri.pre_error = 0;
|
|
||||||
self->pri.sum_iterm = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 更新控制区间
|
|
||||||
* @param {PID_G} *self
|
|
||||||
* @param {float32} out_min
|
|
||||||
* @param {float32} out_max
|
|
||||||
* @return {*}
|
|
||||||
* @note
|
|
||||||
*/
|
|
||||||
static void _set_range(struct PID_G *self, float32 out_min, float32 out_max)
|
|
||||||
{
|
|
||||||
self->pri.out_max = out_max;
|
|
||||||
self->pri.out_min = out_min;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 更新kp
|
|
||||||
* @param {PID_G} *self
|
|
||||||
* @param {float32} kp
|
|
||||||
* @return {*}
|
|
||||||
* @note
|
|
||||||
*/
|
|
||||||
static void _set_kp(struct PID_G *self, float32 kp)
|
|
||||||
{
|
|
||||||
self->pri.kp = kp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 更新ki
|
|
||||||
* @param {PID_G} *self
|
|
||||||
* @param {float32} ki
|
|
||||||
* @return {*}
|
|
||||||
* @note
|
|
||||||
*/
|
|
||||||
static void _set_ki(struct PID_G *self, float32 ki)
|
|
||||||
{
|
|
||||||
self->pri.ki = ki;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 更新kd
|
|
||||||
* @param {PID_G} *self
|
|
||||||
* @param {float32} kd
|
|
||||||
* @return {*}
|
|
||||||
* @note
|
|
||||||
*/
|
|
||||||
static void _set_kd(struct PID_G *self, float32 kd)
|
|
||||||
{
|
|
||||||
self->pri.kd = kd;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 使能积分控制
|
|
||||||
* @param {PID_G} *self
|
|
||||||
* @param {BOOL} enable
|
|
||||||
* @return {*}
|
|
||||||
* @note
|
|
||||||
*/
|
|
||||||
static void _set_ki_enable(struct PID_G *self, BOOL enable)
|
|
||||||
{
|
|
||||||
self->pri.ki_enable = enable;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 使能微分控制
|
|
||||||
* @param {PID_G} *self
|
|
||||||
* @param {BOOL} enable
|
|
||||||
* @return {*}
|
|
||||||
* @note
|
|
||||||
*/
|
|
||||||
static void _set_kd_enable(struct PID_G *self, BOOL enable)
|
|
||||||
{
|
|
||||||
self->pri.kd_enable = enable;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 初始化控制参数
|
|
||||||
* @return {*}
|
|
||||||
* @note
|
|
||||||
*/
|
|
||||||
static void _set_ctrl_prm(struct PID_G *self, float32 kp, float32 ki, float32 kd, float32 err_dead, float32 out_min, float32 out_max)
|
|
||||||
{
|
|
||||||
g_param_t *pri = &self->pri;
|
|
||||||
osel_memset((uint8_t *)pri, 0, sizeof(pid_g_t));
|
|
||||||
pri->kp = kp;
|
|
||||||
pri->ki = ki;
|
|
||||||
pri->kd = kd;
|
|
||||||
pri->err_dead = err_dead;
|
|
||||||
pri->out_max = out_max;
|
|
||||||
pri->out_min = out_min;
|
|
||||||
pri->detach = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _update_ctrl_prm(struct PID_G *self, float32 kp, float32 ki, float32 kd, float32 err_dead, float32 out_min, float32 out_max)
|
|
||||||
{
|
|
||||||
g_param_t *pri = &self->pri;
|
|
||||||
pri->kp = kp;
|
|
||||||
pri->ki = ki;
|
|
||||||
pri->kd = kd;
|
|
||||||
pri->err_dead = err_dead;
|
|
||||||
pri->out_max = out_max;
|
|
||||||
pri->out_min = out_min;
|
|
||||||
pri->detach = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 非0时配置为积分分离+抗积分饱和PID,否则为普通抗积分饱和PID
|
|
||||||
* @param {PID_G} *self
|
|
||||||
* @param {float32} max_err
|
|
||||||
* @param {BOOL} mode
|
|
||||||
* @return {*}
|
|
||||||
*/
|
|
||||||
static void _set_cfg(struct PID_G *self, float32 max_err, BOOL mode)
|
|
||||||
{
|
|
||||||
self->pri.err_limit = max_err;
|
|
||||||
self->pri.detach = mode == FALSE ? FALSE : TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 设置积分权重
|
|
||||||
* @param {PID_G} *self
|
|
||||||
* @param {float32} max_weight
|
|
||||||
* @return {*}
|
|
||||||
* @note
|
|
||||||
*/
|
|
||||||
static void _set_weight(struct PID_G *self, float32 max_ratio, BOOL mode)
|
|
||||||
{
|
|
||||||
self->pri.ui_ratio = max_ratio;
|
|
||||||
self->pri.weight = mode == FALSE ? FALSE : TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief PID算法函数
|
|
||||||
* @param {PID_G} *self
|
|
||||||
* @param {float32} target 目标位置
|
|
||||||
* @param {float32} feedback 实际位置
|
|
||||||
* @return {*}
|
|
||||||
* @note
|
|
||||||
*/
|
|
||||||
static float32 _PID(struct PID_G *self, float32 target, float32 feedback)
|
|
||||||
{
|
|
||||||
float32 error = 0.0f;
|
|
||||||
float32 insert = 0.0f; ///< 该值为0时积分不介入计算
|
|
||||||
float32 temp_iterm = 0.0f;
|
|
||||||
float32 temp_kd = 0.0f;
|
|
||||||
|
|
||||||
g_param_t *pri = &self->pri;
|
|
||||||
|
|
||||||
pri->ref = target; ///< 目标位置
|
|
||||||
pri->feed_back = feedback; ///< 实际位置
|
|
||||||
pri->error = pri->ref - pri->feed_back; /// 误差
|
|
||||||
error = pri->error;
|
|
||||||
if (fabs(pri->error) <= pri->err_dead) ///< 误差小于死区,不计算
|
|
||||||
{
|
|
||||||
error = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*根据PID配置的模式,获取积分数据,进行积分累加*/
|
|
||||||
if (pri->out >= pri->out_max) ///< 到达输出上限
|
|
||||||
{
|
|
||||||
if (fabs(error) > pri->err_limit && pri->detach) ///< 误差大于积分介入区间,积分不介入计算
|
|
||||||
{
|
|
||||||
insert = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
insert = 1;
|
|
||||||
if (error < 0)
|
|
||||||
{
|
|
||||||
temp_iterm = pri->ki * error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pri->out <= pri->out_min) ///< 到达输出下限
|
|
||||||
{
|
|
||||||
if (fabs(error) > pri->err_limit && pri->detach) ///< 误差大于积分介入区间,积分不介入计算
|
|
||||||
{
|
|
||||||
insert = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
insert = 1;
|
|
||||||
if (error > 0)
|
|
||||||
{
|
|
||||||
temp_iterm = pri->ki * error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (fabs(error) > pri->err_limit && pri->detach)
|
|
||||||
{
|
|
||||||
insert = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
insert = 1;
|
|
||||||
temp_iterm = pri->ki * error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pri->ki_enable == FALSE)
|
|
||||||
{
|
|
||||||
temp_iterm = 0;
|
|
||||||
insert = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* integral */
|
|
||||||
pri->sum_iterm += temp_iterm;
|
|
||||||
|
|
||||||
if (pri->weight == TRUE)
|
|
||||||
{
|
|
||||||
if (pri->sum_iterm > pri->ui_ratio)
|
|
||||||
{
|
|
||||||
pri->sum_iterm = pri->ui_ratio;
|
|
||||||
}
|
|
||||||
else if (pri->sum_iterm < -pri->ui_ratio)
|
|
||||||
{
|
|
||||||
pri->sum_iterm = -pri->ui_ratio;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (pri->sum_iterm > pri->out_max)
|
|
||||||
{
|
|
||||||
pri->sum_iterm = pri->out_max;
|
|
||||||
}
|
|
||||||
else if (pri->sum_iterm < pri->out_min)
|
|
||||||
{
|
|
||||||
pri->sum_iterm = pri->out_min;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* differential */
|
|
||||||
if (pri->kd_enable == TRUE)
|
|
||||||
{
|
|
||||||
temp_kd = pri->kd;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
temp_kd = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pri->out = pri->kp * pri->error + pri->sum_iterm * insert + (pri->error - pri->pre_error) * temp_kd;
|
|
||||||
pri->pre_error = pri->error; ///< 记录这次误差,为下次微分计算做准备
|
|
||||||
pri->pre_feed_back = pri->feed_back;
|
|
||||||
|
|
||||||
/*limt pid output*/
|
|
||||||
pri->out = RANGE(pri->out, pri->out_min, pri->out_max); ///< 限制输出
|
|
||||||
return pri->out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief PID接口
|
|
||||||
* @param {PID_G} *self
|
|
||||||
* @return {*}
|
|
||||||
* @note
|
|
||||||
*/
|
|
||||||
void pid_g_constructor(struct PID_G *self)
|
|
||||||
{
|
|
||||||
self->set_ctrl_prm = _set_ctrl_prm;
|
|
||||||
self->update_ctrl_prm = _update_ctrl_prm;
|
|
||||||
self->set_cfg = _set_cfg;
|
|
||||||
self->set_kp = _set_kp;
|
|
||||||
self->set_ki_enable = _set_ki_enable;
|
|
||||||
self->set_ki = _set_ki;
|
|
||||||
self->set_kd_enable = _set_kd_enable;
|
|
||||||
self->set_kd = _set_kd;
|
|
||||||
self->set_range = _set_range;
|
|
||||||
self->restctrl = _restctrl;
|
|
||||||
self->PID = _PID;
|
|
||||||
self->set_weight = _set_weight;
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
#ifndef __PID_G_H__
|
|
||||||
#define __PID_G_H__
|
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
float32 ref; /*目标*/
|
|
||||||
float32 feed_back; /*实际*/
|
|
||||||
float32 pre_feed_back; /*上一次实际*/
|
|
||||||
float32 kp; /*比例学习速度*/
|
|
||||||
float32 ki; /*积分学习速度*/
|
|
||||||
float32 kd; /*微分学习速度*/
|
|
||||||
float32 ki_error; /*积分误差*/
|
|
||||||
float32 error; /*误差*/
|
|
||||||
float32 pre_error; /*前一拍偏差*/
|
|
||||||
float32 prev_error; /*前两拍偏差*/
|
|
||||||
float32 err_dead; /*死区*/
|
|
||||||
float32 err_limit; /*积分分离上限*/
|
|
||||||
float32 maximum; /*输出值的上限*/
|
|
||||||
float32 minimum; /*输出值的下限*/
|
|
||||||
float32 out; /*输出值*/
|
|
||||||
float32 sum_iterm; /*积分累加*/
|
|
||||||
float32 ui_ratio; /*积分权重*/
|
|
||||||
BOOL ki_enable; /*积分使能*/
|
|
||||||
BOOL kd_enable; /*微分使能*/
|
|
||||||
BOOL detach; /*积分分离标志*/
|
|
||||||
BOOL weight; /*积分权重标志*/
|
|
||||||
float32 out_max; /*输出最大值*/
|
|
||||||
float32 out_min; /*输出最小值*/
|
|
||||||
} g_param_t;
|
|
||||||
|
|
||||||
typedef struct PID_G
|
|
||||||
{
|
|
||||||
/* 设置PID三个参数 */
|
|
||||||
void (*set_ctrl_prm)(struct PID_G *self, float32 kp, float32 ki, float32 kd, float32 err_dead, float32 out_min, float32 out_max);
|
|
||||||
/* 更新PID参数 */
|
|
||||||
void (*update_ctrl_prm)(struct PID_G *self, float32 kp, float32 ki, float32 kd, float32 err_dead, float32 out_min, float32 out_max);
|
|
||||||
/* 控制接口 */
|
|
||||||
float32 (*PID)(struct PID_G *self, float32 target, float32 feedback);
|
|
||||||
/* 更新控制区间 */
|
|
||||||
void (*set_range)(struct PID_G *self, float32 out_min, float32 out_max);
|
|
||||||
/* 设置积分分离 */
|
|
||||||
void (*set_cfg)(struct PID_G *self, float32 max_err, BOOL mode);
|
|
||||||
/* 设置积分权重 */
|
|
||||||
void (*set_weight)(struct PID_G *self, float32 max_ratio, BOOL mode);
|
|
||||||
/* 更新kp */
|
|
||||||
void (*set_kp)(struct PID_G *self, float32 kp);
|
|
||||||
/* 使能ki */
|
|
||||||
void (*set_ki_enable)(struct PID_G *self, BOOL enable);
|
|
||||||
/* 更新ki */
|
|
||||||
void (*set_ki)(struct PID_G *self, float32 ki);
|
|
||||||
/* 使能kd */
|
|
||||||
void (*set_kd_enable)(struct PID_G *self, BOOL enable);
|
|
||||||
/* 更新kd */
|
|
||||||
void (*set_kd)(struct PID_G *self, float32 kd);
|
|
||||||
/* 复位PID积分及微分控制数据 */
|
|
||||||
void (*restctrl)(struct PID_G *self);
|
|
||||||
|
|
||||||
/* private */
|
|
||||||
g_param_t pri;
|
|
||||||
|
|
||||||
} pid_g_t;
|
|
||||||
|
|
||||||
extern void pid_g_constructor(struct PID_G *self);
|
|
||||||
#endif // __PID_G_H__
|
|
|
@ -1,166 +0,0 @@
|
||||||
#include "pid_hd.h"
|
|
||||||
#include <math.h>
|
|
||||||
#include "sys.h"
|
|
||||||
#include "app.h"
|
|
||||||
|
|
||||||
#if INCOMPLETE_DIFFEREN_HD == 1 // 积分分离
|
|
||||||
/*计算微分项,使用追随误差微分项*/
|
|
||||||
static float32 td_derivative(struct PID_HD *self, float32 current_err, float32 pre_err, float32 dt)
|
|
||||||
{
|
|
||||||
pid_hd_position_t *pri = &self->pri_u.position;
|
|
||||||
float32 derivative = (current_err - pre_err) / dt; // 计算积分项
|
|
||||||
derivative = pri->td_alpha * derivative + (1 - pri->td_alpha) * pri->td_beta * pri->pre_derivative; // 追随误差微分器平滑输出
|
|
||||||
pri->pre_derivative = derivative; // 更新上一次误差
|
|
||||||
return derivative;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*杭电:设置位置式PID参数*/
|
|
||||||
static void _set_ctrl_prm_position(struct PID_HD *self, float32 kp, float32 ki, float32 kd)
|
|
||||||
{
|
|
||||||
pid_hd_position_t *pri = &self->pri_u.position;
|
|
||||||
osel_memset((uint8_t *)pri, 0, sizeof(pid_hd_position_t));
|
|
||||||
|
|
||||||
/*观测传进来的Kp、Ki、Kd*/
|
|
||||||
|
|
||||||
pri->kp = kp;
|
|
||||||
pri->ki = ki;
|
|
||||||
pri->kd = kd;
|
|
||||||
pri->ki_limit = 10; // 积分分离界限
|
|
||||||
pri->err_dead = 0.5; // 控制死区范围
|
|
||||||
#if INCOMPLETE_DIFFEREN_HD == 1
|
|
||||||
/*不完全微分系数*/
|
|
||||||
pri->td_alpha = 0.5;
|
|
||||||
pri->td_beta = 0.5;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*杭电:设置输出限幅参数*/
|
|
||||||
static void _set_out_prm_position(struct PID_HD *self, float32 maximum, float32 minimum)
|
|
||||||
{
|
|
||||||
self->pri_u.position.out_max = maximum;
|
|
||||||
self->pri_u.position.out_min = minimum;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*杭电:位置式PID控制算法*/
|
|
||||||
static float32 _pid_position(struct PID_HD *self, float32 err)
|
|
||||||
{
|
|
||||||
/*计算控制的运行时间*/
|
|
||||||
// sys_millis_reset();
|
|
||||||
self->pri_u.position.control_time = sys_millis();
|
|
||||||
self->pri_u.position.tmp_time = 0;
|
|
||||||
|
|
||||||
/*测试:4.18*/
|
|
||||||
if (fabs(err) < 0.1)
|
|
||||||
{
|
|
||||||
err = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
float32 x[3];
|
|
||||||
self->pri_u.position.err = err;
|
|
||||||
|
|
||||||
/*抗积分饱和*/
|
|
||||||
#if INTEGRAL_SEPARATION == 1 // 积分分离
|
|
||||||
if (self->pri_u.position.out > self->pri_u.position.out_max)
|
|
||||||
{
|
|
||||||
if (self->pri_u.position.err > self->pri_u.position.ki_limit) // 积分分离
|
|
||||||
{
|
|
||||||
self->pri_u.position.ki_error += 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (self->pri_u.position.err < 0) // 若偏差为负值,执行负偏差的累加
|
|
||||||
{
|
|
||||||
self->pri_u.position.ki_error += self->pri_u.position.err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (self->pri_u.position.out < self->pri_u.position.out_min)
|
|
||||||
{
|
|
||||||
if (self->pri_u.position.err > self->pri_u.position.ki_limit) // 若偏差为负值,停止积分
|
|
||||||
{
|
|
||||||
self->pri_u.position.ki_error += 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (self->pri_u.position.err > 0) // 若偏差为正值,执行正偏差的累加
|
|
||||||
{
|
|
||||||
self->pri_u.position.ki_error += self->pri_u.position.err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (fabs(err) > self->pri_u.position.ki_limit || fabs(err) < 0.5)
|
|
||||||
{
|
|
||||||
self->pri_u.position.ki_error += 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
self->pri_u.position.ki_error += self->pri_u.position.err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else /*无积分分离操作*/
|
|
||||||
if (fabs(err) < 0.4)
|
|
||||||
{
|
|
||||||
self->pri_u.position.ki_error += 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
self->pri_u.position.ki_error += self->pri_u.position.err;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*输出*/
|
|
||||||
if (fabs(err) < self->pri_u.position.err_dead)
|
|
||||||
{
|
|
||||||
/*输出上一次的值*/
|
|
||||||
// self->pri_u.position.out = self->pri_u.position.pre_out;
|
|
||||||
x[0] = self->pri_u.position.err;
|
|
||||||
x[1] = self->pri_u.position.ki_error;
|
|
||||||
self->pri_u.position.out = self->pri_u.position.kp * x[0] + self->pri_u.position.ki * x[1] + self->pri_u.position.kd * x[2];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x[0] = self->pri_u.position.err;
|
|
||||||
x[1] = self->pri_u.position.ki_error;
|
|
||||||
|
|
||||||
#if INCOMPLETE_DIFFEREN_HD == 1
|
|
||||||
/*不完全微分项,为了解决普通PID为微分环节容易振荡的问题*/
|
|
||||||
self->pri_u.position.tmp_time = sys_millis();
|
|
||||||
self->pri_u.position.control_time -= self->pri_u.position.tmp_time;
|
|
||||||
self->pri_u.position.control_time /= 1000.0; // 将单位转换为秒
|
|
||||||
x[2] = td_derivative(&_pid.pid_u.hd, err, self->pri_u.position.pre_error, self->pri_u.position.control_time);
|
|
||||||
#else
|
|
||||||
// 普通的微分环节
|
|
||||||
x[2] = self->pri_u.position.err - self->pri_u.position.pre_error;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
self->pri_u.position.out = self->pri_u.position.kp * x[0] + self->pri_u.position.ki * x[1] + self->pri_u.position.kd * x[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*输出限幅*/
|
|
||||||
if (self->pri_u.position.out > self->pri_u.position.out_max)
|
|
||||||
{
|
|
||||||
self->pri_u.position.out = self->pri_u.position.out_max;
|
|
||||||
}
|
|
||||||
if (self->pri_u.position.out < self->pri_u.position.out_min)
|
|
||||||
{
|
|
||||||
self->pri_u.position.out = self->pri_u.position.out_min;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新误差历史
|
|
||||||
self->pri_u.position.pre_error = self->pri_u.position.err; /*上一次误差值*/
|
|
||||||
// 更新输出历史
|
|
||||||
self->pri_u.position.pre_out = self->pri_u.position.out; /*上一次输出值*/
|
|
||||||
|
|
||||||
return self->pri_u.position.out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*杭电:参数控制器*/
|
|
||||||
void pid_hd_constructor(struct PID_HD *self)
|
|
||||||
{
|
|
||||||
self->set_ctrl_prm_position = _set_ctrl_prm_position;
|
|
||||||
self->set_out_prm_position = _set_out_prm_position;
|
|
||||||
self->pid_position = _pid_position;
|
|
||||||
}
|
|
|
@ -1,66 +0,0 @@
|
||||||
#ifndef __PID_HD__
|
|
||||||
#define __PID_HD__
|
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
#define INTEGRAL_SEPARATION 1 // 积分分离
|
|
||||||
#define INCOMPLETE_DIFFEREN_HD 1 // 不完全微分
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
float32 ref;
|
|
||||||
float32 feed_back;
|
|
||||||
float32 pre_feed_back;
|
|
||||||
float32 pre_error;
|
|
||||||
float32 ki_error; /*积分误差*/
|
|
||||||
float32 ki_limit; /*积分分离界限*/
|
|
||||||
float32 ki_alpha; /*变积分的系数*/
|
|
||||||
float32 err;
|
|
||||||
float32 sum_iterm;
|
|
||||||
float32 kp;
|
|
||||||
float32 kp_small; /*在接近稳态时的Kp*/
|
|
||||||
float32 kp_big; /*在大范围时的Kp*/
|
|
||||||
float32 ki;
|
|
||||||
float32 kd;
|
|
||||||
float32 err_limit;
|
|
||||||
BOOL detach;
|
|
||||||
float32 err_dead;
|
|
||||||
#if INCOMPLETE_DIFFEREN_HD == 1
|
|
||||||
float32 td_alpha; /*不完全微分系数*/
|
|
||||||
float32 td_beta; /*不完全微分系数beta*/
|
|
||||||
float32 pre_derivative; /*上一次微分值*/
|
|
||||||
#endif
|
|
||||||
float32 out;
|
|
||||||
float32 pre_out;
|
|
||||||
float32 out_max;
|
|
||||||
float32 out_min;
|
|
||||||
BOOL sm;
|
|
||||||
float32 sv_range;
|
|
||||||
uint32_t control_time; /*控制算法运行一次花费的时间*/
|
|
||||||
uint32_t tmp_time; /*临时用来记录控制的运行时间*/
|
|
||||||
} pid_hd_position_t; // 位置式PID
|
|
||||||
|
|
||||||
typedef struct PID_HD
|
|
||||||
{
|
|
||||||
/* 设置PID三个参数 */
|
|
||||||
void (*set_ctrl_prm_position)(struct PID_HD *self, float32 kp, float32 ki, float32 kd);
|
|
||||||
/* 设置输出范围 */
|
|
||||||
void (*set_out_prm_position)(struct PID_HD *self, float32 maximum, float32 minimum);
|
|
||||||
|
|
||||||
/* 控制接口 */
|
|
||||||
float32 (*pid_position)(struct PID_HD *self, float32 err);
|
|
||||||
|
|
||||||
// 自定义参数
|
|
||||||
/* 实际值与目标值之间的误差 */
|
|
||||||
float32 err;
|
|
||||||
/* 输出值 */
|
|
||||||
float32 out;
|
|
||||||
/* private */
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
pid_hd_position_t position;
|
|
||||||
} pri_u;
|
|
||||||
} pid_hd_t;
|
|
||||||
|
|
||||||
extern void pid_hd_constructor(struct PID_HD *self);
|
|
||||||
|
|
||||||
#endif // __PID_HD__
|
|
|
@ -1,481 +0,0 @@
|
||||||
#include "pid_x.h"
|
|
||||||
#include "math.h"
|
|
||||||
#define LAG_PHASE (6) // 迟滞相位,单位:拍
|
|
||||||
|
|
||||||
#ifndef PI
|
|
||||||
#define PI 3.14159265358979f
|
|
||||||
#endif
|
|
||||||
// 注1:自适应模糊pid最重要的就是论域的选择,要和你应该控制的对象相切合
|
|
||||||
// 注2:以下各阀值、限幅值、输出值均需要根据具体的使用情况进行更改
|
|
||||||
// 注3:因为我的控制对象惯性比较大,所以以下各部分取值较小
|
|
||||||
// 论域e:[-5,5] ec:[-0.5,0.5]
|
|
||||||
|
|
||||||
// 误差的阀值,小于这个数值的时候,不做PID调整,避免误差较小时频繁调节引起震荡
|
|
||||||
#define Emin 0.3f
|
|
||||||
#define Emid 1.0f
|
|
||||||
#define Emax 5.0f
|
|
||||||
// 调整值限幅,防止积分饱和
|
|
||||||
#define Umax 1
|
|
||||||
#define Umin -1
|
|
||||||
|
|
||||||
#define NB 0
|
|
||||||
#define NM 1
|
|
||||||
#define NS 2
|
|
||||||
#define ZO 3
|
|
||||||
#define PS 4
|
|
||||||
#define PM 5
|
|
||||||
#define PB 6
|
|
||||||
|
|
||||||
int32_t kp[7][7] = {{PB, PB, PM, PM, PS, ZO, ZO},
|
|
||||||
{PB, PB, PM, PS, PS, ZO, ZO},
|
|
||||||
{PM, PM, PM, PS, ZO, NS, NS},
|
|
||||||
{PM, PM, PS, ZO, NS, NM, NM},
|
|
||||||
{PS, PS, ZO, NS, NS, NM, NM},
|
|
||||||
{PS, ZO, NS, NM, NM, NM, NB},
|
|
||||||
{ZO, ZO, NM, NM, NM, NB, NB}};
|
|
||||||
|
|
||||||
int32_t kd[7][7] = {{PS, NS, NB, NB, NB, NM, PS},
|
|
||||||
{PS, NS, NB, NM, NM, NS, ZO},
|
|
||||||
{ZO, NS, NM, NM, NS, NS, ZO},
|
|
||||||
{ZO, NS, NS, NS, NS, NS, ZO},
|
|
||||||
{ZO, ZO, ZO, ZO, ZO, ZO, ZO},
|
|
||||||
{PB, NS, PS, PS, PS, PS, PB},
|
|
||||||
{PB, PM, PM, PM, PS, PS, PB}};
|
|
||||||
|
|
||||||
int32_t ki[7][7] = {{NB, NB, NM, NM, NS, ZO, ZO},
|
|
||||||
{NB, NB, NM, NS, NS, ZO, ZO},
|
|
||||||
{NB, NM, NS, NS, ZO, PS, PS},
|
|
||||||
{NM, NM, NS, ZO, PS, PM, PM},
|
|
||||||
{NM, NS, ZO, PS, PS, PM, PB},
|
|
||||||
{ZO, ZO, PS, PS, PM, PB, PB},
|
|
||||||
{ZO, ZO, PS, PM, PM, PB, PB}};
|
|
||||||
|
|
||||||
static float32 ec; // 误差变化率
|
|
||||||
/**************求隶属度(三角形)***************/
|
|
||||||
float32 FTri(float32 x, float32 a, float32 b, float32 c) // FuzzyTriangle
|
|
||||||
{
|
|
||||||
if (x <= a)
|
|
||||||
return 0;
|
|
||||||
else if ((a < x) && (x <= b))
|
|
||||||
return (x - a) / (b - a);
|
|
||||||
else if ((b < x) && (x <= c))
|
|
||||||
return (c - x) / (c - b);
|
|
||||||
else if (x > c)
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/*****************求隶属度(梯形左)*******************/
|
|
||||||
float32 FTraL(float32 x, float32 a, float32 b) // FuzzyTrapezoidLeft
|
|
||||||
{
|
|
||||||
if (x <= a)
|
|
||||||
return 1;
|
|
||||||
else if ((a < x) && (x <= b))
|
|
||||||
return (b - x) / (b - a);
|
|
||||||
else if (x > b)
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/*****************求隶属度(梯形右)*******************/
|
|
||||||
float32 FTraR(float32 x, float32 a, float32 b) // FuzzyTrapezoidRight
|
|
||||||
{
|
|
||||||
if (x <= a)
|
|
||||||
return 0;
|
|
||||||
if ((a < x) && (x < b))
|
|
||||||
return (x - a) / (b - a);
|
|
||||||
if (x >= b)
|
|
||||||
return 1;
|
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
/****************三角形反模糊化处理**********************/
|
|
||||||
float32 uFTri(float32 x, float32 a, float32 b, float32 c)
|
|
||||||
{
|
|
||||||
float32 y, z;
|
|
||||||
z = (b - a) * x + a;
|
|
||||||
y = c - (c - b) * x;
|
|
||||||
return (y + z) / 2;
|
|
||||||
}
|
|
||||||
/*******************梯形(左)反模糊化***********************/
|
|
||||||
float32 uFTraL(float32 x, float32 a, float32 b)
|
|
||||||
{
|
|
||||||
return b - (b - a) * x;
|
|
||||||
}
|
|
||||||
/*******************梯形(右)反模糊化***********************/
|
|
||||||
float32 uFTraR(float32 x, float32 a, float32 b)
|
|
||||||
{
|
|
||||||
return (b - a) * x + a;
|
|
||||||
}
|
|
||||||
/**************************求交集****************************/
|
|
||||||
float32 fand(float32 a, float32 b)
|
|
||||||
{
|
|
||||||
return (a < b) ? a : b;
|
|
||||||
}
|
|
||||||
/**************************求并集****************************/
|
|
||||||
float32 forr(float32 a, float32 b)
|
|
||||||
{
|
|
||||||
return (a < b) ? b : a;
|
|
||||||
}
|
|
||||||
|
|
||||||
static float32 _PID(struct PID_X *self, float32 target, float32 feedback)
|
|
||||||
{
|
|
||||||
float32 pwm_var; // pwm调整量
|
|
||||||
float32 iError; // 当前误差
|
|
||||||
float32 set, input;
|
|
||||||
CLASSICPID *pri = &self->pri;
|
|
||||||
// 计算隶属度表
|
|
||||||
float32 es[7], ecs[7], e;
|
|
||||||
float32 form[7][7];
|
|
||||||
int i = 0, j = 0;
|
|
||||||
int MaxX = 0, MaxY = 0;
|
|
||||||
|
|
||||||
// 记录隶属度最大项及相应推理表的p、i、d值
|
|
||||||
float32 lsd;
|
|
||||||
int temp_p, temp_d, temp_i;
|
|
||||||
float32 detkp, detkd, detki; // 推理后的结果
|
|
||||||
|
|
||||||
// 输入格式的转化及偏差计算
|
|
||||||
set = target;
|
|
||||||
input = feedback;
|
|
||||||
iError = set - input; // 偏差
|
|
||||||
|
|
||||||
e = iError;
|
|
||||||
ec = iError - pri->lasterror;
|
|
||||||
|
|
||||||
// 当温度差的绝对值小于Emax时,对pid的参数进行调整
|
|
||||||
if (fabs(iError) <= Emax)
|
|
||||||
{
|
|
||||||
// 计算iError在es与ecs中各项的隶属度
|
|
||||||
es[NB] = FTraL(e * 5, -3, -1); // e
|
|
||||||
es[NM] = FTri(e * 5, -3, -2, 0);
|
|
||||||
es[NS] = FTri(e * 5, -3, -1, 1);
|
|
||||||
es[ZO] = FTri(e * 5, -2, 0, 2);
|
|
||||||
es[PS] = FTri(e * 5, -1, 1, 3);
|
|
||||||
es[PM] = FTri(e * 5, 0, 2, 3);
|
|
||||||
es[PB] = FTraR(e * 5, 1, 3);
|
|
||||||
|
|
||||||
ecs[NB] = FTraL(ec * 30, -3, -1); // ec
|
|
||||||
ecs[NM] = FTri(ec * 30, -3, -2, 0);
|
|
||||||
ecs[NS] = FTri(ec * 30, -3, -1, 1);
|
|
||||||
ecs[ZO] = FTri(ec * 30, -2, 0, 2);
|
|
||||||
ecs[PS] = FTri(ec * 30, -1, 1, 3);
|
|
||||||
ecs[PM] = FTri(ec * 30, 0, 2, 3);
|
|
||||||
ecs[PB] = FTraR(ec * 30, 1, 3);
|
|
||||||
|
|
||||||
// 计算隶属度表,确定e和ec相关联后表格各项隶属度的值
|
|
||||||
for (i = 0; i < 7; i++)
|
|
||||||
{
|
|
||||||
for (j = 0; j < 7; j++)
|
|
||||||
{
|
|
||||||
form[i][j] = fand(es[i], ecs[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 取出具有最大隶属度的那一项
|
|
||||||
for (i = 0; i < 7; i++)
|
|
||||||
{
|
|
||||||
for (j = 0; j < 7; j++)
|
|
||||||
{
|
|
||||||
if (form[MaxX][MaxY] < form[i][j])
|
|
||||||
{
|
|
||||||
MaxX = i;
|
|
||||||
MaxY = j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 进行模糊推理,并去模糊
|
|
||||||
lsd = form[MaxX][MaxY];
|
|
||||||
temp_p = kp[MaxX][MaxY];
|
|
||||||
temp_d = kd[MaxX][MaxY];
|
|
||||||
temp_i = ki[MaxX][MaxY];
|
|
||||||
|
|
||||||
if (temp_p == NB)
|
|
||||||
detkp = uFTraL(lsd, -0.3, -0.1);
|
|
||||||
else if (temp_p == NM)
|
|
||||||
detkp = uFTri(lsd, -0.3, -0.2, 0);
|
|
||||||
else if (temp_p == NS)
|
|
||||||
detkp = uFTri(lsd, -0.3, -0.1, 0.1);
|
|
||||||
else if (temp_p == ZO)
|
|
||||||
detkp = uFTri(lsd, -0.2, 0, 0.2);
|
|
||||||
else if (temp_p == PS)
|
|
||||||
detkp = uFTri(lsd, -0.1, 0.1, 0.3);
|
|
||||||
else if (temp_p == PM)
|
|
||||||
detkp = uFTri(lsd, 0, 0.2, 0.3);
|
|
||||||
else if (temp_p == PB)
|
|
||||||
detkp = uFTraR(lsd, 0.1, 0.3);
|
|
||||||
|
|
||||||
if (temp_d == NB)
|
|
||||||
detkd = uFTraL(lsd, -3, -1);
|
|
||||||
else if (temp_d == NM)
|
|
||||||
detkd = uFTri(lsd, -3, -2, 0);
|
|
||||||
else if (temp_d == NS)
|
|
||||||
detkd = uFTri(lsd, -3, 1, 1);
|
|
||||||
else if (temp_d == ZO)
|
|
||||||
detkd = uFTri(lsd, -2, 0, 2);
|
|
||||||
else if (temp_d == PS)
|
|
||||||
detkd = uFTri(lsd, -1, 1, 3);
|
|
||||||
else if (temp_d == PM)
|
|
||||||
detkd = uFTri(lsd, 0, 2, 3);
|
|
||||||
else if (temp_d == PB)
|
|
||||||
detkd = uFTraR(lsd, 1, 3);
|
|
||||||
|
|
||||||
if (temp_i == NB)
|
|
||||||
detki = uFTraL(lsd, -0.06, -0.02);
|
|
||||||
else if (temp_i == NM)
|
|
||||||
detki = uFTri(lsd, -0.06, -0.04, 0);
|
|
||||||
else if (temp_i == NS)
|
|
||||||
detki = uFTri(lsd, -0.06, -0.02, 0.02);
|
|
||||||
else if (temp_i == ZO)
|
|
||||||
detki = uFTri(lsd, -0.04, 0, 0.04);
|
|
||||||
else if (temp_i == PS)
|
|
||||||
detki = uFTri(lsd, -0.02, 0.02, 0.06);
|
|
||||||
else if (temp_i == PM)
|
|
||||||
detki = uFTri(lsd, 0, 0.04, 0.06);
|
|
||||||
else if (temp_i == PB)
|
|
||||||
detki = uFTraR(lsd, 0.02, 0.06);
|
|
||||||
|
|
||||||
// pid三项系数的修改
|
|
||||||
pri->pKp += detkp;
|
|
||||||
pri->pKi += detki;
|
|
||||||
if (pri->kd_e)
|
|
||||||
{
|
|
||||||
pri->pKd += detkd;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pri->pKd = 0; // 取消微分作用
|
|
||||||
}
|
|
||||||
|
|
||||||
// 对Kp,Ki进行限幅
|
|
||||||
if (pri->pKp < 0)
|
|
||||||
{
|
|
||||||
pri->pKp = 0;
|
|
||||||
}
|
|
||||||
if (pri->pKi < 0)
|
|
||||||
{
|
|
||||||
pri->pKi = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 计算新的K1,nKi,nKd
|
|
||||||
pri->nKp = pri->pKp + pri->pKi + pri->pKd;
|
|
||||||
pri->nKi = -(pri->pKp + 2 * pri->pKd);
|
|
||||||
pri->nKd = pri->pKd;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iError > Emax)
|
|
||||||
{
|
|
||||||
pri->out = pri->max;
|
|
||||||
pwm_var = 0;
|
|
||||||
pri->flag = 1; // 设定标志位,如果误差超过了门限值,则认为当控制量第一次到达给定值时,应该采取下面的 抑制超调 的措施
|
|
||||||
}
|
|
||||||
else if (iError < -Emax)
|
|
||||||
{
|
|
||||||
pri->out = pri->min;
|
|
||||||
pwm_var = 0;
|
|
||||||
}
|
|
||||||
else if (fabsf(iError) <= Emin)
|
|
||||||
{
|
|
||||||
pwm_var = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (iError < Emid && pri->flag == 1) // 第一次超过(设定值-Emid(-0.08)摄氏度),是输出为零,防止超调,也可以输出其他值,不至于太小而引起震荡
|
|
||||||
{
|
|
||||||
pri->out = 0;
|
|
||||||
pri->flag = 0;
|
|
||||||
}
|
|
||||||
else if (-iError > Emid) // 超过(设定+Emid(+0.08)摄氏度)
|
|
||||||
{
|
|
||||||
pwm_var = -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 增量计算
|
|
||||||
pwm_var = (pri->nKp * iError // e[k]
|
|
||||||
+ pri->nKi * pri->lasterror // e[k-1]
|
|
||||||
+ pri->nKd * pri->preverror); // e[k-2]
|
|
||||||
}
|
|
||||||
if (pwm_var >= Umax)
|
|
||||||
pwm_var = Umax; // 调整值限幅,防止积分饱和
|
|
||||||
if (pwm_var <= Umin)
|
|
||||||
pwm_var = Umin; // 调整值限幅,防止积分饱和
|
|
||||||
}
|
|
||||||
pri->preverror = pri->lasterror;
|
|
||||||
pri->lasterror = iError;
|
|
||||||
|
|
||||||
pri->out += pwm_var; // 调整PWM输出
|
|
||||||
|
|
||||||
if (pri->out > pri->max)
|
|
||||||
pri->out = pri->max; // 输出值限幅
|
|
||||||
if (pri->out < pri->min)
|
|
||||||
pri->out = pri->min; // 输出值限幅
|
|
||||||
|
|
||||||
return pri->out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*整定开始前的预处理,判断状态及初始化变量*/
|
|
||||||
static void tune_pretreatment(struct PID_X *self)
|
|
||||||
{
|
|
||||||
CLASSIC_AUTOTUNE *tune = &self->tune;
|
|
||||||
CLASSICPID *vPID = &self->pri;
|
|
||||||
|
|
||||||
tune->tuneTimer = 0;
|
|
||||||
tune->startTime = 0;
|
|
||||||
tune->endTime = 0;
|
|
||||||
tune->outputStep = 100;
|
|
||||||
|
|
||||||
if (*vPID->pSV >= *vPID->pPV)
|
|
||||||
{
|
|
||||||
tune->initialStatus = 1;
|
|
||||||
tune->outputStatus = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tune->initialStatus = 0;
|
|
||||||
tune->outputStatus = 1;
|
|
||||||
}
|
|
||||||
tune->tuneEnable = 1;
|
|
||||||
tune->preEnable = 0;
|
|
||||||
tune->zeroAcrossCounter = 0;
|
|
||||||
tune->riseLagCounter = 0;
|
|
||||||
tune->fallLagCounter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*计算PID参数值*/
|
|
||||||
static void calculation_parameters(struct PID_X *self)
|
|
||||||
{
|
|
||||||
CLASSIC_AUTOTUNE *tune = &self->tune;
|
|
||||||
CLASSICPID *vPID = &self->pri;
|
|
||||||
float32 kc = 0.0f;
|
|
||||||
float32 tc = 0.0f;
|
|
||||||
float32 zn[3][3] = {{0.5f, 100000.0f, 0.0f}, {0.45f, 0.8f, 0.0f}, {0.6f, 0.5f, 0.125f}};
|
|
||||||
|
|
||||||
tc = (tune->endTime - tune->startTime) * tune->tunePeriod / 1000.0;
|
|
||||||
kc = (8.0f * tune->outputStep) / (PI * (tune->maxPV - tune->minPV));
|
|
||||||
|
|
||||||
vPID->pKp = zn[tune->controllerType][0] * kc; // 比例系数
|
|
||||||
vPID->pKi = vPID->pKp * tune->tunePeriod / (zn[tune->controllerType][1] * tc); // 积分系数
|
|
||||||
vPID->pKd = vPID->pKp * zn[tune->controllerType][2] * tc / tune->tunePeriod; // 微分系数
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 自整定函数
|
|
||||||
* @param {PID_X} *self
|
|
||||||
* @return {*}
|
|
||||||
* @note 成员变量tuneEnable、preEnable和controllerType需要提前赋值。tuneEnable变量值为0时是使用PID控制器,而tuneEnable变量值为1时是开启整定过程,当tuneEnable变量值为2时是指示整定失败。preEnable变量在整定前赋值为1,表示先做预处理。而controllerType则根据所整定的控制器的类型来定,主要用于参数的计算。
|
|
||||||
*/
|
|
||||||
static uint8_t _auto_tune(struct PID_X *self)
|
|
||||||
{
|
|
||||||
CLASSIC_AUTOTUNE *tune = &self->tune;
|
|
||||||
CLASSICPID *vPID = &self->pri;
|
|
||||||
/*整定开始前的预处理,只执行一次*/
|
|
||||||
if (tune->preEnable == 1)
|
|
||||||
{
|
|
||||||
tune_pretreatment(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t tuneDuration = 0;
|
|
||||||
tune->tuneTimer++;
|
|
||||||
tuneDuration = (tune->tuneTimer * tune->tunePeriod) / 1000;
|
|
||||||
if (tuneDuration > (10 * 60)) // 整定过程持续超过10分钟,未能形成有效振荡,整定失败
|
|
||||||
{
|
|
||||||
tune->tuneEnable = 2;
|
|
||||||
tune->preEnable = 1;
|
|
||||||
return tune->tuneEnable;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*vPID->pSV >= *vPID->pPV) // 设定值大于测量值,则开执行单元
|
|
||||||
{
|
|
||||||
tune->riseLagCounter++;
|
|
||||||
tune->fallLagCounter = 0;
|
|
||||||
|
|
||||||
if (tune->riseLagCounter > LAG_PHASE)
|
|
||||||
{
|
|
||||||
*vPID->pMV = vPID->max;
|
|
||||||
if (tune->outputStatus == 0)
|
|
||||||
{
|
|
||||||
tune->outputStatus = 1;
|
|
||||||
tune->zeroAcrossCounter++;
|
|
||||||
|
|
||||||
if (tune->zeroAcrossCounter == 3)
|
|
||||||
{
|
|
||||||
tune->startTime = tune->tuneTimer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tune->riseLagCounter = 0;
|
|
||||||
tune->fallLagCounter++;
|
|
||||||
|
|
||||||
if (tune->fallLagCounter > LAG_PHASE)
|
|
||||||
{
|
|
||||||
*vPID->pMV = vPID->min;
|
|
||||||
if (tune->outputStatus == 1)
|
|
||||||
{
|
|
||||||
tune->outputStatus = 0;
|
|
||||||
tune->zeroAcrossCounter++;
|
|
||||||
|
|
||||||
if (tune->zeroAcrossCounter == 3)
|
|
||||||
{
|
|
||||||
tune->startTime = tune->tuneTimer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tune->zeroAcrossCounter == 3) // 已经两次过零,可以记录波形数据
|
|
||||||
{
|
|
||||||
if (tune->initialStatus == 1) // 初始设定值大于测量值,则区域3出现最小值
|
|
||||||
{
|
|
||||||
if (*vPID->pPV < tune->minPV)
|
|
||||||
{
|
|
||||||
tune->minPV = *vPID->pPV;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (tune->initialStatus == 0) // 初始设定值小于测量值,则区域3出现最大值
|
|
||||||
{
|
|
||||||
if (*vPID->pPV > tune->maxPV)
|
|
||||||
{
|
|
||||||
tune->maxPV = *vPID->pPV;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (tune->zeroAcrossCounter == 4) // 已经三次过零,记录另半波的数据
|
|
||||||
{
|
|
||||||
if (tune->initialStatus == 1) // 初始设定值大于测量值,则区域4出现最大值
|
|
||||||
{
|
|
||||||
if (*vPID->pPV > tune->maxPV)
|
|
||||||
{
|
|
||||||
tune->maxPV = *vPID->pPV;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (tune->initialStatus == 0) // 初始设定值小于测量值,则区域4出现最小值
|
|
||||||
{
|
|
||||||
if (*vPID->pPV < tune->minPV)
|
|
||||||
{
|
|
||||||
tune->minPV = *vPID->pPV;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (tune->zeroAcrossCounter == 5) // 已经四次过零,振荡已形成可以整定参数
|
|
||||||
{
|
|
||||||
calculation_parameters(self);
|
|
||||||
|
|
||||||
tune->tuneEnable = 0;
|
|
||||||
tune->preEnable = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return tune->tuneEnable;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pid_x_constructor(struct PID_X *self)
|
|
||||||
{
|
|
||||||
self->PID = _PID;
|
|
||||||
self->AUTO_TUNE = _auto_tune;
|
|
||||||
self->pri.flag = 0;
|
|
||||||
self->pri.out = 0;
|
|
||||||
self->tune.preEnable = 1;
|
|
||||||
}
|
|
|
@ -1,71 +0,0 @@
|
||||||
#ifndef __PID_X_H__
|
|
||||||
#define __PID_X_H__
|
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
/*定义PID对象类型*/
|
|
||||||
typedef struct CLASSIC
|
|
||||||
{
|
|
||||||
float32 *pPV; // 测量值指针
|
|
||||||
float32 *pSV; // 设定值指针
|
|
||||||
float32 *pMV; // 输出值指针
|
|
||||||
BOOL *pMA; // 手自动操作指针
|
|
||||||
|
|
||||||
float32 out; // 输出值
|
|
||||||
float32 setpoint; // 设定值
|
|
||||||
float32 lasterror; // 前一拍偏差
|
|
||||||
float32 preverror; // 前两拍偏差
|
|
||||||
float32 max; // 输出值上限
|
|
||||||
float32 min; // 输出值下限
|
|
||||||
|
|
||||||
uint16_t flag; // 状态标志位
|
|
||||||
|
|
||||||
float32 pKp; // 比例系数
|
|
||||||
float32 pKi; // 积分系数
|
|
||||||
float32 pKd; // 微分系数
|
|
||||||
|
|
||||||
float32 nKp; // 比例系数
|
|
||||||
float32 nKi; // 积分系数
|
|
||||||
float32 nKd; // 微分系数
|
|
||||||
|
|
||||||
BOOL direct; // 正反作用
|
|
||||||
BOOL sm; // 设定值平滑
|
|
||||||
BOOL cas; // 串级设定
|
|
||||||
BOOL pac; // 输出防陡变
|
|
||||||
BOOL kd_e; // 微分使能
|
|
||||||
} CLASSICPID;
|
|
||||||
|
|
||||||
// 定义整定参数
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint8_t tuneEnable : 2; // 整定与PID控制开关,0:PID控制;1:参数整定;2:整定失败
|
|
||||||
uint8_t preEnable : 2; // 预处理使能,在开始整定前置位
|
|
||||||
uint8_t initialStatus : 1; // 记录开始整定前偏差的初始状态
|
|
||||||
uint8_t outputStatus : 1; // 记录输出的初始状态,0允许上升过零计数;1允许下降过零计数
|
|
||||||
uint8_t controllerType : 2; // 控制器类型:0,P控制器;1,PI控制器;2,PID控制器
|
|
||||||
|
|
||||||
uint8_t zeroAcrossCounter; // 过零点计数器,每次输出改变加1,比实际过零次数多1
|
|
||||||
uint8_t riseLagCounter; // 上升迟滞时间计数器
|
|
||||||
uint8_t fallLagCounter; // 下降迟滞时间计数器
|
|
||||||
|
|
||||||
uint16_t tunePeriod; // 整定采样周期
|
|
||||||
uint32_t tuneTimer; // 整定计时器
|
|
||||||
uint32_t startTime; // 记录波形周期起始时间
|
|
||||||
uint32_t endTime; // 记录波形周期结束时间
|
|
||||||
|
|
||||||
float32 outputStep; // 输出阶跃d
|
|
||||||
float32 maxPV; // 振荡波形中测量值的最大值
|
|
||||||
float32 minPV; // 振荡波形中测量值的最小值
|
|
||||||
} CLASSIC_AUTOTUNE;
|
|
||||||
|
|
||||||
typedef struct PID_X
|
|
||||||
{
|
|
||||||
/* 控制接口 */
|
|
||||||
float32 (*PID)(struct PID_X *self, float32 target, float32 feedback);
|
|
||||||
uint8_t (*AUTO_TUNE)(struct PID_X *self);
|
|
||||||
/* private */
|
|
||||||
CLASSICPID pri;
|
|
||||||
CLASSIC_AUTOTUNE tune;
|
|
||||||
} pid_x_t;
|
|
||||||
|
|
||||||
extern void pid_x_constructor(struct PID_X *self);
|
|
||||||
#endif // __PID_X_H__
|
|
|
@ -1,467 +0,0 @@
|
||||||
#include "pid_zh.h"
|
|
||||||
#include "sys.h"
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
// 定义输出量比例因子
|
|
||||||
#ifdef GPS3000
|
|
||||||
#define KUP 0.0f // #define KUP 3.0f
|
|
||||||
#define KUI 0.00f
|
|
||||||
#define KUD 0.0f // #define KUP 3.0f
|
|
||||||
#else
|
|
||||||
#define KUP 3.0f
|
|
||||||
#define KUI 0.0f
|
|
||||||
#define KUD 0.0f
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// 模糊集合
|
|
||||||
#define NL -3
|
|
||||||
#define NM -2
|
|
||||||
#define NS -1
|
|
||||||
#define ZE 0
|
|
||||||
#define PS 1
|
|
||||||
#define PM 2
|
|
||||||
#define PL 3
|
|
||||||
|
|
||||||
// 定义偏差E的范围,因为设置了非线性区间,误差在10时才开始进行PID调节,这里E的范围为10
|
|
||||||
#define MAXE (10)
|
|
||||||
#define MINE (-MAXE)
|
|
||||||
// 定义EC的范围,因为变化非常缓慢!,每次的EC都非常小,这里可以根据实际需求来调整,
|
|
||||||
#define MAXEC (10)
|
|
||||||
#define MINEC (-MAXEC)
|
|
||||||
// 定义e,ec的量化因子
|
|
||||||
#define KE 3 / MAXE
|
|
||||||
#define KEC 3 / MAXEC
|
|
||||||
|
|
||||||
static const float32 fuzzyRuleKp[7][7] = {
|
|
||||||
PL, PL, PM, PL, PS, PM, PL,
|
|
||||||
PL, PM, PM, PM, PS, PM, PL,
|
|
||||||
PM, PS, PS, PS, PS, PS, PM,
|
|
||||||
PM, PS, ZE, ZE, ZE, PS, PM,
|
|
||||||
PS, PS, PS, PS, PS, PM, PM,
|
|
||||||
PM, PM, PM, PM, PL, PL, PL,
|
|
||||||
PM, PL, PL, PL, PL, PL, PL};
|
|
||||||
|
|
||||||
static const float32 fuzzyRuleKi[7][7] = {
|
|
||||||
PL, PL, PL, PL, PM, PL, PL,
|
|
||||||
PL, PL, PM, PM, PM, PL, PL,
|
|
||||||
PM, PM, PS, PS, PS, PM, PM,
|
|
||||||
PM, PS, ZE, ZE, ZE, PS, PM,
|
|
||||||
PM, PS, PS, PS, PS, PM, PM,
|
|
||||||
PM, PM, PS, PM, PM, PL, PL,
|
|
||||||
PM, PL, PM, PL, PL, PL, PL};
|
|
||||||
|
|
||||||
/*
|
|
||||||
static const float32 fuzzyRuleKi[7][7] = {
|
|
||||||
NL, NL, NL, NL, NM, NL, NL,
|
|
||||||
NL, NL, NM, NM, NM, NL, NL,
|
|
||||||
NM, NM, NS, NS, NS, NM, NM,
|
|
||||||
NM, NS, ZE, ZE, ZE, NS, NM,
|
|
||||||
NM, NS, NS, NS, NS, NM, NM,
|
|
||||||
NM, NM, NS, NM, NM, NL, NL,
|
|
||||||
NM, NL, NM, NL, NL, NL, NL};
|
|
||||||
*/
|
|
||||||
|
|
||||||
static const float32 fuzzyRuleKd[7][7] = {
|
|
||||||
PS, PS, ZE, ZE, ZE, PL, PL,
|
|
||||||
PS, PS, PS, PS, ZE, PS, PM,
|
|
||||||
PL, PL, PM, PS, ZE, PS, PM,
|
|
||||||
PL, PM, PM, PS, ZE, PS, PM,
|
|
||||||
PL, PM, PS, PS, ZE, PS, PS,
|
|
||||||
PM, PS, PS, PS, ZE, PS, PS,
|
|
||||||
PS, ZE, ZE, ZE, ZE, PL, PL};
|
|
||||||
|
|
||||||
/*
|
|
||||||
static const float32 fuzzyRuleKp[7][7] = {
|
|
||||||
PL, PL, PM, PM, PS, ZE, ZE,
|
|
||||||
PL, PL, PM, PS, PS, ZE, NS,
|
|
||||||
PM, PM, PM, PS, ZE, NS, NS,
|
|
||||||
PM, PM, PS, ZE, NS, NM, NM,
|
|
||||||
PS, PS, ZE, NS, NS, NM, NM,
|
|
||||||
PS, ZE, NS, NM, NM, NM, NL,
|
|
||||||
ZE, ZE, NM, NM, NM, NL, NL};
|
|
||||||
|
|
||||||
static const float32 fuzzyRuleKi[7][7] = {
|
|
||||||
NL, NL, NM, NM, NS, ZE, ZE,
|
|
||||||
NL, NL, NM, NS, NS, ZE, ZE,
|
|
||||||
NL, NM, NS, NS, ZE, PS, PS,
|
|
||||||
NM, NM, NS, ZE, PS, PM, PM,
|
|
||||||
NM, NS, ZE, PS, PS, NM, PL,
|
|
||||||
ZE, ZE, PS, PS, PM, PL, PL,
|
|
||||||
ZE, ZE, PS, PM, PM, PL, PL};
|
|
||||||
|
|
||||||
static const float32 fuzzyRuleKd[7][7] = {
|
|
||||||
PS, NS, NL, NL, NL, NM, PS,
|
|
||||||
PS, NS, NL, NM, NM, NS, ZE,
|
|
||||||
ZE, NS, NM, NM, NS, NS, ZE,
|
|
||||||
ZE, NS, NS, NS, NS, NS, ZE,
|
|
||||||
|
|
||||||
ZE, ZE, ZE, ZE, ZE, ZE, ZE,
|
|
||||||
PL, NS, PS, PS, PS, PS, PL,
|
|
||||||
PL, PM, PM, PM, PS, PS, PL};
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void fuzzy(float32 e, float32 ec, FUZZY_PID_ZH_t *fuzzy_pid)
|
|
||||||
{
|
|
||||||
|
|
||||||
float32 etemp, ectemp;
|
|
||||||
float32 eLefttemp, ecLefttemp; // ec,e,左隶属度
|
|
||||||
float32 eRighttemp, ecRighttemp;
|
|
||||||
|
|
||||||
int eLeftIndex, ecLeftIndex; // 模糊位置标号
|
|
||||||
int eRightIndex, ecRightIndex;
|
|
||||||
e = RANGE(e, MINE, MAXE);
|
|
||||||
ec = RANGE(ec, MINEC, MAXEC);
|
|
||||||
e = e * KE;
|
|
||||||
ec = ec * KEC;
|
|
||||||
|
|
||||||
etemp = e > 3.0f ? 0.0f : (e < -3.0f ? 0.0f : (e >= 0.0f ? (e >= 2.0f ? 2.5f : (e >= 1.0f ? 1.5f : 0.5f)) : (e >= -1.0f ? -0.5f : (e >= -2.0f ? -1.5f : (e >= -3.0f ? -2.5f : 0.0f)))));
|
|
||||||
eLeftIndex = (int)((etemp - 0.5f) + 3); //[-3,2] -> [0,5]
|
|
||||||
eRightIndex = (int)((etemp + 0.5f) + 3);
|
|
||||||
eLefttemp = etemp == 0.0f ? 0.0f : ((etemp + 0.5f) - e);
|
|
||||||
eRighttemp = etemp == 0.0f ? 0.0f : (e - (etemp - 0.5f));
|
|
||||||
|
|
||||||
ectemp = ec > 3.0f ? 0.0f : (ec < -3.0f ? 0.0f : (ec >= 0.0f ? (ec >= 2.0f ? 2.5f : (ec >= 1.0f ? 1.5f : 0.5f)) : (ec >= -1.0f ? -0.5f : (ec >= -2.0f ? -1.5f : (ec >= -3.0f ? -2.5f : 0.0f)))));
|
|
||||||
ecLeftIndex = (int)((ectemp - 0.5f) + 3); //[-3,2] -> [0,5]
|
|
||||||
ecRightIndex = (int)((ectemp + 0.5f) + 3);
|
|
||||||
ecLefttemp = ectemp == 0.0f ? 0.0f : ((ectemp + 0.5f) - ec);
|
|
||||||
ecRighttemp = ectemp == 0.0f ? 0.0f : (ec - (ectemp - 0.5f));
|
|
||||||
|
|
||||||
/*************************************反模糊*************************************/
|
|
||||||
|
|
||||||
fuzzy_pid->kp = (eLefttemp * ecLefttemp * fuzzyRuleKp[eLeftIndex][ecLeftIndex] + eLefttemp * ecRighttemp * fuzzyRuleKp[eLeftIndex][ecRightIndex] + eRighttemp * ecLefttemp * fuzzyRuleKp[eRightIndex][ecLeftIndex] + eRighttemp * ecRighttemp * fuzzyRuleKp[eRightIndex][ecRightIndex]);
|
|
||||||
|
|
||||||
fuzzy_pid->ki = (eLefttemp * ecLefttemp * fuzzyRuleKi[eLeftIndex][ecLeftIndex] + eLefttemp * ecRighttemp * fuzzyRuleKi[eLeftIndex][ecRightIndex] + eRighttemp * ecLefttemp * fuzzyRuleKi[eRightIndex][ecLeftIndex] + eRighttemp * ecRighttemp * fuzzyRuleKi[eRightIndex][ecRightIndex]);
|
|
||||||
|
|
||||||
fuzzy_pid->kd = (eLefttemp * ecLefttemp * fuzzyRuleKd[eLeftIndex][ecLeftIndex] + eLefttemp * ecRighttemp * fuzzyRuleKd[eLeftIndex][ecRightIndex] + eRighttemp * ecLefttemp * fuzzyRuleKd[eRightIndex][ecLeftIndex] + eRighttemp * ecRighttemp * fuzzyRuleKd[eRightIndex][ecRightIndex]);
|
|
||||||
// 对解算出的KP,KI,KD进行量化映射
|
|
||||||
fuzzy_pid->kp = fuzzy_pid->kp * fuzzy_pid->kup;
|
|
||||||
fuzzy_pid->ki = fuzzy_pid->ki * fuzzy_pid->kui;
|
|
||||||
fuzzy_pid->kd = fuzzy_pid->kd * fuzzy_pid->kud;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void smoothSetpoint(struct PID_FUZZY_ZH *self, float32 target_sv)
|
|
||||||
{
|
|
||||||
#if FUZZY_SUB_TYPE == PID_SUB_TYPE_POSITION
|
|
||||||
pid_zh_position_t *pri = &self->pri;
|
|
||||||
#else
|
|
||||||
pid_common_increment_t *pri = &self->pri;
|
|
||||||
#endif
|
|
||||||
float32 stepIn = (pri->sv_range) * 0.1f;
|
|
||||||
float32 kFactor = 0.0f;
|
|
||||||
if (fabs(pri->ref - target_sv) <= stepIn)
|
|
||||||
{
|
|
||||||
pri->ref = target_sv;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (pri->ref - target_sv > 0)
|
|
||||||
{
|
|
||||||
kFactor = -1.0f;
|
|
||||||
}
|
|
||||||
else if (pri->ref - target_sv < 0)
|
|
||||||
{
|
|
||||||
kFactor = 1.0f;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
kFactor = 0.0f;
|
|
||||||
}
|
|
||||||
pri->ref = pri->ref + kFactor * stepIn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*封装模糊接口*/
|
|
||||||
static void compensate(float32 e, float32 ec, FUZZY_PID_ZH_t *fuzzy_d)
|
|
||||||
{
|
|
||||||
fuzzy(e, ec, fuzzy_d);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 复位PID积分及微分控制数据
|
|
||||||
* @param {PID_FUZZY_ZH} *self
|
|
||||||
* @return {*}
|
|
||||||
*/
|
|
||||||
static void _restctrl(struct PID_FUZZY_ZH *self)
|
|
||||||
{
|
|
||||||
self->pri.pre_error = 0;
|
|
||||||
self->pri.sum_iterm = 0;
|
|
||||||
#if INCOMPLETE_DIFFEREN == 1
|
|
||||||
self->pri.lastdev = 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 更新最大最小值
|
|
||||||
* @param {PID_FUZZY_ZH} *self
|
|
||||||
* @param {float32} out_min
|
|
||||||
* @param {float32} out_max
|
|
||||||
* @return {*}
|
|
||||||
* @note
|
|
||||||
*/
|
|
||||||
static void _set_range(struct PID_FUZZY_ZH *self, float32 out_min, float32 out_max)
|
|
||||||
{
|
|
||||||
self->pri.out_max = out_max;
|
|
||||||
self->pri.out_min = out_min;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 使能积分控制
|
|
||||||
* @param {PID_FUZZY_ZH} *self
|
|
||||||
* @param {BOOL} enable
|
|
||||||
* @return {*}
|
|
||||||
* @note
|
|
||||||
*/
|
|
||||||
// static void _set_ki_enable(struct PID_FUZZY_ZH *self, BOOL enable)
|
|
||||||
// {
|
|
||||||
// self->pri.ki_enable = enable;
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 使能微分控制
|
|
||||||
* @param {PID_FUZZY_ZH} *self
|
|
||||||
* @param {BOOL} enable
|
|
||||||
* @return {*}
|
|
||||||
* @note
|
|
||||||
*/
|
|
||||||
static void _set_kd_enable(struct PID_FUZZY_ZH *self, BOOL enable)
|
|
||||||
{
|
|
||||||
self->pri.kd_enable = enable;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Function:使能平滑控制
|
|
||||||
* parameter:*pid需要配,PID参数结构指针,sv_range控制范围sv的范围
|
|
||||||
* return:无
|
|
||||||
*/
|
|
||||||
static void _set_smooth_enable(struct PID_FUZZY_ZH *self, BOOL enable, float32 sv_range)
|
|
||||||
{
|
|
||||||
#if FUZZY_SUB_TYPE == PID_SUB_TYPE_POSITION
|
|
||||||
pid_zh_position_t *pri = &self->pri;
|
|
||||||
#else
|
|
||||||
pid_common_increment_t *pri = &self->pri;
|
|
||||||
#endif
|
|
||||||
pri->sm = enable;
|
|
||||||
pri->sv_range = sv_range;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置控制参数
|
|
||||||
static void _set_ctrl_prm(struct PID_FUZZY_ZH *self, float32 kp, float32 ki, float32 kd, float32 err_dead,
|
|
||||||
float32 out_min, float32 out_max)
|
|
||||||
{
|
|
||||||
self->open = TRUE;
|
|
||||||
self->fuzzy.kup = KUP;
|
|
||||||
self->fuzzy.kui = KUI;
|
|
||||||
self->fuzzy.kud = KUD;
|
|
||||||
#if FUZZY_SUB_TYPE == PID_SUB_TYPE_POSITION
|
|
||||||
pid_zh_position_t *pri = &self->pri;
|
|
||||||
osel_memset((uint8_t *)pri, 0, sizeof(pid_zh_position_t));
|
|
||||||
pri->kp = kp;
|
|
||||||
pri->ki = ki;
|
|
||||||
pri->kd = kd;
|
|
||||||
pri->err_dead = err_dead;
|
|
||||||
pri->out_max = out_max;
|
|
||||||
pri->out_min = out_min;
|
|
||||||
pri->detach = FALSE;
|
|
||||||
pri->sm = FALSE;
|
|
||||||
#else
|
|
||||||
pid_common_increment_t *pri = &self->pri;
|
|
||||||
osel_memset((uint8_t *)pri, 0, sizeof(pid_common_increment_t));
|
|
||||||
pri->kp = kp;
|
|
||||||
pri->ki = ki;
|
|
||||||
pri->kd = kd;
|
|
||||||
pri->err_dead = err_dead;
|
|
||||||
pri->out_max = out_max;
|
|
||||||
pri->out_min = out_min;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (kd > 0)
|
|
||||||
{
|
|
||||||
pri->kd_enable = TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pri->kd_enable = FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _update_ctrl_prm(struct PID_FUZZY_ZH *self, float32 kp, float32 ki, float32 kd, float32 err_dead,
|
|
||||||
float32 out_min, float32 out_max)
|
|
||||||
{
|
|
||||||
#if FUZZY_SUB_TYPE == PID_SUB_TYPE_POSITION
|
|
||||||
pid_zh_position_t *pri = &self->pri;
|
|
||||||
pri->kp = kp;
|
|
||||||
pri->ki = ki;
|
|
||||||
pri->kd = kd;
|
|
||||||
pri->err_dead = err_dead;
|
|
||||||
pri->out_max = out_max;
|
|
||||||
pri->out_min = out_min;
|
|
||||||
pri->detach = FALSE;
|
|
||||||
pri->sm = FALSE;
|
|
||||||
#else
|
|
||||||
pid_common_increment_t *pri = &self->pri;
|
|
||||||
pri->kp = kp;
|
|
||||||
pri->ki = ki;
|
|
||||||
pri->kd = kd;
|
|
||||||
pri->err_dead = err_dead;
|
|
||||||
pri->out_max = out_max;
|
|
||||||
pri->out_min = out_min;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (kd > 0)
|
|
||||||
{
|
|
||||||
pri->kd_enable = TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pri->kd_enable = FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 非0时配置为积分分离+抗积分饱和PID,否则为普通抗积分饱和PID
|
|
||||||
* @param {PID_FUZZY_ZH} *self
|
|
||||||
* @param {float32} max_err
|
|
||||||
* @param {BOOL} mode
|
|
||||||
* @return {*}
|
|
||||||
*/
|
|
||||||
static void _set_cfg(struct PID_FUZZY_ZH *self, float32 max_err, BOOL mode)
|
|
||||||
{
|
|
||||||
self->pri.err_limit = max_err;
|
|
||||||
self->pri.detach = mode == FALSE ? FALSE : TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if FUZZY_SUB_TYPE == PID_SUB_TYPE_POSITION
|
|
||||||
static float32 _PID(struct PID_FUZZY_ZH *self, float32 target, float32 feedback)
|
|
||||||
{
|
|
||||||
float32 error = 0;
|
|
||||||
float32 insert = 0;
|
|
||||||
float32 ec = 0;
|
|
||||||
float32 kd = 0;
|
|
||||||
#if INCOMPLETE_DIFFEREN == 1
|
|
||||||
float32 thisdev = 0;
|
|
||||||
#else
|
|
||||||
// float32 dinput = 0.0f;
|
|
||||||
#endif
|
|
||||||
float32 temp_iterm = 0.0f;
|
|
||||||
pid_zh_position_t *pri = &self->pri;
|
|
||||||
|
|
||||||
/*获取期望值与实际值,进行偏差计算*/
|
|
||||||
if (pri->sm == 1)
|
|
||||||
{
|
|
||||||
smoothSetpoint(self, target);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pri->ref = target;
|
|
||||||
}
|
|
||||||
|
|
||||||
pri->feed_back = feedback;
|
|
||||||
error = pri->ref - pri->feed_back;
|
|
||||||
if (fabs(error) <= pri->err_dead)
|
|
||||||
error = 0;
|
|
||||||
|
|
||||||
/* fuzzy control caculate */
|
|
||||||
ec = error - pri->pre_error;
|
|
||||||
if (self->open == TRUE)
|
|
||||||
{
|
|
||||||
compensate(error, ec, &self->fuzzy);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*根据PID配置的模式,获取积分数据,进行积分累加*/
|
|
||||||
if (pri->out >= pri->out_max)
|
|
||||||
{
|
|
||||||
if (fabs(error) > pri->err_limit && pri->detach)
|
|
||||||
{
|
|
||||||
insert = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
insert = 1;
|
|
||||||
if (error < 0)
|
|
||||||
{
|
|
||||||
temp_iterm = (pri->ki + self->fuzzy.ki) * error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pri->out <= pri->out_min)
|
|
||||||
{
|
|
||||||
if (fabs(error) > pri->err_limit && pri->detach)
|
|
||||||
{
|
|
||||||
insert = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
insert = 1;
|
|
||||||
if (error > 0)
|
|
||||||
{
|
|
||||||
temp_iterm = (pri->ki + self->fuzzy.ki) * error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (fabs(error) > pri->err_limit && pri->detach)
|
|
||||||
{
|
|
||||||
insert = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
insert = 1;
|
|
||||||
temp_iterm = (pri->ki + self->fuzzy.ki) * error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pri->sum_iterm += temp_iterm;
|
|
||||||
/* limt integral */
|
|
||||||
pri->sum_iterm = RANGE(pri->sum_iterm, pri->out_min, pri->out_max);
|
|
||||||
/*
|
|
||||||
if (pri->sum_ref)
|
|
||||||
pri->sum_iterm = RANGE(pri->sum_iterm, pri->sum_ref - 1.0f, pri->sum_ref + 1.0f);
|
|
||||||
else
|
|
||||||
pri->sum_iterm = RANGE(pri->sum_iterm, pri->out_min, pri->out_max);
|
|
||||||
*/
|
|
||||||
#if INCOMPLETE_DIFFEREN == 1
|
|
||||||
/*不完全微分*/
|
|
||||||
thisdev = (pri->kd + self->fuzzy.kd) * (1.0 - pri->alpha) * (error - pri->pre_error) + pri->alpha * pri->lastdev;
|
|
||||||
/*caculate pid out*/
|
|
||||||
pri->out = (pri->kp + self->fuzzy.kp) * error + pri->sum_iterm * insert + thisdev;
|
|
||||||
|
|
||||||
/*record last dev result*/
|
|
||||||
pri->lastdev = thisdev;
|
|
||||||
#else
|
|
||||||
|
|
||||||
if (pri->kd_enable == TRUE)
|
|
||||||
{
|
|
||||||
kd = pri->kd + self->fuzzy.kd;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
kd = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pri->out = (pri->kp + self->fuzzy.kp) * error + pri->sum_iterm * insert + (error - pri->pre_error) * (kd);
|
|
||||||
// pri->out += pri->sum_ref;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pri->pre_error = error;
|
|
||||||
/*record last feedback sensor result*/
|
|
||||||
pri->pre_feed_back = pri->feed_back;
|
|
||||||
/*limt pid output*/
|
|
||||||
pri->out = RANGE(pri->out, pri->out_min, pri->out_max);
|
|
||||||
return pri->out;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void pid_zh_constructor(struct PID_FUZZY_ZH *self)
|
|
||||||
{
|
|
||||||
self->set_ctrl_prm = _set_ctrl_prm;
|
|
||||||
self->update_ctrl_prm = _update_ctrl_prm;
|
|
||||||
self->set_cfg = _set_cfg;
|
|
||||||
self->set_smooth_enable = _set_smooth_enable;
|
|
||||||
// self->set_ki_enable = _set_ki_enable;
|
|
||||||
self->set_kd_enable = _set_kd_enable;
|
|
||||||
self->set_range = _set_range;
|
|
||||||
self->restctrl = _restctrl;
|
|
||||||
self->PID = _PID;
|
|
||||||
}
|
|
|
@ -1,73 +0,0 @@
|
||||||
#ifndef __PID_ZH_H__
|
|
||||||
#define __PID_ZH_H__
|
|
||||||
#include "lib.h"
|
|
||||||
#include "pid_auto_tune.h"
|
|
||||||
|
|
||||||
#define GPS2000
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
float32 ref;
|
|
||||||
float32 feed_back;
|
|
||||||
float32 pre_feed_back;
|
|
||||||
float32 pre_error;
|
|
||||||
float32 sum_ref;
|
|
||||||
float32 sum_iterm;
|
|
||||||
float32 kp;
|
|
||||||
float32 ki;
|
|
||||||
float32 kd;
|
|
||||||
float32 err_limit;
|
|
||||||
BOOL detach;
|
|
||||||
float32 err_dead;
|
|
||||||
#if INCOMPLETE_DIFFEREN == 1
|
|
||||||
float32 alpha;
|
|
||||||
float32 lastdev;
|
|
||||||
#endif
|
|
||||||
float32 out;
|
|
||||||
float32 out_max;
|
|
||||||
float32 out_min;
|
|
||||||
float32 sv_range;
|
|
||||||
BOOL sm;
|
|
||||||
BOOL ki_enable;
|
|
||||||
BOOL kd_enable;
|
|
||||||
} pid_zh_position_t; // 位置式PID
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
float32 kp;
|
|
||||||
float32 ki;
|
|
||||||
float32 kd;
|
|
||||||
|
|
||||||
float32 kup;
|
|
||||||
float32 kui;
|
|
||||||
float32 kud;
|
|
||||||
} FUZZY_PID_ZH_t;
|
|
||||||
|
|
||||||
// 模糊PID
|
|
||||||
typedef struct PID_FUZZY_ZH
|
|
||||||
{
|
|
||||||
/* 设置PID三个参数 */
|
|
||||||
void (*set_ctrl_prm)(struct PID_FUZZY_ZH *self, float32 kp, float32 ki, float32 kd, float32 err_dead,
|
|
||||||
float32 out_min, float32 out_max); // 设置PID参数
|
|
||||||
void (*update_ctrl_prm)(struct PID_FUZZY_ZH *self, float32 kp, float32 ki, float32 kd, float32 err_dead,
|
|
||||||
float32 out_min, float32 out_max); // 更新PID参数
|
|
||||||
void (*set_range)(struct PID_FUZZY_ZH *self, float32 out_min, float32 out_max); // 更新最大最小值
|
|
||||||
void (*set_cfg)(struct PID_FUZZY_ZH *self, float32 max_err, BOOL mode); // 配置PID模式,默认不使用积分分离
|
|
||||||
void (*set_smooth_enable)(struct PID_FUZZY_ZH *self, BOOL enable, float32 sv_range); // 设置平滑范围
|
|
||||||
// void (*set_ki_enable)(struct PID_FUZZY *self, BOOL enable);
|
|
||||||
// 微分开启使能
|
|
||||||
void (*set_kd_enable)(struct PID_FUZZY_ZH *self, BOOL enable);
|
|
||||||
void (*restctrl)(struct PID_FUZZY_ZH *self); // 复位PID积分及微分控制数据
|
|
||||||
/* 控制接口 */
|
|
||||||
float32 (*PID)(struct PID_FUZZY_ZH *self, float32 target, float32 feedback);
|
|
||||||
|
|
||||||
pid_zh_position_t pri;
|
|
||||||
|
|
||||||
BOOL open; // 是否使用模糊PID控制
|
|
||||||
|
|
||||||
FUZZY_PID_ZH_t fuzzy;
|
|
||||||
|
|
||||||
} pid_zh_t; // 模糊PID
|
|
||||||
|
|
||||||
extern void pid_zh_constructor(struct PID_FUZZY_ZH *self);
|
|
||||||
#endif
|
|
|
@ -1,619 +0,0 @@
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include "pid_zh1.h"
|
|
||||||
|
|
||||||
// 定义输出量比例因子
|
|
||||||
#define KUP 1.0f
|
|
||||||
#define KUI 1.0f
|
|
||||||
#define KUD 1.0f
|
|
||||||
|
|
||||||
// 模糊集合
|
|
||||||
#define NL -3
|
|
||||||
#define NM -2
|
|
||||||
#define NS -1
|
|
||||||
#define ZE 0
|
|
||||||
#define PS 1
|
|
||||||
#define PM 2
|
|
||||||
#define PL 3
|
|
||||||
|
|
||||||
// 定义偏差E的范围,因为设置了非线性区间,误差在10时才开始进行PID调节,这里E的范围为10
|
|
||||||
#define MAXE (10)
|
|
||||||
#define MINE (-MAXE)
|
|
||||||
// 定义EC的范围,因为变化非常缓慢!,每次的EC都非常小,这里可以根据实际需求来调整,
|
|
||||||
#define MAXEC (10)
|
|
||||||
#define MINEC (-MAXEC)
|
|
||||||
// 定义e,ec的量化因子
|
|
||||||
#define KE 3 / MAXE
|
|
||||||
#define KEC 3 / MAXEC
|
|
||||||
/*
|
|
||||||
static const float fuzzyRuleKp[7][7] = {
|
|
||||||
PL, PL, PM, PL, PS, PM, PL,
|
|
||||||
PL, PM, PM, PM, PS, PM, PL,
|
|
||||||
PM, PS, PS, PS, PS, PS, PM,
|
|
||||||
PM, PS, ZE, ZE, ZE, PS, PM,
|
|
||||||
PS, PS, PS, PS, PS, PM, PM,
|
|
||||||
PM, PM, PM, PM, PL, PL, PL,
|
|
||||||
PM, PL, PL, PL, PL, PL, PL};
|
|
||||||
|
|
||||||
static const float fuzzyRuleKi[7][7] = {
|
|
||||||
PL, PL, PL, PL, PM, PL, PL,
|
|
||||||
PL, PL, PM, PM, PM, PL, PL,
|
|
||||||
PM, PM, PS, PS, PS, PM, PM,
|
|
||||||
PM, PS, ZE, ZE, ZE, PS, PM,
|
|
||||||
PM, PS, PS, PS, PS, PM, PM,
|
|
||||||
PM, PM, PS, PM, PM, PL, PL,
|
|
||||||
PM, PL, PM, PL, PL, PL, PL};
|
|
||||||
|
|
||||||
static const float fuzzyRuleKd[7][7] = {
|
|
||||||
PS, PS, ZE, ZE, ZE, PL, PL,
|
|
||||||
PS, PS, PS, PS, ZE, PS, PM,
|
|
||||||
PL, PL, PM, PS, ZE, PS, PM,
|
|
||||||
PL, PM, PM, PS, ZE, PS, PM,
|
|
||||||
PL, PM, PS, PS, ZE, PS, PS,
|
|
||||||
PM, PS, PS, PS, ZE, PS, PS,
|
|
||||||
PS, ZE, ZE, ZE, ZE, PL, PL};
|
|
||||||
*/
|
|
||||||
static const float fuzzyRuleKp[7][7] = {
|
|
||||||
PL, PL, PM, PL, PS, PM, PL,
|
|
||||||
PL, PM, PM, PM, PS, PM, PL,
|
|
||||||
PM, PS, PS, PS, PS, PS, PM,
|
|
||||||
PM, PS, ZE, ZE, ZE, PS, PM,
|
|
||||||
PS, PS, PS, PS, PS, PM, PM,
|
|
||||||
PM, PM, PM, PM, PL, PL, PL,
|
|
||||||
PM, PL, PL, PL, PL, PL, PL};
|
|
||||||
|
|
||||||
static const float fuzzyRuleKi[7][7] = {
|
|
||||||
PL, PL, PL, PL, PM, PL, PL,
|
|
||||||
PL, PL, PM, PM, PM, PL, PL,
|
|
||||||
PM, PM, PS, PS, PS, PM, PM,
|
|
||||||
PM, PS, ZE, ZE, ZE, PS, PM,
|
|
||||||
PM, PS, PS, PS, PS, PM, PM,
|
|
||||||
PM, PM, PS, PM, PM, PL, PL,
|
|
||||||
PM, PL, PM, PL, PL, PL, PL};
|
|
||||||
|
|
||||||
static const float fuzzyRuleKd[7][7] = {
|
|
||||||
PS, PS, ZE, ZE, ZE, PL, PL,
|
|
||||||
PS, PS, PS, PS, ZE, PS, PM,
|
|
||||||
PL, PL, PM, PS, ZE, PS, PM,
|
|
||||||
PL, PM, PM, PS, ZE, PS, PM,
|
|
||||||
PL, PM, PS, PS, ZE, PS, PS,
|
|
||||||
PM, PS, PS, PS, ZE, PS, PS,
|
|
||||||
PS, ZE, ZE, ZE, ZE, PL, PL};
|
|
||||||
|
|
||||||
static void fuzzy(float e, float ec, fuzzy_pid_t *fuzzy_pid)
|
|
||||||
{
|
|
||||||
|
|
||||||
float etemp, ectemp;
|
|
||||||
float eLefttemp, ecLefttemp; // 左隶属度
|
|
||||||
float eRighttemp, ecRighttemp; // 右隶属度
|
|
||||||
|
|
||||||
int eLeftIndex, ecLeftIndex; // 模糊位置标号
|
|
||||||
int eRightIndex, ecRightIndex;
|
|
||||||
e = RANGE(e, MINE, MAXE);
|
|
||||||
ec = RANGE(ec, MINEC, MAXEC);
|
|
||||||
e = e * KE;
|
|
||||||
ec = ec * KEC;
|
|
||||||
|
|
||||||
etemp = e > 3.0f ? 0.0f : (e < -3.0f ? 0.0f : (e >= 0.0f ? (e >= 2.0f ? 2.5f : (e >= 1.0f ? 1.5f : 0.5f)) : (e >= -1.0f ? -0.5f : (e >= -2.0f ? -1.5f : (e >= -3.0f ? -2.5f : 0.0f)))));
|
|
||||||
eLeftIndex = (int)((etemp - 0.5f) + 3);
|
|
||||||
eRightIndex = (int)((etemp + 0.5f) + 3);
|
|
||||||
eLefttemp = etemp == 0.0f ? 0.0f : ((etemp + 0.5f) - e);
|
|
||||||
eRighttemp = etemp == 0.0f ? 0.0f : (e - (etemp - 0.5f));
|
|
||||||
|
|
||||||
ectemp = ec > 3.0f ? 0.0f : (ec < -3.0f ? 0.0f : (ec >= 0.0f ? (ec >= 2.0f ? 2.5f : (ec >= 1.0f ? 1.5f : 0.5f)) : (ec >= -1.0f ? -0.5f : (ec >= -2.0f ? -1.5f : (ec >= -3.0f ? -2.5f : 0.0f)))));
|
|
||||||
ecLeftIndex = (int)((ectemp - 0.5f) + 3);
|
|
||||||
ecRightIndex = (int)((ectemp + 0.5f) + 3);
|
|
||||||
ecLefttemp = ectemp == 0.0f ? 0.0f : ((ectemp + 0.5f) - ec);
|
|
||||||
ecRighttemp = ectemp == 0.0f ? 0.0f : (ec - (ectemp - 0.5f));
|
|
||||||
|
|
||||||
/*************************************反模糊*************************************/
|
|
||||||
|
|
||||||
fuzzy_pid->kp = (eLefttemp * ecLefttemp * fuzzyRuleKp[eLeftIndex][ecLeftIndex] + eLefttemp * ecRighttemp * fuzzyRuleKp[eLeftIndex][ecRightIndex] + eRighttemp * ecLefttemp * fuzzyRuleKp[eRightIndex][ecLeftIndex] + eRighttemp * ecRighttemp * fuzzyRuleKp[eRightIndex][ecRightIndex]);
|
|
||||||
|
|
||||||
fuzzy_pid->ki = (eLefttemp * ecLefttemp * fuzzyRuleKi[eLeftIndex][ecLeftIndex] + eLefttemp * ecRighttemp * fuzzyRuleKi[eLeftIndex][ecRightIndex] + eRighttemp * ecLefttemp * fuzzyRuleKi[eRightIndex][ecLeftIndex] + eRighttemp * ecRighttemp * fuzzyRuleKi[eRightIndex][ecRightIndex]);
|
|
||||||
|
|
||||||
fuzzy_pid->kd = (eLefttemp * ecLefttemp * fuzzyRuleKd[eLeftIndex][ecLeftIndex] + eLefttemp * ecRighttemp * fuzzyRuleKd[eLeftIndex][ecRightIndex] + eRighttemp * ecLefttemp * fuzzyRuleKd[eRightIndex][ecLeftIndex] + eRighttemp * ecRighttemp * fuzzyRuleKd[eRightIndex][ecRightIndex]);
|
|
||||||
// 对解算出的KP,KI,KD进行量化映射
|
|
||||||
fuzzy_pid->kp = fuzzy_pid->kp * fuzzy_pid->kup;
|
|
||||||
fuzzy_pid->ki = fuzzy_pid->ki * fuzzy_pid->kui;
|
|
||||||
fuzzy_pid->kd = fuzzy_pid->kd * fuzzy_pid->kud;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void smooth_init(smart_pid_t *pid, BOOL sm_open, float maxTarget)
|
|
||||||
{
|
|
||||||
if (!pid)
|
|
||||||
return;
|
|
||||||
|
|
||||||
pid->sm_open = sm_open;
|
|
||||||
pid->maxTarget = maxTarget;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void smooth_target(smart_pid_t *pid, float *target)
|
|
||||||
{
|
|
||||||
|
|
||||||
if ((!pid) || (!target))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!pid->maxTarget)
|
|
||||||
return;
|
|
||||||
|
|
||||||
float sm_step = (pid->maxTarget) * 0.1f;
|
|
||||||
float k = 0.0f;
|
|
||||||
|
|
||||||
if (fabs(pid->target - *target) <= sm_step)
|
|
||||||
{
|
|
||||||
pid->target = *target;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (pid->target - *target > 0)
|
|
||||||
{
|
|
||||||
k = -1.0f;
|
|
||||||
}
|
|
||||||
else if (pid->target - *target < 0)
|
|
||||||
{
|
|
||||||
k = 1.0f;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
k = 0.0f;
|
|
||||||
}
|
|
||||||
pid->target += k * sm_step;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void smart_pid_init(smart_pid_t *pid, float *duty, float *kp, float *ki, float *kd, float *errorDead, float *iDetachCondation, float *maxOut)
|
|
||||||
{
|
|
||||||
if ((!pid) || (!duty) || (!kp) || (!ki) || (!kd) || (!iDetachCondation) || (!maxOut))
|
|
||||||
return;
|
|
||||||
|
|
||||||
pid->duty = *duty;
|
|
||||||
pid->kp = *kp;
|
|
||||||
pid->ki = *ki;
|
|
||||||
pid->kd = *kd;
|
|
||||||
pid->errorDead = *errorDead;
|
|
||||||
pid->iDetachCondation = *iDetachCondation;
|
|
||||||
pid->maxOutput = *maxOut;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cascade_pid_init(cascade_pid_t *pid, smart_pid_t *pid_outer, smart_pid_t *pid_inner)
|
|
||||||
{
|
|
||||||
|
|
||||||
smooth_init(&pid->outer, pid_outer->sm_open, pid_outer->maxTarget);
|
|
||||||
smooth_init(&pid->inner, pid_inner->sm_open, pid_inner->maxTarget);
|
|
||||||
|
|
||||||
smart_pid_init(&pid->outer, &pid_outer->duty, &pid_outer->kp, &pid_outer->ki, &pid_outer->kd, &pid_outer->errorDead, &pid_outer->iDetachCondation, &pid_outer->maxOutput);
|
|
||||||
smart_pid_init(&pid->inner, &pid_inner->duty, &pid_inner->kp, &pid_inner->ki, &pid_inner->kd, &pid_inner->errorDead, &pid_inner->iDetachCondation, &pid_inner->maxOutput);
|
|
||||||
}
|
|
||||||
|
|
||||||
void smart_pid_calc(smart_pid_t *pid, float *target, float *feedback)
|
|
||||||
{
|
|
||||||
// 将旧error存起来
|
|
||||||
pid->lastError = pid->error;
|
|
||||||
// 平滑处理目标值
|
|
||||||
if (pid->sm_open == TRUE)
|
|
||||||
smooth_target(pid, target);
|
|
||||||
else
|
|
||||||
pid->target = *target;
|
|
||||||
// 计算新error
|
|
||||||
pid->error = pid->target - *feedback;
|
|
||||||
if (fabs(pid->error) <= pid->errorDead)
|
|
||||||
pid->error = 0.0f;
|
|
||||||
// 计算误差变化
|
|
||||||
pid->dError = pid->error - pid->lastError;
|
|
||||||
// 选用模糊规则
|
|
||||||
if (pid->fuzzy_open == TRUE)
|
|
||||||
{
|
|
||||||
fuzzy(pid->error, pid->dError, &pid->fuzzy_pid);
|
|
||||||
}
|
|
||||||
// 计算微分
|
|
||||||
float dout = pid->dError * (pid->kd + pid->fuzzy_pid.kd);
|
|
||||||
// 计算比例
|
|
||||||
float pout = pid->error * (pid->kp + pid->fuzzy_pid.kp);
|
|
||||||
// 积分分离
|
|
||||||
if (fabs(pid->error) <= pid->iDetachCondation)
|
|
||||||
{
|
|
||||||
pid->integral += pid->error * (pid->ki + pid->fuzzy_pid.ki);
|
|
||||||
pid->iDetach = FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pid->iDetach = TRUE;
|
|
||||||
pid->integral = 0;
|
|
||||||
}
|
|
||||||
// 积分限幅
|
|
||||||
if (pid->integral > pid->maxOutput)
|
|
||||||
pid->integral = pid->maxOutput;
|
|
||||||
else if (pid->integral < -pid->maxOutput)
|
|
||||||
pid->integral = -pid->maxOutput;
|
|
||||||
// 计算输出
|
|
||||||
pid->output = pout + dout + pid->integral * (!pid->iDetach);
|
|
||||||
// 输出限幅
|
|
||||||
if (pid->output > pid->maxOutput)
|
|
||||||
pid->output = pid->maxOutput;
|
|
||||||
else if (pid->output < -pid->maxOutput)
|
|
||||||
pid->output = -pid->maxOutput;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cascade_pid_calc(struct CascadePID *pid, float *outerRef, float *outerFdb, float *innerFdb)
|
|
||||||
{
|
|
||||||
// 外环位置控制
|
|
||||||
smart_pid_calc(&pid->cascade_pid.outer, outerRef, outerFdb);
|
|
||||||
// 内环速度控制
|
|
||||||
smart_pid_calc(&pid->cascade_pid.inner, &pid->cascade_pid.outer.output, innerFdb);
|
|
||||||
// 内环输出就是串级PID的输出
|
|
||||||
// pid->cascade_pid.output = pid->cascade_pid.inner.output;
|
|
||||||
pid->cascade_pid.output = pid->cascade_pid.outer.output;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pid_zh_constructor1(struct CascadePID *pid)
|
|
||||||
{
|
|
||||||
pid->smart_pid_init = smart_pid_init;
|
|
||||||
pid->smart_pid_calc = smart_pid_calc;
|
|
||||||
pid->cascade_pid_init = cascade_pid_init;
|
|
||||||
pid->cascade_pid_calc = cascade_pid_calc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
典型输入信号
|
|
||||||
L[1] -> 1/s
|
|
||||||
L[t] -> 1/s^2
|
|
||||||
L[1/2t^2] -> 1/s^3
|
|
||||||
系统传递函数
|
|
||||||
G(s) = k/(TS+1)
|
|
||||||
G(s) = k/S^i(TS+1)
|
|
||||||
i = 0 0型系统 i = 1 I 型系统 I = 2 II 型系统
|
|
||||||
系统开环传递函数: G(s)
|
|
||||||
系统闭环传递函数: G闭(s) = G(s) / 1 + G(s)
|
|
||||||
系统静差: R(s) = 1/1+G(s)
|
|
||||||
终值定理:limf(t) = lim s*G(s)
|
|
||||||
t->无穷 s->0
|
|
||||||
o型系统,单位输入:r/s
|
|
||||||
e = lim f(t) = lim s*G(s) = G(s) = k/1+G(s) = k/ 1 + (Ts+1+k)..
|
|
||||||
t->无穷 s->0 s->0 s->0 = s->0
|
|
||||||
*系统误差有给定和扰动引起的
|
|
||||||
*线性系统符合叠加原理
|
|
||||||
*动态性能指标
|
|
||||||
超调 、过度过程时间、上升时间 tr 延迟时间 td 峰值指标tp
|
|
||||||
误差积分指标大 好小 好?
|
|
||||||
典型二阶系统
|
|
||||||
G(s) = 1/ s^2 *(2ξwn)s + wn^2
|
|
||||||
ξ:阻尼系统
|
|
||||||
wn = 1/T:震荡频率
|
|
||||||
如果有一个极点和零点很接近,可以忽略该极点。
|
|
||||||
主导极点用二阶系统定义的
|
|
||||||
开环传递函数 K T
|
|
||||||
复变函数
|
|
||||||
频率特性
|
|
||||||
阻容RC电路 一阶低通滤波器 一阶惰性系统
|
|
||||||
Gs = 1/Ts+1
|
|
||||||
正弦稳态
|
|
||||||
|
|
||||||
控制系统设计依据:
|
|
||||||
考虑到被控对象包含 弹簧储能、填料阻尼、EPM气压控制等主导环节,忽略其它非主导惯性、阻尼环节,将被控系统模型归纳为典型二阶阻尼震荡系统:
|
|
||||||
被控对象开环传递函数:G(s) = wn^2/ s*( s + 2ξwn)
|
|
||||||
未加控制器被控对象闭环传递函数:G(s) = wn^2/ (s^2 + (2ξwn)s + wn^2)
|
|
||||||
ξ :为系统阻尼比。跟阀座填料材、压力正相关(忽略其他非主导阻尼环节)
|
|
||||||
Wn :无阻尼自然震荡角频率。跟弹簧的固有振荡频率正相关(忽略其他非主导惯性环节)
|
|
||||||
|
|
||||||
阀杆填料阻尼比: 0 < ξ < 1
|
|
||||||
|
|
||||||
系统特征方程s^2 + (2ξwn)s + wn^2 = 0 时,有两个共轭复根,要想系统稳定,根的实部要远离虚轴,且在允许情况下,越远越稳定。
|
|
||||||
标准二阶系统是零型系统,存在静差。而且,考虑气体压缩比大,导致系统的惯性环节增大。
|
|
||||||
因此需要控制器将系统变为I型系统来消除静差(增加积分环节),而且需要在控制器传递函数的零点增加最小项来克服系统的大惯性(增加微分环节)。因此,设计控制器类型为PID控制器。
|
|
||||||
|
|
||||||
※ 难点在于系统的无阻尼自然震荡角频率和阀座阻尼系数无法准确获得,整定算法计算的特性参数不一定合理。
|
|
||||||
※ 另一个难点在于EPM本身的控制特性线性度差,会导致控制器的矫正环节达不到理想效果或在部分区间达不到理想效果,因此,
|
|
||||||
系统会不稳定或在部分区间不稳定。
|
|
||||||
※ EMP本身的控制线性度差,通过控制器弥补EPM性能的不足。
|
|
||||||
(因为阀杆速度变化快慢,直接由EPM IP开度大小决定,因此考虑增加阀杆速度环控制来弥补EPM本身的不足)
|
|
||||||
|
|
||||||
算法核心原理说明 :
|
|
||||||
核心算法: PID
|
|
||||||
u(t) = k*(e(t) +∫e(t)dt + de(t)dt)
|
|
||||||
u(n) = k*(e(n) + ∑e(n)/Ti + Td*(e(n) - e(n-1)))
|
|
||||||
|
|
||||||
位置控制:PID + PD控制
|
|
||||||
误差在[-5%,5%] 内 PID 控制,控制静差 < 0.3%
|
|
||||||
误差在[-100%,5%] 或 [5%,100%] 时,PD控制,防止积分引起的系统不稳定
|
|
||||||
|
|
||||||
积分分离:当误差<= 5% 时,加入积分
|
|
||||||
当误差> 5%时,积分分离、积分项清零
|
|
||||||
积分限幅:
|
|
||||||
当积分项 >= 100% 积分项 = 100%
|
|
||||||
当积分项 <= -100% 积分项 = -100%
|
|
||||||
|
|
||||||
整定算法: 继电反馈整定
|
|
||||||
设定目标位置:额定行程 60%
|
|
||||||
控制初始位置: < 60%
|
|
||||||
施加最大控制量 ->检测实时位置->过零,计t0、上冲峰值 -> 施加最小控制量 -> 检测实时位置 -> 过零,计t1、下冲峰值— ↓
|
|
||||||
↑ <—————————————————————————————————————————————————————————————————————————————————————————————————|
|
|
||||||
|
|
||||||
循环三次,记录系统稳态下波峰、波谷,和震荡周期Tu
|
|
||||||
计算: Ku = (控制量最大值 - 控制量最小值)/ (位置波峰 - 位置波谷)
|
|
||||||
查表:Kp = 0.8 * Ku
|
|
||||||
Ti = 0.6 * Tu
|
|
||||||
Td = 0.125 * Tu
|
|
||||||
Ki = Kp / Ti = Kp / (0.6 * Tu)
|
|
||||||
Kd = Kp * Td = Kp * 0.125 * Td
|
|
||||||
|
|
||||||
速度控制算法:
|
|
||||||
s1:初始位置AD值
|
|
||||||
s2:单位时间位置移动后AD值
|
|
||||||
v1:当前速度
|
|
||||||
v2: 前速度
|
|
||||||
v: 实时速度
|
|
||||||
a:实时加速度
|
|
||||||
t: 速度计算周期
|
|
||||||
v = (s2 - s1) / t
|
|
||||||
a = (v2 - v1) / t
|
|
||||||
|
|
||||||
整定过程,分别整定上升过程平均速度和下降过程平均速度。
|
|
||||||
分别以上升和下降速度为PID 内环参考速度,计算速度控制量。
|
|
||||||
速度偏差 = 当前速度 - 参考速度
|
|
||||||
加速度 = 速度偏差变化(即位置的二阶导数)
|
|
||||||
速度控制量 = Kp*速度偏差 + Ki * ∑速度偏差 + Kd * 加速度
|
|
||||||
|
|
||||||
串级控制
|
|
||||||
外环位置检测,进行速度控制
|
|
||||||
内环速度检测,进行位置控制
|
|
||||||
位置偏差 = 位置给定 - 位置反馈
|
|
||||||
位置偏差变化 = 位置偏差 - 上次位置偏差
|
|
||||||
速度控制量 = Kp1*位置偏差 + Ki1 * ∑位置偏差 + Kd1 * 位置偏差变化
|
|
||||||
速度偏差 = 速度控制量 - 速度反馈
|
|
||||||
速度偏差变化 = 速度偏差 - 上次速度偏差
|
|
||||||
位置控制量 = Kp2*速度偏差 + Ki2 * ∑速度偏差 + Kd2 * 速度偏差变化
|
|
||||||
串级速度整定:???
|
|
||||||
|
|
||||||
automatic control theory
|
|
||||||
control system
|
|
||||||
linear and nonlinear system
|
|
||||||
线性连续系统
|
|
||||||
离散系统
|
|
||||||
modelling
|
|
||||||
analysis
|
|
||||||
矫正
|
|
||||||
分析 时域分析方法 微分方程 传递函数 一阶系统 二阶系统
|
|
||||||
频域分析方法 闭环特性 低频特性 高频特性
|
|
||||||
根轨迹
|
|
||||||
建模 分析 矫正
|
|
||||||
离散系统
|
|
||||||
非线性控制理论
|
|
||||||
L变换 Z变换
|
|
||||||
采样控制系统 数字控制系统
|
|
||||||
条件稳定系统
|
|
||||||
problems
|
|
||||||
time consuming
|
|
||||||
行列式计算
|
|
||||||
相对稳定性
|
|
||||||
劳斯准则只能判断系统是否稳定,不能判断稳定程度
|
|
||||||
伯德图
|
|
||||||
nyquist 图
|
|
||||||
相位裕度
|
|
||||||
闭环特征方程的根闭,开环增益0到无穷 特征方程根的变化规律
|
|
||||||
root locus
|
|
||||||
单位负反馈
|
|
||||||
G(s) = k/s(s+1)
|
|
||||||
复角条件复值条件
|
|
||||||
渐近线与实轴交点
|
|
||||||
出射角p-n/n-m
|
|
||||||
|
|
||||||
lambda
|
|
||||||
大纯滞后
|
|
||||||
积分对象
|
|
||||||
lambda
|
|
||||||
纯滞后 tao/t
|
|
||||||
斯密斯预估 闭环传递函数 整定方法
|
|
||||||
阶跃响应 鲁棒性 积分过程 输入干扰
|
|
||||||
执行机构偏离,不确定不准确,调整速度
|
|
||||||
PI 为主 D
|
|
||||||
两自由度PID 比例积分先行
|
|
||||||
鲁棒性 性能不完全微分
|
|
||||||
负载扰
|
|
||||||
|
|
||||||
makefile 工作原理:
|
|
||||||
1、可执行文件生成过程:预处理->编译->链接
|
|
||||||
#source object target
|
|
||||||
SRC := *.c
|
|
||||||
OBJ := *.o
|
|
||||||
TARGET := mqtt_test
|
|
||||||
|
|
||||||
#compile library include
|
|
||||||
CC := cc
|
|
||||||
LIB:= -lpthread
|
|
||||||
LDFLAG := -L. libmosquitto.so
|
|
||||||
CFLAG :=
|
|
||||||
CXXFLAG :=
|
|
||||||
#link
|
|
||||||
$(TARGET):$(OBJ)
|
|
||||||
$(CC) -o $(TARGET) $(BOJ) $(LIB) $(LDFLAG)
|
|
||||||
$(CC) -o $@ $^ $(LIB) $(LDFLAG)
|
|
||||||
$(OBJ):$(SRC)
|
|
||||||
$(CC) -c $(SRC)
|
|
||||||
#all
|
|
||||||
all:$(TARGET)
|
|
||||||
$(CC) -o $(TARGET) $(SRC) $(LIB) $(LDFLAG)
|
|
||||||
#clean
|
|
||||||
clean:
|
|
||||||
rm -rf *.o $(TARGET)
|
|
||||||
*/
|
|
||||||
// ————————————————————————————————————
|
|
||||||
|
|
||||||
/*
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
int argc;
|
|
||||||
char **argv;
|
|
||||||
int sock;
|
|
||||||
}st_app_param;
|
|
||||||
|
|
||||||
const char *g_version = "V1.0.0 24.08.16";
|
|
||||||
int child_mian_ini()
|
|
||||||
{
|
|
||||||
int i_re;
|
|
||||||
i_re = gw_support_init();
|
|
||||||
if(i_re < 0)
|
|
||||||
{
|
|
||||||
printf("解析支持文件错误.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
i_re = gw_config_init();
|
|
||||||
if(i_re < 0)
|
|
||||||
{
|
|
||||||
printf("解析配置文件错误.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
i_re = gw_data_init();
|
|
||||||
if(i_re < 0)
|
|
||||||
{
|
|
||||||
printf("数据初始化错误.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
i_re = gw_modol_init();
|
|
||||||
if(i_re < 0)
|
|
||||||
{
|
|
||||||
printf("解析模型文件错误.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
i_re = gw_stat_init();
|
|
||||||
if(i_re < 0)
|
|
||||||
{
|
|
||||||
printf("数据统计初始化错误.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
i_re = gw_process_init();
|
|
||||||
if(i_re < 0)
|
|
||||||
{
|
|
||||||
printf("规约初始化错误.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
i_re = gw_manage_init();
|
|
||||||
if(i_re < 0)
|
|
||||||
{
|
|
||||||
printf("界面通讯初始化错误.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pthread_create(tid,thread_task1,p_param);
|
|
||||||
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
get_sys_time();
|
|
||||||
sleep(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int child_main(int argc,char **argv)
|
|
||||||
{
|
|
||||||
|
|
||||||
if((argc == 2)&&(strcasecmp(argv[1],"-version") == 0))
|
|
||||||
{
|
|
||||||
printf("version [%s]",g_version);
|
|
||||||
}
|
|
||||||
|
|
||||||
child_mian_ini();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static int run_child_process_thread((void *)param)
|
|
||||||
{
|
|
||||||
st_app_param *p_param;
|
|
||||||
|
|
||||||
p_param = param;
|
|
||||||
chlid_main(p_parm->argc,p_param->argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int run_child_process(int argc,char **argv,int sock)
|
|
||||||
{
|
|
||||||
int i_re;
|
|
||||||
pthread_t *tid;
|
|
||||||
st_app_param p_param;
|
|
||||||
|
|
||||||
p_param.argc = argc;
|
|
||||||
p_param.argv = argv;
|
|
||||||
p_param.sock = sock;
|
|
||||||
|
|
||||||
pthread_creat(tid,run_child_process_thread,(void *)p_param);
|
|
||||||
i_re = recv(sock,..,0);//阻塞接收
|
|
||||||
send(sock,'q',0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc,char**argv)
|
|
||||||
{
|
|
||||||
int i_re,fd,pid;
|
|
||||||
char lock_file[16];
|
|
||||||
socketpair sockpaire[2];
|
|
||||||
|
|
||||||
sprintf(lock_file,"%s.lock",argv[0]);
|
|
||||||
|
|
||||||
fd = open(lock_file,_O_WRONLY|_EXC,0777);
|
|
||||||
if(fd < 0)
|
|
||||||
{
|
|
||||||
printf("应用:[%s]已运行.\n",argv[0]);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sockpaire[0] = -1;
|
|
||||||
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
i_re = socketpaire(sockpaire,AN_UNIX,..);
|
|
||||||
if(i_re < 0)
|
|
||||||
{
|
|
||||||
printf("[%d]创建sockpaire失败.\n",getpid());
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pid = fork();
|
|
||||||
|
|
||||||
if(pid < 0)
|
|
||||||
{
|
|
||||||
printf("[%d]创建进程失败.\n",getpid());
|
|
||||||
close(sockpaire[0]);
|
|
||||||
sockpaire[0] = -1
|
|
||||||
close(sockpaire[1]);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(pid == 0)//child process
|
|
||||||
{
|
|
||||||
close(sockpair[0]);
|
|
||||||
return run_child_process(argc,argv,sockpair[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("[%d]创建子进程成功.\n",getpid());
|
|
||||||
close(sockpair[1]);
|
|
||||||
while(1)//father process
|
|
||||||
{
|
|
||||||
i_re = recv(sockpaire[0],....,0);//阻塞接收
|
|
||||||
if(i_re <= 0)
|
|
||||||
{
|
|
||||||
//连接中断,重连
|
|
||||||
sockpaire[0] = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//正常退出
|
|
||||||
goto EXIT:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EXIT:
|
|
||||||
//退出操作
|
|
||||||
if(sockpaire[0] == -1)
|
|
||||||
{
|
|
||||||
//有子进程,关闭子进程
|
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
unlink(file_lock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
|
@ -1,63 +0,0 @@
|
||||||
/*
|
|
||||||
* @Author: 张小明 zxm5337@163.com
|
|
||||||
* @Date: 2024-06-25 10:26:36
|
|
||||||
* @LastEditors: DaMingSY zxm5337@163.com
|
|
||||||
* @LastEditTime: 2024-09-03 09:19:23
|
|
||||||
* @FilePath: \controller-v2\User\lib\control\custom\cascade_pid_zh.h
|
|
||||||
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
|
||||||
*/
|
|
||||||
#ifndef __CASCADE_PID_ZH__
|
|
||||||
#define __CASCADE_PID_ZH__
|
|
||||||
|
|
||||||
#include "data_type_def.h"
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
TARGET_DIR_ADD,
|
|
||||||
TARGET_DIR_SUB,
|
|
||||||
} target_dir_e;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
float kp;
|
|
||||||
float ki;
|
|
||||||
float kd;
|
|
||||||
|
|
||||||
float kup;
|
|
||||||
float kui;
|
|
||||||
float kud;
|
|
||||||
} fuzzy_pid_t;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
BOOL iDetach, sm_open, fuzzy_open;
|
|
||||||
float feedBack;
|
|
||||||
float target, maxTarget;
|
|
||||||
float duty, kp, ki, kd;
|
|
||||||
float error, dError, lastError, errorDead;
|
|
||||||
float integral, iDetachCondation;
|
|
||||||
float output, maxOutput;
|
|
||||||
fuzzy_pid_t fuzzy_pid;
|
|
||||||
} smart_pid_t;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
smart_pid_t inner;
|
|
||||||
smart_pid_t outer;
|
|
||||||
float output;
|
|
||||||
} cascade_pid_t;
|
|
||||||
|
|
||||||
typedef struct CascadePID
|
|
||||||
{
|
|
||||||
void (*smart_pid_init)(smart_pid_t *pid, float *duty, float *kp, float *ki, float *kd, float *errorDead, float *iDetachCondation, float *maxOut);
|
|
||||||
void (*cascade_pid_init)(cascade_pid_t *pid, smart_pid_t *pid_outer, smart_pid_t *pid_inner);
|
|
||||||
void (*smart_pid_calc)(smart_pid_t *pid, float *target, float *feedback);
|
|
||||||
void (*cascade_pid_calc)(struct CascadePID *pid, float *outerRef, float *outerFdb, float *innerFdb);
|
|
||||||
|
|
||||||
smart_pid_t smart_pid;
|
|
||||||
cascade_pid_t cascade_pid;
|
|
||||||
} pid_zh1_t; // PID_t;
|
|
||||||
|
|
||||||
extern void pid_zh_constructor1(struct CascadePID *pid);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,26 +0,0 @@
|
||||||
# 架构
|
|
||||||
|文件|路径| <div style="width:300px">说明</div>|
|
|
||||||
|:--|:--|:--|
|
|
||||||
|pid|User\lib\control\src|PID算法模块|
|
|
||||||
|execute|User\application\src|执行器|
|
|
||||||
|app_flow|User|任务流程控制|
|
|
||||||
|
|
||||||
## APP_FLOW任务流程控制
|
|
||||||
> adjust_inspection 中在没有检测到调试信号时执行<b style="color:blue">execute_dac,EXECUTE_PLAN</b>定义了需要执行的算法任务计划
|
|
||||||
|
|
||||||
## PID算法模块
|
|
||||||
文件内容:
|
|
||||||
|文件| <div style="width:300px">说明</div>|
|
|
||||||
|:--|:--|
|
|
||||||
|pid.c|构造算法的入口|
|
|
||||||
|pid_common.c|普通算法|
|
|
||||||
|pid_neural.c|神经网络算法|
|
|
||||||
|pid_fuzzy.c|模糊算法|
|
|
||||||
|
|
||||||
<b style="color:blue">custom 目录下为各自算法实现</b>
|
|
||||||
|
|
||||||
|
|
||||||
## EXECUTE执行器
|
|
||||||
> execute_pid_init中定义了初始化参数
|
|
||||||
> execute_dac中定义了执行器
|
|
||||||
|
|
|
@ -1,16 +1,8 @@
|
||||||
#ifndef __PID_H__
|
#ifndef __PID_H__
|
||||||
#define __PID_H__
|
#define __PID_H__
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
|
|
||||||
#include "pid_auto_tune.h"
|
#include "pid_auto_tune.h"
|
||||||
|
|
||||||
#include "pid_c.h"
|
|
||||||
#include "pid_g.h"
|
|
||||||
#include "pid_x.h"
|
|
||||||
#include "pid_zh.h"
|
|
||||||
#include "pid_zh1.h"
|
|
||||||
#include "pid_hd.h"
|
|
||||||
|
|
||||||
#define INCOMPLETE_DIFFEREN 0 // 不完全微分
|
#define INCOMPLETE_DIFFEREN 0 // 不完全微分
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
|
@ -227,14 +219,6 @@ typedef struct
|
||||||
pid_common_t common;
|
pid_common_t common;
|
||||||
pid_neural_t neural;
|
pid_neural_t neural;
|
||||||
pid_fuzzy_t fuzzy;
|
pid_fuzzy_t fuzzy;
|
||||||
|
|
||||||
// 自定义PID
|
|
||||||
pid_c_t cao;
|
|
||||||
pid_g_t gao;
|
|
||||||
pid_x_t xu;
|
|
||||||
pid_zh_t zhang;
|
|
||||||
pid_zh1_t zhang1;
|
|
||||||
pid_hd_t hd;
|
|
||||||
} pid_u;
|
} pid_u;
|
||||||
pid_auto_tune_t auto_tune;
|
pid_auto_tune_t auto_tune;
|
||||||
} pid_t;
|
} pid_t;
|
||||||
|
|
|
@ -19,22 +19,6 @@ void pid_constructor(pid_t *self)
|
||||||
case PID_TYPE_AUTO_TUNE:
|
case PID_TYPE_AUTO_TUNE:
|
||||||
pid_auto_tune_constructor(&self->auto_tune);
|
pid_auto_tune_constructor(&self->auto_tune);
|
||||||
break;
|
break;
|
||||||
case PID_TYPE_CUSTOM_CAO:
|
|
||||||
pid_c_constructor(&self->pid_u.cao);
|
|
||||||
break;
|
|
||||||
case PID_TYPE_CUSTOM_GAO:
|
|
||||||
pid_g_constructor(&self->pid_u.gao);
|
|
||||||
break;
|
|
||||||
case PID_TYPE_CUSTOM_XU:
|
|
||||||
pid_x_constructor(&self->pid_u.xu);
|
|
||||||
break;
|
|
||||||
case PID_TYPE_CUSTOM_ZHANG:
|
|
||||||
// pid_zh_constructor(&self->pid_u.zhang);
|
|
||||||
pid_zh_constructor1(&self->pid_u.zhang1);
|
|
||||||
break;
|
|
||||||
case PID_TYPE_CUSTOM_HANGDIAN:
|
|
||||||
pid_hd_constructor(&self->pid_u.hd);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,8 +47,8 @@ while(1) {
|
||||||
|
|
||||||
// 根据您的需求修改常量。
|
// 根据您的需求修改常量。
|
||||||
#define TICKS_INTERVAL 10 // 按钮扫描间隔,单位ms
|
#define TICKS_INTERVAL 10 // 按钮扫描间隔,单位ms
|
||||||
#define DEBOUNCE_TICKS 20 / TICKS_INTERVAL // 按键去抖动时间,单位ms
|
#define DEBOUNCE_TICKS 30 / TICKS_INTERVAL // 按键去抖动时间,单位ms
|
||||||
#define SHORT_TICKS (100 / TICKS_INTERVAL) // 短按时间阈值,单位ms
|
#define SHORT_TICKS (30 / TICKS_INTERVAL) // 短按时间阈值,单位ms
|
||||||
#define LONG_TICKS (500 / TICKS_INTERVAL) // 长按时间阈值,单位ms
|
#define LONG_TICKS (500 / TICKS_INTERVAL) // 长按时间阈值,单位ms
|
||||||
|
|
||||||
typedef void (*BtnCallback)(void *);
|
typedef void (*BtnCallback)(void *);
|
||||||
|
|
65
motor.ioc
65
motor.ioc
|
@ -34,28 +34,33 @@ Mcu.IP2=RCC
|
||||||
Mcu.IP3=SYS
|
Mcu.IP3=SYS
|
||||||
Mcu.IP4=TIM1
|
Mcu.IP4=TIM1
|
||||||
Mcu.IP5=TIM2
|
Mcu.IP5=TIM2
|
||||||
Mcu.IP6=USART1
|
Mcu.IP6=TIM3
|
||||||
Mcu.IPNb=7
|
Mcu.IP7=USART1
|
||||||
|
Mcu.IPNb=8
|
||||||
Mcu.Name=STM32F103C(8-B)Tx
|
Mcu.Name=STM32F103C(8-B)Tx
|
||||||
Mcu.Package=LQFP48
|
Mcu.Package=LQFP48
|
||||||
Mcu.Pin0=PC13-TAMPER-RTC
|
Mcu.Pin0=PC13-TAMPER-RTC
|
||||||
Mcu.Pin1=PC15-OSC32_OUT
|
Mcu.Pin1=PC15-OSC32_OUT
|
||||||
Mcu.Pin10=PA9
|
Mcu.Pin10=PB0
|
||||||
Mcu.Pin11=PA10
|
Mcu.Pin11=PB12
|
||||||
Mcu.Pin12=PA13
|
Mcu.Pin12=PB13
|
||||||
Mcu.Pin13=PA14
|
Mcu.Pin13=PA9
|
||||||
Mcu.Pin14=VP_SYS_VS_Systick
|
Mcu.Pin14=PA10
|
||||||
Mcu.Pin15=VP_TIM1_VS_ClockSourceINT
|
Mcu.Pin15=PA13
|
||||||
Mcu.Pin16=VP_TIM2_VS_ClockSourceINT
|
Mcu.Pin16=PA14
|
||||||
|
Mcu.Pin17=VP_SYS_VS_Systick
|
||||||
|
Mcu.Pin18=VP_TIM1_VS_ClockSourceINT
|
||||||
|
Mcu.Pin19=VP_TIM2_VS_ClockSourceINT
|
||||||
Mcu.Pin2=PD0-OSC_IN
|
Mcu.Pin2=PD0-OSC_IN
|
||||||
|
Mcu.Pin20=VP_TIM3_VS_ClockSourceINT
|
||||||
Mcu.Pin3=PD1-OSC_OUT
|
Mcu.Pin3=PD1-OSC_OUT
|
||||||
Mcu.Pin4=PA0-WKUP
|
Mcu.Pin4=PA0-WKUP
|
||||||
Mcu.Pin5=PA1
|
Mcu.Pin5=PA1
|
||||||
Mcu.Pin6=PA4
|
Mcu.Pin6=PA4
|
||||||
Mcu.Pin7=PA5
|
Mcu.Pin7=PA5
|
||||||
Mcu.Pin8=PB12
|
Mcu.Pin8=PA6
|
||||||
Mcu.Pin9=PB13
|
Mcu.Pin9=PA7
|
||||||
Mcu.PinsNb=17
|
Mcu.PinsNb=21
|
||||||
Mcu.ThirdParty0=RealThread.RT-Thread.3.1.5
|
Mcu.ThirdParty0=RealThread.RT-Thread.3.1.5
|
||||||
Mcu.ThirdPartyNb=1
|
Mcu.ThirdPartyNb=1
|
||||||
Mcu.UserConstants=
|
Mcu.UserConstants=
|
||||||
|
@ -66,6 +71,7 @@ NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||||
NVIC.DMA1_Channel4_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true
|
NVIC.DMA1_Channel4_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true
|
||||||
NVIC.DMA1_Channel5_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true
|
NVIC.DMA1_Channel5_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true
|
||||||
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||||
|
NVIC.EXTI0_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
|
||||||
NVIC.ForceEnableDMAVector=true
|
NVIC.ForceEnableDMAVector=true
|
||||||
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||||
NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||||
|
@ -74,11 +80,13 @@ NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||||
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
|
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
|
||||||
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||||
NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:false
|
NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:false
|
||||||
NVIC.TIM1_UP_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
|
NVIC.TIM1_UP_IRQn=true\:3\:0\:true\:false\:true\:true\:true\:true
|
||||||
NVIC.TIM2_IRQn=true\:15\:0\:true\:false\:true\:true\:true\:true
|
NVIC.TIM3_IRQn=true\:1\:0\:true\:false\:true\:true\:true\:true
|
||||||
NVIC.USART1_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
|
NVIC.USART1_IRQn=true\:5\:0\:true\:false\:true\:true\:true\:true
|
||||||
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||||
PA0-WKUP.Signal=GPIO_Input
|
PA0-WKUP.GPIOParameters=GPIO_Label
|
||||||
|
PA0-WKUP.GPIO_Label=MOTOR_A
|
||||||
|
PA0-WKUP.Signal=GPXTI0
|
||||||
PA1.Signal=S_TIM2_CH2
|
PA1.Signal=S_TIM2_CH2
|
||||||
PA10.Mode=Asynchronous
|
PA10.Mode=Asynchronous
|
||||||
PA10.Signal=USART1_RX
|
PA10.Signal=USART1_RX
|
||||||
|
@ -96,8 +104,20 @@ PA5.GPIO_Label=AIN2
|
||||||
PA5.GPIO_ModeDefaultOutputPP=GPIO_MODE_OUTPUT_PP
|
PA5.GPIO_ModeDefaultOutputPP=GPIO_MODE_OUTPUT_PP
|
||||||
PA5.GPIO_PuPd=GPIO_PULLUP
|
PA5.GPIO_PuPd=GPIO_PULLUP
|
||||||
PA5.Signal=GPIO_Output
|
PA5.Signal=GPIO_Output
|
||||||
|
PA6.GPIOParameters=GPIO_PuPd,GPIO_Label
|
||||||
|
PA6.GPIO_Label=KEY_ADD
|
||||||
|
PA6.GPIO_PuPd=GPIO_PULLDOWN
|
||||||
|
PA6.Signal=GPIO_Input
|
||||||
|
PA7.GPIOParameters=GPIO_PuPd,GPIO_Label
|
||||||
|
PA7.GPIO_Label=KEY_SUB
|
||||||
|
PA7.GPIO_PuPd=GPIO_PULLDOWN
|
||||||
|
PA7.Signal=GPIO_Input
|
||||||
PA9.Mode=Asynchronous
|
PA9.Mode=Asynchronous
|
||||||
PA9.Signal=USART1_TX
|
PA9.Signal=USART1_TX
|
||||||
|
PB0.GPIOParameters=GPIO_PuPd,GPIO_Label
|
||||||
|
PB0.GPIO_Label=KEY_S
|
||||||
|
PB0.GPIO_PuPd=GPIO_PULLDOWN
|
||||||
|
PB0.Signal=GPIO_Input
|
||||||
PB12.GPIOParameters=GPIO_Speed,PinState,GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultOutputPP
|
PB12.GPIOParameters=GPIO_Speed,PinState,GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultOutputPP
|
||||||
PB12.GPIO_Label=OLED_SDA
|
PB12.GPIO_Label=OLED_SDA
|
||||||
PB12.GPIO_ModeDefaultOutputPP=GPIO_MODE_OUTPUT_PP
|
PB12.GPIO_ModeDefaultOutputPP=GPIO_MODE_OUTPUT_PP
|
||||||
|
@ -115,6 +135,8 @@ PB13.Signal=GPIO_Output
|
||||||
PC13-TAMPER-RTC.GPIOParameters=GPIO_Label
|
PC13-TAMPER-RTC.GPIOParameters=GPIO_Label
|
||||||
PC13-TAMPER-RTC.GPIO_Label=LED_BLUE
|
PC13-TAMPER-RTC.GPIO_Label=LED_BLUE
|
||||||
PC13-TAMPER-RTC.Signal=GPIO_Output
|
PC13-TAMPER-RTC.Signal=GPIO_Output
|
||||||
|
PC15-OSC32_OUT.GPIOParameters=GPIO_Label
|
||||||
|
PC15-OSC32_OUT.GPIO_Label=MOTOR_B
|
||||||
PC15-OSC32_OUT.Signal=GPIO_Input
|
PC15-OSC32_OUT.Signal=GPIO_Input
|
||||||
PD0-OSC_IN.Mode=HSE-External-Oscillator
|
PD0-OSC_IN.Mode=HSE-External-Oscillator
|
||||||
PD0-OSC_IN.Signal=RCC_OSC_IN
|
PD0-OSC_IN.Signal=RCC_OSC_IN
|
||||||
|
@ -151,7 +173,7 @@ ProjectManager.ToolChainLocation=
|
||||||
ProjectManager.UAScriptAfterPath=
|
ProjectManager.UAScriptAfterPath=
|
||||||
ProjectManager.UAScriptBeforePath=
|
ProjectManager.UAScriptBeforePath=
|
||||||
ProjectManager.UnderRoot=false
|
ProjectManager.UnderRoot=false
|
||||||
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-LL-false,2-MX_GPIO_Init-GPIO-false-LL-true,3-MX_DMA_Init-DMA-false-LL-true,4-MX_TIM2_Init-TIM2-false-LL-true,5-MX_USART1_UART_Init-USART1-false-LL-true,6-MX_TIM1_Init-TIM1-false-LL-true
|
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-LL-false,2-MX_GPIO_Init-GPIO-false-LL-true,3-MX_DMA_Init-DMA-false-LL-true,4-MX_TIM2_Init-TIM2-false-LL-true,5-MX_USART1_UART_Init-USART1-false-LL-true,6-MX_TIM1_Init-TIM1-false-LL-true,7-MX_TIM3_Init-TIM3-false-LL-true
|
||||||
RCC.ADCFreqValue=36000000
|
RCC.ADCFreqValue=36000000
|
||||||
RCC.AHBFreq_Value=72000000
|
RCC.AHBFreq_Value=72000000
|
||||||
RCC.APB1CLKDivider=RCC_HCLK_DIV2
|
RCC.APB1CLKDivider=RCC_HCLK_DIV2
|
||||||
|
@ -181,12 +203,14 @@ RealThread.RT-Thread.3.1.5.RT_USING_COMPONENTS_INIT=1
|
||||||
RealThread.RT-Thread.3.1.5.RT_USING_CONSOLE=0
|
RealThread.RT-Thread.3.1.5.RT_USING_CONSOLE=0
|
||||||
RealThread.RT-Thread.3.1.5.RT_USING_DEVICE=1
|
RealThread.RT-Thread.3.1.5.RT_USING_DEVICE=1
|
||||||
RealThread.RT-Thread.3.1.5_SwParameter=RTOSJjkernel\:true;RTOSJjshell\:true;RTOSJjdevice\:true;
|
RealThread.RT-Thread.3.1.5_SwParameter=RTOSJjkernel\:true;RTOSJjshell\:true;RTOSJjdevice\:true;
|
||||||
|
SH.GPXTI0.0=GPIO_EXTI0
|
||||||
|
SH.GPXTI0.ConfNb=1
|
||||||
SH.S_TIM2_CH2.0=TIM2_CH2,PWM Generation2 CH2
|
SH.S_TIM2_CH2.0=TIM2_CH2,PWM Generation2 CH2
|
||||||
SH.S_TIM2_CH2.ConfNb=1
|
SH.S_TIM2_CH2.ConfNb=1
|
||||||
TIM1.IPParameters=Prescaler,Period
|
TIM1.IPParameters=Prescaler,Period
|
||||||
TIM1.Period=99
|
TIM1.Period=99
|
||||||
TIM1.Prescaler=7199
|
TIM1.Prescaler=7199
|
||||||
TIM2.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_DISABLE
|
TIM2.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE
|
||||||
TIM2.Channel-PWM\ Generation2\ CH2=TIM_CHANNEL_2
|
TIM2.Channel-PWM\ Generation2\ CH2=TIM_CHANNEL_2
|
||||||
TIM2.CounterMode=TIM_COUNTERMODE_UP
|
TIM2.CounterMode=TIM_COUNTERMODE_UP
|
||||||
TIM2.IPParameters=Prescaler,Period,CounterMode,AutoReloadPreload,OCPolarity_2,TIM_MasterOutputTrigger,Channel-PWM Generation2 CH2,OCFastMode_PWM-PWM Generation2 CH2,OCMode_PWM-PWM Generation2 CH2
|
TIM2.IPParameters=Prescaler,Period,CounterMode,AutoReloadPreload,OCPolarity_2,TIM_MasterOutputTrigger,Channel-PWM Generation2 CH2,OCFastMode_PWM-PWM Generation2 CH2,OCMode_PWM-PWM Generation2 CH2
|
||||||
|
@ -196,6 +220,9 @@ TIM2.OCPolarity_2=TIM_OCPOLARITY_LOW
|
||||||
TIM2.Period=7199
|
TIM2.Period=7199
|
||||||
TIM2.Prescaler=0
|
TIM2.Prescaler=0
|
||||||
TIM2.TIM_MasterOutputTrigger=TIM_TRGO_RESET
|
TIM2.TIM_MasterOutputTrigger=TIM_TRGO_RESET
|
||||||
|
TIM3.IPParameters=Prescaler,Period
|
||||||
|
TIM3.Period=99
|
||||||
|
TIM3.Prescaler=7199
|
||||||
USART1.IPParameters=VirtualMode
|
USART1.IPParameters=VirtualMode
|
||||||
USART1.VirtualMode=VM_ASYNC
|
USART1.VirtualMode=VM_ASYNC
|
||||||
VP_SYS_VS_Systick.Mode=SysTick
|
VP_SYS_VS_Systick.Mode=SysTick
|
||||||
|
@ -204,4 +231,6 @@ VP_TIM1_VS_ClockSourceINT.Mode=Internal
|
||||||
VP_TIM1_VS_ClockSourceINT.Signal=TIM1_VS_ClockSourceINT
|
VP_TIM1_VS_ClockSourceINT.Signal=TIM1_VS_ClockSourceINT
|
||||||
VP_TIM2_VS_ClockSourceINT.Mode=Internal
|
VP_TIM2_VS_ClockSourceINT.Mode=Internal
|
||||||
VP_TIM2_VS_ClockSourceINT.Signal=TIM2_VS_ClockSourceINT
|
VP_TIM2_VS_ClockSourceINT.Signal=TIM2_VS_ClockSourceINT
|
||||||
|
VP_TIM3_VS_ClockSourceINT.Mode=Internal
|
||||||
|
VP_TIM3_VS_ClockSourceINT.Signal=TIM3_VS_ClockSourceINT
|
||||||
board=custom
|
board=custom
|
||||||
|
|
Loading…
Reference in New Issue