【STM32 HAL】用旋钮电位器进行PID调参

本文介绍了一种用于简化PID参数调整的硬件设计,通过电位器采集电压并转换为PID参数。在软件部分,使用STM32HAL库实现了ADC和DMA的配置,以及外部中断处理,实现在按钮触发时快速读取PID参数。这种方法避免了反复烧录程序的麻烦,提高了调试效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

pid调参很麻烦是怎么回事呢?pid相信大家都很熟悉,但是pid调参很麻烦是怎么回事呢,下面就让小编带大家一起了解吧。
pid调参很麻烦,其实就是因为每改一次就要重新烧录程序,大家可能会很惊讶pid怎么会调参很麻烦呢?但事实就是这样,小编也感到非常惊讶。
这就是关于pid调参很麻烦的事情了,大家有什么想法呢,欢迎在评论区告诉小编一起讨论哦!

所以小编做了一个简单的小工具——

1 硬件设计

思路就是采集三个电位器分得的电压值,经过换算后作为PID的参数值。当然你也可以把它用来调节其他参数
原理图
PCB
3D预览
设计很简单,转动三个旋钮电位器到合适位置,按下按键,SW被拉高,上升沿触发ADC采样,此时获得的三个电压值经过换算就可以作为PID的参数。

2 软件设计

这里给出STM32 HAL库的示例

2.1 CubeMX设置

基本配置

RCC、SYS、串口、时钟树之类的,略过不表

ADC+DMA

在这里插入图片描述
这里不开连续转换模式,每次开启转换后只采样一次就停止,和我们的要求相符

在这里插入图片描述
这里采样时间设置得稍微大一点就行

在这里插入图片描述

外部中断

在这里插入图片描述
根据电路,这里要配置成上升沿触发中断、下拉

在这里插入图片描述
中断一定要记得使能!
因为我们要在回调函数里用delay进行按键消抖,所以一定要把外部中断的优先级调得比系统时钟低,否则程序会卡在回调函数里

2.2 代码

魔术棒里勾选Use MicroLlB和Reset and Run

/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */

/* USER CODE BEGIN PV */
uint16_t AD_Value[3];
/* USER CODE END PV */
/* USER CODE BEGIN 4 */
int fputc(int ch, FILE *f)
{
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
  return ch;
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(GPIO_Pin == SW_Pin)
	{
		HAL_Delay(20);
		if(HAL_GPIO_ReadPin(SW_GPIO_Port, SW_Pin) == GPIO_PIN_SET)
		{
			//HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
			printf("Button triggered!\r\n");
      		HAL_ADC_Start_DMA(&hadc1,(uint32_t *)AD_Value,3);
		}
	}
}

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
  HAL_ADC_Stop_DMA(&hadc1);
  printf("P:%d I:%d D:%d\r\n", AD_Value[0], AD_Value[1], AD_Value[2]);
}
/* USER CODE END 4 */

进入中断回调函数后,先delay消抖,然后开启ADC DMA传输,DMA传输完成后在回调函数里关闭DMA,这一次读取就完成了。AD_Value里的数据经过换算后就可以作为PID的参数

3 效果

在这里插入图片描述

### STM32通过电位器控制LED亮度 为了实现STM32通过电位器控制LED亮度的功能,可以采用PWM技术。PWM是一种有效的手段来调节输出电压的有效值,从而改变LED的亮度[^1]。 具体来说,在STM32上可以通过ADC读取电位器输入的模拟量,并将其转换成相应的占空比数值去调整PWM信号。这样做的好处是可以线性地映射电位器位置到LED的不同亮度等级之间变化。当电位器旋转时,其电阻发生变化,进而影响分压电路中的电压水平;此电压作为ADC模块的输入,经过采样量化后得到代表当前旋钮角度的数据值;最后利用这些数据动态设定PWM周期内的高电平持续时间长短,以此达到渐变效果[^2]。 下面给出一段简单的C语言程序示范如何完成上述过程: ```c #include "stm32f1xx_hal.h" TIM_HandleTypeDef htim3; ADC_HandleTypeDef hadc1; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_TIM3_Init(void); static void MX_ADC1_Init(void); int main(void){ HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); // 初始化GPIO MX_TIM3_Init(); // 初始化定时器 TIM3 用于生成 PWM 波形 MX_ADC1_Init(); // 初始化 ADC while (1){ uint32_t adcValue; __HAL_RCC_ADC1_CLK_ENABLE(); // 开启ADC时钟 HAL_ADC_Start(&hadc1); // 启动一次转换 if(HAL_OK == HAL_ADC_PollForConversion(&hadc1, 10)){ adcValue = HAL_ADC_GetValue(&hadc1); // 获取转换后的结果 // 将AD采集的结果转化为合适的PWM占空比范围(假设最大分辨率为4095) int dutyCycle = ((adcValue * 100) / 4095); // 设置新的PWM参数并更新通道 __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1,dutyCycle*65535/100); HAL_Delay(100); // 延迟一段时间再重复测量 } HAL_ADC_Stop(&hadc1); // 结束本次转换 __HAL_RCC_ADC1_CLK_DISABLE(); // 关闭ADC时钟节省功耗 } } ``` 这段代码展示了基本框架,实际应用中可能还需要考虑更多细节优化以及错误处理机制等问题。例如,应该加入必要的初始化函数定义、中断服务例程以及其他外设配置等部分未在此处展示的内容。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值