固件库开发的直流电机pid控制系统
单片机源程序如下:
- /**
- ******************************************************************************
- * 文件名程: BDCMOTOR.c
- * 作 者: 学习小组
- * 功 能: 有刷直流电机驱动板基本驱动程序
- ******************************************************************************
- * 说明:
- ******************************************************************************
- */
- /* 包含头文件 ----------------------------------------------------------------*/
- #include "BDCMotor.h"
- /* 私有类型定义 --------------------------------------------------------------*/
- /* 私有宏定义 ----------------------------------------------------------------*/
- /* 私有变量 ------------------------------------------------------------------*/
- TIM_HandleTypeDef htimx_BDCMOTOR;
- __IO int16_t PWM_Duty=BDCMOTOR_DUTY_ZERO; // 占空比:PWM_Duty/BDCMOTOR_TIM_PERIOD*100%
- /* 扩展变量 ------------------------------------------------------------------*/
- /* 私有函数原形 --------------------------------------------------------------*/
- /* 函数体 --------------------------------------------------------------------*/
- /**
- * 函数功能: 基本定时器硬件初始化配置
- * 输入参数: htim_base:基本定时器句柄类型指针
- * 返 回 值: 无
- * 说 明: BDCMOTOR相关GPIO初始化配置,该函数被HAL库内部调用.
- */
- void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
- {
- /* BDCMOTOR相关GPIO初始化配置 */
- if(htim == &htimx_BDCMOTOR)
- {
- GPIO_InitTypeDef GPIO_InitStruct;
- /* 引脚端口时钟使能 */
- __HAL_RCC_GPIOE_CLK_ENABLE();
- BDCMOTOR_TIM_CH1_GPIO_CLK_ENABLE();
- BDCMOTOR_TIM_CH1N_GPIO_CLK_ENABLE();
- SHUTDOWN_GPIO_CLK_ENABLE();
- /* BDCMOTOR输出脉冲控制引脚IO初始化 */
- GPIO_InitStruct.Pin = BDCMOTOR_TIM_CH1_PIN;
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
- GPIO_InitStruct.Alternate = GPIO_AFx_TIMx;
- HAL_GPIO_Init(BDCMOTOR_TIM_CH1_PORT, &GPIO_InitStruct);
-
- GPIO_InitStruct.Pin = BDCMOTOR_TIM_CH1N_PIN;
- HAL_GPIO_Init(BDCMOTOR_TIM_CH1N_PORT, &GPIO_InitStruct);
-
- __HAL_RCC_GPIOE_CLK_ENABLE();
- GPIO_InitStruct.Pin = GPIO_PIN_11;
- HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
-
- GPIO_InitStruct.Pin = SHUTDOWN_PIN;
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
- GPIO_InitStruct.Alternate = 0;
- HAL_GPIO_Init(SHUTDOWN_PORT, &GPIO_InitStruct);
-
- /* 使能电机控制引脚 */
- ENABLE_MOTOR();
- }
- }
- /**
- * 函数功能: BDCMOTOR定时器初始化
- * 输入参数: 无
- * 返 回 值: 无
- * 说 明: 无
- */
- void BDCMOTOR_TIMx_Init(void)
- {
- TIM_ClockConfigTypeDef sClockSourceConfig; // 定时器时钟
- TIM_OC_InitTypeDef sConfigOC;
- TIM_BreakDeadTimeConfigTypeDef sBDTConfig; // 定时器死区时间比较输出
- /* 基本定时器外设时钟使能 */
- BDCMOTOR_TIM_RCC_CLK_ENABLE();
-
- /* 定时器基本环境配置 */
- htimx_BDCMOTOR.Instance = BDCMOTOR_TIMx; // 定时器编号
- htimx_BDCMOTOR.Init.Prescaler = BDCMOTOR_TIM_PRESCALER; // 定时器预分频器
- htimx_BDCMOTOR.Init.CounterMode = TIM_COUNTERMODE_UP; // 计数方向:向上计数
- htimx_BDCMOTOR.Init.Period = BDCMOTOR_TIM_PERIOD; // 定时器周期
- htimx_BDCMOTOR.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1; // 时钟分频
- htimx_BDCMOTOR.Init.RepetitionCounter = BDCMOTOR_TIM_REPETITIONCOUNTER; // 重复计数器
- /* 初始化定时器比较输出环境 */
- HAL_TIM_PWM_Init(&htimx_BDCMOTOR);
- /* 定时器时钟源配置 */
- sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; // 使用内部时钟源
- HAL_TIM_ConfigClockSource(&htimx_BDCMOTOR, &sClockSourceConfig);
- /* 死区刹车配置,实际上配置无效电平是高电平 */
- sBDTConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE ;
- sBDTConfig.BreakPolarity = TIM_BREAKPOLARITY_LOW ;
- sBDTConfig.BreakState = TIM_BREAK_DISABLE ;
- sBDTConfig.DeadTime = 0 ;
- sBDTConfig.LockLevel = TIM_LOCKLEVEL_OFF ;
- sBDTConfig.OffStateIDLEMode= TIM_OSSI_DISABLE ;
- sBDTConfig.OffStateRunMode = TIM_OSSR_ENABLE ;
- HAL_TIMEx_ConfigBreakDeadTime(&htimx_BDCMOTOR,&sBDTConfig);
- /* 定时器比较输出配置 */
- sConfigOC.OCMode = TIM_OCMODE_PWM1; // 比较输出模式:PWM1模式
- sConfigOC.Pulse = PWM_Duty; // 占空比
- sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW; // 输出极性
- sConfigOC.OCNPolarity = TIM_OCNPOLARITY_LOW; // 互补通道输出极性
- sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; // 快速模式
- sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; // 空闲电平
- sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; // 互补通道空闲电平
- HAL_TIM_PWM_ConfigChannel(&htimx_BDCMOTOR, &sConfigOC, TIM_CHANNEL_1);
- /* 启动定时器 */
- HAL_TIM_Base_Start(&htimx_BDCMOTOR);
- }
- /**
- * 函数功能: 基本定时器硬件反初始化配置
- * 输入参数: htim_base:基本定时器句柄类型指针
- * 返 回 值: 无
- * 说 明: 该函数被HAL库内部调用
- */
- void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base)
- {
- if(htim_base->Instance==BDCMOTOR_TIMx)
- {
- /* 基本定时器外设时钟禁用 */
- BDCMOTOR_TIM_RCC_CLK_DISABLE();
-
- HAL_GPIO_DeInit(BDCMOTOR_TIM_CH1_PORT,BDCMOTOR_TIM_CH1_PIN);
- HAL_GPIO_DeInit(BDCMOTOR_TIM_CH1N_PORT,BDCMOTOR_TIM_CH1N_PIN);
- }
- }
- /************************************END OF FILE**************************/
复制代码
- /**
- ******************************************************************************
- * 文件名程: main.c
- * 作 者: 学习小组
- * 功 能: 位置速度电流闭环控制
- ******************************************************************************
- * 说明:
- ******************************************************************************
- */
- /* 包含头文件 ----------------------------------------------------------------*/
- #include "stm32f4xx_hal.h"
- #include "key.h"
- #include "encoder.h"
- #include "usartx.h"
- #include "adc.h"
- #include "BDCMotor.h"
- /* 私有类型定义 --------------------------------------------------------------*/
- typedef struct
- {
- __IO int32_t SetPoint; // 设定目标 Desired Value
- __IO float SumError; // 误差累计
- __IO float Proportion; // 比例常数 Proportional Const
- __IO float Integral; // 积分常数 Integral Const
- __IO float Derivative; // 微分常数 Derivative Const
- __IO int LastError; // Error[-1]
- __IO int PrevError; // Error[-2]
- }PID_TypeDef;
- /* 私有宏定义 ----------------------------------------------------------------*/
- #define ADC_Base 8 // 取2的整数倍作为缓存区大小,得到14bits
- /* 使用DMA传输数据,采集n个数据点的时间是0.65ms,采样率大约是 1500 KHz */
- #define ADC_BUFFER 1024 // 采样数据缓存区
- #define SPEEDRATIO 270
- #define ENCODER_RESOLUTION 11
- #define PPR ((SPEEDRATIO*ENCODER_RESOLUTION)*4) // Pulse/Round 每圈可捕获到的脉冲数
- /*************************************/
- // 定义PID相关宏
- // 这三个参数设定对电机运行影响非常大
- // PID参数跟采样时间息息相关
- /*************************************/
- #define CUR_P_DATA 0.35f // P参数
- #define CUR_I_DATA 0.6f // I参数
- #define CUR_D_DATA 0.0f // D参数
- #define TARGET_CURRENT 300 // 最大电流值 300mA
- #define SPD_P_DATA 4.5f // P参数
- #define SPD_I_DATA 0.5f // I参数
- #define SPD_D_DATA 0.0f // D参数
- #define TARGET_SPEED 20.0f // 目标速度 20r/m
- #define LOC_P_DATA 0.009f // P参数
- #define LOC_I_DATA 0.002f // I参数
- #define LOC_D_DATA 0.04f // D参数
- #define TARGET_LOC (3*PPR) // 目标位置 11880Pulse = 1r
- /* 私有变量 ------------------------------------------------------------------*/
- __IO uint8_t Start_flag = 0; // PID 开始标志
- uint32_t Motor_Dir = CW; // 电机方向
- __IO int32_t tmpPWM_DutySpd = 0;
- __IO int32_t tmpPWM_Duty = 0;
- /* 用于保存转换计算后的数值 */
- __IO float ADC_VoltBus; // 总线电压值
- __IO int32_t Sample_Pulse; // 编码器捕获值 Pulse
- __IO int32_t LastSample_Pulse; // 编码器捕获值 Pulse
- __IO int32_t Spd_PPS; // 速度值 Pulse/Sample
- __IO float Spd_RPM; // 速度值 r/m
- /* AD转换结果值 */
- __IO int16_t ADC_ConvValueHex[ADC_BUFFER]; // AD转换结果缓存
- __IO int32_t AverSum = 0; // 平均值的累加值
- __IO int32_t AverCnt = 0; // 平均值的计数器
- __IO uint32_t OffsetCnt_Flag = 0 ; // 偏差值的计数器标志
- __IO int32_t OffSetHex ; // 偏差值
- /* 扩展变量 ------------------------------------------------------------------ */
- extern __IO uint32_t uwTick;
- /* PID结构体 */
- PID_TypeDef cPID,sPID,lPID; // PID参数结构体
- /* 扩展变量 ------------------------------------------------------------------*/
- /* 私有函数原形 --------------------------------------------------------------*/
- void PID_ParamInit(void) ;
- int32_t CurPIDCalc(int32_t NextPoint);
- int32_t SpdPIDCalc(float NextPoint);
- int32_t LocPIDCalc(int32_t NextPoint);
- int32_t ADC_GetSampleAvgN(int16_t *Data, uint32_t N );
- /* 函数体 --------------------------------------------------------------------*/
- /**
- * 函数功能: 系统时钟配置
- * 输入参数: 无
- * 返 回 值: 无
- * 说 明: 无
- */
- void SystemClock_Config(void)
- {
- RCC_OscInitTypeDef RCC_OscInitStruct;
- RCC_ClkInitTypeDef RCC_ClkInitStruct;
-
- __HAL_RCC_PWR_CLK_ENABLE(); // 使能PWR时钟
- __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); // 设置调压器输出电压级别1
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; // 外部晶振,8MHz
- RCC_OscInitStruct.HSEState = RCC_HSE_ON; // 打开HSE
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; // 打开PLL
- RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; // PLL时钟源选择HSE
- RCC_OscInitStruct.PLL.PLLM = 8; // 8分频MHz
- RCC_OscInitStruct.PLL.PLLN = 336; // 336倍频
- RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; // 2分频,得到168MHz主时钟
- RCC_OscInitStruct.PLL.PLLQ = 7; // USB/SDIO/随机数产生器等的主PLL分频系数
- HAL_RCC_OscConfig(&RCC_OscInitStruct);
- RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
- |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
- RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 系统时钟:168MHz
- RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // AHB时钟: 168MHz
- RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; // APB1时钟:42MHz
- RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; // APB2时钟:84MHz
- HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
- HAL_RCC_EnableCSS(); // 使能CSS功能,优先使用外部晶振,内部时钟源为备用
-
- // HAL_RCC_GetHCLKFreq()/1000 1ms中断一次
- // HAL_RCC_GetHCLKFreq()/100000 10us中断一次
- // HAL_RCC_GetHCLKFreq()/1000000 1us中断一次
- HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); // 配置并启动系统滴答定时器
- /* 系统滴答定时器时钟源 */
- HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
- /* 系统滴答定时器中断优先级配置 */
- HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
- }
-
- /**
- * 函数功能: 主函数.
- * 输入参数: 无
- * 返 回 值: 无
- * 说 明: 无
- */
- int main(void)
- {
- /* 复位所有外设,初始化Flash接口和系统滴答定时器 */
- HAL_Init();
- /* 配置系统时钟 */
- SystemClock_Config();
- /* 串口初始化 */
- MX_USARTx_Init();
- /* 按键初始化 */
- KEY_GPIO_Init();
- /* 编码器初始化及使能编码器模式 */
- ENCODER_TIMx_Init();
- /* ADC-DMA 初始化 */
- MX_ADCx_Init();
- /* 启动AD转换并使能DMA传输和中断 */
- HAL_ADC_Start_DMA(&hadcx,(uint32_t*)ADC_ConvValueHex,ADC_BUFFER);
- __HAL_DMA_DISABLE_IT(&hdma_adcx,DMA_IT_HT);
- __HAL_DMA_DISABLE_IT(&hdma_adcx,DMA_IT_TE);
- __HAL_DMA_DISABLE_IT(&hdma_adcx,DMA_IT_FE);
- __HAL_DMA_DISABLE_IT(&hdma_adcx,DMA_IT_DME);
- /* 高级控制定时器初始化并配置PWM输出功能 */
- BDCMOTOR_TIMx_Init();
- /* 启动定时器通道和互补通道PWM输出 */
- PWM_Duty = 0;
- __HAL_TIM_SET_COMPARE(&htimx_BDCMOTOR,TIM_CHANNEL_1,PWM_Duty); // 0%
- /* PID 参数初始化 */
- PID_ParamInit();
- /* 无限循环 */
- while (1)
- {
- /* 停止按钮 */
- if(KEY1_StateRead()==KEY_DOWN)
- {
- HAL_TIM_PWM_Start(&htimx_BDCMOTOR,TIM_CHANNEL_1);
- HAL_TIMEx_PWMN_Stop(&htimx_BDCMOTOR,TIM_CHANNEL_1);
- __HAL_TIM_SET_COMPARE(&htimx_BDCMOTOR,TIM_CHANNEL_1,0); // 0%
- Start_flag = 1;
- }
- if(KEY2_StateRead()==KEY_DOWN)
- {
- SHUTDOWN_MOTOR();
- HAL_TIM_PWM_Stop(&htimx_BDCMOTOR,TIM_CHANNEL_1);
- HAL_TIMEx_PWMN_Stop(&htimx_BDCMOTOR,TIM_CHANNEL_1); // 停止输出
- }
- if(KEY3_StateRead()==KEY_DOWN) // 圈数+1
- {
- lPID.SetPoint += PPR;
- }
- if(KEY4_StateRead()==KEY_DOWN) // 圈数-1
- {
- lPID.SetPoint -= PPR;
- }
- }
- }
- /**
- * 函数功能: 系统滴答定时器中断回调函数
- * 输入参数: 无
- * 返 回 值: 无
- * 说 明: 每隔一定的时间就执行pid算法
- */
- void HAL_SYSTICK_Callback(void)
- {
- __IO int32_t ADC_Resul= 0;
- __IO float Volt_Result = 0;
- __IO float ADC_CurrentValue; // 电流
- /* 位置环周期250ms */
- if(uwTick % 250 == 0)
- {
- /* 获取当前位置值,编码器4倍频之后的数值 */
- Sample_Pulse = (OverflowCount*CNT_MAX) + (int32_t)__HAL_TIM_GET_COUNTER(&htimx_Encoder);
- /* 计算PID结果 */
- if(Start_flag == 1)
- {
- tmpPWM_DutySpd = LocPIDCalc(Sample_Pulse);
-
- /* 设定速度环的目标值 */
- if(tmpPWM_DutySpd >= TARGET_SPEED)
- tmpPWM_DutySpd = TARGET_SPEED;
- if(tmpPWM_DutySpd <= -TARGET_SPEED)
- tmpPWM_DutySpd = -TARGET_SPEED;
- }
- }
- /* 速度环周期100ms */
- if(uwTick % 100 == 0)
- {
- /* 获得当前速度 */
- Sample_Pulse = (OverflowCount*CNT_MAX) + (int32_t)__HAL_TIM_GET_COUNTER(&htimx_Encoder);
- Spd_PPS = Sample_Pulse - LastSample_Pulse;
- LastSample_Pulse = Sample_Pulse ;
- /* 11线编码器,270减速比,一圈脉冲信号是11*270*4 PPR */
- Spd_RPM = ((((float)Spd_PPS/(float)PPR)*10.0f)*(float)60);//单位是rpm
-
- /* 计算PID结果 */
- if(Start_flag == 1)
- {
- sPID.SetPoint = tmpPWM_DutySpd;
- tmpPWM_Duty = SpdPIDCalc(Spd_RPM);
-
- /* 根据速度环的计算结果判断当前运动方向 */
- if(tmpPWM_Duty < 0)
- {
- Motor_Dir = CW;
- BDDCMOTOR_DIR_CW();
- tmpPWM_Duty = -tmpPWM_Duty;
-
- }
- else
- {
- Motor_Dir = CCW;
- BDDCMOTOR_DIR_CCW();
- }
-
- /* 设定电流环的目标值,电流没有负数 */
- if(tmpPWM_Duty >= TARGET_CURRENT)
- tmpPWM_Duty = TARGET_CURRENT;
- }
- }
- /* 电流环周期是40ms,电流单次采集周期大约是 2ms,最好不要低于2ms */
- if(uwTick % 40 == 0)
- {
- ADC_Resul = AverSum/AverCnt ;
- /* 连续采样16次以后,作为偏差值 */
- OffsetCnt_Flag++;
- if(OffsetCnt_Flag >= 16)
- {
- if(OffsetCnt_Flag == 16)
- {
- OffSetHex /= OffsetCnt_Flag-1;
- }
- OffsetCnt_Flag = 32;
- ADC_Resul -= OffSetHex;//减去偏差值
- }
- else
- OffSetHex += ADC_Resul;
- /* 计算电压值和电流值 */
- Volt_Result = ( (float)( (float)(ADC_Resul) * VOLT_RESOLUTION) );
- ADC_CurrentValue = (float)( (Volt_Result / GAIN) / SAMPLING_RES);
- if(Volt_Result<0)
- Volt_Result = 0;
- /* 清空计数 */
- AverCnt = 0;
- AverSum = 0;
-
- /* 计算PID结果 */
- if(Start_flag == 1)
- {
- cPID.SetPoint = tmpPWM_Duty ;
- PWM_Duty = CurPIDCalc( (int32_t)ADC_CurrentValue);
- if(PWM_Duty >= BDCMOTOR_DUTY_FULL)
- PWM_Duty = BDCMOTOR_DUTY_FULL;
- if(PWM_Duty <=0)
- PWM_Duty = 0;
- __HAL_TIM_SET_COMPARE(&htimx_BDCMOTOR,TIM_CHANNEL_1,PWM_Duty);
- }
- printf("LOC:%d Sped: %2.2f r/m Curr: %d mA \n",Sample_Pulse,
- Spd_RPM ,(int32_t)ADC_CurrentValue);
- }
- }
-
- /**
- * 函数功能: ADC转换完成回调函数
- * 输入参数: hadc:ADC外设设备句柄
- * 返 回 值: 无
- * 说 明: 中断一次的时间是1.479ms,利用过采样和求均值方法,提高分辨率
- */
- void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
- {
- int32_t ADConv = 0 ;
- /* ADC采集太快,需要先停止再处理数据 */
- HAL_ADC_Stop_DMA(hadc);
- /* 采集总线电压 */
- SetChannelAsRank1(hadc,ADC_VOLT_CHANNEL);
- HAL_ADC_Start(hadc);
-
- /* 去掉高和低总共SORT_NUM个采样数据,取中间部分的数据做平均 */
- ADConv = ADC_GetSampleAvgN((int16_t*)&ADC_ConvValueHex,ADC_BUFFER);
-
- /* 累加采样结果并记录采样次数*/
- AverSum += ADConv;
- AverCnt++;
-
- /* 读取总线电压值 */
- HAL_ADC_Stop(hadc);
- SetChannelAsRank1(hadc,ADC_CURRENT_CHANNEL);
-
- HAL_ADC_Start_DMA(hadc,(uint32_t*)ADC_ConvValueHex,ADC_BUFFER);
- }
- /**
- * 函数功能: ADC看门狗中断回调函数
- * 输入参数: ADC句柄
- * 返 回 值: 无
- * 说 明: 检测到电压过低或者过高的时候就调用这个函数,停止输出.
- */
- void HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef* hadc)
- {
- /* 使能电机控制引脚 */
- static uint8_t i = 0;
- i++;
- if(ADC_VoltBus > VOLT_LIMIT_MIN && ADC_VoltBus < VOLT_LIMIT_MAX)
- i = 0 ;
- else if(i>=6)
- {
- SHUTDOWN_MOTOR();
- HAL_TIM_PWM_Stop(&htimx_BDCMOTOR,TIM_CHANNEL_1);
- HAL_TIMEx_PWMN_Stop(&htimx_BDCMOTOR,TIM_CHANNEL_1);
- PWM_Duty = 0;
- printf("Bus Voltage is out of range!!\n");
- printf("Please Reset the Target!\n");
- while(1);
- }
- }
- /**
- * 函数功能: 得到N 个ADC 采样的均值
- * 输入参数: 要做平均的ADC 采样数
- * 返 回 值: 均值
- * 说 明: 计算平均值,获得14bitsADC值
- */
- int32_t ADC_GetSampleAvgN(int16_t *Data, uint32_t N)
- {
- int32_t avg_sample =0x00;
- uint32_t index=0x00;
- /* 累加N 个ADC 采样 */
- for (index = 0; index < N; index++)
- {
- avg_sample += ((int32_t)Data[index]);
- }
- /* 计算N 个ADC 采样的均值 */
- avg_sample >>= ADC_Base;
- /* 返回均值 */
- return avg_sample;
- }
- /******************** PID 控制设计 ***************************/
- /**
- * 函数功能: PID参数初始化
- * 输入参数: 无
- * 返 回 值: 无
- * 说 明: 无
- */
- void PID_ParamInit()
- {
- cPID.LastError = 0; // Error[-1]
- cPID.PrevError = 0; // Error[-2]
- cPID.Proportion = CUR_P_DATA; // 比例常数 Proportional Const
- cPID.Integral = CUR_I_DATA; // 积分常数 Integral Const
- cPID.Derivative = CUR_D_DATA; // 微分常数 Derivative Const
- cPID.SetPoint = TARGET_CURRENT;// 设定目标Desired Value
- sPID.LastError = 0; // Error[-1]
- sPID.PrevError = 0; // Error[-2]
- sPID.Proportion = SPD_P_DATA; // 比例常数 Proportional Const
- sPID.Integral = SPD_I_DATA; // 积分常数 Integral Const
- sPID.Derivative = SPD_D_DATA; // 微分常数 Derivative Const
- sPID.SetPoint = TARGET_SPEED; // 设定目标Desired Value
-
- lPID.LastError = 0; // Error[-1]
- lPID.PrevError = 0; // Error[-2]
- lPID.Proportion = LOC_P_DATA; // 比例常数 Proportional Const
- lPID.Integral = LOC_I_DATA; // 积分常数 Integral Const
- lPID.Derivative = LOC_D_DATA; // 微分常数 Derivative Const
- lPID.SetPoint = TARGET_LOC; // 设定目标Desired Value
- }
- /**
- * 函数名称:电流闭环PID控制设计
- * 输入参数:当前控制量
- * 返 回 值:目标控制量
- * 说 明:无
- */
- int32_t CurPIDCalc(int32_t NextPoint)
- {
- int32_t iError,dError;
- iError = cPID.SetPoint - NextPoint; //偏差
- /* 设定闭环死区 */
- if((iError >= -3) && (iError <= 3))
- iError = 0;
-
- cPID.SumError += iError; //积分
- dError = iError - cPID.LastError; //微分
- cPID.LastError = iError;
-
- return (int32_t)(cPID.Proportion * (float)iError //比例项
- + cPID.Integral * (float)cPID.SumError //积分项
- + cPID.Derivative * (float)dError); //微分项
- }
- /**
- * 函数名称:速度闭环PID控制设计
- * 输入参数:当前控制量
- * 返 回 值:目标控制量
- * 说 明:无
- */
- int32_t SpdPIDCalc(float NextPoint)
- {
- float iError,dError;
- iError = sPID.SetPoint - NextPoint; //偏差
-
- if((iError<0.3f )&& (iError>-0.3f))
- iError = 0.0f;
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有代码51hei提供下载:
STM32编程实现直流有刷电机位置速度电流三闭环PID控制.7z
(1.54 MB, 下载次数: 135)
|