stm32(HAL)库编码器电机pid代码及利用VOFA+对Pid波形显示调参

这篇具有很好参考价值的文章主要介绍了stm32(HAL)库编码器电机pid代码及利用VOFA+对Pid波形显示调参。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

stm32(HAL)库编码器电机pid代码及利用VOFA+对Pid波形显示调参

基本介绍

PID控制是一种经典的反馈控制算法,它通过不断地调整输出来使系统的实际值与设定值尽量接近,并保持在设定值附近。PID控制器由三个部分组成:比例§、积分(I)和微分(D)。

比例作用(P):比例作用通过测量实际值与设定值之间的偏差,乘以一个比例系数来产生输出。输出与偏差成正比,用来调整系统的响应速度和稳定性。较大的比例系数会增加系统的灵敏度,但可能导致过渡振荡。
积分作用(I):积分作用通过将偏差的累积值乘以一个积分系数来产生输出。积分作用能够消除系统的静差,提高系统的稳定性和响应速度。然而,过大的积分系数可能导致系统过度响应和振荡。
微分作用(D):微分作用通过测量偏差变化率,并乘以一个微分系数来产生输出。微分作用能够预测系统的未来趋势,以防止过冲和振荡。合适的微分系数可以提高系统的响应速度和稳定性,但过大的微分系数可能导致灵敏度降低。
PID控制器的输出是比例、积分和微分的加权和,即输出 = P * 偏差 + I * 积分值 + D * 变化率。通过调整比例、积分和微分系数,可以根据实际需求优化系统的性能。
hal编码器,stm32,单片机,嵌入式硬件pid的控制规律:
hal编码器,stm32,单片机,嵌入式硬件
Kp——比例系数; Ti——积分时间常数; TD——微分时间常数

利用pid控制电机是我们学习pid的基础,以下是我用HAL库通过stm32控制编码器电机pid代码及利用VOFA+对Pid波形显示调参

配置与程序部分

以F103为例配置hal,其实其他版本的也差不多
先基础配置时钟树,RCC,SYS,这里可以略过了
hal编码器,stm32,单片机,嵌入式硬件
先配置io输出引脚,供一个电机,到下面写代码会define控制引脚高电平低电平,控制电机正反转

接下来需要配置3个定时器,分别用于pwm输出,编码器捕获,和中断。编码器捕获用于识别脉冲,计算速度反馈给pid调速,中断定时器里就用于中断回调计算pid。接下来配置定时器
hal编码器,stm32,单片机,嵌入式硬件
配置定时器2打开编码器捕获
hal编码器,stm32,单片机,嵌入式硬件
定时器3,pwm输出
hal编码器,stm32,单片机,嵌入式硬件
定时器4
hal编码器,stm32,单片机,嵌入式硬件
我们还要利用usart与上位机通信显示波形
这里我用的usart2,usart1和I2c是之前我用来和蓝牙通信的和iled的,可以不管
最后还要去NVIC里设置中断优先
hal编码器,stm32,单片机,嵌入式硬件
这里配置就完成了,建立工程

首先我们需要打开定时器和USART,放在main中,while之前,定时器初始化之后,为了方便我们之后的函数都写在main.c里都可以,首先定时器就是以下代码

// 为了方便我们的函数都写在main.c里
HAL_TIM_Encoder_Start(&htim2, TIM_CHANNEL_ALL); //开启编码器模式
	HAL_TIM_Base_Start_IT(&htim2);
	HAL_TIM_Base_Start(&htim2);
	HAL_TIM_Base_Start_IT(&htim4);                  //开启定时器的中断
	HAL_TIM_Base_Start(&htim4);  
	HAL_TIM_Base_Start_IT(&htim3);
	HAL_TIM_Base_Start(&htim3);
	HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);

因为我们需要用VOFA+来打印波形,要用printf命令(VOFA的特点就是不用协议有printf就可打印波形非常好用),所以需要在函数前include <stdio.h>就可

// An highlighted block
#include <stdio.h>

了解上面的pid的控制规律
然后就写pid的代码了
直接把下面的代码无脑复制到main前面就行了

// An highlighted block
typedef struct __PID_Increment_Struct//一个定义结构体
{
    float Kp, Ki, Kd;  //系数
    float Error_Last1; //上次误差
    float Error_Last2; //上次误差
    float Out_Last;    //上次输出
} PID_Increment_Struct;
void motor1()//正//BIN()是我在main.h里define的,往下可以看到
{	
BIN1(0);
 BIN2(1);}
void motor0()//反//如果你的反了改0,1即可
{	
BIN1(1);
 BIN2(0);}
//vofa的FireWater数据协议  换行结尾  /n或/r/n  逗号分隔通道
//指定三个通道
/* USER CODE BEGIN 0 */
#define Encoder_TIM_Handle htim2
#define Motor_MAX_Duty 2000
// PID_Increment_Struct PID_Speed = {80, 5};
float Get_Speed()//计算速度
{
    int16_t zj;
    float Speed = 0;
    zj = __HAL_TIM_GetCounter(&Encoder_TIM_Handle);
    __HAL_TIM_SetCounter(&Encoder_TIM_Handle, 0);
    Speed = (float)zj / (4 * 11 * 30) * 100 * 60;//30是减速比,11是基础脉冲,4是因为4分频,可不改,最后算出速度是一分钟多少转
	b=Speed;//提取数值到外部变量,到时候放到while中显示实时速度
    return Speed;
   
}
//float Get_Angle()//计算角度(只速度控制可忽略)
//{
//    int16_t zj;
//    float angle = 0;
//    zj = __HAL_TIM_GetCounter(&Encoder_TIM_Handle);
//    angle = (float)zj / (4 * 15 * 34) * 360;
//    return angle;
//}
float PID_Increment(PID_Increment_Struct *PID, float Current, float Target)//pid计算
{
    float err,                                                                                                       //误差
        out,                                                                                                         //输出
        proportion,                                                                                                  //比例
        differential;                                                                                                //微分
    err = (float)Target - (float)Current;    	//计算误差
    proportion = (float)err - (float)PID->Error_Last1;                                                               //计算比例项
    differential = (float)err - 2 * (float)PID->Error_Last1 + (float)PID->Error_Last2;                               //计算微分项
    if(err<=40&&err>-40)
		out = (float)PID->Out_Last + (float)PID->Kp * proportion+(float)PID->Ki * err+ (float)PID->Kd * differential; //计算PID
	else//如果不if  else,调试的时候如果单片机只是5v上电但电机没转,你接12v电源开电机,电机速度会拉满,这就不好了
		out = (float)PID->Out_Last + (float)PID->Kp * proportion+ (float)PID->Kd * differential; //计算PID
    PID->Error_Last2 = PID->Error_Last1;                                                                             //更新上上次误差
    PID->Error_Last1 = err;                                                                                          //更新误差
    PID->Out_Last = out;                                                                                             //更新上此输出
    return out;
}
void motor(int16_t Speed)
{
    if (Speed == 0)
    {
		
        __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1,Motor_MAX_Duty+1 );
    }
    else if (Speed > 0)
    {
		motor0();
		
        __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1,Speed);
        
    }
    else if (Speed < 0)
    {
        Speed *= -1;
		motor1();
         __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1,Speed);
    }
}
PID_Increment_Struct PID_Speed = {20, 0.1, 0};//这个参数是我调的,不同参数得看不同电机
//PID_Increment_Struct PID_Angle = {3.1, 0, 0.06};//角度控制的,可忽略
//float angle;
float mb_speed_last;
float aa = 0;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    float Speed = 0;
    float set_speed = 0;
    float mb_speed;
    if (htim == &htim2)
    {
    }
    else if (htim == &htim4)//注释的都是角度控制的,到时候可以在深入使用
    {
//        angle += Get_Angle();
//        mb_speed = (int16_t)PID_Increment(&PID_Angle, angle, aa);

//        if (PID_Angle.Error_Last1 > 360)
//            mb_speed = 300;
//        else if (PID_Angle.Error_Last1 < -360)
//            mb_speed = -300;
        Speed = Get_Speed();
		mb_speed = 120;//目标速度
        set_speed = PID_Increment(&PID_Speed, Speed, mb_speed);
        if (set_speed > 2000)
            set_speed = 2000;
        else if (set_speed < -2000)
            set_speed = -2000;
			motor(set_speed);
		if (set_speed > 100 || set_speed < -100)//死区控制,改善电机异响
            motor(set_speed);
        a=set_speed;//提取数值到外部变量,到时候放到while中显示实时占空比
    }
}

宏定义电机输出变量

#define BIN1(state) HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,(GPIO_PinState)(state))    //IN1
#define BIN2(state) HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,(GPIO_PinState)(state))    //IN2
//控制电机正反的输出

接下来在while里加入printf命令

printf("%2f\n",b);//显示实时速度,vofa的FireWater数据协议  记得要换行结尾  \n,不然打印不出来,逗号分隔通道

下载编译烧录就可完成了

vofa+调试显示波形调参

需要下载vofa可从官网下链接: link
打开vofa,按图选择FireWater,FireWater是用来显示波形的协议,更多可参考官网的使用说明链接: link
hal编码器,stm32,单片机,嵌入式硬件

选择控件,将波形显示器加入到主屏幕上,长按拖动即可
hal编码器,stm32,单片机,嵌入式硬件

x轴默认为t轴,y轴选择io,即变量,单片机接上usb to ttl 转换器,再接上位机,识别到串口,打开串口,给电机上电即可显示出波形,愉快的调参。
hal编码器,stm32,单片机,嵌入式硬件
我最后的结果是这样的
hal编码器,stm32,单片机,嵌入式硬件
hal编码器,stm32,单片机,嵌入式硬件文章来源地址https://www.toymoban.com/news/detail-546722.html

到了这里,关于stm32(HAL)库编码器电机pid代码及利用VOFA+对Pid波形显示调参的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • stm32霍尔编码器电机测速原理

            本次选用的编码器电机为13线的霍尔编码器电机,电机减速比为30:1,转动一圈输出13*30=390个脉冲。轮胎直径为75mm,轮胎周长为pi*d=3*75=225mm.定时器采用四倍频计数,则一圈输出390*4=1560个脉冲。具体编码器知识这里就不多说了。          根据测速原理:假设编

    2024年02月15日
    浏览(44)
  • STM32之增量式编码器电机测速

    编码器,是一种用来测量机械旋转或位移的传感器。它能够测量机械部件在旋转或直线运动时的位移位置或速度等信息,并将其转换成一系列电信号。 . 按监测原理分类 光电编码器 光电编码器,是一种通过光电转换将输出轴上的机械几何位移量转换成脉冲或数字量的传感器

    2024年02月13日
    浏览(31)
  • STM32F407 电机编码器测量

    STM32的定时器功能非常强大,根据官方手册,定时器的功能如下 高级定时器 TIM1 和 TIM8 主要特性 TIM1 和 TIM8 定时器具有以下特性: ● 16 位递增、递减、递增/递减自动重载计数器。 ● 16 位可编程预分频器,用于对计数器时钟频率进行分频(即运行时修改),分频系数 介于

    2023年04月08日
    浏览(41)
  • SimpleFOC移植STM32(九)—— ABZ编码器电机

      SimpleFOC、ODrive和VESC 教程链接汇总:请点击     在SimpleFOC代码中,ABZ信号和霍尔电机信号处理方式很像,都是信号边沿触发中断,在中断中获取状态计算角度。 本次移植驱动板103和官方代码保持一致。 驱动板405采用的是定时器计数脉冲,处理方式不同。   ABZ或者ABI,叫

    2023年04月11日
    浏览(84)
  • stm32 HAL库 4096线ABZ编码器

    @[TOC]目录 买的是这个 AB相代表计数方向,Z代表过零点 也可以选上DMA 中断 找一个空闲管脚 打开对应中断 用DMA 过机械零点就+/-360

    2024年04月17日
    浏览(70)
  • STM32 HAL库 AS5600编码器程序

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 STM32 HAL库 AS5600编码器程序 提示:这里可以添加本文要记录的大概内容: AS5600磁性旋转位置编码器是一款可编程、12位高分辨率、非接触式的设备,具有卓越的可靠性和耐久性。这个旋转位置传感器提供

    2024年02月20日
    浏览(34)
  • Stm32-使用TB6612驱动电机及编码器测速

    最近在 学习编码电机以及尝试使用编码电机测速 。遇到了很多问题,花费了很多时间,在这里做一个记录,对自己学习到的知识进行一个总结 找了很多资料,看了很多视频,这些太多了,以至于让我不知道究竟哪一个是正确的,今天看这个,明天看这个,导致自己的学习效

    2023年04月16日
    浏览(62)
  • 【STM32】HAL库自学记录-旋转编码器的使用

    通过本文可学会两种实现判断旋转编码器正转反转的方法,可根据自己的应用场景来选择使用哪种方法。 1、芯片:STM32F103RCT6 2、STM32CubeMx软件 3、IDE: MDK-Keil软件 4、旋转编码器模块 5、XCOM V1.4串口软件 图中C端为GND。 方向 :A相和B相相差一个相位,一般来说是90°。A相信号在

    2024年02月11日
    浏览(42)
  • 【STM32】【HAL库】定时器编码器模式测速

    目录 概述 HAL设置  定时器的编码器模式 定时器设置  常用函数 代码 电机AB相增量型编码器的介绍和解码方法在这里介绍过了 电机编码器 https://blog.csdn.net/m0_57585228/article/details/125791283 测速可以使用外部中断进行脉冲计数 很多型号的单片机中有专门的电路来计算脉冲的速度和

    2023年04月18日
    浏览(50)
  • (STM32)PWM输出控制电机旋转并且使用编码器读取脉冲数

    目录  前言 一、pwm输出让电机转  1.电机的接线说明 2.驱动的接线说明 3.pwm输出代码  pwm.c pwm.h 4.输出pwm控制电机旋转 二、配置定时器编码器模式 1.定时器编码器模式 编码器原理 编码器相关的概念 2.编码器模式——代码部分 3.获取脉冲数 三、定时读取编码器读取的脉冲数

    2024年02月03日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包