【重要】【程序】 使用VOFA+进行PID调试

这篇具有很好参考价值的文章主要介绍了【重要】【程序】 使用VOFA+进行PID调试。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

使用VOFA+ 进行PID调试

1. VOFA+是啥

​ 简单地来说,VOFA+是一个超级串口助手,除了可以实现一般串口助手的串口数据收发,它还可以实现数据绘图(包括直方图、FFT图),控件编辑,图像显示等功能。使用VOFA+,可以给我们平常的PID调参等调试带来方便,还可以自己制作符合自己要求的上位机,为嵌入式开发带来方便。

​ 这个是VOFA+的官网VOFA+ | VOFA+。

2. 如何使用VOFA+调试PID

2.1 VOFA+部分

​ 在正式开始使用VOFA+之前,最好先花十几分钟把官网的文档看一遍,熟悉一下基本操作。

​ 如果只是想要用VOFA+来进行数据绘图,直接使用一个波形图控件就行,但是如果想要把VOFA+当作一个长期使用的调参助手,我们最好设置一下控件。下面是我为调试直流电机的速度环和位置环设置的控件,包含一个波形图,六个参数调节框,两个目标值调节框。

【重要】【程序】 使用VOFA+进行PID调试

在设置好控件后我们需要对参数调节控件编写命令,这里用速度环的P进行举例。来到命令界面,添加一个新命令并重命名为Spe_P,发送内容为P2=%.2f!,这里的%.2f在实际发送中将被控件中的数值替代(详见官网文档),而感叹号是我自定义的命令结束符。

然后在控件上绑定命令即可

这样每次移动控件就可以发送相应的命令了

重复以上步骤设置完所有命令后VOFA+的部分就完成了。我这里还调整了参数控件的最大最小值,小数点位数,步进值和鼠标弹起后发送而不是边移动边发送等,各位可以按自己的需求调整

【重要】【程序】 使用VOFA+进行PID调试

编辑完成后记得保存控件和命令,否则软件卡死这些东西就都没了

【重要】【程序】 使用VOFA+进行PID调试

2.2 STM32部分

在STM32这边,我们要解析VOFA+上位机发过来的数据,并将其数据赋值到相应的变量。

我这里使用的是串口中断进行接收,当然也可以使用DMA进行接收。

首先我们要在CubeMax上设置好串口并开启串口中断,然后在main的while前开启串口中断

uint8_t RxBuffer[1];//串口接收缓冲
uint16_t RxLine = 0;//指令长度
uint8_t DataBuff[200];//指令内容

HAL_UART_Receive_IT(&huart2,(uint8_t *)RxBuffer,1);//开启串口中断,我用的是串口2

下一步要编写串口中断函数

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
    if(UartHandle->Instance==USART2)//如果是串口2
    {
        RxLine++;                      //每接收到一个数据,进入回调数据长度加1
        DataBuff[RxLine-1]=RxBuffer[0];  //把每次接收到的数据保存到缓存数组
        if(RxBuffer[0]==0x21)            //接收结束标志位,这个数据可以自定义,根据实际需求,这里只做示例使用,不一定是0x21
        {
            printf("RXLen=%d\r\n",RxLine);
            for(int i=0;i<RxLine;i++)
                printf("UART DataBuff[%d] = %c\r\n",i,DataBuff[i]);
            USART_PID_Adjust(1);//数据解析和参数赋值函数
            memset(DataBuff,0,sizeof(DataBuff));  //清空缓存数组
            RxLine=0;  //清空接收长度
        }
        RxBuffer[0]=0;
        HAL_UART_Receive_IT(&huart2, (uint8_t *)RxBuffer, 1); //每接收一个数据,就打开一次串口中断接收,否则只会接收一个数据就停止接收
    }
}

这里有个注意点,我们在VOFA+中设置的是以ASCII码的形式发送,所以如果发送了一个感叹号“!”,此时STM32接收到的将会是感叹号的ASCII码,十六进制下是0x21。如果发送数字0,那么接收到的数据用十进制表示是48,用十六进制表示是0x72。

接下来,我们要将指令中的数据提取出来

/*
 * 解析出DataBuff中的数据
 * 返回解析得到的数据
 */
float Get_Data(void)
{
    uint8_t data_Start_Num = 0; // 记录数据位开始的地方
    uint8_t data_End_Num = 0; // 记录数据位结束的地方
    uint8_t data_Num = 0; // 记录数据位数
    uint8_t minus_Flag = 0; // 判断是不是负数
    float data_return = 0; // 解析得到的数据
    for(uint8_t i=0;i<200;i++) // 查找等号和感叹号的位置
    {
        if(DataBuff[i] == '=') data_Start_Num = i + 1; // +1是直接定位到数据起始位
        if(DataBuff[i] == '!')
        {
            data_End_Num = i - 1;
            break;
        }
    }
    if(DataBuff[data_Start_Num] == '-') // 如果是负数
    {
        data_Start_Num += 1; // 后移一位到数据位
        minus_Flag = 1; // 负数flag
    }
    data_Num = data_End_Num - data_Start_Num + 1;
    if(data_Num == 4) // 数据共4位
    {
        data_return = (DataBuff[data_Start_Num]-48)  + (DataBuff[data_Start_Num+2]-48)*0.1f +
                (DataBuff[data_Start_Num+3]-48)*0.01f;
    }
    else if(data_Num == 5) // 数据共5位
    {
        data_return = (DataBuff[data_Start_Num]-48)*10 + (DataBuff[data_Start_Num+1]-48) + (DataBuff[data_Start_Num+3]-48)*0.1f +
                (DataBuff[data_Start_Num+4]-48)*0.01f;
    }
    else if(data_Num == 6) // 数据共6位
    {
        data_return = (DataBuff[data_Start_Num]-48)*100 + (DataBuff[data_Start_Num+1]-48)*10 + (DataBuff[data_Start_Num+2]-48) +
                (DataBuff[data_Start_Num+4]-48)*0.1f + (DataBuff[data_Start_Num+5]-48)*0.01f;
    }
    if(minus_Flag == 1)  data_return = -data_return;
//    printf("data=%.2f\r\n",data_return);
    return data_return;
}

最后,将解析得到的数值赋值到PID参数变量中就行啦。

/*
 * 根据串口信息进行PID调参
 */
void USART_PID_Adjust(uint8_t Motor_n)
{
    float data_Get = Get_Data(); // 存放接收到的数据
//    printf("data=%.2f\r\n",data_Get);
    if(Motor_n == 1)//左边电机
    {
        if(DataBuff[0]=='P' && DataBuff[1]=='1') // 位置环P
            pid_l_position.kp = data_Get;
        else if(DataBuff[0]=='I' && DataBuff[1]=='1') // 位置环I
            pid_l_position.ki = data_Get;
        else if(DataBuff[0]=='D' && DataBuff[1]=='1') // 位置环D
            pid_l_position.kd = data_Get;
        else if(DataBuff[0]=='P' && DataBuff[1]=='2') // 速度环P
            pid_l_speed.kp = data_Get;
        else if(DataBuff[0]=='I' && DataBuff[1]=='2') // 速度环I
            pid_l_speed.ki = data_Get;
        else if(DataBuff[0]=='D' && DataBuff[1]=='2') // 速度环D
            pid_l_speed.kd = data_Get;
        else if((DataBuff[0]=='S' && DataBuff[1]=='p') && DataBuff[2]=='e') //目标速度
            L_Target_Speed = data_Get;
        else if((DataBuff[0]=='P' && DataBuff[1]=='o') && DataBuff[2]=='s') //目标位置
            L_Target_Position = data_Get;
    }
    else if(Motor_n == 0) // 右边电机
    {
        if(DataBuff[0]=='P' && DataBuff[1]=='1') // 位置环P
            pid_r_position.kp = data_Get;
        else if(DataBuff[0]=='I' && DataBuff[1]=='1') // 位置环I
            pid_r_position.ki = data_Get;
        else if(DataBuff[0]=='D' && DataBuff[1]=='1') // 位置环D
            pid_r_position.kd = data_Get;
        else if(DataBuff[0]=='P' && DataBuff[1]=='2') // 速度环P
            pid_r_speed.kp = data_Get;
        else if(DataBuff[0]=='I' && DataBuff[1]=='2') // 速度环I
            pid_r_speed.ki = data_Get;
        else if(DataBuff[0]=='D' && DataBuff[1]=='2') // 速度环D
            pid_r_speed.kd = data_Get;
        else if((DataBuff[0]=='S' && DataBuff[1]=='p') && DataBuff[2]=='e') //目标速度
            R_Target_Speed = data_Get;
        else if((DataBuff[0]=='P' && DataBuff[1]=='o') && DataBuff[2]=='s') //目标位置
            R_Target_Position = data_Get;
    }
}

到这里,串口调试的部分就全部完成了,PID部分和定时器部分就不赘述了。

2.2 开始调参

代码写完后,开启串口,就可以实时调整PID各个参数和电机的目标速度了,当PID调节完成后再将参数写进代码中。

这里要注意数据发送时必须严格按照数据引擎的格式,否则软件将不能解析数据进行画图。想要查看格式的花把鼠标移动到数据引擎那里的黑色问号上就行了

【重要】【程序】 使用VOFA+进行PID调试

这不比原来那种看波形→改参数→烧代码→看波形的流程爽多了

如果在小车和电脑分别插一个蓝牙模块,就能实现小车边跑边调,直接化身远程遥控车,很好玩。

3. 其他

VOFA+简洁好用,但是又有点太简洁了,部分体验并不是很好(比如不能调整控件大小,保存文件不太方便等),所以如果学有余力,推荐自己用QT/PyQT写上位机。文章来源地址https://www.toymoban.com/news/detail-427909.html

到了这里,关于【重要】【程序】 使用VOFA+进行PID调试的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 使用自带的IDLE进行程序调试

    1.打开IDLE,在主菜单选择debug---debugger菜单项,将打开debug control对话框 2.在Python-shell窗口选择file-open菜单项,打开要调试的文件 3.添加断点,鼠标右击选择set-breakpoint菜单项,添加断点的行将以黄色底纹标记,删除断点,选择clear-breakpoint菜单项( 断点调试 是指在程序的某一行

    2023年04月20日
    浏览(38)
  • C# 中的单元测试,如何使用单元测试进行程序测试和调试?

    单元测试是一种软件测试方法,用于测试单个功能或方法是否按预期工作。在 C# 中,可以使用 .NET 框架中的单元测试工具来编写和运行单元测试。 下面是使用 Visual Studio 内置的单元测试框架来创建一个简单的单元测试的步骤: 在 Visual Studio 中创建一个新的类库项目。 在新项

    2024年02月15日
    浏览(63)
  • 微信小程序如何开发,调试技巧,对程序员小白来说太重要了

    简要介绍一下微信小程序开发的基本流程和一些常用组件,供你参考。在实际开发过程中,你可以根据需求选择合适的组件和 API 进行开发。 首先,你需要注册成为微信小程序开发者。访问微信公众平台(https://mp.weixin.qq.com/)并用你的微信号登录。进入“小程序”模块,按照

    2024年02月07日
    浏览(74)
  • Linux下ROS程序崩溃,程序段错误process has died [pid 20083, exit code -11, cmd /home GDB core dump 调试

           在Linux下可通过core文件来获取当程序异常退出(如异常信号SIGSEGV, SIGABRT等)时的堆栈信息。 core dump叫做核心转储 ,当程序运行过程中发生异常的那一刻的一个内存快照,操作系统在程序发生异常而异常在进程内部又没有被捕获的情况下,会把进程此刻内存、寄存器状态

    2024年02月12日
    浏览(47)
  • 【STM32】使用HAL库进行电机PID位置环控制,代码+调参

    前面两篇博文已经实现了电机测速和PID速度环控制,在这篇博文中,我们主要说明位置环的代码怎么写以及PID参数怎么调。 ​ 写完速度环后位置环就很简单了。 ​ 在串级PID中,内环的控制量一般是外环控制量的微分。在我们这里,外环是控制量是电机转动的位置(也可以说

    2024年02月16日
    浏览(45)
  • 【STM32】使用HAL库进行电机速度环PID控制,代码+调参

    主控:STM32F103C8T6 在进行速度控制之前,我们首先需要进行速度采样,这里参见这篇博文 ​ 这里不细说电机驱动模块的选型和使用,而是说一个常见的误区。我们驱动电机要使用两路PWM,一般是一路给PWM信号,一路是纯低电平。但这其实是不好的,正确的做法是一路给PWM,另

    2023年04月20日
    浏览(52)
  • windows下使用microsoft、intel、gnu不同编译器利用cmake和vscode对c++和fortran程序进行编译和调试

    由于编译器支持特性、编译后程序运行速度、安装使用便捷程度等的不同,我们往往会安装多种不同的编译器。对于c++语言主要的编译器有:microsoft、intel、gnu等,对于fortran语言则更多,包括gnu、intel、pgi等等。不同的编译器在一个系统下,往往需要利用一些手段进行区分,

    2024年02月05日
    浏览(59)
  • STM32通过K210进行PID巡线,使用蓝牙模块与电脑通信从而进行P,I,D参数的调节

    目录 一.前言部分(废话部分) 二.K210色块识别 1.必要知识 2.色块识别 3.单片机的接收代码 三.通过蓝牙连接在电脑上实现PID的调参 我使用的是HAL库,如果你使用的是标准库的话可以根据对应标准库的函数进行更改即可 因为之前使用灰度传感器进行巡线,即使用上PID,最后的效果也

    2024年02月14日
    浏览(47)
  • PID现场参数调试解密

    反馈与给定曲线 1.超调过大,减小比例,增大积分时间 2.迅速变化,存在小超调 3.实际值缓慢接近设定值,并且无超调的达到设定值 4.增益系数太小和/或微分时间太长 5.益系数太小和/或积分时间太长 现象 工业现场煤气流量满量程200000m³/h;通常在40000m³/h~150000m³/h范围波动,

    2024年02月04日
    浏览(39)
  • 让golang程序生成coredump文件并进行调试

    今天讲讲怎么让golang程序生成coredump文件,并且进行调试的。 别看我写了不少golang的博客,其实我平时写c++的时间更多,所以也算和coredump是老相识了。 core dump 文件实际上是进程在某个时间点时的内存映像,当时进程使用的内存是啥样就会被原样保存下来存在文件系统的某个

    2024年02月12日
    浏览(38)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包