VOFA+ :PID速度环调参

VOFA+ :PID速度环调参

一、PID

PID是一种常见的反馈控制系统,广泛应用于工业控制、自动化和机器人等领域。PID控制器基于当前系统的误差(偏差)、积分(偏差的累积)和微分(偏差的变化率)来调整控制输出,以使系统的实际输出尽可能接近期望值或设定点。

这里是PID的三个组成部分:

  1. 比例(Proportional, P):该部分产生一个输出,与当前误差成比例。增加比例增益(P增益)会增加系统对误差的敏感度,但可能导致系统过冲或振荡。
  2. 积分(Integral, I):该部分根据时间对误差的积累来产生一个输出。它可以用来消除静态误差,即使系统有漂移或存在持续偏差。
  3. 微分(Derivative, D):该部分根据误差变化率来产生一个输出。它可以减少系统的超调,并改善系统的动态响应,但过大的D增益可能导致系统过于敏感,产生噪声或抖动。

PID控制器的输出是这三个部分的加权和,通常用以下公式表示:
O u t p u t = K p ∗ e r r o r + K i ∗ ∫ e r r o r d t + K d ∗ d ( e r r o r ) / d t Output = Kp * error + Ki * ∫error dt + Kd * d(error)/dt Output=Kperror+Kierrordt+Kdd(error)/dt
其中, K p 、 K I 、 K D K_p、K_I、K_D KpK

<think>好的,我现在要解决的问题是用户如何在STM32C8T6上使用标准库通过串口将PID参数发送到VOFA+软件,生成波形图并实时调整。首先,我需要回顾用户提供的参考信息,然后逐步分析所需的步骤。 用户提到他们使用的是STM32C8T6系统板,并且参考了正点原子的代码,其中MPU6050和OLED的底层代码已经移植。他们的平衡小车控制逻辑涉及PID算法,直立环和速度环的输出通过中断函数处理,然后驱动电机。现在的问题是如何通过串口发送这些数据到VOFA+,实现波形显示和实时调参。 首先,我需要明确VOFA+的要求。VOFA+通常支持多种数据协议,比如FireWater协议,它使用特定的数据格式,比如以“:”分隔数据,以“\n”结尾。用户需要将PID_OUT、目标速度、Vertical_Kp等变量按照这种格式发送,才能在VOFA+中正确显示波形。 接下来,我需要考虑STM32端的实现。用户使用标准库,所以需要配置USART,设置合适的波特率(比如115200),并确保发送函数正确。可能需要使用DMA或中断方式发送数据,但如果是实时调参,可能发送频率不需要太高,所以查询方式发送可能足够,但需注意不要阻塞主程序。 然后是数据打包的问题。如何将浮点型数据转换成字节流发送。通常,可以将浮点数转换为字节数组,然后通过串口发送。例如,使用联合体(union)或者指针的方式将float分解为四个字节,然后发送。同时,需要按照VOFA+的协议格式来组织数据,比如每个变量之间用冒号分隔,最后加换行符。 另外,实时调参需要STM32能够接收来自VOFA+的数据,比如新的PID参数。这需要实现串口接收中断,解析接收到的数据,并更新相应的变量。例如,当VOFA+发送“Kp=1.5,Kd=0.2”这样的字符串时,STM32需要解析这些参数并更新Vertical_Kp和Vertical_Kd的值。 可能需要注意的问题包括:数据同步问题,比如如何确保发送的数据在VOFA+中正确对应各个通道;浮点数传输的精度问题;以及如何避免串口缓冲区溢出。此外,波特率设置需要匹配,数据发送的频率不能过高,否则可能导致丢数据。 总结步骤应该是: 1. 配置USART,初始化串口通信。 2. 实现数据打包函数,将PID参数按照VOFA+的协议格式打包。 3. 定时或在控制循环中发送数据。 4. 实现串口接收中断,解析接收到的参数并更新变量。 5. 在VOFA+中设置对应的协议和波形显示。 需要验证的地方包括:数据是否正确发送,VOFA+是否能正确解析,参数调整是否能实时生效,以及是否影响控制循环的实时性。 可能还需要考虑使用DMA发送以减少CPU负担,但需要根据具体情况判断。此外,使用标准库的函数,如USART_SendData,可能需要循环发送每个字节,尤其是当数据长度超过单个字节时。</think>### 实现步骤及代码示例 #### 1. 配置串口通信(USART) 在STM32C8T6上启用USART(如USART1),配置波特率为115200,8位数据位,无校验,1位停止位。使用标准库函数初始化: ```c // 串口初始化配置(以USART1为例) void USART1_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE); // 配置TX(PA9)和RX(PA10) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; USART_Init(USART1, &USART_InitStructure); USART_Cmd(USART1, ENABLE); } ``` #### 2. 数据打包与发送 将PID参数按VOFA+的**FireWater协议**格式发送,例如: `PID_OUT:Target_Speed:Vertical_Kp:Vertical_Kd:Velocity_Kp\n` ```c // 发送函数(浮点转字节流) void Send_Data_To_VOFA(float pid_out, float target_speed, float kp_v, float kd_v, float kp_vel) { uint8_t buffer[50]; int len = sprintf((char*)buffer, "%.2f:%.2f:%.2f:%.2f:%.2f\n", pid_out, target_speed, kp_v, kd_v, kp_vel); for (int i = 0; i < len; i++) { USART_SendData(USART1, buffer[i]); while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); } } ``` #### 3. 在控制循环中调用发送函数 在平衡小车的主循环或中断中周期性地发送数据(建议频率50-100Hz): ```c // 示例:直立环控制中调用发送 void Vertical_Control(void) { // ...PID计算... Send_Data_To_VOFA(PID_OUT, Target_Speed, Vertical_Kp, Vertical_Kd, Velocity_Kp); } ``` #### 4. 实现实时调参(接收VOFA+指令) 配置串口接收中断,解析参数指令(如`Kp=1.2,Kd=0.5`): ```c // 串口接收中断服务函数 uint8_t rx_buf[64]; uint8_t rx_index = 0; void USART1_IRQHandler(void) { if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { uint8_t ch = USART_ReceiveData(USART1); if (ch == '\n') { // 指令结束符 rx_buf[rx_index] = '\0'; Parse_Command((char*)rx_buf); // 解析指令 rx_index = 0; } else { rx_buf[rx_index++] = ch; } } } // 解析指令并更新参数 void Parse_Command(char* cmd) { char *token = strtok(cmd, ","); while (token != NULL) { if (strstr(token, "Kp=")) { sscanf(token, "Kp=%f", &Vertical_Kp); } else if (strstr(token, "Kd=")) { sscanf(token, "Kd=%f", &Vertical_Kd); } token = strtok(NULL, ","); } } ``` #### 5. VOFA+配置 1. 打开VOFA+,选择串口端口并设置相同的波特率(115200)。 2. 在控件面板中添加**Waveform**组件,绑定对应通道(PID_OUT、Target_Speed等)。 3. 添加**TextCommand**控件,设置发送格式为`Kp=1.2,Kd=0.5\n`,点击发送实时更新参数。 --- ### 注意事项 1. **数据同步**:确保发送频率与VOFA+采样率匹配,避免波形抖动。 2. **浮点精度**:使用`%.2f`限制小数位数以减少数据量。 3. **中断优先级**:串口接收中断优先级需低于控制中断(如MPU6050中断)[^1]。 4. **数据校验**:可在协议中添加校验字节(如CRC8)提高可靠性。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值