当前位置: 首页 > news >正文

嵌入式硬件篇---超声波|PID


文章目录

  • 前言
  • 1. 硬件准备
    • 主控芯片
    • 超声波模块
    • 执行机构
    • 其他
  • 2. 硬件连接
  • 3. 超声波测距原理
    • 触发信号
    • 回波检测
    • 中断捕获
  • 4. 代码实现(基于HAL库)
    • (1) 初始化定时器(用于测量Echo高电平时间)
    • (2) 超声波触发与距离计算
  • 5. PID算法实现
    • (1) PID结构体定义
    • (2) PID计算函数
  • 6. 控制执行机构
    • (1) 电机控制(PWM调速)
    • (2) 舵机控制(角度调整)
  • 7. 主循环逻辑
  • 8. PID参数整定技巧
    • 先调P
    • 再调D
    • 最后调I
    • 测试
  • 9. 关键问题与优化
    • 超声波噪声
    • 死区处理
    • 动态目标


前言

STM32F103RCT6上使用超声波传感器(如HC-SR04)结合PID算法实现稳定距离控制,通常用于避障、跟随或定位等场景。以下是详细实现步骤:


1. 硬件准备

主控芯片

主控芯片:STM32F103RCT6(72MHz Cortex-M3,足够处理超声波数据与PID运算)。

超声波模块

超声波模块:HC-SR04(测距范围2cm~400cm,精度±3mm)。

执行机构

执行机构:电机(如直流电机+编码器)或舵机(用于调整方向)。

其他

其他:电源、驱动电路(如L298N)、OLED/LCD(可选,用于显示距离)。

2. 硬件连接

HC-SR04引脚 STM32引脚 说明
VCC 5V 模块供电
Trig PA1 触发信号(输出)
Echo PA0 回波信号(输入,需EXTI中断)
GND GND 共地
注意:Echo信号为5V电平,需通过**电阻分压(如1kΩ+2kΩ)**转换为3.3V,避免损坏STM32。

3. 超声波测距原理

触发信号

触发信号:STM32发送10μs的高电平脉冲到Trig引脚。

回波检测

回波检测:HC-SR04发射超声波并接收回波,Echo引脚输出高电平,
持续时间与距离成正比(公式:距离(cm) = 高电平时间(μs) / 58)。

中断捕获

中断捕获:使用定时器输入捕获模式或EXTI中断+普通定时器测量Echo高电平时间。

4. 代码实现(基于HAL库)

(1) 初始化定时器(用于测量Echo高电平时间)

// 定时器2初始化(1MHz计数频率,72MHz/72分频)
TIM_HandleTypeDef htim2;
void MX_TIM2_Init(void) {htim2.Instance = TIM2;htim2.Init.Prescaler = 71;          // 72分频htim2.Init.CounterMode = TIM_COUNTERMODE_UP;htim2.Init.Period = 0xFFFF;         // 最大计数值HAL_TIM_IC_Init(&htim2);
}// 输入捕获配置(通道1,PA0)
TIM_IC_InitTypeDef sConfigIC;
sConfigIC.ICPolarity = TIM_ICPOLARITY_RISING; // 上升沿触发
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter = 0;
HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_1);

(2) 超声波触发与距离计算

float Get_Distance(void) {uint32_t start_time = 0, end_time = 0;float distance_cm = 0;// 发送10us触发脉冲HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);delay_us(10);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);// 等待Echo上升沿(启动定时器)while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET);HAL_TIM_IC_Start(&htim2, TIM_CHANNEL_1);start_time = htim2.Instance->CCR1;// 等待Echo下降沿(停止定时器)while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET);end_time = htim2.Instance->CCR1;HAL_TIM_IC_Stop(&htim2, TIM_CHANNEL_1);// 计算距离(单位:cm)distance_cm = (end_time - start_time) / 58.0f;return distance_cm;
}

5. PID算法实现

PID控制器通过调节输出使当前距离(反馈值)趋近目标距离(设定值)。

(1) PID结构体定义

typedef struct {float Kp, Ki, Kd;      // PID参数float target;          // 目标距离(cm)float error, last_error, integral;
} PID_Controller;PID_Controller pid = {0.5, 0.01, 0.2, 10.0, 0, 0, 0}; // 示例参数

(2) PID计算函数

float PID_Update(PID_Controller *pid, float current) {pid->error = pid->target - current;  // 误差=目标值-当前值// 积分项(防饱和)pid->integral += pid->error;if (pid->integral > 100) pid->integral = 100;else if (pid->integral < -100) pid->integral = -100;// 微分项float derivative = pid->error - pid->last_error;pid->last_error = pid->error;// PID输出float output = pid->Kp * pid->error + pid->Ki * pid->integral + pid->Kd * derivative;return output;
}

6. 控制执行机构

根据PID输出调整电机或舵机:

(1) 电机控制(PWM调速)

// 初始化PWM(TIM3通道1,PA6)
void MX_TIM3_Init(void) {TIM_OC_InitTypeDef sConfigOC = {0};htim3.Instance = TIM3;htim3.Init.Prescaler = 71;          // 1MHz频率htim3.Init.Period = 999;             // 1kHz PWMHAL_TIM_PWM_Init(&htim3);sConfigOC.Pulse = 0;                // 初始占空比0sConfigOC.OCMode = TIM_OCMODE_PWM1;HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1);HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
}// 更新电机速度(PID输出映射到PWM占空比)
void Set_Motor_Speed(float pid_output) {uint16_t pwm = (uint16_t)fabs(pid_output * 10); // 比例缩放if (pwm > 999) pwm = 999;__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, pwm);// 根据输出正负设置电机方向if (pid_output > 0) {HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);   // 正转} else {HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET); // 反转}
}

(2) 舵机控制(角度调整)

// 设置舵机角度(PID输出映射到0~180°)
void Set_Servo_Angle(float pid_output) {uint16_t angle = 90 + (uint16_t)(pid_output * 10); // 示例映射uint16_t pwm = 500 + angle * 2000 / 180;           // 0.5ms~2.5ms__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, pwm);
}

7. 主循环逻辑

int main(void) {HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_TIM2_Init();MX_TIM3_Init();float current_distance = 0;float pid_output = 0;while (1) {current_distance = Get_Distance();      // 获取当前距离pid_output = PID_Update(&pid, current_distance);Set_Motor_Speed(pid_output);           // 调整电机速度// 或 Set_Servo_Angle(pid_output);     // 调整舵机角度HAL_Delay(50); // 控制周期50ms(20Hz)}
}

8. PID参数整定技巧

先调P

先调P:增大Kp直到系统快速响应但出现振荡。

再调D

再调D:加入Kd抑制振荡。

最后调I

最后调I:小幅增加Ki消除静态误差。

测试

测试场景:目标距离从远到近阶跃变化,观察响应曲线。

9. 关键问题与优化

超声波噪声

超声波噪声:多次采样取中值滤波

死区处理

死区处理:当误差小于阈值关闭PID输出,避免抖动。

动态目标

动态目标:若目标距离变化,需重新整定PID参数
通过上述步骤,STM32F103RCT6可稳定控制物体与超声波传感器间的距离。实际应用中需根据机械特性(如电机惯性)调整PID参数。


相关文章:

  • 三维空间中的组织行为映射:MATLAB 数据插值可视化技术
  • 实战项目6(09)
  • 企业内训|智能调控系统算法与优化——某汽车厂商
  • JVM内存结构有哪些?HashMap和HashTable的区别?
  • NX989NY104美光科技芯片NY109NY113
  • mem0跟Memgraph交互
  • 当 Manus AI 遇上 OpenAI Operator,谁能更胜一筹?
  • 大模型应用中常说的Rerank是什么技术?
  • 大模型核心基础简介
  • GIF图像技术介绍
  • MacOS Python3安装
  • Java在人工智能中的应用:机器学习与深度学习技术探讨
  • 剪板机结构设计:关键技术分析与优化策略
  • python 实现文件批量重命名
  • 网络IP分片
  • JVM——Java字节码基础
  • Web 实时通信技术:WebSocket 与 Server-Sent Events (SSE) 深入解析
  • SpringCloud Gateway知识点整理和全局过滤器实现
  • 梯形路径规划详解
  • Linux共享内存深度解析:从内核机制到云原生应用
  • 超新星|18岁冲击中超金靴,王钰栋的未来无限可能
  • 专访|韩国世宗研究所中国研究中心主任:李在明若上台将推行均衡外交
  • 城市轨道交通安全、内河港区布局规划、扎实做好防汛工作……今天的上海市政府常务会议研究了这些重要事项
  • 为证明我爸是我爸,我将奶奶告上法庭
  • 学习时报头版:世界要公道不要霸道
  • 上海工匠学院首届学历班56人毕业,新一届拟招生200人