例程下载:
资料包括程序、相关说明资料以及软件使用截图
百度云盘:https://pan.baidu.com/s/1slN8rIt 密码:u6m1 360云盘:https://yunpan.cn/OcPiRp3wEcA92u密码 cfb6 (硬石YS-F1Pro开发板HAL库例程持续更新\5. 软件设计之电机控制(HAL库版本)\有刷直流电机.zip)
/**
******************************************************************************
* 硬石YS-F1Pro开发板例程功能说明
*
* 例程名称: YSF1_HAL_MOTOR-046. 单轴25GA370直流电机位置式PID旋转控制(L298N驱动)
*
******************************************************************************
* 说明:
* 本例程配套硬石stm32开发板YS-F1Pro使用。
*
* 淘宝:
* 论坛:http://www.ing10bbs.com
* 版权归硬石嵌入式开发团队所有,请勿商用。
******************************************************************************
*/
【1】例程简介
【2】跳线帽情况
【3】操作及现象
/******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/
main.c文件内容
/* 私有类型定义 --------------------------------------------------------------*/
//定义PID结构体
typedef struct
{
__IO int SetPoint; //设定目标 Desired Value
__IO long SumError; //误差累计
__IO double Proportion; //比例常数 Proportional Const
__IO double Integral; //积分常数 Integral Const
__IO double Derivative; //微分常数 Derivative Const
__IO int LastError; //Error[-1]
__IO int PrevError; //Error[-2]
}PID;
/* 私有宏定义 ----------------------------------------------------------------*/
/*************************************/
//定义PID相关宏
// 这三个参数设定对电机运行影响非常大
/*************************************/
#define P_DATA 3.2 //P参数
#define I_DATA 1.1 //I参数
#define D_DATA -0.15 //D参数
/* 私有变量 ------------------------------------------------------------------*/
__IO uint16_t time_count=0; // 时间计数,每1ms增加一(与滴定时器频率有关)
__IO uint32_t CaptureNumber=0; // 输入捕获数
__IO uint8_t start_flag=0;
__IO double encoder_speed=0;
static PID sPID;
static PID *sptr = &sPID;
/* 扩展变量 ------------------------------------------------------------------*/
/* 私有函数原形 --------------------------------------------------------------*/
void IncPIDInit(void);
int IncPIDCalc(int NextPoint);
unsigned int LocPIDCalc(int NextPoint);
/* 函数体 --------------------------------------------------------------------*/
/**
* 函数功能: 主函数.
* 输入参数: 无
* 返 回 值: 无
* 说 明: 无
*/
int main(void)
{
/* 复位所有外设,初始化Flash接口和系统滴答定时器 */
HAL_Init();
/* 配置系统时钟 */
SystemClock_Config();
KEY_GPIO_Init();
MX_DEBUG_USART_Init();
IncPIDInit();
ENCODER_TIMx_Init();
HAL_TIM_Base_Start(&htimx_ENCODER);
/* 高级控制定时器初始化并配置PWM输出功能 */
L298N_TIMx_Init();
/* 启动定时器 */
HAL_TIM_Base_Start(&htimx_L298N);
HAL_TIM_IC_Start_IT(&htimx_ENCODER,ENCODER_TIM_CHANNELx);
/* 启动定时器通道和互补通道PWM输出 */
L298N_DCMOTOR_Contrl(1,2,0);
start_flag=1;
printf("增量式PID算法控制电机旋转\n");
/* 无限循环 */
while (1)
{
if(KEY1_StateRead()==KEY_DOWN) // 增速
{
/* 设置目标速度 */
sptr->SetPoint =50;
}
if(KEY2_StateRead()==KEY_DOWN) // 减速
{
/* 设置目标速度 */
sptr->SetPoint =300;
}
}
}
/**
* 函数功能: 系统滴答定时器中断回调函数
* 输入参数: 无
* 返 回 值: 无
* 说 明: 每发生一次滴答定时器中断进入该回调函数一次
*/
void HAL_SYSTICK_Callback(void)
{
if(start_flag) // 等待脉冲输出后才开始计时
{
time_count++; // 每1ms自动增一
if(time_count==200)
{
__IO uint32_t count;
__IO double cal;
/* 得到编码器计数值,数值越大说明速度越大 */
count=CaptureNumber;
CaptureNumber=0; // 清零,从零开始计数
/* 计数得到位置式PID的位置数值 */
PWM_Duty=LocPIDCalc(count);
if(PWM_Duty>899)PWM_Duty=899;
// 11:编码器线数(转速一圈输出脉冲数)
// 34:电机减数比,内部电机转动圈数与电机输出轴转动圈数比,即减速齿轮比
cal=sptr->SetPoint;
printf("\n设定目标速度 -> 编码器在%ds时间计数%d个脉冲\n",time_count,sptr->SetPoint);
printf(" 相当于实际目标速度为:%0.2f圈/s\n",cal*(1000/time_count)/11/34);
cal=count;
printf("当前电机速度-> 编码器在%ds时间计数%d个脉冲\n",time_count,count);
printf(" 相当于当前实际速度为:%0.2f圈/s\n",cal*(1000/time_count)/11/34);
printf("设置新的占空比为:%d\n",PWM_Duty);
L298N_DCMOTOR_Contrl(1,2,PWM_Duty);
time_count=0;
}
}
}
/**
* 函数功能: 定时器输入捕获中断回调函数
* 输入参数: htim:定时器句柄
* 返 回 值: 无
* 说 明: 无
*/
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
CaptureNumber++;
}
/**************PID参数初始化********************************/
void IncPIDInit(void)
{
sptr->LastError=0; //Error[-1]
sptr->PrevError=0; //Error[-2]
sptr->Proportion=P_DATA; //比例常数 Proportional Const
sptr->Integral=I_DATA; //积分常数 Integral Const
sptr->Derivative=D_DATA; //微分常数 Derivative Const
sptr->SetPoint=100; //设定目标Desired Value
}
/********************增量式PID控制设计************************************/
int IncPIDCalc(int NextPoint)
{
int iError,iIncpid; //当前误差
iError=sptr->SetPoint-NextPoint; //增量计算
iIncpid=(sptr->Proportion * iError) //E[k]项
-(sptr->Integral * sptr->LastError) //E[k-1]项
+(sptr->Derivative * sptr->PrevError); //E[k-2]项
sptr->PrevError=sptr->LastError; //存储误差,用于下次计算
sptr->LastError=iError;
return(iIncpid); //返回增量值
}
/********************位置式 PID 控制设计************************************/
unsigned int LocPIDCalc(int NextPoint)
{
int iError,dError;
iError = sptr->SetPoint - NextPoint; //偏差
sptr->SumError += iError; //积分
dError = iError - sptr->LastError; //微分
sptr->LastError = iError;
return(sptr->Proportion * iError //比例项
+ sptr->Integral * sptr->SumError //积分项
+ sptr->Derivative * dError); //微分项
}
/******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/
|